ManaPlus
widget.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2011-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 /* _______ __ __ __ ______ __ __ _______ __ __
23  * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
24  * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
25  * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
26  * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
27  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
28  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
29  *
30  * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
31  *
32  *
33  * Per Larsson a.k.a finalman
34  * Olof Naessén a.k.a jansem/yakslem
35  *
36  * Visit: http://guichan.sourceforge.net
37  *
38  * License: (BSD)
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  * notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  * notice, this list of conditions and the following disclaimer in
46  * the documentation and/or other materials provided with the
47  * distribution.
48  * 3. Neither the name of Guichan nor the names of its contributors may
49  * be used to endorse or promote products derived from this software
50  * without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
55  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
56  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
57  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
58  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
59  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
60  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
61  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
62  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63  */
64 
65 /*
66  * For comments regarding functions please see the header file.
67  */
68 
69 #include "gui/widgets/widget.h"
70 
71 #include "gui/focushandler.h"
72 
76 
77 #include "utils/foreach.h"
78 
79 #include "debug.h"
80 
81 Font* Widget::mGlobalFont = nullptr;
82 std::list<Widget*> Widget::mAllWidgets;
83 std::set<Widget*> Widget::mAllWidgetsSet;
84 
85 Widget::Widget(const Widget2 *const widget) :
86  Widget2(widget),
87  mVisible(Visible_true),
88  mMouseListeners(),
89  mKeyListeners(),
90  mActionListeners(),
91  mDeathListeners(),
92  mFocusListeners(),
93  mWidgetListeners(),
94  mForegroundColor(0x000000),
95  mBackgroundColor(0xffffff),
96  mBaseColor(0x808090),
97  mDimension(),
98  mActionEventId(),
99  mId(),
100  mFocusHandler(nullptr),
101  mInternalFocusHandler(nullptr),
102  mParent(nullptr),
103  mCurrentFont(nullptr),
104  mFrameSize(0),
105  mFocusable(false),
106  mTabIn(true),
107  mTabOut(true),
108  mEnabled(true),
109  mAllowLogic(true),
110  mMouseConsume(true),
111  mRedraw(true),
112  mSelectable(true)
113 {
114  mAllWidgets.push_back(this);
115  mAllWidgetsSet.insert(this);
116 }
117 
119 {
121  {
122  Event event(this);
123  (*iter)->death(event);
124  }
125 
126  // +++ call to virtual member
127  setFocusHandler(nullptr);
128 
129  mAllWidgets.remove(this);
130  mAllWidgetsSet.erase(this);
131 }
132 
133 void Widget::setWidth(const int width)
134 {
135  Rect newDimension = mDimension;
136  newDimension.width = width;
137  setDimension(newDimension);
138 }
139 
140 void Widget::setHeight(const int height)
141 {
142  Rect newDimension = mDimension;
143  newDimension.height = height;
144  setDimension(newDimension);
145 }
146 
147 void Widget::setX(const int x)
148 {
149  Rect newDimension = mDimension;
150  newDimension.x = x;
151  setDimension(newDimension);
152 }
153 
154 void Widget::setY(const int y)
155 {
156  Rect newDimension = mDimension;
157  newDimension.y = y;
158  setDimension(newDimension);
159 }
160 
161 void Widget::setPosition(const int x, const int y)
162 {
163  Rect newDimension = mDimension;
164  newDimension.x = x;
165  newDimension.y = y;
166  setDimension(newDimension);
167 }
168 
169 void Widget::setDimension(const Rect& dimension)
170 {
171  const Rect oldDimension = mDimension;
172  mDimension = dimension;
173 
174  if (mDimension.width != oldDimension.width
175  || mDimension.height != oldDimension.height)
176  {
178  }
179 
180  if (mDimension.x != oldDimension.x || mDimension.y != oldDimension.y)
182 }
183 
184 bool Widget::isFocused() const
185 {
186  if (mFocusHandler == nullptr)
187  return false;
188 
189  return mFocusHandler->isFocused(this);
190 }
191 
192 void Widget::setFocusable(const bool focusable)
193 {
194  if (!focusable && isFocused() && (mFocusHandler != nullptr))
196  mFocusable = focusable;
197 }
198 
200 {
201  return mFocusable && isVisible() && isEnabled();
202 }
203 
205 {
206  if (mFocusHandler == nullptr)
207  return;
208 
209  if (isFocusable())
211 }
212 
214 {
215  if (mParent != nullptr)
216  mParent->moveToTop(this);
217 }
218 
220 {
221  if (mParent != nullptr)
222  mParent->moveToBottom(this);
223 }
224 
226 {
227  if (visible == Visible_false && isFocused() && (mFocusHandler != nullptr))
229 
230  if (visible == Visible_true)
232  else
234 
235  mVisible = visible;
236 }
237 
238 void Widget::setFocusHandler(FocusHandler *const focusHandler)
239 {
240  if (mFocusHandler != nullptr)
241  {
243  mFocusHandler->remove(this);
244  }
245 
246  if (focusHandler != nullptr)
247  focusHandler->add(this);
248 
249  mFocusHandler = focusHandler;
250 }
251 
252 void Widget::addActionListener(ActionListener *const actionListener)
253 {
254  mActionListeners.push_back(actionListener);
255 }
256 
257 void Widget::removeActionListener(ActionListener *const actionListener)
258 {
259  mActionListeners.remove(actionListener);
260 }
261 
263 {
264  mDeathListeners.push_back(deathListener);
265 }
266 
268 {
269  mDeathListeners.remove(deathListener);
270 }
271 
272 void Widget::addKeyListener(KeyListener *const keyListener)
273 {
274  mKeyListeners.push_back(keyListener);
275 }
276 
277 void Widget::removeKeyListener(KeyListener *const keyListener)
278 {
279  mKeyListeners.remove(keyListener);
280 }
281 
282 void Widget::addFocusListener(FocusListener *const focusListener)
283 {
284  mFocusListeners.push_back(focusListener);
285 }
286 
287 void Widget::removeFocusListener(FocusListener *const focusListener)
288 {
289  mFocusListeners.remove(focusListener);
290 }
291 
292 void Widget::addMouseListener(MouseListener *const mouseListener)
293 {
294  mMouseListeners.push_back(mouseListener);
295 }
296 
297 void Widget::removeMouseListener(MouseListener *const mouseListener)
298 {
299  mMouseListeners.remove(mouseListener);
300 }
301 
302 void Widget::addWidgetListener(WidgetListener *const widgetListener)
303 {
304  mWidgetListeners.push_back(widgetListener);
305 }
306 
307 void Widget::removeWidgetListener(WidgetListener *const widgetListener)
308 {
309  mWidgetListeners.remove(widgetListener);
310 }
311 
312 void Widget::getAbsolutePosition(int& x, int& y) const
313 {
314  if (mParent == nullptr)
315  {
316  x = mDimension.x;
317  y = mDimension.y;
318  return;
319  }
320 
321  int parentX;
322  int parentY;
323 
324  mParent->getAbsolutePosition(parentX, parentY);
325 
326  const Rect &rect = mParent->getChildrenArea();
327  x = parentX + mDimension.x + rect.x;
328  y = parentY + mDimension.y + rect.y;
329 }
330 
332 {
333  if (mCurrentFont == nullptr)
334  return mGlobalFont;
335  return mCurrentFont;
336 }
337 
338 void Widget::setGlobalFont(Font *const font)
339 {
340  mGlobalFont = font;
341 
342  FOR_EACH (std::list<Widget*>::const_iterator, iter, mAllWidgets)
343  {
344  if ((*iter)->mCurrentFont == nullptr)
345  (*iter)->fontChanged();
346  }
347 }
348 
349 void Widget::setFont(Font *const font)
350 {
351  mCurrentFont = font;
352  fontChanged();
353 }
354 
356 {
357  FOR_EACH (std::list<Widget*>::const_iterator, iter, mAllWidgets)
358  (*iter)->windowResized();
359 }
360 
361 bool Widget::widgetExists(const Widget *const widget)
362 {
363  return mAllWidgetsSet.find(const_cast<Widget*>(widget))
364  != mAllWidgetsSet.end();
365 }
366 
367 void Widget::setSize(const int width, const int height)
368 {
369  Rect newDimension = mDimension;
370  newDimension.width = width;
371  newDimension.height = height;
372  setDimension(newDimension);
373 }
374 
375 bool Widget::isEnabled() const
376 {
377  return mEnabled && isVisible();
378 }
379 
381 {
382  if (mFocusHandler == nullptr)
383  return;
385 }
386 
388 {
389  if (mFocusHandler == nullptr)
390  return;
392 }
393 
395 {
396  if (mFocusHandler == nullptr)
397  return;
399 }
400 
402 {
403  if (mFocusHandler == nullptr)
404  return;
406 }
407 
409 {
410  if (mFocusHandler == nullptr)
411  return false;
412 
413  if (mParent != nullptr)
414  {
415  return (mFocusHandler->getModalFocused() == this)
416  || mParent->isModalFocused();
417  }
418 
419  return mFocusHandler->getModalFocused() == this;
420 }
421 
423 {
424  if (mFocusHandler == nullptr)
425  return false;
426 
427  if (mParent != nullptr)
428  {
429  return (mFocusHandler->getModalMouseInputFocused() == this)
431  }
432 
433  return mFocusHandler->getModalMouseInputFocused() == this;
434 }
435 
436 const std::list<MouseListener*> &Widget::getMouseListeners() const
437 {
438  return mMouseListeners;
439 }
440 
441 const std::list<KeyListener*> &Widget::getKeyListeners() const
442 {
443  return mKeyListeners;
444 }
445 
446 const std::list<FocusListener*> &Widget::getFocusListeners() const
447 {
448  return mFocusListeners;
449 }
450 
452 {
453  return Rect(0, 0, 0, 0);
454 }
455 
457 {
458  return mInternalFocusHandler;
459 }
460 
462 {
463  mInternalFocusHandler = focusHandler;
464 }
465 
467 {
469  {
470  Event event(this);
471  (*iter)->widgetResized(event);
472  }
473 }
474 
476 {
478  {
479  Event event(this);
480  (*iter)->widgetMoved(event);
481  }
482 }
483 
485 {
487  {
488  Event event(this);
489  (*iter)->widgetHidden(event);
490  }
491 }
492 
494 {
496  {
497  ActionEvent actionEvent(this, mActionEventId);
498  (*iter)->action(actionEvent);
499  }
500 }
501 
503 {
505  {
506  Event event(this);
507  (*iter)->widgetShown(event);
508  }
509 }
510 
511 void Widget::showPart(const Rect &rectangle)
512 {
513  if (mParent != nullptr)
514  mParent->showWidgetPart(this, rectangle);
515 }
516 
518 {
519  mRedraw = true;
520 }
521 
523 {
524  if (widget != nullptr)
525  widget->postInit();
526  return widget;
527 }
Definition: event.h:79
void add(Widget *const widget)
void requestModalFocus(Widget *const widget)
Widget * getModalMouseInputFocused() const
void requestModalMouseInputFocus(Widget *const widget)
void requestFocus(const Widget *const widget)
void releaseModalMouseInputFocus(const Widget *const widget)
void releaseModalFocus(Widget *const widget)
void remove(Widget *const widget)
Widget * getModalFocused() const
bool isFocused(const Widget *const widget) const
Definition: font.h:90
Definition: rect.h:74
int y
Definition: rect.h:214
int width
Definition: rect.h:219
int x
Definition: rect.h:209
int height
Definition: rect.h:224
Definition: widget.h:99
void setVisible(Visible visible)
Definition: widget.cpp:225
bool mFocusable
Definition: widget.h:1143
static std::set< Widget * > mAllWidgetsSet
Definition: widget.h:1179
virtual void setFocusHandler(FocusHandler *const focusHandler)
Definition: widget.cpp:238
virtual Rect getChildrenArea()
Definition: widget.cpp:451
static std::list< Widget * > mAllWidgets
Definition: widget.h:1177
void setFocusable(const bool focusable)
Definition: widget.cpp:192
void removeActionListener(ActionListener *const actionListener)
Definition: widget.cpp:257
static void distributeWindowResizeEvent()
Definition: widget.cpp:355
void setWidth(const int width)
Definition: widget.cpp:133
void setSize(const int width, const int height)
Definition: widget.cpp:367
void distributeActionEvent()
Definition: widget.cpp:493
void distributeMovedEvent()
Definition: widget.cpp:475
void setInternalFocusHandler(FocusHandler *const internalFocusHandler)
Definition: widget.cpp:461
virtual void getAbsolutePosition(int &x, int &y) const
Definition: widget.cpp:312
virtual void requestMoveToTop()
Definition: widget.cpp:213
void removeMouseListener(MouseListener *const mouseListener)
Definition: widget.cpp:297
virtual void postInit()
Definition: widget.h:957
virtual bool isModalMouseInputFocused() const
Definition: widget.cpp:422
virtual FocusHandler * getInternalFocusHandler()
Definition: widget.cpp:456
virtual void showPart(const Rect &rectangle)
Definition: widget.cpp:511
Widget * mParent
Definition: widget.h:1128
Widget(const Widget2 *const widget)
Definition: widget.cpp:85
virtual void showWidgetPart(Widget *const widget, const Rect &area)
Definition: widget.h:903
virtual void moveToBottom(Widget *widget)
Definition: widget.h:877
Rect mDimension
Definition: widget.h:1101
WidgetListenerList::iterator WidgetListenerIterator
Definition: widget.h:1081
void setY(const int y)
Definition: widget.cpp:154
void removeKeyListener(KeyListener *const keyListener)
Definition: widget.cpp:277
static bool widgetExists(const Widget *const widget)
Definition: widget.cpp:361
static Font * mGlobalFont
Definition: widget.h:1171
Font * mCurrentFont
Definition: widget.h:1133
virtual void releaseModalMouseInputFocus()
Definition: widget.cpp:401
FocusHandler * mFocusHandler
Definition: widget.h:1116
void removeDeathListener(WidgetDeathListener *const deathListener)
Definition: widget.cpp:267
const std::list< MouseListener * > & getMouseListeners() const A_CONST
Definition: widget.cpp:436
virtual void requestModalMouseInputFocus()
Definition: widget.cpp:387
void windowResized()
Definition: widget.cpp:517
static Widget * callPostInit(Widget *const widget)
Definition: widget.cpp:522
void requestModalFocus()
Definition: widget.cpp:380
bool isFocusable() const
Definition: widget.cpp:199
void addMouseListener(MouseListener *const mouseListener)
Definition: widget.cpp:292
ActionListenerList mActionListeners
Definition: widget.h:1034
static void setGlobalFont(Font *const font)
Definition: widget.cpp:338
void setFont(Font *const font)
Definition: widget.cpp:349
void addWidgetListener(WidgetListener *const widgetListener)
Definition: widget.cpp:302
void setHeight(const int height)
Definition: widget.cpp:140
KeyListenerList mKeyListeners
Definition: widget.h:1019
void distributeResizedEvent()
Definition: widget.cpp:466
virtual void fontChanged()
Definition: widget.h:667
~Widget()
Definition: widget.cpp:118
bool mEnabled
Definition: widget.h:1158
void addKeyListener(KeyListener *const keyListener)
Definition: widget.cpp:272
FocusListenerList mFocusListeners
Definition: widget.h:1064
virtual void moveToTop(Widget *widget)
Definition: widget.h:867
virtual void requestFocus()
Definition: widget.cpp:204
void setDimension(const Rect &dimension)
Definition: widget.cpp:169
bool mRedraw
Definition: widget.h:1164
MouseListenerList mMouseListeners
Definition: widget.h:1009
Font * getFont() const
Definition: widget.cpp:331
WidgetDeathListenerList::iterator WidgetDeathListenerIterator
Definition: widget.h:1054
Visible mVisible
Definition: widget.h:963
virtual void requestMoveToBottom()
Definition: widget.cpp:219
virtual bool isModalFocused() const
Definition: widget.cpp:408
FocusHandler * mInternalFocusHandler
Definition: widget.h:1122
void removeWidgetListener(WidgetListener *const widgetListener)
Definition: widget.cpp:307
void addDeathListener(WidgetDeathListener *const deathListener)
Definition: widget.cpp:262
void distributeHiddenEvent()
Definition: widget.cpp:484
std::string mActionEventId
Definition: widget.h:1106
bool isEnabled() const
Definition: widget.cpp:375
const std::list< KeyListener * > & getKeyListeners() const A_CONST
Definition: widget.cpp:441
WidgetListenerList mWidgetListeners
Definition: widget.h:1076
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:252
void setX(const int x)
Definition: widget.cpp:147
void setPosition(const int x, const int y)
Definition: widget.cpp:161
virtual void releaseModalFocus()
Definition: widget.cpp:394
void addFocusListener(FocusListener *const focusListener)
Definition: widget.cpp:282
bool isVisible() const
Definition: widget.h:378
const std::list< FocusListener * > & getFocusListeners() const A_CONST
Definition: widget.cpp:446
void distributeShownEvent()
Definition: widget.cpp:502
void removeFocusListener(FocusListener *const focusListener)
Definition: widget.cpp:287
ActionListenerList::iterator ActionListenerIterator
Definition: widget.h:1039
virtual bool isFocused() const
Definition: widget.cpp:184
WidgetDeathListenerList mDeathListeners
Definition: widget.h:1049
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define nullptr
Definition: localconsts.h:45
bool Visible
Definition: visible.h:30
const bool Visible_false
Definition: visible.h:30
const bool Visible_true
Definition: visible.h:30