1 /** @file relaywidget.cpp Relays drawing and events.
2 *
3 * @authors Copyright (c) 2014-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4 *
5 * @par License
6 * LGPL: http://www.gnu.org/licenses/lgpl.html
7 *
8 * <small>This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or (at your
11 * option) any later version. This program is distributed in the hope that it
12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14 * General Public License for more details. You should have received a copy of
15 * the GNU Lesser General Public License along with this program; if not, see:
16 * http://www.gnu.org/licenses</small>
17 */
18
19 #include "de/RelayWidget"
20
21 namespace de {
22
DENG2_PIMPL(RelayWidget)23 DENG2_PIMPL(RelayWidget)
24 , DENG2_OBSERVES(Widget, Deletion)
25 {
26 GuiWidget *target = nullptr;
27
28 Impl(Public *i) : Base(i) {}
29
30 ~Impl()
31 {
32 setTarget(nullptr);
33 }
34
35 void setTarget(GuiWidget *w)
36 {
37 if (target) target->audienceForDeletion() -= this;
38 target = w;
39 if (target) target->audienceForDeletion() += this;
40 }
41
42 void widgetBeingDeleted(Widget &w)
43 {
44 if (target == &w)
45 {
46 DENG2_FOR_PUBLIC_AUDIENCE2(Target, i)
47 {
48 i->relayTargetBeingDeleted(self());
49 }
50 target = nullptr;
51 }
52 }
53
54 DENG2_PIMPL_AUDIENCE(Target)
55 };
56
DENG2_AUDIENCE_METHOD(RelayWidget,Target)57 DENG2_AUDIENCE_METHOD(RelayWidget, Target)
58
59 RelayWidget::RelayWidget(GuiWidget *target, String const &name)
60 : GuiWidget(name), d(new Impl(this))
61 {
62 d->setTarget(target);
63 }
64
setTarget(GuiWidget * target)65 void RelayWidget::setTarget(GuiWidget *target)
66 {
67 d->setTarget(target);
68 }
69
target() const70 GuiWidget *RelayWidget::target() const
71 {
72 return d->target;
73 }
74
initialize()75 void RelayWidget::initialize()
76 {
77 GuiWidget::initialize();
78 if (d->target)
79 {
80 d->target->setRoot(&root());
81 d->target->notifySelfAndTree(&Widget::initialize);
82 }
83 }
84
deinitialize()85 void RelayWidget::deinitialize()
86 {
87 GuiWidget::deinitialize();
88 if (d->target)
89 {
90 d->target->notifySelfAndTree(&Widget::deinitialize);
91 }
92 }
93
viewResized()94 void RelayWidget::viewResized()
95 {
96 GuiWidget::viewResized();
97 if (d->target)
98 {
99 d->target->notifySelfAndTree(&Widget::viewResized);
100 }
101 }
102
update()103 void RelayWidget::update()
104 {
105 GuiWidget::update();
106 if (d->target)
107 {
108 d->target->setRoot(&root());
109 d->target->notifySelfAndTree(&Widget::update);
110 }
111 }
112
handleEvent(Event const & event)113 bool RelayWidget::handleEvent(Event const &event)
114 {
115 if (d->target)
116 {
117 return d->target->dispatchEvent(event, &Widget::handleEvent);
118 }
119 return GuiWidget::handleEvent(event);
120 }
121
hitTest(Vector2i const & pos) const122 bool RelayWidget::hitTest(Vector2i const &pos) const
123 {
124 if (d->target)
125 {
126 return d->target->hitTest(pos);
127 }
128 return false;
129 }
130
drawContent()131 void RelayWidget::drawContent()
132 {
133 if (d->target)
134 {
135 NotifyArgs args(&Widget::draw);
136 args.conditionFunc = &Widget::isVisible;
137 args.preNotifyFunc = &Widget::preDrawChildren;
138 args.postNotifyFunc = &Widget::postDrawChildren;
139 d->target->notifySelfAndTree(args);
140 }
141 }
142
143 } // namespace de
144