Skip to content

Commit

Permalink
Cleanup|libdeng2: Arguments of Widget::notifyTree()
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Jun 17, 2013
1 parent f9be758 commit 02a90a0
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 51 deletions.
10 changes: 7 additions & 3 deletions doomsday/client/src/ui/widgets/guirootwidget.cpp
Expand Up @@ -50,7 +50,7 @@ DENG2_PIMPL(GuiRootWidget)
// Tell all widgets to release their resource allocations. The base
// class destructor will destroy all widgets, but this class governs
// shared GL resources, so we'll ask the widgets to do this now.
self.notifyTree(&Widget::deinitialize);
self.notifyTree(NotifyArgs(&Widget::deinitialize));
}

void initAtlas()
Expand Down Expand Up @@ -180,6 +180,10 @@ void GuiRootWidget::update()

void GuiRootWidget::drawUntil(Widget &until)
{
notifyTree(&Widget::draw, &Widget::isVisible,
&Widget::preDrawChildren, &Widget::postDrawChildren, &until);
NotifyArgs args(&Widget::draw);
args.conditionFunc = &Widget::isVisible;
args.preNotifyFunc = &Widget::preDrawChildren;
args.postNotifyFunc = &Widget::postDrawChildren;
args.until = &until;
notifyTree(args);
}
33 changes: 21 additions & 12 deletions doomsday/libdeng2/include/de/widgets/widget.h
Expand Up @@ -148,19 +148,28 @@ class DENG2_PUBLIC Widget

// Utilities.
String uniqueName(String const &name) const;
enum NotifyResult {
AbortNotify,
ContinueNotify

/**
* Arguments for notifyTree() and notifyTreeReversed().
*/
struct NotifyArgs {
enum Result {
Abort,
Continue
};
void (Widget::*notifyFunc)();
bool (Widget::*conditionFunc)() const;
void (Widget::*preNotifyFunc)();
void (Widget::*postNotifyFunc)();
Widget *until;

NotifyArgs(void (Widget::*notify)()) : notifyFunc(notify),
conditionFunc(0), preNotifyFunc(0), postNotifyFunc(0),
until(0) {}
};
NotifyResult notifyTree(void (Widget::*notifyFunc)(),
bool (Widget::*conditionFunc)() const = 0,
void (Widget::*preNotifyFunc)() = 0,
void (Widget::*postNotifyFunc)() = 0,
Widget *until = 0);
void notifyTreeReversed(void (Widget::*notifyFunc)(),
bool (Widget::*conditionFunc)() const = 0,
void (Widget::*preNotifyFunc)() = 0,
void (Widget::*postNotifyFunc)() = 0);

NotifyArgs::Result notifyTree(NotifyArgs const &args);
void notifyTreeReversed(NotifyArgs const &args);
bool dispatchEvent(Event const &event, bool (Widget::*memberFunc)(Event const &));

// Events.
Expand Down
6 changes: 5 additions & 1 deletion doomsday/libdeng2/src/widgets/rootwidget.cpp
Expand Up @@ -120,7 +120,11 @@ void RootWidget::update()

void RootWidget::draw()
{
notifyTree(&Widget::draw, &Widget::isVisible, &Widget::preDrawChildren, &Widget::postDrawChildren);
NotifyArgs args(&Widget::draw);
args.conditionFunc = &Widget::isVisible;
args.preNotifyFunc = &Widget::preDrawChildren;
args.postNotifyFunc = &Widget::postDrawChildren;
notifyTree(args);

Rule::markRulesValid(); // All done for this frame.
}
Expand Down
60 changes: 26 additions & 34 deletions doomsday/libdeng2/src/widgets/widget.cpp
Expand Up @@ -275,67 +275,60 @@ String Widget::uniqueName(String const &name) const
return String("#%1.%2").arg(id().asInt64()).arg(name);
}

Widget::NotifyResult Widget::notifyTree(void (Widget::*notifyFunc)(),
bool (Widget::*conditionFunc)() const,
void (Widget::*preFunc)(),
void (Widget::*postFunc)(),
Widget *until)
Widget::NotifyArgs::Result Widget::notifyTree(NotifyArgs const &args)
{
if(preFunc)
if(args.preNotifyFunc)
{
(this->*preFunc)();
(this->*args.preNotifyFunc)();
}

DENG2_FOR_EACH(Instance::Children, i, d->children)
{
if(*i == until)
if(*i == args.until)
{
return AbortNotify;
return NotifyArgs::Abort;
}

if(conditionFunc && !((*i)->*conditionFunc)())
if(args.conditionFunc && !((*i)->*args.conditionFunc)())
continue; // Skip this one.

((*i)->*notifyFunc)();
((*i)->*args.notifyFunc)();

if((*i)->notifyTree(notifyFunc, conditionFunc, preFunc, postFunc, until) == AbortNotify)
if((*i)->notifyTree(args) == NotifyArgs::Abort)
{
return AbortNotify;
return NotifyArgs::Abort;
}
}

if(postFunc)
if(args.postNotifyFunc)
{
(this->*postFunc)();
(this->*args.postNotifyFunc)();
}

return ContinueNotify;
return NotifyArgs::Continue;
}

void Widget::notifyTreeReversed(void (Widget::*notifyFunc)(),
bool (Widget::*conditionFunc)() const,
void (Widget::*preFunc)(),
void (Widget::*postFunc)())
void Widget::notifyTreeReversed(NotifyArgs const &args)
{
if(preFunc)
if(args.preNotifyFunc)
{
(this->*preFunc)();
(this->*args.preNotifyFunc)();
}

for(int i = d->children.size() - 1; i >= 0; --i)
{
Widget *w = d->children[i];

if(conditionFunc && !(w->*conditionFunc)())
if(args.conditionFunc && !(w->*args.conditionFunc)())
continue; // Skip this one.

w->notifyTreeReversed(notifyFunc, conditionFunc, preFunc, postFunc);
(w->*notifyFunc)();
w->notifyTreeReversed(args);
(w->*args.notifyFunc)();
}

if(postFunc)
if(args.postNotifyFunc)
{
(this->*postFunc)();
(this->*args.postNotifyFunc)();
}
}

Expand All @@ -344,25 +337,24 @@ bool Widget::dispatchEvent(Event const &event, bool (Widget::*memberFunc)(Event
// Hidden widgets do not get events.
if(isHidden()) return false;

// Routing has priority.
if(d->routing.contains(event.type()))
{
return d->routing[event.type()]->dispatchEvent(event, memberFunc);
}

bool const thisHasFocus = (hasRoot() && root().focus() == this);

if(d->behavior.testFlag(HandleEventsOnlyWhenFocused) && !thisHasFocus)
{
return false;
}

if(thisHasFocus)
{
// The focused widget is offered events before dispatching to the tree.
return false;
}

// Routing has priority.
if(d->routing.contains(event.type()))
{
return d->routing[event.type()]->dispatchEvent(event, memberFunc);
}

// Tree is traversed in reverse order.
for(int i = d->children.size() - 1; i >= 0; --i)
{
Expand Down
6 changes: 5 additions & 1 deletion doomsday/libshell/src/textwidget.cpp
Expand Up @@ -96,7 +96,11 @@ void TextWidget::drawAndShow()
if(!isHidden())
{
draw();
notifyTree(&Widget::draw, &Widget::isVisible);

NotifyArgs args(&Widget::draw);
args.conditionFunc = &Widget::isVisible;
notifyTree(args);

targetCanvas().show();
}
}
Expand Down

0 comments on commit 02a90a0

Please sign in to comment.