Skip to content

Commit

Permalink
libappfw: Added a new "annotation" semantic for UI items
Browse files Browse the repository at this point in the history
This is useful in PopupMenuWidget to specify items that provide
additional information in addition to being separators.
  • Loading branch information
skyjake committed Jun 20, 2014
1 parent 6f482d2 commit ca7383d
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 3 deletions.
1 change: 1 addition & 0 deletions doomsday/libappfw/include/de/framework/item.h
Expand Up @@ -55,6 +55,7 @@ class LIBAPPFW_PUBLIC Item

ActivationClosesPopup = 0x100,
Separator = 0x200,
Annotation = 0x400 | Separator,

DefaultSemantics = ShownAsLabel
};
Expand Down
97 changes: 94 additions & 3 deletions doomsday/libappfw/src/widgets/popupmenuwidget.cpp
Expand Up @@ -21,8 +21,11 @@
#include "de/ToggleWidget"
#include "de/GuiRootWidget"
#include "de/ChildWidgetOrganizer"
#include "de/AtlasProceduralImage"
#include "de/ui/Item"

#include <de/IndirectRule>

namespace de {

DENG_GUI_PIMPL(PopupMenuWidget)
Expand All @@ -31,10 +34,82 @@ DENG_GUI_PIMPL(PopupMenuWidget)
, DENG2_OBSERVES(ChildWidgetOrganizer, WidgetCreation)
, DENG2_OBSERVES(ChildWidgetOrganizer, WidgetUpdate)
{
class HeadingOverlayImage : public ProceduralImage
{
public:
HeadingOverlayImage(GuiWidget &owner)
: _owner(owner)
, _id(Id::None)
{
if(_owner.hasRoot())
{
// We can set this up right away.
alloc();
}
}

GuiRootWidget &root()
{
return _owner.root();
}

void alloc()
{
_id = root().solidWhitePixel();
setSize(Vector2f(1, 1)); //root().atlas().imageRect(_id).size());
}

void glInit()
{
alloc();
}

void glDeinit()
{
_id = Id::None;
}

void glMakeGeometry(DefaultVertexBuf::Builder &verts, Rectanglef const &rect)
{
if(!_id.isNone())
{
Rectanglef visible = rect;
visible.setWidth(_owner.rule().width().value());
verts.makeQuad(visible, color(), root().atlas().imageRectf(_id));
}
}

private:
GuiWidget &_owner;
Id _id;
};

ButtonWidget *hover;
int oldScrollY;
Rule const *widestItem;
IndirectRule *maxItemWidth;

Instance(Public *i)
: Base(i)
, hover(0)
, oldScrollY(0)
, widestItem(0)
, maxItemWidth(0)
{
maxItemWidth = new IndirectRule;
}

Instance(Public *i) : Base(i), hover(0), oldScrollY(0) {}
~Instance()
{
releaseRef(maxItemWidth);
releaseRef(widestItem);
}

void addToMaxWidth(GuiWidget &widget)
{
maxInto(widestItem, widget.rule().width());
maxItemWidth->setSource(*widestItem);
}

void widgetCreatedForItem(GuiWidget &widget, ui::Item const &item)
{
Expand All @@ -45,19 +120,24 @@ DENG_GUI_PIMPL(PopupMenuWidget)
{
LabelWidget &lab = widget.as<LabelWidget>();
lab.setTextColor("label.accent");
lab.setMaximumTextWidth(*maxItemWidth);
lab.rule().setInput(Rule::Width, *maxItemWidth);
return;
}

if(LabelWidget *lab = widget.maybeAs<LabelWidget>())
{
lab->margins().set("unit");
addToMaxWidth(widget);
}

// Customize buttons for use in the popup. We will observe the button
// state for highlighting and possibly close the popup when an action
// gets triggered.
if(ButtonWidget *b = widget.maybeAs<ButtonWidget>())
{
addToMaxWidth(widget);

b->setHoverTextColor("inverted.text");
b->setSizePolicy(ui::Expand, ui::Expand);

Expand All @@ -79,18 +159,29 @@ DENG_GUI_PIMPL(PopupMenuWidget)

void widgetUpdatedForItem(GuiWidget &widget, ui::Item const &item)
{
if(item.semantics().testFlag(ui::Item::Separator))
if(item.semantics().testFlag(ui::Item::Annotation))
{
widget.margins().set("halfunit").setLeft("unit");
widget.setFont("separator.annotation");
}
else if(item.semantics().testFlag(ui::Item::Separator))
{
// The label of a separator may change.
if(item.label().isEmpty())
{
widget.margins().set("");
widget.setFont("separator.empty");
widget.as<LabelWidget>().setOverlayImage(0);
}
else
{
widget.margins().set("halfunit");
LabelWidget &lab = widget.as<LabelWidget>();
widget.margins().set("halfunit");//.setLeft("");
lab.setAlignment(ui::AlignCenter);
widget.setFont("separator.label");
HeadingOverlayImage *img = new HeadingOverlayImage(widget);
img->setColor(style().colors().colorf("accent"));
lab.setOverlayImage(img, ui::AlignBottomLeft);
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions doomsday/libcore/include/de/widgets/operatorrule.h
Expand Up @@ -170,6 +170,12 @@ inline void sumInto(RuleType const *&sum, Rule const &value) {
else { changeRef(sum, *sum + value); }
}

template <typename RuleType>
inline void maxInto(RuleType const *&maximum, Rule const &value) {
if(!maximum) { maximum = holdRef(value); }
else { changeRef(maximum, OperatorRule::maximum(*maximum, value)); }
}

} // namespace de

#endif // LIBDENG2_OPERATORRULE_H

0 comments on commit ca7383d

Please sign in to comment.