Skip to content

Commit

Permalink
libappfw: Submenu popups close their parent popup menus
Browse files Browse the repository at this point in the history
Selecting an item in a submenu causes the parent popup menu to
close as well.
  • Loading branch information
skyjake committed Mar 27, 2016
1 parent cabea51 commit 16a2072
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 53 deletions.
2 changes: 2 additions & 0 deletions doomsday/sdk/libappfw/include/de/widgets/popupmenuwidget.h
Expand Up @@ -34,6 +34,8 @@ class LIBAPPFW_PUBLIC PopupMenuWidget : public PopupWidget
public:
PopupMenuWidget(String const &name = "");

void setParentPopup(PopupWidget *parentPopup);

MenuWidget &menu() const;

ui::Data &items() { return menu().items(); }
Expand Down
9 changes: 9 additions & 0 deletions doomsday/sdk/libappfw/src/widgets/menuwidget.cpp
Expand Up @@ -87,6 +87,15 @@ DENG2_PIMPL(MenuWidget)

Action::trigger();

if(auto *subMenu = _widget->maybeAs<PopupMenuWidget>())
{
// Parent is the anchor button, owned by a MenuWidget, possibly owned a
// the popup menu.
if(auto *parentMenu = parent().parentWidget())
{
subMenu->setParentPopup(parentMenu->parent()->maybeAs<PopupWidget>());
}
}
_widget->setAnchorAndOpeningDirection(parent().hitRule(), _dir);

d->keepTrackOfSubWidget(_widget);
Expand Down
9 changes: 9 additions & 0 deletions doomsday/sdk/libappfw/src/widgets/popupmenuwidget.cpp
Expand Up @@ -94,6 +94,7 @@ DENG_GUI_PIMPL(PopupMenuWidget)
int oldScrollY;
Rule const *widestItem;
IndirectRule *maxItemWidth;
SafeWidgetPtr<PopupWidget> parentPopup;

Instance(Public *i)
: Base(i)
Expand Down Expand Up @@ -351,6 +352,8 @@ DENG_GUI_PIMPL(PopupMenuWidget)
{
// The popup menu is closed when an action is triggered.
self.close();

if(parentPopup) parentPopup->close();
}

void updateIfScrolled()
Expand Down Expand Up @@ -413,6 +416,12 @@ PopupMenuWidget::PopupMenuWidget(String const &name)
menu().organizer().audienceForWidgetUpdate() += d;
}

void PopupMenuWidget::setParentPopup(PopupWidget *parentPopup)
{
// The parent will be closed, too, if the submenu is closed due to activation.
d->parentPopup.reset(parentPopup);
}

MenuWidget &PopupMenuWidget::menu() const
{
return static_cast<MenuWidget &>(content());
Expand Down
61 changes: 8 additions & 53 deletions doomsday/sdk/libappfw/src/widgets/popupwidget.cpp
Expand Up @@ -32,19 +32,13 @@
namespace de {

DENG_GUI_PIMPL(PopupWidget)
, DENG2_OBSERVES(Widget, Deletion)
{
bool flexibleDir = true;
ColorTheme colorTheme = Normal;
bool deleteAfterDismiss = false;
bool clickToClose = true;
bool outsideClickOngoing = false;
Widget *realParent = nullptr;
/*Rule const *anchorTop = nullptr;
Rule const *anchorY = nullptr;
//Rule const *anchorWidth = nullptr;
Rule const *anchorBottom = nullptr;
Rule const *anchorOffset = new ConstantRule(0);*/
SafeWidgetPtr<Widget> realParent;
RuleRectangle anchor;
Rule const *marker;

Expand All @@ -54,11 +48,6 @@ DENG_GUI_PIMPL(PopupWidget)
marker = &rule("gap");
}

~Instance()
{
if(realParent) realParent->audienceForDeletion() -= this;
}

void flipOpeningDirectionIfNeeded()
{
ui::Direction openDir = self.openingDirection();
Expand Down Expand Up @@ -225,15 +214,6 @@ DENG_GUI_PIMPL(PopupWidget)
self.set(self.background().withSolidFillOpacity(1));
}
}

void widgetBeingDeleted(Widget &widget)
{
if(&widget == realParent)
{
// We don't know who the real parent is any more.
realParent = nullptr;
}
}
};

PopupWidget::PopupWidget(String const &name) : PanelWidget(name), d(new Instance(this))
Expand All @@ -245,7 +225,7 @@ PopupWidget::PopupWidget(String const &name) : PanelWidget(name), d(new Instance
int PopupWidget::levelOfNesting() const
{
int nesting = 0;
for(Widget const *p = d->realParent? d->realParent : parentWidget(); p; p = p->parent())
for(Widget const *p = d->realParent? d->realParent.get() : parentWidget(); p; p = p->parent())
{
if(p->is<PopupWidget>())
{
Expand All @@ -258,27 +238,6 @@ int PopupWidget::levelOfNesting() const
void PopupWidget::setAnchorAndOpeningDirection(RuleRectangle const &rule, ui::Direction dir)
{
d->anchor.setRect(rule);

/* if(dir == ui::NoDirection)
{
// Anchored to the middle by default.
setAnchor(rule.left() + rule.width() / 2,
rule.top() + rule.height() / 2);
}
else if(dir == ui::Left || dir == ui::Right)
{
setAnchorY(rule.top() + rule.height() / 2);
setAnchorX(dir == ui::Left? rule.left() : rule.right());
}
else if(dir == ui::Up || dir == ui::Down)
{
setAnchorX(rule.left() + rule.width() / 2);
setAnchorY(dir == ui::Up? rule.top() : rule.bottom());
}
changeRef(d->anchorWidth, rule.width());
changeRef(d->anchorHeight, rule.height());*/

setOpeningDirection(dir);
}

Expand Down Expand Up @@ -477,9 +436,8 @@ void PopupWidget::preparePanelForOpening()
}

// Reparent the popup into the root widget, on top of everything else.
d->realParent = Widget::parent();
DENG2_ASSERT(d->realParent != 0);
d->realParent->audienceForDeletion() += d;
d->realParent.reset(Widget::parent());
DENG2_ASSERT(d->realParent);
d->realParent->remove(*this);
d->realParent->root().as<GuiRootWidget>().addOnTop(this);

Expand All @@ -491,14 +449,11 @@ void PopupWidget::panelDismissed()
PanelWidget::panelDismissed();

// Move back to the original parent widget.
if(d->realParent)
{
d->realParent->audienceForDeletion() -= d;
}
else
if(!d->realParent)
{
// The real parent has been deleted.
d->realParent = &root();
d->realParent.reset(&root());
DENG2_ASSERT(d->realParent);
}
parentWidget()->remove(*this);

Expand All @@ -512,7 +467,7 @@ void PopupWidget::panelDismissed()
d->realParent->add(this);
}

d->realParent = 0;
d->realParent.reset();
}

} // namespace de

0 comments on commit 16a2072

Please sign in to comment.