瀏覽代碼

Fixed Some Tab Issues

This fixes a number of issues with tabbing through the controls on the inspector. This adds a way to display when a check box and a drop down is the first responder. It also sets visibility of hidden direct children of an expand control to false when the expand control is collapsed and further makes it so non-visible controls cannot be tabbed to. It also fixes the focus code so that textboxes can lose focus when a click happens outside of the text box. When a textbox gains focus through tabbing, it now selects the contents of the box.
Peter Robinson 2 年之前
父節點
當前提交
de0219d9fd

+ 6 - 4
editor/EditorCore/Themes/BaseTheme/BaseTheme.cs

@@ -830,6 +830,7 @@ function BaseTheme::makeCheckboxProfile(%this)
 		fontColorNA = %this.setAlpha(%this.color4, 100);
 		fontColorNA = %this.setAlpha(%this.color4, 100);
 		align = left;
 		align = left;
 		vAlign = middle;
 		vAlign = middle;
+		cursorColor = %this.color5;
 
 
 		borderLeft = %borderLight;
 		borderLeft = %borderLight;
 		borderRight = %borderDark;
 		borderRight = %borderDark;
@@ -1175,10 +1176,10 @@ function BaseTheme::makeTextEditProfile(%this)
 
 
 	%textBorderH = new GuiBorderProfile()
 	%textBorderH = new GuiBorderProfile()
 	{
 	{
-		padding = 10;
-		paddingHL = 10;
-		paddingSL = 10;
-		paddingNA = 10;
+		padding = 5;
+		paddingHL = 5;
+		paddingSL = 5;
+		paddingNA = 5;
 
 
 		border = %this.borderSize;
 		border = %this.borderSize;
 		borderHL = %this.borderSize;
 		borderHL = %this.borderSize;
@@ -1637,6 +1638,7 @@ function BaseTheme::makeDropDownProfile(%this)
 		fontColorNA = %this.setAlpha(%this.color1, 100);
 		fontColorNA = %this.setAlpha(%this.color1, 100);
 		align = left;
 		align = left;
 		vAlign = middle;
 		vAlign = middle;
+		cursorColor = %this.color5;
 
 
 		borderLeft = %borderLightH;
 		borderLeft = %borderLightH;
 		borderRight = %borderDarkH;
 		borderRight = %borderDarkH;

+ 1 - 1
editor/EditorCore/Themes/TorqueSuit/TorqueSuitTheme.cs

@@ -373,7 +373,7 @@ function TorqueSuitTheme::makeTextEditProfile(%this)
 		borderRight = %textBorderRight;
 		borderRight = %textBorderRight;
 		borderLeft = %textBorderLeft;
 		borderLeft = %textBorderLeft;
 
 
-		tab = false;
+		tab = true;
 		canKeyFocus = true;
 		canKeyFocus = true;
 		returnTab = true;
 		returnTab = true;
 	};
 	};

+ 2 - 0
engine/source/gui/buttons/guiButtonCtrl.cc

@@ -208,6 +208,7 @@ bool GuiButtonCtrl::onKeyDown(const GuiEvent &event)
 			AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
 			AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
 			alxPlay(handle);
 			alxPlay(handle);
 		}
 		}
+		mDepressed = true;
 		return true;
 		return true;
 	}
 	}
 	//otherwise, pass the event to it's parent
 	//otherwise, pass the event to it's parent
@@ -224,6 +225,7 @@ bool GuiButtonCtrl::onKeyUp(const GuiEvent &event)
 		(event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
 		(event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
 		event.modifier == 0)
 		event.modifier == 0)
 	{
 	{
+		mDepressed = false;
 		onAction();
 		onAction();
 		return true;
 		return true;
 	}
 	}

+ 6 - 1
engine/source/gui/buttons/guiCheckBoxCtrl.cc

@@ -73,7 +73,7 @@ void GuiCheckBoxCtrl::onRender(Point2I offset, const RectI &updateRect)
 	{
 	{
 		currentState = mStateOn ? GuiControlState::SelectedStateOn : GuiControlState::SelectedState;
 		currentState = mStateOn ? GuiControlState::SelectedStateOn : GuiControlState::SelectedState;
 	}
 	}
