Browse Source

Saving the Frame Set

This code allows the frames of a frame set control to be saved in regular object notation. It also sets up mouse locking within the edit control itself and fixes a bug with positioning child of a window control.
Peter Robinson 2 years ago
parent
commit
b51a040b46

+ 2 - 3
engine/source/gui/containers/guiChainCtrl.cc

@@ -150,9 +150,8 @@ void GuiChainCtrl::onChildRemoved(SimObject *child)
 
 void GuiChainCtrl::calculateExtent(bool holdLength)
 {
-	Point2I offset = Point2I(mBounds.point.Zero);
-	Point2I extent = Point2I(getExtent());
-	RectI innerRect = getInnerRect(offset, extent, NormalState, mProfile);
+	Point2I offset = Point2I::Zero;
+	RectI innerRect = getInnerRect(offset);
 
 	S32 length = positionChildren(innerRect);
 	S32 oldLength = mIsVertical ? innerRect.extent.y : innerRect.extent.x;

+ 126 - 3
engine/source/gui/containers/guiFrameSetCtrl.cc

@@ -191,6 +191,20 @@ GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findEmptyFrame()
 	return nullptr;
 }
 
+GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findEmptyFrameAtLocation(const RectI& location)
+{
+	if (!control && !child1 && !child2 && localPosition == location.point && extent == location.extent)
+	{
+		return this;
+	}
+	else if (child1 && child2)
+	{
+		Frame* attempt = child1->findEmptyFrameAtLocation(location);
+		return attempt ? attempt : child2->findEmptyFrameAtLocation(location);
+	}
+	return nullptr;
+}
+
 GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::twin()
 {
 	if (parent)
@@ -460,6 +474,13 @@ bool GuiFrameSetCtrl::onAdd()
 	// Always expand to fill the parent (we just ignore the points passed in).
 	parentResized(Point2I(), Point2I());
 
+	Frame* frame = &mRootFrame;
+	loadFrame(frame, 1);
+	clearDynamicFields();
+
+	//resize one last time for the frames
+	resize(getPosition(), getExtent());
+
 	// Return Success.
 	return true;
 }
@@ -470,13 +491,33 @@ void GuiFrameSetCtrl::parentResized(const Point2I& oldParentExtent, const Point2
 	GuiControl* parent = getParent();
 	if(parent)
 	{
-		Point2I origin = Point2I(0, 0);
-		Point2I parentInnerExt = getInnerRect(origin, parent->mBounds.extent, NormalState, parent->mProfile).extent;
+		Point2I origin = Point2I::Zero;
+		Point2I parentInnerExt = parent->getInnerRect().extent;
 
 		resize(origin, parentInnerExt);
 	}
 }
 
+void GuiFrameSetCtrl::loadFrame(GuiFrameSetCtrl::Frame* frame, const U32 frameID)
+{
+	frame->id = frameID;
+	U32 child1ID = dAtoi(getDataField("child1ID", frameID));
+	U32 child2ID = dAtoi(getDataField("child2ID", frameID));
+	frame->isVertical = dAtob(getDataField("isVertical", frameID));
+	U32 frameExtentX = dAtoi(getDataField("frameExtentX", frameID));
+	U32 frameExtentY = dAtoi(getDataField("frameExtentY", frameID));
+	frame->isAnchored = dAtob(getDataField("isAnchored", frameID));
+
+	frame->extent.set(frameExtentX, frameExtentY);
+	if (child1ID && child2ID)
+	{
+		splitFrame(frame, frame->isVertical ? GuiDirection::Up : GuiDirection::Left);
+
+		loadFrame(frame->child1, child1ID);
+		loadFrame(frame->child2, child2ID);
+	}
+}
+
 void GuiFrameSetCtrl::onChildAdded(GuiControl* child)
 {
 	//Ensure the child isn't positioned to the center
@@ -494,11 +535,19 @@ void GuiFrameSetCtrl::onChildAdded(GuiControl* child)
 	Frame* frame = mRootFrame.findFrameWithCtrl(child);
 	if(!frame)
 	{
-		Frame* emptyFrame = mRootFrame.findEmptyFrame();
+		Frame* emptyFrame = mRootFrame.findEmptyFrameAtLocation(child->getBounds());
 		if(emptyFrame)
 		{
 			emptyFrame->control = child;
 		}
+		else
+		{
+			Frame* emptyFrame = mRootFrame.findEmptyFrame();
+			if (emptyFrame)
+			{
+				emptyFrame->control = child;
+			}
+		}
 	}
 	//resize(getPosition(), getExtent());
 }
