comparison ext/guichan-0.8.1/src/basiccontainer.cpp @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
1 /* _______ __ __ __ ______ __ __ _______ __ __
2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
8 *
9 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
10 *
11 *
12 * Per Larsson a.k.a finalman
13 * Olof Naessén a.k.a jansem/yakslem
14 *
15 * Visit: http://guichan.sourceforge.net
16 *
17 * License: (BSD)
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in
25 * the documentation and/or other materials provided with the
26 * distribution.
27 * 3. Neither the name of Guichan nor the names of its contributors may
28 * be used to endorse or promote products derived from this software
29 * without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43
44 /*
45 * For comments regarding functions please see the header file.
46 */
47
48 #include "guichan/basiccontainer.hpp"
49
50 #include <algorithm>
51
52 #include "guichan/exception.hpp"
53 #include "guichan/focushandler.hpp"
54 #include "guichan/graphics.hpp"
55 #include "guichan/mouseinput.hpp"
56
57 namespace gcn
58 {
59 BasicContainer::~BasicContainer()
60 {
61 clear();
62 }
63
64 void BasicContainer::moveToTop(Widget* widget)
65 {
66 WidgetListIterator iter;
67 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
68 {
69 if (*iter == widget)
70 {
71 mWidgets.erase(iter);
72 mWidgets.push_back(widget);
73 return;
74 }
75 }
76
77 throw GCN_EXCEPTION("There is no such widget in this container.");
78 }
79
80 void BasicContainer::moveToBottom(Widget* widget)
81 {
82 WidgetListIterator iter;
83 iter = find(mWidgets.begin(), mWidgets.end(), widget);
84
85 if (iter == mWidgets.end())
86 {
87 throw GCN_EXCEPTION("There is no such widget in this container.");
88 }
89 mWidgets.erase(iter);
90 mWidgets.push_front(widget);
91 }
92
93 void BasicContainer::death(const Event& event)
94 {
95 WidgetListIterator iter;
96 iter = find(mWidgets.begin(), mWidgets.end(), event.getSource());
97
98 if (iter == mWidgets.end())
99 {
100 throw GCN_EXCEPTION("There is no such widget in this container.");
101 }
102
103 mWidgets.erase(iter);
104 }
105
106 Rectangle BasicContainer::getChildrenArea()
107 {
108 return Rectangle(0, 0, getWidth(), getHeight());
109 }
110
111 void BasicContainer::focusNext()
112 {
113 WidgetListIterator it;
114
115 for (it = mWidgets.begin(); it != mWidgets.end(); it++)
116 {
117 if ((*it)->isFocused())
118 {
119 break;
120 }
121 }
122
123 WidgetListIterator end = it;
124
125 if (it == mWidgets.end())
126 {
127 it = mWidgets.begin();
128 }
129
130 it++;
131
132 for ( ; it != end; it++)
133 {
134 if (it == mWidgets.end())
135 {
136 it = mWidgets.begin();
137 }
138
139 if ((*it)->isFocusable())
140 {
141 (*it)->requestFocus();
142 return;
143 }
144 }
145 }
146
147 void BasicContainer::focusPrevious()
148 {
149 WidgetListReverseIterator it;
150
151 for (it = mWidgets.rbegin(); it != mWidgets.rend(); it++)
152 {
153 if ((*it)->isFocused())
154 {
155 break;
156 }
157 }
158
159 WidgetListReverseIterator end = it;
160
161 it++;
162
163 if (it == mWidgets.rend())
164 {
165 it = mWidgets.rbegin();
166 }
167
168 for ( ; it != end; it++)
169 {
170 if (it == mWidgets.rend())
171 {
172 it = mWidgets.rbegin();
173 }
174
175 if ((*it)->isFocusable())
176 {
177 (*it)->requestFocus();
178 return;
179 }
180 }
181 }
182
183 Widget *BasicContainer::getWidgetAt(int x, int y)
184 {
185 Rectangle r = getChildrenArea();
186
187 if (!r.isPointInRect(x, y))
188 {
189 return NULL;
190 }
191
192 x -= r.x;
193 y -= r.y;
194
195 WidgetListReverseIterator it;
196 for (it = mWidgets.rbegin(); it != mWidgets.rend(); it++)
197 {
198 if ((*it)->isVisible() && (*it)->getDimension().isPointInRect(x, y))
199 {
200 return (*it);
201 }
202 }
203
204 return NULL;
205 }
206
207 void BasicContainer::logic()
208 {
209 logicChildren();
210 }
211
212 void BasicContainer::_setFocusHandler(FocusHandler* focusHandler)
213 {
214 Widget::_setFocusHandler(focusHandler);
215
216 if (mInternalFocusHandler != NULL)
217 {
218 return;
219 }
220
221 WidgetListIterator iter;
222 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
223 {
224 (*iter)->_setFocusHandler(focusHandler);
225 }
226 }
227
228 void BasicContainer::add(Widget* widget)
229 {
230 mWidgets.push_back(widget);
231
232 if (mInternalFocusHandler == NULL)
233 {
234 widget->_setFocusHandler(_getFocusHandler());
235 }
236 else
237 {
238 widget->_setFocusHandler(mInternalFocusHandler);
239 }
240
241 widget->_setParent(this);
242 widget->addDeathListener(this);
243 }
244
245 void BasicContainer::remove(Widget* widget)
246 {
247 WidgetListIterator iter;
248 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
249 {
250 if (*iter == widget)
251 {
252 mWidgets.erase(iter);
253 widget->_setFocusHandler(NULL);
254 widget->_setParent(NULL);
255 widget->removeDeathListener(this);
256 return;
257 }
258 }
259
260 throw GCN_EXCEPTION("There is no such widget in this container.");
261 }
262
263 void BasicContainer::clear()
264 {
265 WidgetListIterator iter;
266
267 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
268 {
269 (*iter)->_setFocusHandler(NULL);
270 (*iter)->_setParent(NULL);
271 (*iter)->removeDeathListener(this);
272 }
273
274 mWidgets.clear();
275 }
276
277 void BasicContainer::drawChildren(Graphics* graphics)
278 {
279 graphics->pushClipArea(getChildrenArea());
280
281 WidgetListIterator iter;
282 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
283 {
284 if ((*iter)->isVisible())
285 {
286 // If the widget has a frame,
287 // draw it before drawing the widget
288 if ((*iter)->getFrameSize() > 0)
289 {
290 Rectangle rec = (*iter)->getDimension();
291 rec.x -= (*iter)->getFrameSize();
292 rec.y -= (*iter)->getFrameSize();
293 rec.width += 2 * (*iter)->getFrameSize();
294 rec.height += 2 * (*iter)->getFrameSize();
295 graphics->pushClipArea(rec);
296 (*iter)->drawFrame(graphics);
297 graphics->popClipArea();
298 }
299
300 graphics->pushClipArea((*iter)->getDimension());
301 (*iter)->draw(graphics);
302 graphics->popClipArea();
303 }
304 }
305
306 graphics->popClipArea();
307 }
308
309 void BasicContainer::logicChildren()
310 {
311 WidgetListIterator iter;
312 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
313 {
314 (*iter)->logic();
315 }
316 }
317
318 void BasicContainer::showWidgetPart(Widget* widget, Rectangle area)
319 {
320 Rectangle widgetArea = getChildrenArea();
321
322 area.x += widget->getX();
323 area.y += widget->getY();
324
325 if (area.x + area.width > widgetArea.width)
326 {
327 widget->setX(widget->getX() - area.x - area.width + widgetArea.width);
328 }
329
330 if (area.y + area.height > widgetArea.height)
331 {
332 widget->setY(widget->getY() - area.y - area.height + widgetArea.height);
333 }
334
335 if (area.x < 0)
336 {
337 widget->setX(widget->getX() - area.x);
338 }
339
340 if (area.y < 0)
341 {
342 widget->setY(widget->getY() - area.y);
343 }
344 }
345
346
347 void BasicContainer::setInternalFocusHandler(FocusHandler* focusHandler)
348 {
349 Widget::setInternalFocusHandler(focusHandler);
350
351 WidgetListIterator iter;
352 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
353 {
354 if (mInternalFocusHandler == NULL)
355 {
356 (*iter)->_setFocusHandler(_getFocusHandler());
357 }
358 else
359 {
360 (*iter)->_setFocusHandler(mInternalFocusHandler);
361 }
362 }
363 }
364
365 Widget* BasicContainer::findWidgetById(const std::string& id)
366 {
367 WidgetListIterator iter;
368 for (iter = mWidgets.begin(); iter != mWidgets.end(); iter++)
369 {
370 if ((*iter)->getId() == id)
371 {
372 return (*iter);
373 }
374
375 BasicContainer *basicContainer = dynamic_cast<BasicContainer*>(*iter);
376
377 if (basicContainer != NULL)
378 {
379 Widget *widget = basicContainer->findWidgetById(id);
380
381 if (widget != NULL)
382 {
383 return widget;
384 }
385 }
386 }
387
388 return NULL;
389 }
390 }