-	else if (mMouseOver)
+	else if (mMouseOver || isFirstResponder())
 	{
 	{
 		currentState = mStateOn ? GuiControlState::HighlightStateOn : GuiControlState::HighlightState;
 		currentState = mStateOn ? GuiControlState::HighlightStateOn : GuiControlState::HighlightState;
 	}
 	}
@@ -119,6 +119,11 @@ void GuiCheckBoxCtrl::onRender(Point2I offset, const RectI &updateRect)
 void GuiCheckBoxCtrl::renderInnerControl(RectI &boxRect, const GuiControlState currentState)
 void GuiCheckBoxCtrl::renderInnerControl(RectI &boxRect, const GuiControlState currentState)
 {
 {
 	renderUniversalRect(boxRect, mProfile, currentState);
 	renderUniversalRect(boxRect, mProfile, currentState);
+
+	if(isFirstResponder())
+	{
+		dglDrawRect(boxRect, mProfile->mCursorColor);
+	}
 }
 }
 
 
 void GuiCheckBoxCtrl::onAction()
 void GuiCheckBoxCtrl::onAction()

+ 6 - 1
engine/source/gui/buttons/guiDropDownCtrl.cc

@@ -162,7 +162,7 @@ GuiControlState GuiDropDownCtrl::getCurrentState()
 		return GuiControlState::DisabledState;
 		return GuiControlState::DisabledState;
 	else if (mDepressed || mIsOpen)
 	else if (mDepressed || mIsOpen)
 		return GuiControlState::SelectedState;
 		return GuiControlState::SelectedState;
-	else if (mMouseOver)
+	else if (mMouseOver || isFirstResponder())
 		return GuiControlState::HighlightState;
 		return GuiControlState::HighlightState;
 	else
 	else
 		return GuiControlState::NormalState;
 		return GuiControlState::NormalState;
@@ -206,6 +206,11 @@ void GuiDropDownCtrl::onRender(Point2I offset, const RectI& updateRect)
 		}
 		}
 		renderText(contentRect.point, contentRect.extent, mListBox->getItemText(index), mProfile);
 		renderText(contentRect.point, contentRect.extent, mListBox->getItemText(index), mProfile);
 	}
 	}
+
+	if (isFirstResponder())
+	{
+		dglDrawRect(ctrlRect, mProfile->mCursorColor);
+	}
 }
 }
 
 
 bool GuiDropDownCtrl::onKeyDown(const GuiEvent &event)
 bool GuiDropDownCtrl::onKeyDown(const GuiEvent &event)

+ 86 - 0
engine/source/gui/containers/guiExpandCtrl.cc

@@ -37,6 +37,8 @@ GuiExpandCtrl::GuiExpandCtrl()
    mEasingFunction = EasingFunction::Linear;
    mEasingFunction = EasingFunction::Linear;
    mAnimationLength = 500;
    mAnimationLength = 500;
    mCalcGuard = false;
    mCalcGuard = false;
+
+   setField("profile", "GuiDefaultProfile");
 }
 }
 
 
 void GuiExpandCtrl::initPersistFields()
 void GuiExpandCtrl::initPersistFields()
@@ -47,6 +49,13 @@ void GuiExpandCtrl::initPersistFields()
   addField("easeTimeExpand", TypeS32, Offset(mAnimationLength, GuiExpandCtrl));
   addField("easeTimeExpand", TypeS32, Offset(mAnimationLength, GuiExpandCtrl));
 }
 }
 
 