@@ -1173,4 +1222,78 @@ void GuiFrameSetCtrl::setControlUpDownCursor(GuiCursor* cursor)
 	if (cursor == mUpDownCursor)
 		return;
 	mUpDownCursor = cursor;
+}
+
+void GuiFrameSetCtrl::writeFields(Stream& stream, U32 tabStop)
+{
+	if (mRootFrame.child1 && mRootFrame.child2)
+	{
+		setModDynamicFields(true);
+		setCanSaveDynamicFields(true);
+
+		Frame* frame = &mRootFrame;
+		generateFrameFields(frame);
+		Parent::writeFields(stream, tabStop);
+		clearDynamicFields();
+
+		setModDynamicFields(false);
+		setCanSaveDynamicFields(false);
+	}
+	else
+	{
+		Parent::writeFields(stream, tabStop);
+	}
+}
+
+void GuiFrameSetCtrl::generateFrameFields(GuiFrameSetCtrl::Frame* frame)
+{
+	//parentID = frame->parent->id
+	//child1ID = frame->child1->id
+	//child2ID = frame->child2->id
+	//isVertical
+	//frameExtent = isVertical ? frame->extent.y : frame->extent.x
+	//isAnchored
+	//and make sure control has the correctID for 
+
+	U32 id = frame->id;
+	U32 child1ID = frame->child1 ? frame->child1->id : 0;
+	U32 child2ID = frame->child2 ? frame->child2->id : 0;
+
+	setDataField("child1ID", id, child1ID);
+	setDataField("child2ID", id, child2ID);
+	setDataField("isVertical", id, frame->isVertical);
+	setDataField("frameExtentX", id, frame->extent.x);
+	setDataField("frameExtentY", id, frame->extent.y);
+	setDataField("isAnchored", id, frame->isAnchored);
+
+	if (frame->child1)
+	{
+		generateFrameFields(frame->child1);
+	}
+
+	if (frame->child2)
+	{
+		generateFrameFields(frame->child2);
+	}
+}
+
+void GuiFrameSetCtrl::setDataField(const char* tag, const U32 id, const U32 value)
+{
+	char idBuffer[16];
+	char valueBuffer[16];
+
+	StringTableEntry tagFieldName = StringTable->insert(tag);
+
+	dSprintf(idBuffer, 16, "%d", id);
+	dSprintf(valueBuffer, 16, "%d", value);
+	SimObject::setDataField(tagFieldName, idBuffer, valueBuffer);
+}
+
+const char* GuiFrameSetCtrl::getDataField(const char* tag, const U32 id)
+{
+	char idBuffer[16];
+	StringTableEntry tagFieldName = StringTable->insert(tag);
+
+	dSprintf(idBuffer, 16, "%d", id);
+	return SimObject::getDataField(tagFieldName, idBuffer);
 }

+ 10 - 1
engine/source/gui/containers/guiFrameSetCtrl.h

@@ -46,8 +46,9 @@ public:
 		bool isVertical;
 		U32 id;
 		Point2I extent;
-		Point2I localPosition;
 		bool isAnchored;
+
+		Point2I localPosition;
 		RectI dividerRect;
 		RectI spliterRect1;//shown in edit mode
 		RectI spliterRect2;//shown in edit mode
