ManaPlus
basiccontainer.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2011-2018 The ManaPlus Developers
4  *
5  * This file is part of The ManaPlus Client.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /* _______ __ __ __ ______ __ __ _______ __ __
22  * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
23  * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
24  * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
25  * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
26  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
27  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
28  *
29  * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
30  *
31  *
32  * Per Larsson a.k.a finalman
33  * Olof Naessén a.k.a jansem/yakslem
34  *
35  * Visit: http://guichan.sourceforge.net
36  *
37  * License: (BSD)
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  * notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  * notice, this list of conditions and the following disclaimer in
45  * the documentation and/or other materials provided with the
46  * distribution.
47  * 3. Neither the name of Guichan nor the names of its contributors may
48  * be used to endorse or promote products derived from this software
49  * without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
57  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
58  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
59  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
60  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
65 
66 #include "utils/foreach.h"
67 
68 #include "render/graphics.h"
69 
70 #include <algorithm>
71 
72 #include "debug.h"
73 
75 {
76  clear();
77 }
78 
80 {
82  {
83  if (*iter == widget)
84  {
85  mWidgets.erase(iter);
86  mWidgets.push_back(widget);
87  break;
88  }
89  }
91  {
92  if (*iter == widget)
93  {
94  mLogicWidgets.erase(iter);
95  mLogicWidgets.push_back(widget);
96  return;
97  }
98  }
99 }
100 
102 {
103  const WidgetListIterator iter = std::find(mWidgets.begin(),
104  mWidgets.end(), widget);
105  if (iter != mWidgets.end())
106  {
107  mWidgets.erase(iter);
108  mWidgets.insert(mWidgets.begin(), widget);
109  }
110 
111  const WidgetListIterator iter2 = std::find(mLogicWidgets.begin(),
112  mLogicWidgets.end(), widget);
113  if (iter2 != mLogicWidgets.end())
114  {
115  mLogicWidgets.erase(iter2);
116  mLogicWidgets.insert(mLogicWidgets.begin(), widget);
117  }
118 }
119 
121 {
122  const WidgetListIterator iter = std::find(mWidgets.begin(),
123  mWidgets.end(), event.getSource());
124  if (iter != mWidgets.end())
125  mWidgets.erase(iter);
126 
127  const WidgetListIterator iter2 = std::find(mLogicWidgets.begin(),
128  mLogicWidgets.end(), event.getSource());
129  if (iter2 != mLogicWidgets.end())
130  mLogicWidgets.erase(iter2);
131 }
132 
134 {
135  return Rect(0, 0, mDimension.width, mDimension.height);
136 }
137 
139 {
141 
142  for (it = mWidgets.begin(); it != mWidgets.end(); ++ it)
143  {
144  if ((*it)->isFocused())
145  break;
146  }
147 
148  const WidgetListConstIterator end = it;
149 
150  if (it == mWidgets.end())
151  it = mWidgets.begin();
152 
153  ++ it;
154 
155  for ( ; it != end; ++ it)
156  {
157  if (it == mWidgets.end())
158  it = mWidgets.begin();
159 
160  if ((*it)->isFocusable())
161  {
162  (*it)->requestFocus();
163  return;
164  }
165  }
166 }
167 
169 {
171 
172  for (it = mWidgets.rbegin(); it != mWidgets.rend(); ++ it)
173  {
174  if ((*it)->isFocused())
175  break;
176  }
177 
178  const WidgetListReverseIterator end = it;
179 
180  ++ it;
181 
182  if (it == mWidgets.rend())
183  it = mWidgets.rbegin();
184 
185  for ( ; it != end; ++ it)
186  {
187  if (it == mWidgets.rend())
188  it = mWidgets.rbegin();
189 
190  if ((*it)->isFocusable())
191  {
192  (*it)->requestFocus();
193  return;
194  }
195  }
196 }
197 
199 {
200  const Rect r = getChildrenArea();
201 
202  if (!r.isPointInRect(x, y))
203  return nullptr;
204 
205  x -= r.x;
206  y -= r.y;
207 
208  for (WidgetListReverseIterator it = mWidgets.rbegin();
209  it != mWidgets.rend(); ++ it)
210  {
211  const Widget *restrict const widget = *it;
212  if (widget->isVisible() &&
213  widget->getDimension().isPointInRect(x, y))
214  {
215  return *it;
216  }
217  }
218 
219  return nullptr;
220 }
221 
223 {
224  BLOCK_START("BasicContainer::logic")
225  if (mVisible == Visible_false)
226  {
227  BLOCK_END("BasicContainer::logic")
228  return;
229  }
230  logicChildren();
231  BLOCK_END("BasicContainer::logic")
232 }
233 
235  focusHandler) restrict2
236 {
237  Widget::setFocusHandler(focusHandler);
238 
239  if (mInternalFocusHandler != nullptr)
240  return;
241 
243  (*iter)->setFocusHandler(focusHandler);
244 }
245 
247 {
248  if (widget == nullptr)
249  return;
250  mWidgets.push_back(widget);
251  if (widget->isAllowLogic())
252  mLogicWidgets.push_back(widget);
253 
254  if (mInternalFocusHandler == nullptr)
255  widget->setFocusHandler(getFocusHandler());
256  else
257  widget->setFocusHandler(mInternalFocusHandler);
258 
259  widget->setParent(this);
260  widget->addDeathListener(this);
261 }
262 
264 {
265  if (widget == nullptr)
266  return;
268  {
269  if (*iter == widget)
270  {
271  mWidgets.erase(iter);
272  widget->setFocusHandler(nullptr);
273  widget->setWindow(nullptr);
274  widget->setParent(nullptr);
275  widget->removeDeathListener(this);
276  break;
277  }
278  }
280  {
281  if (*iter == widget)
282  {
283  mLogicWidgets.erase(iter);
284  return;
285  }
286  }
287 }
288 
290 {
292  {
293  Widget *restrict const widget = *iter;
294  widget->setFocusHandler(nullptr);
295  widget->setWindow(nullptr);
296  widget->setParent(nullptr);
297  widget->removeDeathListener(this);
298  }
299 
300  mWidgets.clear();
301  mLogicWidgets.clear();
302 }
303 
305 {
306  BLOCK_START("BasicContainer::drawChildren")
307  graphics->pushClipArea(getChildrenArea());
308 
310  {
311  Widget *restrict const widget = *iter;
312  if (widget->mVisible == Visible_true)
313  {
314  // If the widget has a frame,
315  // draw it before drawing the widget
316  if (widget->mFrameSize > 0)
317  {
318  Rect rec = widget->mDimension;
319  const int frame = CAST_S32(widget->mFrameSize);
320  const int frame2 = frame * 2;
321  rec.x -= frame;
322  rec.y -= frame;
323  rec.width += frame2;
324  rec.height += frame2;
325  graphics->pushClipArea(rec);
326  BLOCK_START("BasicContainer::drawChildren 1")
327  widget->drawFrame(graphics);
328  BLOCK_END("BasicContainer::drawChildren 1")
329  graphics->popClipArea();
330  }
331 
332  graphics->pushClipArea(widget->mDimension);
333  BLOCK_START("BasicContainer::drawChildren 2")
334  widget->draw(graphics);
335  BLOCK_END("BasicContainer::drawChildren 2")
336  graphics->popClipArea();
337  }
338  }
339 
340  graphics->popClipArea();
341  BLOCK_END("BasicContainer::drawChildren")
342 }
343 
345  restrict2
346 {
347  BLOCK_START("BasicContainer::drawChildren")
348  graphics->pushClipArea(getChildrenArea());
349 
351  {
352  Widget *restrict const widget = *iter;
353  if (widget->mVisible == Visible_true)
354  {
355  // If the widget has a frame,
356  // draw it before drawing the widget
357  if (widget->mFrameSize > 0)
358  {
359  Rect rec = widget->mDimension;
360  const int frame = CAST_S32(widget->mFrameSize);
361  const int frame2 = frame * 2;
362  rec.x -= frame;
363  rec.y -= frame;
364  rec.width += frame2;
365  rec.height += frame2;
366  graphics->pushClipArea(rec);
367  BLOCK_START("BasicContainer::drawChildren 1")
368  widget->safeDrawFrame(graphics);
369  BLOCK_END("BasicContainer::drawChildren 1")
370  graphics->popClipArea();
371  }
372 
373  graphics->pushClipArea(widget->mDimension);
374  BLOCK_START("BasicContainer::drawChildren 2")
375  widget->safeDraw(graphics);
376  BLOCK_END("BasicContainer::drawChildren 2")
377  graphics->popClipArea();
378  }
379  }
380 
381  graphics->popClipArea();
382  BLOCK_END("BasicContainer::drawChildren")
383 }
384 
386 {
387  BLOCK_START("BasicContainer::logicChildren")
389  (*iter)->logic();
390  BLOCK_END("BasicContainer::logicChildren")
391 }
392 
394  const Rect &restrict area) restrict2
395 {
396  if (widget == nullptr)
397  return;
398 
399  const Rect widgetArea = getChildrenArea();
400 
401  const int x = widget->mDimension.x;
402  const int y = widget->mDimension.y;
403  const int ax = area.x + x;
404  const int ay = area.y + y;
405 
406  if (ax < 0)
407  widget->setX(-area.x);
408  else if (ax + area.width > widgetArea.width)
409  widget->setX(widgetArea.width - area.x - area.width);
410 
411  if (ay < 0)
412  widget->setY(-area.y);
413  else if (ay + area.height > widgetArea.height)
414  widget->setY(widgetArea.height - area.y - area.height);
415 }
416 
418  focusHandler) restrict2
419 {
420  Widget::setInternalFocusHandler(focusHandler);
421 
422  FocusHandler *const restrict handler = mInternalFocusHandler != nullptr ?
425  {
426  (*iter)->setFocusHandler(handler);
427  }
428 }
429 
430 Widget *BasicContainer::findFirstWidget(const std::set<Widget*> &restrict list)
431  restrict2
432 {
434  {
435  if (list.find(*iter) != list.end())
436  return *iter;
437  }
438  return nullptr;
439 }
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
void showWidgetPart(Widget *const widget, const Rect &area)
int width
Definition: rect.h:218
void moveToBottom(Widget *const widget)
const bool Visible_true
Definition: visible.h:29
WidgetList::const_iterator WidgetListConstIterator
Widget * findFirstWidget(const std::set< Widget *> &list)
Definition: rect.h:72
#define BLOCK_START(name)
Definition: perfomance.h:78
bool isPointInRect(const int x_, const int y_) const
Definition: rect.h:196
FocusHandler * getFocusHandler()
Definition: widget.h:473
#define BLOCK_END(name)
Definition: perfomance.h:79
WidgetList mLogicWidgets
#define FOR_EACHR(type, iter, array)
Definition: foreach.h:27
virtual void clear()
bool find(const std::string &key)
Visible mVisible
Definition: widget.h:962
Widget * getWidgetAt(int x, int y)
int x
Definition: rect.h:208
#define CAST_S32
Definition: cast.h:29
const bool Visible_false
Definition: visible.h:29
WidgetList::reverse_iterator WidgetListReverseIterator
int y
Definition: rect.h:213
virtual void logicChildren()
void moveToTop(Widget *const widget)
void add(Widget *const widget)
virtual void remove(Widget *const widget)
FocusHandler * mInternalFocusHandler
Definition: widget.h:1121
void setFocusHandler(FocusHandler *const focusHandler)
int height
Definition: rect.h:223
Definition: widget.h:97
virtual void drawChildren(Graphics *const graphics)
Definition: event.h:77
void setInternalFocusHandler(FocusHandler *const focusHandler)
void death(const Event &event)
#define restrict
Definition: localconsts.h:176
WidgetList mWidgets
virtual void setFocusHandler(FocusHandler *const focusHandler)
Definition: widget.cpp:237
void setInternalFocusHandler(FocusHandler *const internalFocusHandler)
Definition: widget.cpp:460
Rect mDimension
Definition: widget.h:1100
virtual void safeDrawChildren(Graphics *const graphics)
#define restrict2
Definition: localconsts.h:177
WidgetList::iterator WidgetListIterator