+void GuiExpandCtrl::addObject(SimObject* obj)
+{
+	Parent::addObject(obj);
+
+	toggleHiddenChildren();
+}
+
 void GuiExpandCtrl::parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent)
 void GuiExpandCtrl::parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent)
 {
 {
 	Point2I newPosition = getPosition();
 	Point2I newPosition = getPosition();
@@ -114,6 +123,7 @@ void GuiExpandCtrl::parentResized(const Point2I &oldParentExtent, const Point2I
 	else
 	else
 	{
 	{
 		mBounds.extent = mCollapsedExtent;
 		mBounds.extent = mCollapsedExtent;
+		toggleHiddenChildren();
 	}
 	}
 	setUpdate();
 	setUpdate();
 }
 }
@@ -122,6 +132,7 @@ void GuiExpandCtrl::childResized(GuiControl* child)
 {
 {
 	calcExpandedExtent();
 	calcExpandedExtent();
 	Parent::childResized(child);
 	Parent::childResized(child);
+	toggleHiddenChildren();
 }
 }
 
 
 void GuiExpandCtrl::setCollapsedExtent(const Point2I &extent)
 void GuiExpandCtrl::setCollapsedExtent(const Point2I &extent)
@@ -161,6 +172,15 @@ void GuiExpandCtrl::setExpanded(bool isExpanded)
 	mAnimationProgress = 1 - mAnimationProgress;
 	mAnimationProgress = 1 - mAnimationProgress;
 	mExpanded = isExpanded;
 	mExpanded = isExpanded;
 	setProcessTicks(true);
 	setProcessTicks(true);
+
+	if (mExpanded)
+	{
+		startExpand();
+	}
+	else
+	{
+		startCollapse();
+	}
 }
 }
 
 
 bool GuiExpandCtrl::processExpansion()
 bool GuiExpandCtrl::processExpansion()
@@ -205,6 +225,14 @@ bool GuiExpandCtrl::processExpansion()
 	if (mAnimationProgress >= 1.0f)
 	if (mAnimationProgress >= 1.0f)
 	{
 	{
 		mAnimationProgress = 1.0f;
 		mAnimationProgress = 1.0f;
+		if (!mExpanded)
+		{
+			collapseComplete();
+		}
+		else
+		{
+			expandComplete();
+		}
 		return false;
 		return false;
 	}
 	}
 	return true;
 	return true;
@@ -221,4 +249,62 @@ void GuiExpandCtrl::processTick()
 	{
 	{
 		setProcessTicks(false);
 		setProcessTicks(false);
 	}
 	}
+}
+
+void GuiExpandCtrl::startExpand()
+{
+	if (isMethod("onStartExpand"))
+	{
+		Con::executef(this, 2, "onStartExpand");
+	}
+
+	toggleHiddenChildren();
+}
+
+void GuiExpandCtrl::startCollapse()
+{
+	if (isMethod("onStartCollapse"))
+	{
+		Con::executef(this, 2, "onStartCollapse");
+	}
+}
+
+void GuiExpandCtrl::expandComplete()
+{
+	if (isMethod("onExpandComplete"))
+	{
+		Con::executef(this, 2, "onExpandComplete");
+	}
+}
+
+void GuiExpandCtrl::collapseComplete()
+{
+	if (isMethod("onCollapseComplete"))
+	{
+		Con::executef(this, 2, "onCollapseComplete");
+	}
+
+	toggleHiddenChildren();
+}
+
+void GuiExpandCtrl::toggleHiddenChildren()
+{
+	RectI innerRect = getInnerRect();
+	innerRect.point = Point2I::Zero;
+
+	for (iterator i = begin(); i != end(); i++)
+	{
+		GuiControl* ctrl = static_cast<GuiControl*>(*i);
+		
+		RectI childBounds = ctrl->getBounds();
+		RectI parentBounds = RectI(innerRect);
+		if (!mExpanded && !parentBounds.intersect(childBounds))
+		{
+			ctrl->mVisible = false;
+		}
+		else
+		{
+			ctrl->mVisible = true;
+		}
+	}
 }
 }

+ 12 - 6
engine/source/gui/containers/guiExpandCtrl.h

@@ -60,14 +60,20 @@ protected:
 public:
 public:
 	GuiExpandCtrl();
 	GuiExpandCtrl();
 
 
-   virtual void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
-   virtual void childResized(GuiControl* child);
+	virtual void addObject(SimObject* obj);
+	virtual void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
+	virtual void childResized(GuiControl* child);
 
 
-   inline bool getExpanded() { return mExpanded; };
-   void setExpanded(bool isExpanded);
+	inline bool getExpanded() { return mExpanded; };
+	void setExpanded(bool isExpanded);
+	void startExpand();
+	void startCollapse();
+	void expandComplete();
+	void collapseComplete();
+	void toggleHiddenChildren();
 
 
-   static void initPersistFields();
-   DECLARE_CONOBJECT(GuiExpandCtrl);
+	static void initPersistFields();
+	DECLARE_CONOBJECT(GuiExpandCtrl);
 
 
 protected:
 protected:
 	virtual void processTick();
 	virtual void processTick();