@@ -70,6 +71,7 @@ public:
 		void sizeInsertButtons(const Point2I& newPosition, const Point2I& newExtent);
 		Frame* findFrame(const S32 frameID);
 		Frame* findEmptyFrame();
+		Frame* findEmptyFrameAtLocation(const RectI& location);
 		Frame* twin();
 		Frame* findHitDivider(const Point2I& position);
 		Frame* findFrameWithCtrl(GuiControl* ctrl);
@@ -96,6 +98,7 @@ public:
 	
 	bool onAdd();
 	virtual void parentResized(const Point2I& oldParentExtent, const Point2I& newParentExtent);
+	void loadFrame(GuiFrameSetCtrl::Frame* frame, const U32 frameID);
 	void resize(const Point2I& newPosition, const Point2I& newExtent);
 	void inspectPostApply();
 	bool onWake();
@@ -139,6 +142,12 @@ public:
 	static bool setTabProfileFn(void* obj, const char* data) { GuiControlProfile* profile; Sim::findObject(data, profile); static_cast<GuiFrameSetCtrl*>(obj)->setTabProfile(profile); return true; }
 	static bool setPageProfileFn(void* obj, const char* data) { GuiControlProfile* profile; Sim::findObject(data, profile); static_cast<GuiFrameSetCtrl*>(obj)->setTabPageProfile(profile); return true; }
 
+	void writeFields(Stream& stream, U32 tabStop);
+	void generateFrameFields(Frame* frame);
+
+	void setDataField(const char* tag, const U32 id, const U32 value);
+	const char* getDataField(const char* tag, const U32 id);
+
 	DECLARE_CONOBJECT(GuiFrameSetCtrl);
 };
 

+ 3 - 3
engine/source/gui/containers/guiTabBookCtrl.cc

@@ -536,7 +536,7 @@ void GuiTabBookCtrl::calculatePageTabs()
    S32 currX      = 0;
    S32 currY      = 0;
    S32 tabHeight  = 0;
-   RectI innerRect = getInnerRect(mBounds.point, mBounds.extent, NormalState, mProfile);
+   RectI innerRect = getInnerRect();
    mFontHeight = mTabProfile->getFont(mFontSizeAdjust)->getHeight();
    Point2I innerExtent = Point2I(mFontHeight, mFontHeight);
    Point2I fontBasedBounds = getOuterExtent(innerExtent, NormalState, mTabProfile);
@@ -706,7 +706,7 @@ void GuiTabBookCtrl::balanceColumn( S32 column , S32 totalTabWidth )
       return;
 
    // Balance the tabs across the remaining space
-   RectI innerRect = getInnerRect(mBounds.point, mBounds.extent, NormalState, mProfile);
+   RectI innerRect = getInnerRect();
    S32 spaceToDivide = innerRect.extent.y - totalTabWidth;
    S32 pointDelta    = 0;
    for( S32 i = 0; i < rowTemp.size(); i++ )
@@ -743,7 +743,7 @@ void GuiTabBookCtrl::balanceRow( S32 row, S32 totalTabWidth )
       return;
 
    // Balance the tabs across the remaining space
-   RectI innerRect = getInnerRect(mBounds.point, mBounds.extent, NormalState, mProfile);
+   RectI innerRect = getInnerRect();
    S32 spaceToDivide = innerRect.extent.x - totalTabWidth;
    S32 pointDelta    = 0;
    for( S32 i = 0; i < rowTemp.size(); i++ )

+ 6 - 0
engine/source/gui/containers/guiWindowCtrl.cc

@@ -953,6 +953,12 @@ RectI GuiWindowCtrl::renderButton(const RectI &contentRect, S32 distanceFromEdge
 	return finalButtonContent;
 }
 
