ソースを参照

GuiListBox and GuiDropDown Key Events

This update allows the list box and drop down handle key events. The arrow keys can n ow be used to the change the selection of both. Additionally the enter key can be used to open and close the drop down. Also, the delete key now fires a callback for both allowing the user to handle them.
Peter Robinson 4 年 前
コミット
d42016d091

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

@@ -46,12 +46,16 @@ GuiDropDownListBoxCtrl::GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl)
 	mBounds.point.set(0, 0);
 	mBounds.point.set(0, 0);
 	caller = ctrl;
 	caller = ctrl;
 }
 }
+
 void GuiDropDownListBoxCtrl::addSelection(LBItem *item, S32 index)
 void GuiDropDownListBoxCtrl::addSelection(LBItem *item, S32 index)
 {
 {
 	Parent::addSelection(item, index);
 	Parent::addSelection(item, index);
-
 	mDropDownCtrl->itemSelected();
 	mDropDownCtrl->itemSelected();
+}
 
 
+void GuiDropDownListBoxCtrl::setCurSel(S32 index)
+{
+	Parent::setCurSel(index);
 	mDropDownCtrl->closeDropDown();
 	mDropDownCtrl->closeDropDown();
 }
 }
 #pragma endregion
 #pragma endregion
@@ -199,6 +203,33 @@ void GuiDropDownCtrl::onRender(Point2I offset, const RectI& updateRect)
 	}
 	}
 }
 }
 
 
+bool GuiDropDownCtrl::onKeyDown(const GuiEvent &event)
+{
+	//if the control is a dead end, don't process the input:
+	if (!mVisible || !mActive || !mAwake)
+		return false;
+
+	//see if the key down is a <return> or not
+	if (event.keyCode == KEY_RETURN && event.modifier == 0)
+	{
+		if(!mIsOpen)
+		{
+			openDropDown();
+		}
+		else
+		{
+			closeDropDown();
+		}
+		return true;
+	}
+	else if (mIsOpen)
+	{
+		return mListBox->onKeyDown(event);
+	}
+
+	return false;
+}
+
 void GuiDropDownCtrl::onAction() //called when the button is clicked.
 void GuiDropDownCtrl::onAction() //called when the button is clicked.
 {
 {
 	if (!mActive)
 	if (!mActive)
@@ -263,8 +294,12 @@ void GuiDropDownCtrl::openDropDown()
 
 
 	root->pushDialogControl(mBackground, 99);
 	root->pushDialogControl(mBackground, 99);
 
 
+	mListBox->ScrollToIndex(mListBox->getSelectedItem());
+
 	mIsOpen = true;
 	mIsOpen = true;
 
 
+	setFirstResponder();
+
 	if (isMethod("onOpen"))
 	if (isMethod("onOpen"))
 		Con::executef(this, 1, "onOpen");
 		Con::executef(this, 1, "onOpen");
 }
 }

+ 2 - 0
engine/source/gui/buttons/guiDropDownCtrl.h

@@ -56,6 +56,7 @@ protected:
 public:
 public:
 	GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl);
 	GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl);
 	void addSelection(LBItem *item, S32 index);
 	void addSelection(LBItem *item, S32 index);
+	void setCurSel(S32 index);
 };
 };
 
 
 class GuiDropDownCtrl : public GuiButtonCtrl
 class GuiDropDownCtrl : public GuiButtonCtrl
@@ -91,6 +92,7 @@ public:
    GuiControlState getCurrentState();
    GuiControlState getCurrentState();
    void onRender(Point2I offset, const RectI &updateRect);
    void onRender(Point2I offset, const RectI &updateRect);
 
 
+   bool onKeyDown(const GuiEvent &event);
    virtual void onAction();
    virtual void onAction();
    void itemSelected();
    void itemSelected();
    void openDropDown();
    void openDropDown();

+ 1 - 1
engine/source/gui/containers/guiScrollCtrl.cc

@@ -531,7 +531,7 @@ void GuiScrollCtrl::scrollRectVisible(RectI rect)
 
 
 	// Determine the points bounding the actual visible area...
 	// Determine the points bounding the actual visible area...
 	Point2I visUpperLeft = mScrollOffset;
 	Point2I visUpperLeft = mScrollOffset;
-	Point2I visLowerRight = mContentExt;
+	Point2I visLowerRight = mContentExt + mScrollOffset;
 	Point2I delta(0, 0);
 	Point2I delta(0, 0);
 
 
 	// We basically try to make sure that first the top left of the given
 	// We basically try to make sure that first the top left of the given

+ 62 - 1
engine/source/gui/guiListBoxCtrl.cc

@@ -165,6 +165,8 @@ void GuiListBoxCtrl::addSelection( LBItem *item, S32 index )
    item->isSelected = true;
    item->isSelected = true;
    mSelectedItems.push_front( item );
    mSelectedItems.push_front( item );
 
 
+   ScrollToIndex(index);
+
    if(caller->isMethod("onSelect"))
    if(caller->isMethod("onSelect"))
 		Con::executef(caller, 3, "onSelect", Con::getIntArg( index ), item->itemText, item->ID);
 		Con::executef(caller, 3, "onSelect", Con::getIntArg( index ), item->itemText, item->ID);
 
 
@@ -683,6 +685,13 @@ void GuiListBoxCtrl::onRenderItem( RectI &itemRect, LBItem *item )
 
 
    renderText(contentRect.point, contentRect.extent, item->itemText, mProfile);
    renderText(contentRect.point, contentRect.extent, item->itemText, mProfile);
 }
 }
