comparison ext/guichan-0.8.2/src/basiccontainer.cpp @ 378:64738befdf3b

bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 11 Jan 2010 23:34:52 +0000
parents
children
comparison
equal deleted inserted replaced
377:fe6fb0e0ed23 378:64738befdf3b
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 }