+RectI GuiWindowCtrl::getInnerRect(Point2I& offset, Point2I& extent, GuiControlState currentState, GuiControlProfile* profile)
+{
+	Point2I contentExtent = Point2I(extent.x, extent.y - mTitleHeight);
+	return Parent::getInnerRect(offset, contentExtent, currentState, mContentProfile);
+}
+
 GuiControlState GuiWindowCtrl::getRegionCurrentState(GuiWindowCtrl::Region region)
 {
 	GuiControlState currentState = GuiControlState::NormalState;

+ 1 - 0
engine/source/gui/containers/guiWindowCtrl.h

@@ -146,6 +146,7 @@ class GuiWindowCtrl : public GuiControl
       void onRender(Point2I offset, const RectI &updateRect);
 	  RectI renderButtons(const Point2I &offset, const RectI &contentRect);
 	  RectI renderButton(const RectI &contentRect, S32 distanceFromEdge, GuiControlState buttonState, GuiControlProfile *profile, Icon defaultIcon);
+	  RectI getInnerRect(Point2I& offset, Point2I& extent, GuiControlState currentState, GuiControlProfile* profile);
 
 	  void setControlContentProfile(GuiControlProfile* prof);
 	  void setControlCloseButtonProfile(GuiControlProfile* prof);

+ 37 - 12
engine/source/gui/editor/guiEditCtrl.cc

@@ -44,6 +44,7 @@ GuiEditCtrl::GuiEditCtrl(): mCurrentAddSet(NULL),
    mDragBeginPoints.clear();
    mSelectedControls.clear();
    mUseGridSnap = true;
+   mMouseLockedEditCtrl = nullptr;
 
    mDefaultCursor    = NULL;
    mLeftRightCursor  = NULL;
@@ -728,11 +729,18 @@ void GuiEditCtrl::onTouchDown(const GuiEvent &event)
    if(!mCurrentAddSet)
       mCurrentAddSet = mContentControl;
 
-   //find the control we clicked
-   ctrl = mContentControl->findHitControl(mLastMousePos, mCurrentAddSet->mLayer);
-
-   Point2I editorOffset = localToGlobalCoord(Point2I(0,0));
-   bool handledEvent = ctrl->onMouseDownEditor( event, editorOffset );
+   bool handledEvent = false;
+	Point2I editorOffset = localToGlobalCoord(Point2I(0,0));
+   if(mMouseLockedEditCtrl)
+   {
+		handledEvent = mMouseLockedEditCtrl->onMouseDownEditor(event, editorOffset);
+   }
+   else
+   {
+	   //find the control we clicked
+	   ctrl = mContentControl->findHitControl(mLastMousePos, mCurrentAddSet->mLayer);
+	   handledEvent = ctrl->onMouseDownEditor( event, editorOffset );
+   }
    if( handledEvent )
    {
       // The Control handled the event and requested the edit ctrl
@@ -860,7 +868,16 @@ void GuiEditCtrl::onTouchUp(const GuiEvent &event)
    GuiControl *ctrl = mContentControl->findHitControl(mLastMousePos, mCurrentAddSet->mLayer);
 
    Point2I localOffset = localToGlobalCoord( Point2I(0,0) );
-   bool handledEvent = ctrl->onMouseUpEditor( event, localOffset );
+   bool handledEvent = false;
+   if (mMouseLockedEditCtrl)
+   {
+		handledEvent = mMouseLockedEditCtrl->onMouseUpEditor(event, localOffset);
+   }
+   else 
+   {
+		handledEvent = ctrl->onMouseUpEditor( event, localOffset );
+   }
+
    if( handledEvent == true )
    {
       // The Control handled the event and requested the edit ctrl
@@ -870,6 +887,7 @@ void GuiEditCtrl::onTouchUp(const GuiEvent &event)
 
    //unlock the mouse
    mouseUnlock();
+   editMouseUnlock();
 
    // Reset Drag Axis Alignment Information
    mDragBeginPoint.set(-1,-1);
@@ -920,14 +938,21 @@ void GuiEditCtrl::onTouchDragged(const GuiEvent &event)
 
    if(!mCurrentAddSet)
       mCurrentAddSet = mContentControl;
+		
+	Point2I mousePoint = globalToLocalCoord(event.mousePoint);
 
-   Point2I mousePoint = globalToLocalCoord(event.mousePoint);
-
-   //find the control we clicked
-   GuiControl *ctrl = mContentControl->findHitControl(mousePoint, mCurrentAddSet->mLayer);
+   Point2I localOffset = localToGlobalCoord(Point2I(0, 0));
+   bool handledEvent = false;
+   if (mMouseLockedEditCtrl)
+   {
+	   handledEvent = mMouseLockedEditCtrl->onMouseDraggedEditor(event, localOffset);
+   }
+   else
+   {
+		GuiControl *ctrl = mContentControl->findHitControl(mousePoint, mCurrentAddSet->mLayer);
+	   handledEvent = ctrl->onMouseDraggedEditor(event, localOffset);
+   }
 
-   Point2I dragOffset = localToGlobalCoord( Point2I(0,0) );
-   bool handledEvent = ctrl->onMouseDraggedEditor( event, dragOffset );
    if( handledEvent )
    {
       // The Control handled the event and requested the edit ctrl

+ 6 - 0
engine/source/gui/editor/guiEditCtrl.h

@@ -39,6 +39,7 @@ class GuiEditCtrl : public GuiControl
    bool					mUseGridSnap;
    Point2I				   mDragBeginPoint;
    Vector<Point2I>		mDragBeginPoints;
+   GuiControl*			mMouseLockedEditCtrl;
 
    // Undo
    UndoManager          mUndoManager;
@@ -140,6 +141,11 @@ class GuiEditCtrl : public GuiControl
    S32 getGridSize() { return mGridSnap.x; }
    void moveSelectionToCtrl(GuiControl*);
    ColorI getEditorColor() { return mProfile->getFillColor(DisabledState); }
+
+   //Editor Mouse Locking
+   bool editIsMouseLocked(GuiControl* ctrl) { return ctrl == mMouseLockedEditCtrl; }
+   void editMouseLock(GuiControl* ctrl) { mMouseLockedEditCtrl = ctrl; }
+   void editMouseUnlock() { mMouseLockedEditCtrl = nullptr; }
 };
 
 #endif //_GUI_EDIT_CTRL_H

+ 1 - 3
engine/source/gui/editor/guiMenuBarCtrl.cc

@@ -137,9 +137,7 @@ void GuiMenuBarCtrl::onChildRemoved(SimObject *child)
 
 void GuiMenuBarCtrl::calculateMenus()
 {
-	Point2I zero = mBounds.point.Zero;
-	Point2I extent = getExtent();
-	RectI innerRect = getInnerRect(zero, extent, NormalState, mProfile);
+	RectI innerRect = getInnerRect();
 	iterator i;
 	S32 length = 0;
 	for (i = begin(); i != end(); i++)

+ 29 - 6
engine/source/gui/guiControl.cc

@@ -162,7 +162,7 @@ void GuiControl::onChildAdded( GuiControl *child )
 	if(mProfile)
 	{
 		//This will cause the child control to be centered if it needs to be.
-		RectI innerRect = this->getInnerRect(mBounds.point, mBounds.extent, GuiControlState::NormalState, mProfile);
+		RectI innerRect = getInnerRect();
 		child->parentResized(innerRect.extent, innerRect.extent);
 		
 		if (isMethod("onChildAdded"))
@@ -543,8 +543,7 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
 	if(mHorizSizing == horizResizeCenter || mVertSizing == vertResizeCenter)
 	{
 		//This is based on the "new" outer extent of the parent.
-      Point2I origin = Point2I(0, 0);
-		parentInnerExt = getInnerRect(origin, parent->mBounds.extent, NormalState, parent->mProfile).extent;
+		parentInnerExt = parent->getInnerRect().extent;
 	}
 
     if (mHorizSizing == horizResizeCenter)
@@ -725,6 +724,16 @@ RectI GuiControl::applyPadding(Point2I &offset, Point2I &extent, GuiControlState
 	return RectI(offset.x + leftSize, offset.y + topSize, (extent.x - leftSize) - rightSize, (extent.y - topSize) - bottomSize);
 }
 
+RectI GuiControl::getInnerRect(GuiControlState currentState)
+{
+	return getInnerRect(mBounds.point, mBounds.extent, currentState, mProfile);
+}
+
+RectI GuiControl::getInnerRect(Point2I& offset, GuiControlState currentState)
+{
+	return getInnerRect(offset, mBounds.extent, currentState, mProfile);
+}
+
 RectI GuiControl::getInnerRect(Point2I &offset, Point2I &extent, GuiControlState currentState, GuiControlProfile *profile)
 {
 	//Get the border profiles
@@ -1386,12 +1395,23 @@ GuiControl* GuiControl::findHitControl(const Point2I &pt, S32 initialLayer)
 
 bool GuiControl::isMouseLocked()
 {
+	if (isEditMode())
+	{
+		return smEditorHandle->editIsMouseLocked(this);
+	}
+
    GuiCanvas *root = getRoot();
    return root ? root->getMouseLockedControl() == this : false;
 }
 
 void GuiControl::mouseLock(GuiControl *lockingControl)
 {
+	if (isEditMode())
+	{
+		smEditorHandle->editMouseLock(lockingControl);
+		return;
+	}
+
    GuiCanvas *root = getRoot();
    if (root)
       root->mouseLock(lockingControl);
@@ -1399,13 +1419,16 @@ void GuiControl::mouseLock(GuiControl *lockingControl)
 
 void GuiControl::mouseLock()
 {
-   GuiCanvas *root = getRoot();
-   if (root)
-      root->mouseLock(this);
+   mouseLock(this);
 }
 
 void GuiControl::mouseUnlock()
 {
+	if (isEditMode())
+	{
+		smEditorHandle->editMouseUnlock();
+		return;
+	}
    GuiCanvas *root = getRoot();
    if (root)
       root->mouseUnlock(this);

+ 3 - 1
engine/source/gui/guiControl.h

@@ -777,7 +777,9 @@ public:
 	RectI applyPadding(Point2I &offset, Point2I &extent, GuiControlState currentState, GuiControlProfile *profile);
 
 	/// Returns the bounds of the rect with margin, borders, and padding applied.
-	RectI getInnerRect(Point2I &offset, Point2I &extent, GuiControlState currentState, GuiControlProfile *profile);
+	RectI getInnerRect(GuiControlState currentState = GuiControlState::NormalState);
+	RectI getInnerRect(Point2I& offset, GuiControlState currentState = GuiControlState::NormalState);
+	virtual RectI getInnerRect(Point2I &offset, Point2I &extent, GuiControlState currentState, GuiControlProfile *profile);
 
 	/// Returns the extent of the outer rect given the extent of the inner rect.
 	Point2I getOuterExtent(Point2I &innerExtent, GuiControlState currentState, GuiControlProfile *profile);

+ 1 - 3
engine/source/gui/guiTextEditCtrl.cc

@@ -581,9 +581,7 @@ bool GuiTextEditCtrl::validate()
 
 const RectI GuiTextEditCtrl::getGlobalInnerRect()
 {
-    Point2I offset = Point2I(mBounds.point.Zero);
-    Point2I extent = Point2I(getExtent());
-    RectI innerRect = getInnerRect(offset, extent, SelectedState, mProfile);
+    RectI innerRect = getInnerRect(SelectedState);
 
     Point2I globalCtrlOffset = localToGlobalCoord(innerRect.point);
     RectI globalInnerRect(globalCtrlOffset, innerRect.extent);