Fixed selection handling in combo ribbons. Unfotrunately I broke keyboard navigation to the ribbon in the process.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3919 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2009-08-26 17:58:05 +00:00
parent 4aaddbba4b
commit 298ad53514
3 changed files with 96 additions and 51 deletions

View File

@ -38,6 +38,7 @@ RibbonGridWidget::RibbonGridWidget(const bool combo, const int max_rows)
m_left_widget = NULL;
m_right_widget = NULL;
m_type = WTYPE_RIBBON_GRID;
m_selected_item = 0;
}
// -----------------------------------------------------------------------------
@ -279,19 +280,19 @@ void RibbonGridWidget::registerHoverListener(RibbonGridHoverListener* listener)
bool RibbonGridWidget::rightPressed()
{
RibbonWidget* w = getSelectedRibbon();
if(w != NULL)
if (w != NULL)
{
updateLabel();
propagateSelection();
}
const int listenerAmount = m_hover_listeners.size();
for(int n=0; n<listenerAmount; n++)
for (int n=0; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString());
}
if(m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return false;
if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return false;
return true;
}
@ -299,36 +300,47 @@ bool RibbonGridWidget::rightPressed()
bool RibbonGridWidget::leftPressed()
{
RibbonWidget* w = getSelectedRibbon();
if(w != NULL)
if (w != NULL)
{
updateLabel();
propagateSelection();
}
const int listenerAmount = m_hover_listeners.size();
for(int n=0; n<listenerAmount; n++)
for (int n=0; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, w->getSelectionIDString());
}
if(m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return false;
if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return false;
return true;
}
// -----------------------------------------------------------------------------
bool RibbonGridWidget::transmitEvent(Widget* w, std::string& originator)
{
if(originator=="left")
if (originator=="left")
{
scroll(-1);
return false;
}
if(originator=="right")
if (originator=="right")
{
scroll(1);
return false;
}
// find selection in current ribbon
if (m_combo)
{
RibbonWidget* selected_ribbon = (RibbonWidget*)getSelectedRibbon();
if (selected_ribbon != NULL)
{
m_selected_item = selected_ribbon->m_selection + m_scroll_offset;
if (m_selected_item >= (int)m_items.size()) m_selected_item -= m_items.size();
}
}
return true;
}
// -----------------------------------------------------------------------------
@ -337,10 +349,10 @@ bool RibbonGridWidget::mouseHovered(Widget* child)
updateLabel();
propagateSelection();
if(getSelectedRibbon() != NULL)
if (getSelectedRibbon() != NULL)
{
const int listenerAmount = m_hover_listeners.size();
for(int n=0; n<listenerAmount; n++)
for (int n=0; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, getSelectedRibbon()->getSelectionIDString());
}
@ -365,7 +377,7 @@ void RibbonGridWidget::onRowChange(RibbonWidget* row)
updateLabel(row);
const int listenerAmount = m_hover_listeners.size();
for(int n=0; n<listenerAmount; n++)
for (int n=0; n<listenerAmount; n++)
{
m_hover_listeners[n].onSelectionChanged(this, row->getSelectionIDString());
}
@ -382,10 +394,19 @@ void RibbonGridWidget::scroll(const int x_delta)
const int max_scroll = std::max(m_col_amount, m_needed_cols) - 1;
if(m_scroll_offset < 0) m_scroll_offset = max_scroll;
else if(m_scroll_offset > max_scroll) m_scroll_offset = 0;
if (m_scroll_offset < 0) m_scroll_offset = max_scroll;
else if (m_scroll_offset > max_scroll) m_scroll_offset = 0;
updateItemDisplay();
// update selection markers in child ribbon
if (m_combo)
{
RibbonWidget* ribbon = m_rows.get(0); // there is a single row when we can select items
int id = m_selected_item - m_scroll_offset;
if (id < 0) id += m_items.size();
ribbon->setSelection(id);
}
}
// -----------------------------------------------------------------------------
/** RibbonGridWidget is made of several ribbons; each of them thus has
@ -396,17 +417,23 @@ void RibbonGridWidget::propagateSelection()
{
// find selection in current ribbon
RibbonWidget* selected_ribbon = (RibbonWidget*)getSelectedRibbon();
if(selected_ribbon == NULL) return;
const int i = selected_ribbon->m_selection;
if (selected_ribbon == NULL) return;
const int relative_selection = selected_ribbon->m_selection;
if (m_combo)
{
m_selected_item = relative_selection + m_scroll_offset;
if (m_selected_item >= (int)m_items.size()) m_selected_item -= m_items.size();
}
// set same selection in all ribbons
const int row_amount = m_rows.size();
for(int n=0; n<row_amount; n++)
for (int n=0; n<row_amount; n++)
{
RibbonWidget* ribbon = m_rows.get(n);
if(ribbon != selected_ribbon)
if (ribbon != selected_ribbon)
{
ribbon->m_selection = i;
ribbon->m_selection = relative_selection;
ribbon->updateSelection();
}
}
@ -414,18 +441,18 @@ void RibbonGridWidget::propagateSelection()
// -----------------------------------------------------------------------------
void RibbonGridWidget::updateLabel(RibbonWidget* from_this_ribbon)
{
if(!m_has_label) return;
if (!m_has_label) return;
RibbonWidget* row = from_this_ribbon ? from_this_ribbon : (RibbonWidget*)getSelectedRibbon();
if(row == NULL) return;
if (row == NULL) return;
std::string selection_id = row->getSelectionIDString();
const int amount = m_items.size();
for(int n=0; n<amount; n++)
for (int n=0; n<amount; n++)
{
if(m_items[n].m_code_name == selection_id)
if (m_items[n].m_code_name == selection_id)
{
m_label->setText( stringw(m_items[n].m_user_name.c_str()).c_str() );
return;
@ -435,27 +462,6 @@ void RibbonGridWidget::updateLabel(RibbonWidget* from_this_ribbon)
m_label->setText( L"Random" );
}
// -----------------------------------------------------------------------------
void RibbonGridWidget::setSelection(int item_id)
{
if(m_rows.size() > 1)
{
std::cout << "/!\\ Warning, RibbonGridWidget::setSelection only makes sense on 1-row ribbons (since there can't logically be a selection with more than one row)\n";
}
// scroll so selection is visible
m_scroll_offset = item_id;
updateItemDisplay();
// set selection again, because scrolling made it wrong
RibbonWidget* ribbon = m_rows.get(0);
ribbon->setSelection(0);
}
void RibbonGridWidget::setSelection(const std::string& code_name)
{
assert(false);
}
// -----------------------------------------------------------------------------
void RibbonGridWidget::updateItemDisplay()
{
// Check if we need to update the number of icons in the ribbon
@ -510,4 +516,31 @@ void RibbonGridWidget::updateItemDisplay()
} // next column
} // next row
}
// -----------------------------------------------------------------------------
void RibbonGridWidget::setSelection(int item_id)
{
if (m_rows.size() > 1)
{
std::cout << "\n/!\\ Warning, RibbonGridWidget::setSelection only makes sense on 1-row ribbons " <<
"(since there can't logically be a permanent with more than one row)\n\n";
return;
}
m_selected_item = item_id;
if (m_selected_item >= (int)m_items.size()) m_selected_item -= m_items.size();
// scroll so selection is visible
m_scroll_offset = m_selected_item; // works because in this case there is a single row
updateItemDisplay();
// set selection
RibbonWidget* ribbon = m_rows.get(0); // there is a single row when we can select items
int id = m_selected_item - m_scroll_offset;
if (id < 0) id += m_items.size();
ribbon->setSelection(id);
}
// -----------------------------------------------------------------------------
void RibbonGridWidget::setSelection(const std::string& code_name)
{
assert(false);
}

View File

@ -65,8 +65,10 @@ namespace GUIEngine
IGUIStaticText* m_label;
int m_label_height;
/** Used to keep track of item count changes */
int m_previous_item_count;
/** List of items in the ribbon */
std::vector<ItemDescription> m_items;
/** Width of the scrolling arrows on each side */
@ -80,7 +82,6 @@ namespace GUIEngine
/** Whether this is a "combo" style ribbon grid widget */
bool m_combo;
/* reference pointers only, the actual instances are owned by m_children */
Widget* m_left_widget;
Widget* m_right_widget;
@ -88,6 +89,7 @@ namespace GUIEngine
RibbonWidget* getSelectedRibbon() const;
RibbonWidget* getRowContaining(Widget* w) const;
/** Updates the visible label to match the currently selected item */
void updateLabel(RibbonWidget* from_this_ribbon=NULL);
/** Even though the ribbon grid widget looks like a grid, it is really a vertical stack of
@ -96,24 +98,34 @@ namespace GUIEngine
another row keeps the same selected column. */
void propagateSelection();
/** Callback called widget is focused */
void focused();
bool transmitEvent(Widget* w, std::string& originator);
/** Removes all previously added contents icons, and re-adds them (calculating the new amount) */
void setSubElements();
void scroll(const int x_delta);
/** Used for combo ribbons, to contain the ID of the currently selected item */
int m_selected_item;
public:
RibbonGridWidget(const bool combo=false, const int max_rows=4);
void registerHoverListener(RibbonGridHoverListener* listener);
void add();
/** Called when right key is pressed */
bool rightPressed();
/** Called when left key is pressed */
bool leftPressed();
void addItem( std::string user_name, std::string code_name, std::string image_file );
void updateItemDisplay();
bool mouseHovered(Widget* child);