+
+void GuiListBoxCtrl::ScrollToIndex(const S32 targetIndex)
+{
+	GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl *>(getParent());
+	if (parent)
+		parent->scrollRectVisible(RectI(0, mItemSize.y * targetIndex, mItemSize.x, mItemSize.y));
+}
 #pragma endregion
 #pragma endregion
 
 
 #pragma region InputEvents
 #pragma region InputEvents
@@ -716,6 +725,8 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
 		return;
 		return;
 	}
 	}
 
 
+	setFirstResponder();
+
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
    S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
    S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
 
 
@@ -752,7 +763,6 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
       mLastClickItem = hitItem;
       mLastClickItem = hitItem;
 
 
       return;
       return;
-
    }
    }
    
    
    // Deal with multiple selections
    // Deal with multiple selections
@@ -798,8 +808,59 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
    }
    }
 
 
    mLastClickItem = hitItem;
    mLastClickItem = hitItem;
+}
 
 
+bool GuiListBoxCtrl::onKeyDown(const GuiEvent &event)
+{
+	//if this control is a dead end, make sure the event stops here
+	if (!mVisible || !mActive || !mAwake || mItems.size() == 0)
+		return true;
 
 
+	S32 index = getSelectedItem();
+	switch (event.keyCode)
+	{
+	case KEY_RETURN:
+		if (mAltConsoleCommand[0])
+			Con::evaluate(mAltConsoleCommand, false);
+		break;
+	case KEY_LEFT:
+	case KEY_UP:
+		if (index == -1)
+		{
+			//Select the bottom item
+			addSelection(mItems.size() - 1);
+		}
+		else if(index != 0)
+		{
+			addSelection(index - 1);
+		}
+		break;
+	case KEY_DOWN:
+	case KEY_RIGHT:
+		if (index == -1)
+		{
+			//Select the top item
+			addSelection(0);
+		}
+		else if (index != (mItems.size() - 1))
+		{
+			addSelection(index + 1);
+		}
+		break;
+	case KEY_HOME:
+		addSelection(0);
+		break;
+	case KEY_END:
+		addSelection(mItems.size() - 1);
+		break;
+	case KEY_DELETE:
+		if (index != -1 && isMethod("onDeleteKey"))
+			Con::executef(caller, 3, "onDeleteKey", Con::getIntArg(index), getItemText(index), getItemID(index));
+		break;
+	default:
+		return(Parent::onKeyDown(event));
+		break;
+	};
 }
 }
 #pragma endregion
 #pragma endregion
 
 

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

@@ -106,7 +106,7 @@ public:
    S32               getItemIndex( LBItem *item );
    S32               getItemIndex( LBItem *item );
    StringTableEntry  getItemText( S32 index );
    StringTableEntry  getItemText( S32 index );
    
    
-   void              setCurSel( S32 index );
+   virtual void      setCurSel( S32 index );
    void              setCurSelRange( S32 start, S32 stop );
    void              setCurSelRange( S32 start, S32 stop );
    void              setItemText( S32 index, StringTableEntry text );
    void              setItemText( S32 index, StringTableEntry text );
 
 
@@ -150,10 +150,12 @@ public:
    // Rendering
    // Rendering
    virtual void      onRender( Point2I offset, const RectI &updateRect );
    virtual void      onRender( Point2I offset, const RectI &updateRect );
    virtual void      onRenderItem( RectI &itemRect, LBItem *item );
    virtual void      onRenderItem( RectI &itemRect, LBItem *item );
+   virtual void		 ScrollToIndex(const S32 targetIndex);
 
 
    // Mouse Events
    // Mouse Events
    virtual void      onTouchDown( const GuiEvent &event );
    virtual void      onTouchDown( const GuiEvent &event );
    virtual void      onTouchDragged(const GuiEvent &event);
    virtual void      onTouchDragged(const GuiEvent &event);
+   virtual bool		 GuiListBoxCtrl::onKeyDown(const GuiEvent &event);
 
 
    // Sorting
    // Sorting
    virtual void		 sortByText(bool increasing = true);
    virtual void		 sortByText(bool increasing = true);

+ 4 - 1
toybox/Sandbox/1/gui/guiProfiles.cs

@@ -214,7 +214,7 @@ if(!isObject(GuiListBoxProfile)) new GuiControlProfile (GuiListBoxProfile : GuiD
 	align = left;
 	align = left;
 
 
 	tab = false;
 	tab = false;
-	canKeyFocus = false;
+	canKeyFocus = true;
 	category = "defaultListBox";
 	category = "defaultListBox";
 
 
 	fontColor = $color3;
 	fontColor = $color3;
@@ -807,6 +807,9 @@ if(!isObject(GuiDropDownProfile)) new GuiControlProfile (GuiDropDownProfile : Gu
 	fontColorNA = SetColorAlpha($color1, 100);
 	fontColorNA = SetColorAlpha($color1, 100);
 	align = "left";
 	align = "left";
 
 
+	tab = true;
+	canKeyFocus = true;
+
 	borderDefault = GuiDropDownBrightBorderProfile;
 	borderDefault = GuiDropDownBrightBorderProfile;
 	borderRight = GuiDropDownDarkBorderProfile;
 	borderRight = GuiDropDownDarkBorderProfile;
 	borderBottom = GuiDropDownDarkBorderProfile;
 	borderBottom = GuiDropDownDarkBorderProfile;