+ 4 - 9
engine/source/gui/containers/guiWindowCtrl.cc

@@ -251,7 +251,7 @@ void GuiWindowCtrl::onTouchDown(const GuiEvent &event)
    curHitRegion = findHitRegion(localPoint);
    curHitRegion = findHitRegion(localPoint);
    mDepressed = true;
    mDepressed = true;
 
 
-   //select this window - move it to the front, and set the first responder
+   //select this window - move it to the front
    selectWindow();
    selectWindow();
 
 
    //if we clicked within the title bar
    //if we clicked within the title bar
@@ -669,30 +669,25 @@ bool GuiWindowCtrl::onKeyDown(const GuiEvent &event)
    return Parent::onKeyDown(event);
    return Parent::onKeyDown(event);
 }
 }
 
 
-void GuiWindowCtrl::onFocus()
+void GuiWindowCtrl::onFocus(bool foundFirstResponder)
 {
 {
 	//bubble the focus up
 	//bubble the focus up
 	GuiControl *parent = getParent();
 	GuiControl *parent = getParent();
 	if (parent)
 	if (parent)
 	{
 	{
 		parent->pushObjectToBack(this);
 		parent->pushObjectToBack(this);
-		parent->onFocus();
+		parent->onFocus(foundFirstResponder);
 	}
 	}
-
-	setFirstResponder(mFirstResponder);
 }
 }
 
 
 void GuiWindowCtrl::selectWindow(void)
 void GuiWindowCtrl::selectWindow(void)
 {
 {
-   //first make sure this window is the front most of its siblings
+   //make sure this window is the front most of its siblings
    GuiControl *parent = getParent();
    GuiControl *parent = getParent();
    if (parent)
    if (parent)
    {
    {
       parent->pushObjectToBack(this);
       parent->pushObjectToBack(this);
    }
    }
-
-   //also set the first responder to be the one within this window
-   setFirstResponder(mFirstResponder);
 }
 }
 
 
 void GuiWindowCtrl::ResizeComplete()
 void GuiWindowCtrl::ResizeComplete()

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

@@ -132,7 +132,7 @@ class GuiWindowCtrl : public GuiControl
       void onTouchUp(const GuiEvent &event);
       void onTouchUp(const GuiEvent &event);
 	  void onTouchLeave(const GuiEvent &event);
 	  void onTouchLeave(const GuiEvent &event);
 
 
-	  virtual void onFocus();
+	  virtual void onFocus(bool foundFirstResponder);
 
 
       //only cycle tabs through the current window, so overwrite the method
       //only cycle tabs through the current window, so overwrite the method
       GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);
       GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);

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

@@ -237,9 +237,7 @@ void GuiInspector::inspectPostApply()
 
 
 	if (mTarget)
 	if (mTarget)
 	{
 	{
-		SimObjectPtr<SimObject> oldTarget = mTarget;
-		mTarget = NULL;
-		inspectObject(oldTarget);
+		inspectObject(mTarget);
 	}
 	}
 }
 }
 
 

+ 11 - 2
engine/source/gui/guiCanvas.cc

@@ -629,7 +629,7 @@ void GuiCanvas::rootMouseDown(const GuiEvent &event)
              GuiControl* controlHit = ctrl->findHitControl(event.mousePoint);
              GuiControl* controlHit = ctrl->findHitControl(event.mousePoint);
 
 
              //Regardless of what the control does, it has the user's focus.
              //Regardless of what the control does, it has the user's focus.
-             controlHit->onFocus();
+             controlHit->onFocus(false);
 
 
              if (controlHit->mUseInput)
              if (controlHit->mUseInput)
              {
              {
@@ -733,7 +733,7 @@ void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)
                 }
                 }
 
 
                 //Regardless of what the control does, it has the user's focus.
                 //Regardless of what the control does, it has the user's focus.
-                controlHit->onFocus();
+                controlHit->onFocus(false);
 
 
                 if (controlHit->mUseInput)
                 if (controlHit->mUseInput)
                 {
                 {
@@ -1521,6 +1521,15 @@ void GuiCanvas::resetUpdateRegions()
    mCurUpdateRect = mOldUpdateRects[0];
    mCurUpdateRect = mOldUpdateRects[0];
 }
 }
 
 
