Skip to content

Commit

Permalink
UI|Client: Popup menu content scrolling
Browse files Browse the repository at this point in the history
When a popup menu is too tall to fit into view, the menu will
scroll accordingly.
  • Loading branch information
skyjake committed Sep 1, 2013
1 parent 34ea8b0 commit 9dc4024
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 7 deletions.
3 changes: 3 additions & 0 deletions doomsday/client/include/ui/widgets/popupmenuwidget.h
Expand Up @@ -32,6 +32,9 @@ class PopupMenuWidget : public PopupWidget

MenuWidget &menu() const;

// Events.
void update();

protected:
void glMakeGeometry(DefaultVertexBuf::Builder &verts);
void preparePopupForOpening();
Expand Down
3 changes: 3 additions & 0 deletions doomsday/client/include/ui/widgets/popupwidget.h
Expand Up @@ -57,6 +57,9 @@ class PopupWidget : public GuiWidget
void setAnchorX(de::Rule const &x);
void setAnchorY(de::Rule const &y);

de::Rule const &anchorX() const;
de::Rule const &anchorY() const;

/**
* Sets the preferred opening direction of the popup. If there isn't enough
* room in the specified direction, the opposite direction is used instead.
Expand Down
6 changes: 6 additions & 0 deletions doomsday/client/include/ui/windowsystem.h
Expand Up @@ -96,6 +96,12 @@ class WindowSystem : public de::System
*/
Style &style();

/**
* Dispatches a mouse position event with the latest mouse position. This
* happens automatically whenever the mouse has moved and time advances.
*/
void dispatchLatestMousePosition();

// System.
bool processEvent(de::Event const &);
void timeChanged(de::Clock const &);
Expand Down
40 changes: 37 additions & 3 deletions doomsday/client/src/ui/widgets/popupmenuwidget.cpp
Expand Up @@ -21,6 +21,7 @@
#include "GuiRootWidget"
#include "ContextWidgetOrganizer"
#include "ui/Item"
#include "clientapp.h"

using namespace de;

Expand All @@ -31,9 +32,9 @@ DENG2_OBSERVES(ContextWidgetOrganizer, WidgetCreation),
DENG2_OBSERVES(ContextWidgetOrganizer, WidgetUpdate)
{
ButtonWidget *hover;
Rectanglei hoverHighlightRect;
int oldScrollY;

Instance(Public *i) : Base(i), hover(0) {}
Instance(Public *i) : Base(i), hover(0), oldScrollY(0) {}

void widgetCreatedForItem(GuiWidget &widget, ui::Item const &item)
{
Expand Down Expand Up @@ -144,14 +145,33 @@ DENG2_OBSERVES(ContextWidgetOrganizer, WidgetUpdate)
hi.bottomRight.x = hover->hitRule().right().valuei();
hi.bottomRight.y = hover->hitRule().bottom().valuei();
}
return hi;
// Clip the highlight to the main popup area.
return hi & self.rule().recti();
}

void buttonActionTriggered(ButtonWidget &)
{
// The popup menu is closed when an action is triggered.
self.close();
}

void updateIfScrolled()
{
// If the menu is scrolled, we need to update some things.
int scrollY = self.menu().scrollPositionY().valuei();
if(scrollY == oldScrollY)
{
return;
}
oldScrollY = scrollY;

//qDebug() << "menu scrolling" << scrollY;

// Resend the mouse position so the buttons realize they've moved.
ClientApp::windowSystem().dispatchLatestMousePosition();

self.requestGeometry();
}
};

PopupMenuWidget::PopupMenuWidget(String const &name)
Expand All @@ -170,6 +190,12 @@ MenuWidget &PopupMenuWidget::menu() const
return static_cast<MenuWidget &>(content());
}

void PopupMenuWidget::update()
{
PopupWidget::update();
d->updateIfScrolled();
}

void PopupMenuWidget::glMakeGeometry(DefaultVertexBuf::Builder &verts)
{
PopupWidget::glMakeGeometry(verts);
Expand All @@ -190,6 +216,14 @@ void PopupMenuWidget::preparePopupForOpening()
menu().updateLayout();
d->updateItemHitRules();

// Make sure the menu doesn't go beyond the top of the view.
if(openingDirection() == ui::Up)
{
menu().rule().setInput(Rule::Height,
OperatorRule::minimum(menu().contentRule().height() + menu().margins().height(),
anchorY() - menu().margins().top()));
}

PopupWidget::preparePopupForOpening();
}

Expand Down
10 changes: 10 additions & 0 deletions doomsday/client/src/ui/widgets/popupwidget.cpp
Expand Up @@ -298,6 +298,16 @@ void PopupWidget::setAnchorY(Rule const &y)
d->anchorY = holdRef(y);
}

Rule const &PopupWidget::anchorX() const
{
return *d->anchorX;
}

Rule const &PopupWidget::anchorY() const
{
return *d->anchorY;
}

void PopupWidget::setOpeningDirection(ui::Direction dir)
{
d->dir = dir;
Expand Down
17 changes: 13 additions & 4 deletions doomsday/client/src/ui/windowsystem.cpp
Expand Up @@ -46,13 +46,17 @@ DENG2_PIMPL(WindowSystem)
self.closeAll();
}

void dispatchLatestMousePosition()
void processLatestMousePosition()
{
self.main().root().processEvent(MouseEvent(MouseEvent::Absolute, latestMousePos));
}

void processLatestMousePositionIfMoved()
{
if(mouseMoved)
{
mouseMoved = false;

self.main().root().processEvent(MouseEvent(MouseEvent::Absolute, latestMousePos));
processLatestMousePosition();
}
}
};
Expand Down Expand Up @@ -103,6 +107,11 @@ Style &WindowSystem::style()
return d->style;
}

void WindowSystem::dispatchLatestMousePosition()
{
d->processLatestMousePosition();
}

bool WindowSystem::processEvent(Event const &event)
{
/*
Expand Down Expand Up @@ -131,7 +140,7 @@ bool WindowSystem::processEvent(Event const &event)

void WindowSystem::timeChanged(Clock const &/*clock*/)
{
d->dispatchLatestMousePosition();
d->processLatestMousePositionIfMoved();

// Update periodically.
main().root().update();
Expand Down

0 comments on commit 9dc4024

Please sign in to comment.