GWEN improvement: allow to navigate TreeControl and ComboBox using the cursor keys

This commit is contained in:
erwin coumans
2013-07-01 23:43:49 -07:00
parent 898f423f95
commit 0f78c696b5
14 changed files with 458 additions and 17 deletions

View File

@@ -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 );

View File

@@ -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;

View File

@@ -61,6 +61,7 @@ namespace Gwen
bool m_bAutoHideBars;
public:
Controls::BaseScrollBar* m_VerticalScrollBar;
Controls::BaseScrollBar* m_HorizontalScrollBar;
};

View File

@@ -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;
}

View File

@@ -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 );

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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;