Skip to content

Commit

Permalink
Client|MenuWidget: Added an optional sort order for menu items
Browse files Browse the repository at this point in the history
Any object that implements ISortOrder can be used as the sort order
for menu items.
  • Loading branch information
skyjake committed Jul 16, 2013
1 parent 2393191 commit f24abe9
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
28 changes: 28 additions & 0 deletions doomsday/client/include/ui/widgets/menuwidget.h
Expand Up @@ -28,9 +28,30 @@
* One of the dimensions of the grid can be configured to use ui::Expand
* policy, but then the child widgets must manage their size on that axis by
* themselves.
*
* A sort order for the items can be optionally defined using
* MenuWidget::ISortOrder. Sorting affects layout only, not the actual order of
* the children.
*/
class MenuWidget : public ScrollAreaWidget
{
public:
class ISortOrder
{
public:
virtual ~ISortOrder() {}

/**
* Determines the sort order for a pair of menu items.
*
* @param a First menu item.
* @param b Second menu item.
*
* @return -1 if a < b; +1 if a > b; 0 if equal.
*/
virtual int compareMenuItemsForSorting(Widget const &a, Widget const &b) const = 0;
};

public:
MenuWidget(de::String const &name = "");

Expand All @@ -57,6 +78,13 @@ class MenuWidget : public ScrollAreaWidget
void setGridSize(int columns, ui::SizePolicy columnPolicy,
int rows, ui::SizePolicy rowPolicy);

/**
* Sets the sort order for item layout.
*
* @param sorting Sort order object. MenuWidget takes ownership.
*/
void setLayoutSortOrder(ISortOrder *sorting);

ButtonWidget *addItem(de::String const &styledText, de::Action *action = 0);

ButtonWidget *addItem(de::Image const &image, de::String const &styledText, de::Action *action = 0);
Expand Down
34 changes: 32 additions & 2 deletions doomsday/client/src/ui/widgets/menuwidget.cpp
Expand Up @@ -24,6 +24,8 @@ using namespace ui;
DENG2_PIMPL(MenuWidget)
{
bool needLayout;
QScopedPointer<ISortOrder> sorting;
WidgetList sortedChildren;

SizePolicy colPolicy;
SizePolicy rowPolicy;
Expand Down Expand Up @@ -105,6 +107,8 @@ DENG2_PIMPL(MenuWidget)
Vector2i size;
int ord = 0;

DENG2_ASSERT(sortedChildren.size() == int(self.childCount()));

foreach(Widget *i, self.Widget::children())
{
if(isVisibleItem(i))
Expand All @@ -116,10 +120,29 @@ DENG2_PIMPL(MenuWidget)
return size;
}

// Functor for quicksort comparisons.
struct Sorter {
Instance &d;
Sorter(Instance *inst) : d(*inst) {}
bool operator () (Widget const *a, Widget const *b) const {
DENG2_ASSERT(!d.sorting.isNull());
return d.sorting->compareMenuItemsForSorting(*a, *b) < 0;
}
};

void prepareSortedChildren()
{
sortedChildren = self.Widget::children();
if(!sorting.isNull())
{
qSort(sortedChildren.begin(), sortedChildren.end(), Sorter(this));
}
}

GuiWidget *findItem(int col, int row) const
{
int ord = 0;
foreach(Widget *i, self.Widget::children())
foreach(Widget *i, sortedChildren)
{
if(isVisibleItem(i))
{
Expand Down Expand Up @@ -234,6 +257,12 @@ void MenuWidget::setGridSize(int columns, ui::SizePolicy columnPolicy,
d->needLayout = true;
}

void MenuWidget::setLayoutSortOrder(ISortOrder *sorting)
{
d->sorting.reset(sorting);
d->needLayout = true;
}

ButtonWidget *MenuWidget::addItem(String const &styledText, Action *action)
{
return addItem(Image(), styledText, action);
Expand Down Expand Up @@ -278,7 +307,8 @@ int MenuWidget::count() const

void MenuWidget::updateLayout()
{
//qDebug() << path().toString() << "Menu has" << d->countVisible() << "visible items";
// Sort children again.
d->prepareSortedChildren();

Rule const *baseVert = holdRef(&contentRule().top());

Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/ui/widgets/popupmenuwidget.cpp
Expand Up @@ -150,9 +150,9 @@ void PopupMenuWidget::preparePopupForOpening()
PopupWidget::preparePopupForOpening();

// Redo the layout.
menu().updateLayout();
menu().rule().setInput(Rule::Width,
*refless(menu().newColumnWidthRule(0)) + 2 * margin());
menu().updateLayout();
}

void PopupMenuWidget::popupClosing()
Expand Down

0 comments on commit f24abe9

Please sign in to comment.