+void GuiCanvas::onFocus(bool foundFirstResponder)
+{
+	if (!foundFirstResponder && mFirstResponder)
+	{
+		mFirstResponder->onLoseFirstResponder();
+		mFirstResponder = NULL;
+	}
+}
+
 void GuiCanvas::setFirstResponder( GuiControl* newResponder )
 void GuiCanvas::setFirstResponder( GuiControl* newResponder )
 {
 {
     GuiControl* oldResponder = mFirstResponder;
     GuiControl* oldResponder = mFirstResponder;

+ 2 - 0
engine/source/gui/guiCanvas.h

@@ -397,6 +397,8 @@ public:
    /// @param   modifier   Shift, ctrl, etc.
    /// @param   modifier   Shift, ctrl, etc.
    virtual void addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier);
    virtual void addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier);
 
 
+   virtual void onFocus(bool foundFirstResponder);
+
    /// Sets the first responder.
    /// Sets the first responder.
    /// @param   firstResponder    Control to designate as first responder
    /// @param   firstResponder    Control to designate as first responder
    virtual void setFirstResponder(GuiControl *firstResponder);
    virtual void setFirstResponder(GuiControl *firstResponder);

+ 2 - 0
engine/source/gui/guiConsoleEditCtrl.cc

@@ -183,6 +183,8 @@ void GuiConsoleEditCtrl::onLoseFirstResponder()
 
 
     if (isMethod("onLoseFirstResponder"))
     if (isMethod("onLoseFirstResponder"))
         Con::executef(this, 2, "onLoseFirstResponder");
         Con::executef(this, 2, "onLoseFirstResponder");
+	if (isMethod("onBlur"))
+		Con::executef(this, 2, "onBlur");
 
 
     mSelector.setFirstResponder(false);
     mSelector.setFirstResponder(false);
     mTextOffsetY = 0;
     mTextOffsetY = 0;

+ 46 - 27
engine/source/gui/guiControl.cc

