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