Harmonic Flow Framework (libhffwk)
Cross platform C++ 2D Game Engine Framework
WidgetContainer.cpp
1 /*
2  Harmonic Flow Framework
3  Copyright (C) 2011-2018 Andreas Widen <andreas@harmonicflow.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "WidgetContainer.h"
22 #include "WidgetManager.h"
23 #include "Widget.h"
24 #include "platform/Environment.h"
25 #include <assert.h>
26 #include <algorithm>
27 
28 using namespace HFCore;
29 
30 #include "debug/CrtDbgNew.h"
31 
33 {
34  mX = 0;
35  mY = 0;
36  mWidth = 0;
37  mHeight = 0;
38  mParent = NULL;
41  mUpdateIterator = mWidgets.end();
42  mHasAlpha = false;
43  mClip = true;
44  mPriority = 0;
45  mZOrder = 0;
46 }
47 
49 {
50  // call RemoveWidget before you delete it!
51  assert(mParent == NULL);
52  assert(mWidgets.empty());
53 }
54 
56  int32_hf flags, bool *found,
57  fp32_hf *widgetX, fp32_hf *widgetY)
58 {
59  bool belowModal = false;
60 
61  ModFlags(flags, mWidgetFlagsMod);
62 
63  WidgetList::reverse_iterator itr = mWidgets.rbegin();
64  while (itr != mWidgets.rend())
65  {
66  Widget *widget = *itr;
67 
68  int32_hf curFlags = flags;
69  ModFlags(curFlags, widget->mWidgetFlagsMod);
70  if (belowModal) ModFlags(curFlags, mWidgetManager->mBelowModalFlagsMod);
71 
72  if (curFlags & WIDGETFLAGS_ALLOW_MOUSE)
73  {
74  if (widget->mVisible)
75  {
76  bool childFound;
77  Widget *checkWidget = widget->getWidgetAtHelper(x - widget->mX,
78  y - widget->mY, curFlags,
79  &childFound, widgetX, widgetY);
80  if ((checkWidget != NULL) || (childFound))
81  {
82  *found = true;
83  return checkWidget;
84  }
85 
86  Vector2 point(x, y);
87  if ((widget->mMouseVisible) && (widget->getInsetRect().contains(point)))
88  {
89  *found = true;
90 
91  if (widget->isPointVisible((int32_hf)(x - widget->mX),
92  (int32_hf)(y - widget->mY)))
93  {
94  if (widgetX)
95  *widgetX = x - widget->mX;
96  if (widgetY)
97  *widgetY = y - widget->mY;
98  return widget;
99  }
100  }
101  }
102  }
103 
104  belowModal |= widget == mWidgetManager->mBaseModalWidget;
105 
106  ++itr;
107  }
108 
109  *found = false;
110  return NULL;
111 }
112 
113 bool WidgetContainer::isBelowHelper(Widget *widget1,
114  Widget *widget2, bool *found)
115 {
116  WidgetList::iterator itr = mWidgets.begin();
117  while (itr != mWidgets.end())
118  {
119  Widget *widget = *itr;
120 
121  if (widget == widget1)
122  {
123  *found = true;
124  return true;
125  }
126  else if (widget == widget2)
127  {
128  *found = true;
129  return false;
130  }
131 
132  bool result = widget->isBelowHelper(widget1, widget2, found);
133  if (*found)
134  return result;
135 
136  ++itr;
137  }
138 
139  return false;
140 }
141 
142 void WidgetContainer::insertWidgetHelper(const WidgetList::iterator &where,
143  Widget *widget)
144 {
145  // Search forwards
146  WidgetList::iterator itr = where;
147  while (itr != mWidgets.end())
148  {
149  Widget *tmpWidget = *itr;
150  if (tmpWidget->mZOrder >= widget->mZOrder)
151  {
152  if (itr != mWidgets.begin())
153  {
154  WidgetList::iterator itr2 = itr;
155  itr2--;
156  tmpWidget = *itr;
157  // need to search backwards
158  if (tmpWidget->mZOrder > widget->mZOrder)
159  break;
160  }
161 
162  mWidgets.insert(itr, widget);
163  return;
164  }
165  ++itr;
166  }
167 
168  // Search backwards
169  while (itr != mWidgets.begin())
170  {
171  --itr;
172  Widget *tmpWidget = *itr;
173  if (tmpWidget->mZOrder <= widget->mZOrder)
174  {
175  mWidgets.insert(++itr, widget);
176  return;
177  }
178  }
179 
180  // It goes at the beginning
181  mWidgets.push_front(widget);
182 }
183 
185 {
186  return Rect(mX, mY, mWidth, mHeight);
187 }
188 
190 {
191  return getRect().intersects(widget->getRect());
192 }
193 
195 {
196  if (std::find(mWidgets.begin(), mWidgets.end(), widget) == mWidgets.end())
197  {
198  insertWidgetHelper(mWidgets.end(), widget);
199  widget->mWidgetManager = mWidgetManager;
200  widget->mParent = this;
201 
202  if (mWidgetManager != NULL)
203  {
206  }
207  }
208 }
209 
211 {
212  WidgetList::iterator itr = std::find(mWidgets.begin(), mWidgets.end(), widget);
213  if (itr != mWidgets.end())
214  {
215  widget->widgetRemovedHelper();
216  widget->mParent = NULL;
217 
218  bool erasedCur = (itr == mUpdateIterator);
219  mWidgets.erase(itr++);
220  if (erasedCur)
221  {
222  mUpdateIterator = itr;
224  }
225  }
226 }
227 
229 {
230  return std::find(mWidgets.begin(), mWidgets.end(), widget) != mWidgets.end();
231 }
232 
234 {
235 }
236 
237 void WidgetContainer::removeAllWidgets(bool doDelete, bool recursive)
238 {
239  while (!mWidgets.empty())
240  {
241  Widget *widget = mWidgets.front();
242  removeWidget(widget);
243  if (recursive)
244  widget->removeAllWidgets(doDelete, recursive);
245 
246  if (doDelete)
247  HF_SAFE_DELETE(widget);
248  }
249 }
250 
252 {
253 }
254 
255 bool WidgetContainer::isBelow(Widget *widget1, Widget *widget2)
256 {
257  bool found = false;
258  return isBelowHelper(widget1, widget2, &found);
259 }
260 
262 {
263  WidgetList::iterator itr = std::find(mWidgets.begin(), mWidgets.end(), widget);
264  if (itr != mWidgets.end())
265  {
266  if (itr == mUpdateIterator)
267  {
268  mUpdateIterator++;
270  }
271 
272  mWidgets.erase(itr);
273  insertWidgetHelper(mWidgets.end(), widget);
274 
275  widget->orderInManagerChanged();
276  }
277 }
278 
280 {
281  WidgetList::iterator itr = std::find(mWidgets.begin(), mWidgets.end(), widget);
282  if (itr != mWidgets.end())
283  {
284  if (itr == mUpdateIterator)
285  {
286  mUpdateIterator++;
288  }
289 
290  mWidgets.erase(itr);
291  insertWidgetHelper(mWidgets.begin(), widget);
292 
293  widget->orderInManagerChanged();
294  }
295 }
296 
297 void WidgetContainer::putBehind(Widget *widget, Widget *refWidget)
298 {
299  WidgetList::iterator itr = std::find(mWidgets.begin(), mWidgets.end(), widget);
300  if (itr != mWidgets.end())
301  {
302  if (itr == mUpdateIterator)
303  {
304  mUpdateIterator++;
306  }
307 
308  mWidgets.erase(itr);
309  itr = std::find(mWidgets.begin(), mWidgets.end(), refWidget);
310  insertWidgetHelper(itr, widget);
311 
312  widget->orderInManagerChanged();
313  }
314 }
315 
316 void WidgetContainer::putInfront(Widget *widget, Widget *refWidget)
317 {
318  WidgetList::iterator itr = std::find(mWidgets.begin(), mWidgets.end(), widget);
319  if (itr != mWidgets.end())
320  {
321  if (itr == mUpdateIterator)
322  {
323  mUpdateIterator++;
325  }
326 
327  mWidgets.erase(itr);
328  itr = std::find(mWidgets.begin(), mWidgets.end(), refWidget);
329  if (itr != mWidgets.end())
330  itr++;
331  insertWidgetHelper(itr, widget);
332 
333  widget->orderInManagerChanged();
334  }
335 }
336 
338 {
339  if (mParent == NULL)
340  return Vector2(mX, mY);
341  else
342  return Vector2(mX, mY) +
343  mParent->getAbsPos();
344 }
345 
347 {
348  WidgetList::iterator itr = mWidgets.begin();
349  while (itr != mWidgets.end())
350  {
351  Widget *widget = *itr;
352 
353  widget->mWidgetManager = widgetManager;
354  widget->addedToManager(widgetManager);
355  ++itr;
356  }
357 }
358 
360 {
361  for (WidgetList::iterator itr = mWidgets.begin();
362  itr != mWidgets.end(); ++itr)
363  {
364  Widget *widget = *itr;
365 
366  widgetManager->disableWidget(widget);
367  widget->removedFromManager(widgetManager);
368  widget->mWidgetManager = NULL;
369  }
370 
371  if (widgetManager->mPopupCommandWidget == this)
372  widgetManager->mPopupCommandWidget = NULL;
373 }
374 
376 {
377 }
378 
380 {
381 }
382 
384 {
385 }
386 
388 {
389  AutoModalFlags autoModalFlags(flags, mWidgetFlagsMod);
390 
391  // Can update?
392  if (flags->GetFlags() & WIDGETFLAGS_UPDATE)
393  {
394  update(dt);
395  }
396 
397  int32_hf size = (int32_hf)mWidgets.size();
398  if (size > 0)
399  {
400  mUpdateIterator = mWidgets.begin();
401  while (mUpdateIterator != mWidgets.end())
402  {
403  mUpdateIteratorModified = false;
404 
405  Widget *widget = *mUpdateIterator;
406  if (widget == mWidgetManager->mBaseModalWidget)
407  flags->mIsOver = true;
408 
409  widget->updateAll(flags, dt);
410 
412  ++mUpdateIterator;
413  }
414  }
415 
416  // prevent incrementing iterator off the end of the list
418 }
419 
421 {
422 }
423 
425 {
428 
429  AutoModalFlags autoModalFlags(flags, mWidgetFlagsMod);
430 
431  if (mWidgets.size() == 0)
432  {
433  if (flags->GetFlags() & WIDGETFLAGS_DRAW)
434  draw(g);
435 
436  return;
437  }
438 
439  if (flags->GetFlags() & WIDGETFLAGS_DRAW)
440  {
441  draw(g);
442  }
443 
444  WidgetList::iterator itr = mWidgets.begin();
445  while (itr != mWidgets.end())
446  {
447  Widget *widget = *itr;
448 
449  if (widget->mVisible)
450  {
451  if (widget == mWidgetManager->mBaseModalWidget)
452  flags->mIsOver = true;
453 
454  widget->drawAll(flags, g);
455  }
456  ++itr;
457  }
458 }
459 
461 {
462  sysColorChanged();
463 
464  static int32_hf depthCount = 0;
465  if (mWidgets.size() > 0)
466  depthCount++;
467 
468  WidgetList::iterator itr = mWidgets.begin();
469  while (itr != mWidgets.end())
470  {
471  Widget *widget = *itr;
472 
473  widget->sysColorChangedAll();
474  ++itr;
475  }
476 }
477 
479 {
480 }
virtual Vector2 getAbsPos()
Get abs position relative to top level Widget.
virtual void sysColorChangedAll()
Call sysColorChanged() for all Widget&#39;s in internal list.
Widget * mPopupCommandWidget
Holds pointer to popup command Widget.
int32_hf mPriority
Holds Widget priority (not used!).
virtual void drawAll(ModalFlags *flags, Graphics *g)
Calls draw() for all Widget&#39;s in internal list which have WIDGETFLAGS_DRAW set in flags...
void widgetRemovedHelper()
Helper method for Widget removal and cleanup.
Definition: Widget.cpp:62
virtual void update(fp32_hf dt)
Called by the framework once for every iteration of the game loop, immediately before rendering takes...
WidgetList::iterator mUpdateIterator
WidgetContainer::WidgetList iterator.
WidgetContainer stores and handles Widget&#39;s.
virtual void sysColorChanged()
Handle sys color changed.
Widget * mBaseModalWidget
Holds pointer to base modal Widget.
bool mIsOver
Flag indicating if over or not.
Definition: Flags.h:101
Widget is a base class with core functionality for specialized Widget&#39;s to use / override / inherit f...
Definition: Widget.h:163
#define HF_SAFE_DELETE(p)
Check if not NULL, delete and set to NULL.
Definition: HFDataTypes.h:49
void rehupMouse()
Rehup Mouse (calls Widget::mouseLeave()) if needed for over Widget.
int int32_hf
A type definition for int.
Definition: HFDataTypes.h:349
FlagsMod mBelowModalFlagsMod
Holds below modal FlagsMod.
virtual ~WidgetContainer()
Destructor.
void disableWidget(Widget *widget)
Disable widget.
Widget * getWidgetAtHelper(fp32_hf x, fp32_hf y, int32_hf flags, bool *found, fp32_hf *widgetX, fp32_hf *widgetY)
Get Widget at x and y position which has flags set.
fp32_hf mX
Holds Widget X position.
void ModFlags(int32_hf &flags, const FlagsMod &flagMod)
Initiate flags.
Definition: Flags.h:64
bool mUpdateIteratorModified
Flag indicating if update iterator is modified or not.
virtual void draw(Graphics *g)
Called by the framework once for every iteration of the main loop.
virtual void disableWidget(Widget *widget)
Disable widget.
virtual void modalDialogOpen()
Called for DialogWidget&#39;s which has mIsModal flag set to true during WidgetManager::addDialog() call...
virtual void updateAll(ModalFlags *flags, fp32_hf dt)
Calls update() for all Widget&#39;s in internal list which have WIDGETFLAGS_UPDATE set in flags...
virtual bool contains(const Vector2 &point)
Check if a point collides or not.
Definition: Rect.cpp:54
virtual void removedFromManager(WidgetManager *widgetManager)
Call removedFromManager() for all Widget&#39;s in internal list.
virtual bool intersects(const Rect &rect)
Check is two Rect&#39;s intersect.
Definition: Rect.cpp:115
virtual void addedToManager(WidgetManager *widgetManager)
Call addedToManager() for all Widget&#39;s in internal list.
virtual void setFocus(Widget *widget)
Set focus on widget.
WidgetContainer stores and handles Widget&#39;s.
#define NULL
Convenient define for 0.
Definition: HFDataTypes.h:42
A two-dimensional floating point vector and associated math functions.
Definition: Vector2.h:42
virtual void removeAllWidgets(bool doDelete=false, bool recursive=false)
Remove all Widget&#39;s contained in internal list.
void flushDeferredOverlayWidgets(int32_hf maxPriority)
Calls Widget::drawOverlay() for all Widget&#39;s in internal WidgetManager::DeferredOverlayVector in prio...
Class for modal flags.
Definition: Flags.h:85
virtual void removeWidget(Widget *widget)
Remove a Widget and call removedFromManager().
virtual void orderInManagerChanged()
Method for controlling if order in manager has changed.
Definition: Widget.cpp:92
FlagsMod mWidgetFlagsMod
Holds Widget FlagsMod.
WidgetManager manages Widget&#39;s and interacts with Game interface.
virtual void addWidget(Widget *widget)
Adds a new Widget and call addedToManager().
int32_hf GetFlags()
Get flags.
Definition: Flags.h:120
virtual void bringToFront(Widget *widget)
Bring widget to front.
virtual void modalDialogClose()
Called for DialogWidget&#39;s which has mIsModal flag set to true during WidgetManager::killDialog() call...
virtual bool intersects(WidgetContainer *widget)
Determine whether widget intersects with *this.
virtual Rect getInsetRect()
Get Widget inset Rect.
Definition: Widget.cpp:407
virtual void putBehind(Widget *widget, Widget *refWidget)
Put widget behind refWidget.
virtual bool isBelow(Widget *widget1, Widget *widget2)
Determine whether widget1 is below widget2.
virtual void putInfront(Widget *widget, Widget *refWidget)
Put widget in front of refWidget.
Widget is a base class with core functionality for specialized Widget&#39;s to inherit from...
fp32_hf mY
Holds Widget Y position.
WidgetContainer()
Constructor.
int32_hf mZOrder
Holds Widget Z order.
virtual void bringToBack(Widget *widget)
Bring widget to back.
virtual bool hasWidget(Widget *widget)
Determine whether internal Widget list contains widget.
Definition: Actor.h:34
WidgetContainer * mParent
Pointer to parent WidgetContainer.
bool mClip
Flag indicating if Widget should be clipped or not.
Singleton interface for platform specific things.
bool mHasAlpha
Flag indicating if Widget has Alpha or not.
bool mVisible
Flag indicating if visible or not.
Definition: Widget.h:1045
Specialized Boundary representing a Rect.
Definition: Rect.h:34
virtual bool isPointVisible(int32_hf x, int32_hf y)
Determine whether a point is visible or not.
Definition: Widget.cpp:296
Interface for all rendering related things.
Definition: Graphics.h:120
WidgetManager manages Widget&#39;s and interacts with Game interface.
bool mMouseVisible
Flag indicating if mouse is visible or not.
Definition: Widget.h:1050
WidgetManager * mWidgetManager
Pointer to WidgetManager.
virtual Rect getRect()
Get Widget size Rect.
fp32_hf mWidth
Holds Widget width.
float fp32_hf
A type definition for float.
Definition: HFDataTypes.h:359
Class for auto modal flags.
Definition: Flags.h:129
int32_hf mMinDeferredOverlayPriority
Holds minimum deferred overlay priority.
fp32_hf mHeight
Holds Widget height.
WidgetList mWidgets
WidgetContainer::WidgetList holding child Widget&#39;s.