aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CGUIComboBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CGUIComboBox.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CGUIComboBox.cpp523
1 files changed, 523 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CGUIComboBox.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CGUIComboBox.cpp
new file mode 100644
index 0000000..44d92e4
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CGUIComboBox.cpp
@@ -0,0 +1,523 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CGUIComboBox.h"
6#ifdef _IRR_COMPILE_WITH_GUI_
7
8#include "IGUIEnvironment.h"
9#include "IVideoDriver.h"
10#include "IGUISkin.h"
11#include "IGUIEnvironment.h"
12#include "IGUIFont.h"
13#include "IGUIButton.h"
14#include "CGUIListBox.h"
15#include "os.h"
16
17namespace irr
18{
19namespace gui
20{
21
22//! constructor
23CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
24 s32 id, core::rect<s32> rectangle)
25 : IGUIComboBox(environment, parent, id, rectangle),
26 ListButton(0), SelectedText(0), ListBox(0), LastFocus(0),
27 Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false)
28{
29 #ifdef _DEBUG
30 setDebugName("CGUIComboBox");
31 #endif
32
33 IGUISkin* skin = Environment->getSkin();
34
35 s32 width = 15;
36 if (skin)
37 width = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
38
39 core::rect<s32> r;
40 r.UpperLeftCorner.X = rectangle.getWidth() - width - 2;
41 r.LowerRightCorner.X = rectangle.getWidth() - 2;
42
43 r.UpperLeftCorner.Y = 2;
44 r.LowerRightCorner.Y = rectangle.getHeight() - 2;
45
46 ListButton = Environment->addButton(r, this, -1, L"");
47 if (skin && skin->getSpriteBank())
48 {
49 ListButton->setSpriteBank(skin->getSpriteBank());
50 ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
51 ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
52 }
53 ListButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
54 ListButton->setSubElement(true);
55 ListButton->setTabStop(false);
56
57 r.UpperLeftCorner.X = 2;
58 r.UpperLeftCorner.Y = 2;
59 r.LowerRightCorner.X = RelativeRect.getWidth() - (ListButton->getAbsolutePosition().getWidth() + 2);
60 r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
61
62 SelectedText = Environment->addStaticText(L"", r, false, false, this, -1, false);
63 SelectedText->setSubElement(true);
64 SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
65 SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
66 if (skin)
67 SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT));
68 SelectedText->enableOverrideColor(true);
69
70 // this element can be tabbed to
71 setTabStop(true);
72 setTabOrder(-1);
73}
74
75
76void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
77{
78 HAlign = horizontal;
79 VAlign = vertical;
80 SelectedText->setTextAlignment(horizontal, vertical);
81}
82
83
84//! Set the maximal number of rows for the selection listbox
85void CGUIComboBox::setMaxSelectionRows(u32 max)
86{
87 MaxSelectionRows = max;
88
89 // force recalculation of open listbox
90 if (ListBox)
91 {
92 openCloseMenu();
93 openCloseMenu();
94 }
95}
96
97//! Get the maximimal number of rows for the selection listbox
98u32 CGUIComboBox::getMaxSelectionRows() const
99{
100 return MaxSelectionRows;
101}
102
103
104//! Returns amount of items in box
105u32 CGUIComboBox::getItemCount() const
106{
107 return Items.size();
108}
109
110
111//! returns string of an item. the idx may be a value from 0 to itemCount-1
112const wchar_t* CGUIComboBox::getItem(u32 idx) const
113{
114 if (idx >= Items.size())
115 return 0;
116
117 return Items[idx].Name.c_str();
118}
119
120//! returns string of an item. the idx may be a value from 0 to itemCount-1
121u32 CGUIComboBox::getItemData(u32 idx) const
122{
123 if (idx >= Items.size())
124 return 0;
125
126 return Items[idx].Data;
127}
128
129//! Returns index based on item data
130s32 CGUIComboBox::getIndexForItemData(u32 data ) const
131{
132 for ( u32 i = 0; i < Items.size (); ++i )
133 {
134 if ( Items[i].Data == data )
135 return i;
136 }
137 return -1;
138}
139
140
141//! Removes an item from the combo box.
142void CGUIComboBox::removeItem(u32 idx)
143{
144 if (idx >= Items.size())
145 return;
146
147 if (Selected == (s32)idx)
148 setSelected(-1);
149
150 Items.erase(idx);
151}
152
153
154//! Returns caption of this element.
155const wchar_t* CGUIComboBox::getText() const
156{
157 return getItem(Selected);
158}
159
160
161//! adds an item and returns the index of it
162u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
163{
164 Items.push_back( SComboData ( text, data ) );
165
166 if (Selected == -1)
167 setSelected(0);
168
169 return Items.size() - 1;
170}
171
172
173//! deletes all items in the combo box
174void CGUIComboBox::clear()
175{
176 Items.clear();
177 setSelected(-1);
178}
179
180
181//! returns id of selected item. returns -1 if no item is selected.
182s32 CGUIComboBox::getSelected() const
183{
184 return Selected;
185}
186
187
188//! sets the selected item. Set this to -1 if no item should be selected
189void CGUIComboBox::setSelected(s32 idx)
190{
191 if (idx < -1 || idx >= (s32)Items.size())
192 return;
193
194 Selected = idx;
195 if (Selected == -1)
196 SelectedText->setText(L"");
197 else
198 SelectedText->setText(Items[Selected].Name.c_str());
199}
200
201
202//! called if an event happened.
203bool CGUIComboBox::OnEvent(const SEvent& event)
204{
205 if (isEnabled())
206 {
207 switch(event.EventType)
208 {
209
210 case EET_KEY_INPUT_EVENT:
211 if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
212 {
213 // hide list box
214 openCloseMenu();
215 return true;
216 }
217 else
218 if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)
219 {
220 if (!event.KeyInput.PressedDown)
221 {
222 openCloseMenu();
223 }
224
225 ListButton->setPressed(ListBox == 0);
226
227 return true;
228 }
229 else
230 if (event.KeyInput.PressedDown)
231 {
232 s32 oldSelected = Selected;
233 bool absorb = true;
234 switch (event.KeyInput.Key)
235 {
236 case KEY_DOWN:
237 setSelected(Selected+1);
238 break;
239 case KEY_UP:
240 setSelected(Selected-1);
241 break;
242 case KEY_HOME:
243 case KEY_PRIOR:
244 setSelected(0);
245 break;
246 case KEY_END:
247 case KEY_NEXT:
248 setSelected((s32)Items.size()-1);
249 break;
250 default:
251 absorb = false;
252 }
253
254 if (Selected <0)
255 setSelected(0);
256
257 if (Selected >= (s32)Items.size())
258 setSelected((s32)Items.size() -1);
259
260 if (Selected != oldSelected)
261 {
262 sendSelectionChangedEvent();
263 return true;
264 }
265
266 if (absorb)
267 return true;
268 }
269 break;
270
271 case EET_GUI_EVENT:
272
273 switch(event.GUIEvent.EventType)
274 {
275 case EGET_ELEMENT_FOCUS_LOST:
276 if (ListBox &&
277 (Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
278 event.GUIEvent.Element != this &&
279 !isMyChild(event.GUIEvent.Element) &&
280 !ListBox->isMyChild(event.GUIEvent.Element))
281 {
282 openCloseMenu();
283 }
284 break;
285 case EGET_BUTTON_CLICKED:
286 if (event.GUIEvent.Caller == ListButton)
287 {
288 openCloseMenu();
289 return true;
290 }
291 break;
292 case EGET_LISTBOX_SELECTED_AGAIN:
293 case EGET_LISTBOX_CHANGED:
294 if (event.GUIEvent.Caller == ListBox)
295 {
296 setSelected(ListBox->getSelected());
297 if (Selected <0 || Selected >= (s32)Items.size())
298 setSelected(-1);
299 openCloseMenu();
300
301 sendSelectionChangedEvent();
302 }
303 return true;
304 default:
305 break;
306 }
307 break;
308 case EET_MOUSE_INPUT_EVENT:
309
310 switch(event.MouseInput.Event)
311 {
312 case EMIE_LMOUSE_PRESSED_DOWN:
313 {
314 core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
315
316 // send to list box
317 if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
318 return true;
319
320 return true;
321 }
322 case EMIE_LMOUSE_LEFT_UP:
323 {
324 core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
325
326 // send to list box
327 if (!(ListBox &&
328 ListBox->getAbsolutePosition().isPointInside(p) &&
329 ListBox->OnEvent(event)))
330 {
331 openCloseMenu();
332 }
333 return true;
334 }
335 case EMIE_MOUSE_WHEEL:
336 {
337 s32 oldSelected = Selected;
338 setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));
339
340 if (Selected <0)
341 setSelected(0);
342
343 if (Selected >= (s32)Items.size())
344 setSelected((s32)Items.size() -1);
345
346 if (Selected != oldSelected)
347 {
348 sendSelectionChangedEvent();
349 return true;
350 }
351 }
352 default:
353 break;
354 }
355 break;
356 default:
357 break;
358 }
359 }
360
361 return IGUIElement::OnEvent(event);
362}
363
364
365void CGUIComboBox::sendSelectionChangedEvent()
366{
367 if (Parent)
368 {
369 SEvent event;
370
371 event.EventType = EET_GUI_EVENT;
372 event.GUIEvent.Caller = this;
373 event.GUIEvent.Element = 0;
374 event.GUIEvent.EventType = EGET_COMBO_BOX_CHANGED;
375 Parent->OnEvent(event);
376 }
377}
378
379
380//! draws the element and its children
381void CGUIComboBox::draw()
382{
383 if (!IsVisible)
384 return;
385
386 IGUISkin* skin = Environment->getSkin();
387 IGUIElement *currentFocus = Environment->getFocus();
388 if (currentFocus != LastFocus)
389 {
390 HasFocus = currentFocus == this || isMyChild(currentFocus);
391 LastFocus = currentFocus;
392 }
393
394 // set colors each time as skin-colors can be changed
395 SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
396 if(isEnabled())
397 {
398 SelectedText->setDrawBackground(HasFocus);
399 SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
400 }
401 else
402 {
403 SelectedText->setDrawBackground(false);
404 SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
405 }
406 ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
407 ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
408
409
410 core::rect<s32> frameRect(AbsoluteRect);
411
412 // draw the border
413
414 skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
415 true, true, frameRect, &AbsoluteClippingRect);
416
417 // draw children
418 IGUIElement::draw();
419}
420
421
422void CGUIComboBox::openCloseMenu()
423{
424 if (ListBox)
425 {
426 // close list box
427 Environment->setFocus(this);
428 ListBox->remove();
429 ListBox = 0;
430 }
431 else
432 {
433 if (Parent)
434 Parent->bringToFront(this);
435
436 IGUISkin* skin = Environment->getSkin();
437 u32 h = Items.size();
438
439 if (h > getMaxSelectionRows())
440 h = getMaxSelectionRows();
441 if (h == 0)
442 h = 1;
443
444 IGUIFont* font = skin->getFont();
445 if (font)
446 h *= (font->getDimension(L"A").Height + 4);
447
448 // open list box
449 core::rect<s32> r(0, AbsoluteRect.getHeight(),
450 AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);
451
452 ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
453 ListBox->setSubElement(true);
454 ListBox->setNotClipped(true);
455 ListBox->drop();
456
457 // ensure that list box is always completely visible
458 if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
459 ListBox->setRelativePosition( core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) );
460
461 for (s32 i=0; i<(s32)Items.size(); ++i)
462 ListBox->addItem(Items[i].Name.c_str());
463
464 ListBox->setSelected(Selected);
465
466 // set focus
467 Environment->setFocus(ListBox);
468 }
469}
470
471
472//! Writes attributes of the element.
473void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
474{
475 IGUIComboBox::serializeAttributes(out,options);
476
477 out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
478 out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
479 out->addInt("MaxSelectionRows", (s32)MaxSelectionRows );
480
481 out->addInt ("Selected", Selected );
482 out->addInt ("ItemCount", Items.size());
483 for (u32 i=0; i < Items.size(); ++i)
484 {
485 core::stringc s = "Item";
486 s += i;
487 s += "Text";
488 out->addString(s.c_str(), Items[i].Name.c_str());
489 }
490}
491
492
493//! Reads attributes of the element
494void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
495{
496 IGUIComboBox::deserializeAttributes(in,options);
497
498 setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
499 (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
500 setMaxSelectionRows( (u32)(in->getAttributeAsInt("MaxSelectionRows")) );
501
502 // clear the list
503 clear();
504 // get item count
505 u32 c = in->getAttributeAsInt("ItemCount");
506 // add items
507 for (u32 i=0; i < c; ++i)
508 {
509 core::stringc s = "Item";
510 s += i;
511 s += "Text";
512 addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0);
513 }
514
515 setSelected(in->getAttributeAsInt("Selected"));
516}
517
518} // end namespace gui
519} // end namespace irr
520
521
522#endif // _IRR_COMPILE_WITH_GUI_
523