View File

@ -122,21 +122,21 @@ void RibbonWidget::updateSelection()
{
const int subbuttons_amount = m_children.size();
for(int i=0; i<subbuttons_amount; i++)
for (int i=0; i<subbuttons_amount; i++)
{
m_children[i].m_selected = (i == m_selection);
}
if(subbuttons_amount > 0 && m_ribbon_type == RIBBON_TOOLBAR) m_focus = m_children.get(m_selection);
if (subbuttons_amount > 0 && m_ribbon_type == RIBBON_TOOLBAR) m_focus = m_children.get(m_selection);
}
// -----------------------------------------------------------------------------
bool RibbonWidget::transmitEvent(Widget* w, std::string& originator)
{
const int subbuttons_amount = m_children.size();
for(int i=0; i<subbuttons_amount; i++)
for (int i=0; i<subbuttons_amount; i++)
{
if(m_children[i].m_properties[PROP_ID] == originator)
if (m_children[i].m_properties[PROP_ID] == originator)
{
m_selection = i;
break;
@ -161,11 +161,11 @@ void RibbonWidget::add()
// ---- check how much space each child button will take and fit them within available space
int total_needed_space = 0;
for(int i=0; i<subbuttons_amount; i++)
for (int i=0; i<subbuttons_amount; i++)
{
m_children[i].readCoords(this);
if(m_children[i].m_type != WTYPE_ICON_BUTTON && m_children[i].m_type != WTYPE_BUTTON)
if (m_children[i].m_type != WTYPE_ICON_BUTTON && m_children[i].m_type != WTYPE_BUTTON)
{
std::cerr << "/!\\ Warning /!\\ : ribbon widgets can only have (icon)button widgets as children " << std::endl;
continue;