GWEN improvement: allow to navigate TreeControl and ComboBox using the cursor keys
This commit is contained in:
@@ -81,8 +81,10 @@ Base::~Base()
|
||||
|
||||
SetParent( NULL );
|
||||
|
||||
if ( Gwen::HoveredControl == this ) Gwen::HoveredControl = NULL;
|
||||
if ( Gwen::KeyboardFocus == this ) Gwen::KeyboardFocus = NULL;
|
||||
if ( Gwen::HoveredControl == this )
|
||||
Gwen::HoveredControl = NULL;
|
||||
if ( Gwen::KeyboardFocus == this )
|
||||
Gwen::KeyboardFocus = NULL;
|
||||
if ( Gwen::MouseFocus == this ) Gwen::MouseFocus = NULL;
|
||||
|
||||
DragAndDrop::ControlDeleted( this );
|
||||
|
||||
@@ -176,11 +176,13 @@ bool ComboBox::OnKeyUp( bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
Base::List::reverse_iterator it = std::find( m_Menu->Children.rbegin(), m_Menu->Children.rend(), m_SelectedItem );
|
||||
if ( it != m_Menu->Children.rend() && ( ++it != m_Menu->Children.rend() ) )
|
||||
Base::List & children = m_Menu->GetChildren();
|
||||
Base::List::reverse_iterator it = std::find( children.rbegin(), children.rend(), m_SelectedItem );
|
||||
|
||||
if ( it != children.rend() && ( ++it != children.rend() ) )
|
||||
{
|
||||
Base* pUpElement = *it;
|
||||
OnItemSelected(pUpElement);
|
||||
OnItemSelected( pUpElement );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -189,11 +191,13 @@ bool ComboBox::OnKeyDown( bool bDown )
|
||||
{
|
||||
if ( bDown )
|
||||
{
|
||||
Base::List::iterator it = std::find( m_Menu->Children.begin(), m_Menu->Children.end(), m_SelectedItem );
|
||||
if ( it != m_Menu->Children.end() && ( ++it != m_Menu->Children.end() ) )
|
||||
Base::List & children = m_Menu->GetChildren();
|
||||
Base::List::iterator it = std::find( children.begin(), children.end(), m_SelectedItem );
|
||||
|
||||
if ( it != children.end() && ( ++it != children.end() ) )
|
||||
{
|
||||
Base* pDownElement = *it;
|
||||
OnItemSelected(pDownElement);
|
||||
OnItemSelected( pDownElement );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace Gwen
|
||||
|
||||
bool m_bAutoHideBars;
|
||||
|
||||
public:
|
||||
Controls::BaseScrollBar* m_VerticalScrollBar;
|
||||
Controls::BaseScrollBar* m_HorizontalScrollBar;
|
||||
};
|
||||
|
||||
@@ -71,4 +71,109 @@ void TreeControl::OnNodeSelection( Controls::Base* /*control*/ )
|
||||
{
|
||||
if ( !m_bAllowMultipleSelection || !Gwen::Input::IsKeyDown( Key::Control ) )
|
||||
DeselectAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TreeControl::iterate(int action, int* curIndex, int* targetIndex)
|
||||
{
|
||||
|
||||
Base::List& children = m_InnerPanel->GetChildren();
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
TreeNode* pChild = (*iter)->DynamicCastTreeNode();
|
||||
if ( !pChild )
|
||||
continue;
|
||||
pChild->iterate(action ,curIndex, targetIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool TreeControl::OnKeyUp( bool bDown )
|
||||
{
|
||||
if (bDown)
|
||||
{
|
||||
int maxIndex = 0;
|
||||
int newIndex = 0;
|
||||
int curIndex=0;
|
||||
int targetIndex=-1;
|
||||
iterate(ITERATE_ACTION_FIND_SELECTED_INDEX,&curIndex,&targetIndex);
|
||||
maxIndex = curIndex;
|
||||
if (targetIndex>0)
|
||||
{
|
||||
curIndex=0;
|
||||
int deselectIndex = targetIndex;
|
||||
targetIndex--;
|
||||
newIndex = targetIndex;
|
||||
iterate(ITERATE_ACTION_SELECT,&curIndex,&targetIndex);
|
||||
if (targetIndex<0)
|
||||
{
|
||||
curIndex=0;
|
||||
iterate(ITERATE_ACTION_DESELECT_INDEX,&curIndex,&deselectIndex);
|
||||
}
|
||||
float amount = float(newIndex)/float(maxIndex);
|
||||
m_ScrollControl->m_VerticalScrollBar->SetScrolledAmount(amount,true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TreeControl::OnKeyDown( bool bDown )
|
||||
{
|
||||
if (bDown)
|
||||
{
|
||||
int maxIndex = 0;
|
||||
int newIndex = 0;
|
||||
int curIndex=0;
|
||||
int targetIndex=-1;
|
||||
iterate(ITERATE_ACTION_FIND_SELECTED_INDEX,&curIndex,&targetIndex);
|
||||
maxIndex = curIndex;
|
||||
if (targetIndex>=0)
|
||||
{
|
||||
curIndex=0;
|
||||
int deselectIndex = targetIndex;
|
||||
targetIndex++;
|
||||
newIndex = targetIndex;
|
||||
iterate(ITERATE_ACTION_SELECT,&curIndex,&targetIndex);
|
||||
if (targetIndex<0)
|
||||
{
|
||||
curIndex=0;
|
||||
iterate(ITERATE_ACTION_DESELECT_INDEX,&curIndex,&deselectIndex);
|
||||
}
|
||||
float amount = float(newIndex)/float(maxIndex);
|
||||
m_ScrollControl->m_VerticalScrollBar->SetScrolledAmount(amount,true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TreeControl::OnKeyRight( bool bDown )
|
||||
{
|
||||
if (bDown)
|
||||
{
|
||||
iterate(ITERATE_ACTION_OPEN,0,0);
|
||||
int curIndex=0;
|
||||
int targetIndex=0;
|
||||
iterate(ITERATE_ACTION_FIND_SELECTED_INDEX,&curIndex,&targetIndex);
|
||||
float amount = float(targetIndex)/float(curIndex);
|
||||
m_ScrollControl->m_VerticalScrollBar->SetScrolledAmount(amount,true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool TreeControl::OnKeyLeft( bool bDown )
|
||||
{
|
||||
if (bDown)
|
||||
{
|
||||
iterate(ITERATE_ACTION_CLOSE,0,0);
|
||||
|
||||
int curIndex=0;
|
||||
int targetIndex=0;
|
||||
iterate(ITERATE_ACTION_FIND_SELECTED_INDEX,&curIndex,&targetIndex);
|
||||
float amount = float(targetIndex)/float(curIndex);
|
||||
m_ScrollControl->m_VerticalScrollBar->SetScrolledAmount(amount,true);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,15 @@ namespace Gwen
|
||||
|
||||
virtual void OnNodeAdded( TreeNode* pNode );
|
||||
|
||||
virtual bool OnKeyUp( bool bDown );
|
||||
virtual bool OnKeyDown( bool bDown );
|
||||
virtual bool OnKeyRight( bool bDown );
|
||||
virtual bool OnKeyLeft( bool bDown );
|
||||
|
||||
virtual void iterate(int action,int* curIndex, int* resultIndex);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void OnNodeSelection( Controls::Base* control );
|
||||
|
||||
@@ -208,4 +208,124 @@ void TreeNode::DeselectAll()
|
||||
|
||||
pChild->DeselectAll( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TreeNode::iterate(int action, int* curIndex, int* targetIndex)
|
||||
{
|
||||
|
||||
Gwen::String name = Gwen::Utility::UnicodeToString(m_Title->GetText());
|
||||
|
||||
int actualIndex = curIndex? *curIndex : -1;
|
||||
//printf("iterated over item %d with name = %s\n", actualIndex, name.c_str());
|
||||
|
||||
if (action==ITERATE_ACTION_SELECT)
|
||||
{
|
||||
if (curIndex && targetIndex)
|
||||
{
|
||||
if ((*curIndex)==(*targetIndex))
|
||||
{
|
||||
SetSelected(true);
|
||||
|
||||
*targetIndex=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSelected())
|
||||
{
|
||||
//printf("current selected: name = %s\n", name.c_str());
|
||||
switch (action)
|
||||
{
|
||||
case ITERATE_ACTION_DESELECT_INDEX:
|
||||
{
|
||||
if (targetIndex && curIndex)
|
||||
{
|
||||
if (*targetIndex == *curIndex)
|
||||
SetSelected(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITERATE_ACTION_FIND_SELECTED_INDEX:
|
||||
{
|
||||
if (targetIndex && curIndex)
|
||||
{
|
||||
*targetIndex = *curIndex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITERATE_ACTION_OPEN:
|
||||
{
|
||||
Open();
|
||||
|
||||
break;
|
||||
}
|
||||
case ITERATE_ACTION_CLOSE:
|
||||
{
|
||||
//either close or select parent
|
||||
if (this->GetChildren().size())
|
||||
{
|
||||
if (m_ToggleButton && m_ToggleButton->GetToggleState())
|
||||
{
|
||||
Close();
|
||||
} else
|
||||
{
|
||||
|
||||
TreeNode* pChild = (GetParent())->DynamicCastTreeNode();
|
||||
TreeControl* pChild2 = (GetParent())->DynamicCastTreeControl();
|
||||
if (pChild && !pChild2)
|
||||
{
|
||||
SetSelected(false);
|
||||
pChild->SetSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
TreeNode* pChild = (GetParent())->DynamicCastTreeNode();
|
||||
TreeControl* pChild2 = (GetParent())->DynamicCastTreeControl();
|
||||
if (pChild && !pChild2)
|
||||
{
|
||||
SetSelected(false);
|
||||
pChild->SetSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (curIndex)
|
||||
(*curIndex)++;
|
||||
|
||||
bool needsRecursion = true;
|
||||
|
||||
if (action == ITERATE_ACTION_FIND_SELECTED_INDEX || action==ITERATE_ACTION_SELECT || action==ITERATE_ACTION_DESELECT_INDEX)
|
||||
{
|
||||
if (m_ToggleButton && !m_ToggleButton->GetToggleState())
|
||||
{
|
||||
needsRecursion=false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsRecursion)
|
||||
{
|
||||
Base::List& children = m_InnerPanel->GetChildren();
|
||||
for ( Base::List::iterator iter = children.begin(); iter != children.end(); ++iter )
|
||||
{
|
||||
TreeNode* pChild = (*iter)->DynamicCastTreeNode();
|
||||
if ( !pChild )
|
||||
continue;
|
||||
|
||||
pChild->iterate(action , curIndex, targetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -12,6 +12,14 @@
|
||||
#include "Gwen/Controls/Button.h"
|
||||
#include "Gwen/Controls/ScrollControl.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ITERATE_ACTION_OPEN=1,
|
||||
ITERATE_ACTION_CLOSE,
|
||||
ITERATE_ACTION_FIND_SELECTED_INDEX,
|
||||
ITERATE_ACTION_DESELECT_INDEX,
|
||||
ITERATE_ACTION_SELECT,
|
||||
};
|
||||
|
||||
namespace Gwen
|
||||
{
|
||||
@@ -51,6 +59,9 @@ namespace Gwen
|
||||
|
||||
virtual void DeselectAll();
|
||||
|
||||
virtual void iterate(int action, int* curIndex, int* resultIndex);
|
||||
|
||||
|
||||
Event::Caller onNamePress;
|
||||
Event::Caller onSelectChange;
|
||||
Event::Caller onSelect;
|
||||
|
||||
@@ -125,8 +125,14 @@ void Gwen::Input::OnCanvasThink( Controls::Base* pControl )
|
||||
if ( Gwen::MouseFocus && !Gwen::MouseFocus->Visible() )
|
||||
Gwen::MouseFocus = NULL;
|
||||
|
||||
if ( Gwen::KeyboardFocus && ( !Gwen::KeyboardFocus->Visible() || !KeyboardFocus->GetKeyboardInputEnabled() ) )
|
||||
Gwen::KeyboardFocus = NULL;
|
||||
if (Gwen::KeyboardFocus )
|
||||
{
|
||||
bool isVisible = Gwen::KeyboardFocus->Visible();
|
||||
bool isEnabled = KeyboardFocus->GetKeyboardInputEnabled();
|
||||
|
||||
if ( !isVisible || !isEnabled )
|
||||
Gwen::KeyboardFocus = NULL;
|
||||
}
|
||||
|
||||
if ( !KeyboardFocus ) return;
|
||||
if ( KeyboardFocus->GetCanvas() != pControl ) return;
|
||||
|
||||
Reference in New Issue
Block a user