@@ -1657,16 +1657,19 @@ void GuiControl::onMiddleMouseDragged(const GuiEvent &event)
 GuiControl* GuiControl::findFirstTabable()
 GuiControl* GuiControl::findFirstTabable()
 {
 {
    GuiControl *tabCtrl = NULL;
    GuiControl *tabCtrl = NULL;
-   iterator i;
-   for (i = begin(); i != end(); i++)
+   if(mVisible && mAwake)
    {
    {
-      GuiControl *ctrl = static_cast<GuiControl *>(*i);
-      tabCtrl = ctrl->findFirstTabable();
-      if (tabCtrl)
-      {
-         mFirstResponder = tabCtrl;
-         return tabCtrl;
-      }
+	   iterator i;
+	   for (i = begin(); i != end(); i++)
+	   {
+		  GuiControl *ctrl = static_cast<GuiControl *>(*i);
+		  tabCtrl = ctrl->findFirstTabable();
+		  if (tabCtrl)
+		  {
+			 mFirstResponder = tabCtrl;
+			 return tabCtrl;
+		  }
+	   }
    }
    }
 
 
    //nothing was found, therefore, see if this ctrl is tabable
    //nothing was found, therefore, see if this ctrl is tabable
@@ -1683,11 +1686,14 @@ GuiControl* GuiControl::findLastTabable(bool firstCall)
    if (mProfile->mTabable)
    if (mProfile->mTabable)
       smPrevResponder = this;
       smPrevResponder = this;
 
 
-   iterator i;
-   for (i = begin(); i != end(); i++)
-   {
-      GuiControl *ctrl = static_cast<GuiControl *>(*i);
-      ctrl->findLastTabable(false);
+	if(mVisible && mAwake)
+	{
+	   iterator i;
+	   for (i = begin(); i != end(); i++)
+	   {
+		  GuiControl *ctrl = static_cast<GuiControl *>(*i);
+		  ctrl->findLastTabable(false);
+	   }
    }
    }
 
 
    //after the entire tree has been traversed, return the last responder found
    //after the entire tree has been traversed, return the last responder found
@@ -1711,12 +1717,16 @@ GuiControl *GuiControl::findNextTabable(GuiControl *curResponder, bool firstCall
 
 
    //loop through, checking each child to see if it is the one that follows the firstResponder
    //loop through, checking each child to see if it is the one that follows the firstResponder
    GuiControl *tabCtrl = NULL;
    GuiControl *tabCtrl = NULL;
-   iterator i;
-   for (i = begin(); i != end(); i++)
+
+   if (mVisible && mAwake)
    {
    {
-      GuiControl *ctrl = static_cast<GuiControl *>(*i);
-      tabCtrl = ctrl->findNextTabable(curResponder, false);
-      if (tabCtrl) break;
+	   iterator i;
+	   for (i = begin(); i != end(); i++)
+	   {
+		  GuiControl *ctrl = static_cast<GuiControl *>(*i);
+		  tabCtrl = ctrl->findNextTabable(curResponder, false);
+		  if (tabCtrl) break;
+	   }
    }
    }
    mFirstResponder = tabCtrl;
    mFirstResponder = tabCtrl;
    return tabCtrl;
    return tabCtrl;
@@ -1737,12 +1747,16 @@ GuiControl *GuiControl::findPrevTabable(GuiControl *curResponder, bool firstCall
 
 
    //loop through, checking each child to see if it is the one that follows the firstResponder
    //loop through, checking each child to see if it is the one that follows the firstResponder
    GuiControl *tabCtrl = NULL;
    GuiControl *tabCtrl = NULL;
-   iterator i;
-   for (i = begin(); i != end(); i++)
+
+   if (mVisible && mAwake)
    {
    {
-      GuiControl *ctrl = static_cast<GuiControl *>(*i);
-      tabCtrl = ctrl->findPrevTabable(curResponder, false);
-      if (tabCtrl) break;
+	   iterator i;
+	   for (i = begin(); i != end(); i++)
+	   {
+		  GuiControl *ctrl = static_cast<GuiControl *>(*i);
+		  tabCtrl = ctrl->findPrevTabable(curResponder, false);
+		  if (tabCtrl) break;
+	   }
    }
    }
    mFirstResponder = tabCtrl;
    mFirstResponder = tabCtrl;
    return tabCtrl;
    return tabCtrl;
@@ -1781,12 +1795,17 @@ bool GuiControl::ControlIsChild(GuiControl *child)
    return false;
    return false;
 }
 }
 
 
-void GuiControl::onFocus()
+void GuiControl::onFocus(bool foundFirstResponder)
 {
 {
+	if (!foundFirstResponder && isFirstResponder())
+	{
+		foundFirstResponder = true;
+	}
+
 	//bubble the focus up
 	//bubble the focus up
 	GuiControl *parent = getParent();
 	GuiControl *parent = getParent();
 	if (parent)
 	if (parent)
-		parent->onFocus();
+		parent->onFocus(foundFirstResponder);
 }
 }
 
 
 bool GuiControl::isFirstResponder()
 bool GuiControl::isFirstResponder()
@@ -1810,7 +1829,7 @@ void GuiControl::setFirstResponder()
     if ( mAwake && mVisible )
     if ( mAwake && mVisible )
     {
     {
 		GuiControl *parent = getParent();
 		GuiControl *parent = getParent();
-		if (mProfile->mCanKeyFocus == true && parent != NULL )
+		if (mProfile->mCanKeyFocus && parent )
 		{
 		{
 			parent->setFirstResponder(this);
 			parent->setFirstResponder(this);
 
 

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

@@ -598,8 +598,9 @@ public:
     /// @}
     /// @}
 
 
 	//Called just before onTouch down for the hit control. The focus should then bubble up through the 
 	//Called just before onTouch down for the hit control. The focus should then bubble up through the 
-	//controls allowing windows to move to the front.
-	virtual void onFocus();
+	//controls allowing windows to move to the front. If the focus arrives at the canvas and the first responder
+	//wasn't found, then the first responder loses the focus.
+	virtual void onFocus(bool foundFirstResponder);
     
     
     /// @name Editor Mouse Events
     /// @name Editor Mouse Events
     ///
     ///

+ 23 - 12
engine/source/gui/guiTextEditCtrl.cc

@@ -647,16 +647,16 @@ void GuiTextEditCtrl::onTouchDown( const GuiEvent &event )
     if (!mVisible || !mAwake)
     if (!mVisible || !mAwake)
         return;
         return;
 
 
+   mouseLock();
+   setFirstResponder();
+   mSelector.resetCursorBlink();
+
     mSelector.setTextLength(mTextBuffer.length());
     mSelector.setTextLength(mTextBuffer.length());
-   if(event.mouseClickCount > 2)
-   {
-        selectAllText();
-   } 
-   else if(event.mouseClickCount > 1)
+   if(event.mouseClickCount == 2)
    {
    {
        mSelector.selectWholeWord(mTextBuffer);
        mSelector.selectWholeWord(mTextBuffer);
    }
    }
-   else 
+   else if (event.mouseClickCount < 2)
    {
    {
        S32 newCursorPos = calculateIbeamPosition(event.mousePoint);
        S32 newCursorPos = calculateIbeamPosition(event.mousePoint);
        if (event.modifier & SI_SHIFT)
        if (event.modifier & SI_SHIFT)
@@ -668,10 +668,6 @@ void GuiTextEditCtrl::onTouchDown( const GuiEvent &event )
            mSelector.setCursorPosition(newCursorPos);
            mSelector.setCursorPosition(newCursorPos);
        }
        }
    }
    }
-
-   mouseLock();
-   setFirstResponder();
-   mSelector.resetCursorBlink();
     if( isMethod("onTouchDown") )
     if( isMethod("onTouchDown") )
     {
     {
         char buf[3][32];
         char buf[3][32];
@@ -946,6 +942,11 @@ bool GuiTextEditCtrl::tabPrev()
 
 
 void GuiTextEditCtrl::setFirstResponder()
 void GuiTextEditCtrl::setFirstResponder()
 {
 {
+	selectAllText();
+	if(mTextBuffer.length() == 0)
+	{
+		mSelector.selectTo(mTextBuffer.length());
+	}
     mSelector.setFirstResponder(true);
     mSelector.setFirstResponder(true);
    Parent::setFirstResponder();
    Parent::setFirstResponder();
    
    
@@ -968,6 +969,8 @@ void GuiTextEditCtrl::onLoseFirstResponder()
 
 
    if( isMethod( "onLoseFirstResponder" ) )
    if( isMethod( "onLoseFirstResponder" ) )
       Con::executef( this, 2, "onLoseFirstResponder", valid);
       Con::executef( this, 2, "onLoseFirstResponder", valid);
+   if (isMethod("onBlur"))
+	   Con::executef(this, 2, "onBlur", valid);
 
 
     mSelector.setFirstResponder(false);
     mSelector.setFirstResponder(false);
     mTextOffsetY = 0;
     mTextOffsetY = 0;
@@ -1635,12 +1638,20 @@ bool GuiTextEditCtrl::handleShiftArrowKey(GuiDirection direction)
     else if (direction == GuiDirection::Up)
     else if (direction == GuiDirection::Up)
     {
     {
         S32 newCursorPos = getLineAdjustedIbeamPosition(-mProfile->getFont(mFontSizeAdjust)->getHeight());
         S32 newCursorPos = getLineAdjustedIbeamPosition(-mProfile->getFont(mFontSizeAdjust)->getHeight());
-        modifySelectBlock(newCursorPos);
+		if (newCursorPos == mSelector.getCursorPos())
+		{
+			newCursorPos = 0;
+		}
+		modifySelectBlock(newCursorPos);
     }
     }
     else if (direction == GuiDirection::Down)
     else if (direction == GuiDirection::Down)
     {
     {
         S32 newCursorPos = getLineAdjustedIbeamPosition(mProfile->getFont(mFontSizeAdjust)->getHeight());
         S32 newCursorPos = getLineAdjustedIbeamPosition(mProfile->getFont(mFontSizeAdjust)->getHeight());
-        modifySelectBlock(newCursorPos);
+		if (newCursorPos == mSelector.getCursorPos())
+		{
+			newCursorPos = mTextBuffer.length();
+		}
+		modifySelectBlock(newCursorPos);
     }
     }
     setUpdate();
     setUpdate();
     mSelector.resetCursorBlink();
     mSelector.resetCursorBlink();