]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CGUIListBox.cpp
Drop _IRR_COMPILE_WITH_GUI_
[irrlicht.git] / source / Irrlicht / CGUIListBox.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "CGUIListBox.h"\r
6 \r
7 #include "CGUIListBox.h"\r
8 #include "IGUISkin.h"\r
9 #include "IGUIEnvironment.h"\r
10 #include "IVideoDriver.h"\r
11 #include "IGUIFont.h"\r
12 #include "IGUISpriteBank.h"\r
13 #include "CGUIScrollBar.h"\r
14 #include "os.h"\r
15 \r
16 namespace irr\r
17 {\r
18 namespace gui\r
19 {\r
20 \r
21 //! constructor\r
22 CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,\r
23                         s32 id, core::rect<s32> rectangle, bool clip,\r
24                         bool drawBack, bool moveOverSelect)\r
25 : IGUIListBox(environment, parent, id, rectangle), Selected(-1),\r
26         ItemHeight(0),ItemHeightOverride(0),\r
27         TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),\r
28         ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack),\r
29         MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true)\r
30 {\r
31         #ifdef _DEBUG\r
32         setDebugName("CGUIListBox");\r
33         #endif\r
34 \r
35         IGUISkin* skin = Environment->getSkin();\r
36 \r
37         ScrollBar = new CGUIScrollBar(false, Environment, this, -1,\r
38                 core::recti(0, 0, 1, 1),\r
39                 !clip);\r
40         ScrollBar->setSubElement(true);\r
41         ScrollBar->setTabStop(false);\r
42         ScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);\r
43         ScrollBar->setVisible(false);\r
44         ScrollBar->setPos(0);\r
45 \r
46         updateScrollBarSize(skin->getSize(EGDS_SCROLLBAR_SIZE));\r
47 \r
48         setNotClipped(!clip);\r
49 \r
50         // this element can be tabbed to\r
51         setTabStop(true);\r
52         setTabOrder(-1);\r
53 \r
54         updateAbsolutePosition();\r
55 }\r
56 \r
57 \r
58 //! destructor\r
59 CGUIListBox::~CGUIListBox()\r
60 {\r
61         if (ScrollBar)\r
62                 ScrollBar->drop();\r
63 \r
64         if (Font)\r
65                 Font->drop();\r
66 \r
67         if (IconBank)\r
68                 IconBank->drop();\r
69 }\r
70 \r
71 \r
72 //! returns amount of list items\r
73 u32 CGUIListBox::getItemCount() const\r
74 {\r
75         return Items.size();\r
76 }\r
77 \r
78 \r
79 //! returns string of a list item. the may be a value from 0 to itemCount-1\r
80 const wchar_t* CGUIListBox::getListItem(u32 id) const\r
81 {\r
82         if (id>=Items.size())\r
83                 return 0;\r
84 \r
85         return Items[id].Text.c_str();\r
86 }\r
87 \r
88 \r
89 //! Returns the icon of an item\r
90 s32 CGUIListBox::getIcon(u32 id) const\r
91 {\r
92         if (id>=Items.size())\r
93                 return -1;\r
94 \r
95         return Items[id].Icon;\r
96 }\r
97 \r
98 \r
99 //! adds a list item, returns id of item\r
100 u32 CGUIListBox::addItem(const wchar_t* text)\r
101 {\r
102         return addItem(text, -1);\r
103 }\r
104 \r
105 \r
106 //! adds a list item, returns id of item\r
107 void CGUIListBox::removeItem(u32 id)\r
108 {\r
109         if (id >= Items.size())\r
110                 return;\r
111 \r
112         if ((u32)Selected==id)\r
113         {\r
114                 Selected = -1;\r
115         }\r
116         else if ((u32)Selected > id)\r
117         {\r
118                 Selected -= 1;\r
119                 selectTime = os::Timer::getTime();\r
120         }\r
121 \r
122         Items.erase(id);\r
123 \r
124         recalculateItemHeight();\r
125 }\r
126 \r
127 \r
128 s32 CGUIListBox::getItemAt(s32 xpos, s32 ypos) const\r
129 {\r
130         if (    xpos < AbsoluteRect.UpperLeftCorner.X || xpos >= AbsoluteRect.LowerRightCorner.X\r
131                 ||      ypos < AbsoluteRect.UpperLeftCorner.Y || ypos >= AbsoluteRect.LowerRightCorner.Y\r
132                 )\r
133                 return -1;\r
134 \r
135         if ( ItemHeight == 0 )\r
136                 return -1;\r
137 \r
138         s32 item = ((ypos - AbsoluteRect.UpperLeftCorner.Y - 1) + ScrollBar->getPos()) / ItemHeight;\r
139         if ( item < 0 || item >= (s32)Items.size())\r
140                 return -1;\r
141 \r
142         return item;\r
143 }\r
144 \r
145 //! clears the list\r
146 void CGUIListBox::clear()\r
147 {\r
148         Items.clear();\r
149         ItemsIconWidth = 0;\r
150         Selected = -1;\r
151 \r
152         ScrollBar->setPos(0);\r
153 \r
154         recalculateItemHeight();\r
155 }\r
156 \r
157 \r
158 void CGUIListBox::recalculateItemHeight()\r
159 {\r
160         IGUISkin* skin = Environment->getSkin();\r
161 \r
162         if (Font != skin->getFont())\r
163         {\r
164                 if (Font)\r
165                         Font->drop();\r
166 \r
167                 Font = skin->getFont();\r
168                 if ( 0 == ItemHeightOverride )\r
169                         ItemHeight = 0;\r
170 \r
171                 if (Font)\r
172                 {\r
173                         if ( 0 == ItemHeightOverride )\r
174                                 ItemHeight = Font->getDimension(L"A").Height + 4;\r
175 \r
176                         Font->grab();\r
177                 }\r
178         }\r
179 \r
180         TotalItemHeight = ItemHeight * Items.size();\r
181         ScrollBar->setMax( core::max_(0, TotalItemHeight - AbsoluteRect.getHeight()) );\r
182         s32 minItemHeight = ItemHeight > 0 ? ItemHeight : 1;\r
183         ScrollBar->setSmallStep ( minItemHeight );\r
184         ScrollBar->setLargeStep ( 2*minItemHeight );\r
185 \r
186         if ( TotalItemHeight <= AbsoluteRect.getHeight() )\r
187                 ScrollBar->setVisible(false);\r
188         else\r
189                 ScrollBar->setVisible(true);\r
190 }\r
191 \r
192 //! returns id of selected item. returns -1 if no item is selected.\r
193 s32 CGUIListBox::getSelected() const\r
194 {\r
195         return Selected;\r
196 }\r
197 \r
198 \r
199 //! sets the selected item. Set this to -1 if no item should be selected\r
200 void CGUIListBox::setSelected(s32 id)\r
201 {\r
202         if ((u32)id>=Items.size())\r
203                 Selected = -1;\r
204         else\r
205                 Selected = id;\r
206 \r
207         selectTime = os::Timer::getTime();\r
208 \r
209         recalculateScrollPos();\r
210 }\r
211 \r
212 //! sets the selected item. Set this to -1 if no item should be selected\r
213 void CGUIListBox::setSelected(const wchar_t *item)\r
214 {\r
215         s32 index = -1;\r
216 \r
217         if ( item )\r
218         {\r
219                 for ( index = 0; index < (s32) Items.size(); ++index )\r
220                 {\r
221                         if ( Items[index].Text == item )\r
222                                 break;\r
223                 }\r
224         }\r
225         setSelected ( index );\r
226 }\r
227 \r
228 //! called if an event happened.\r
229 bool CGUIListBox::OnEvent(const SEvent& event)\r
230 {\r
231         if (isEnabled())\r
232         {\r
233                 switch(event.EventType)\r
234                 {\r
235                 case EET_KEY_INPUT_EVENT:\r
236                         if (event.KeyInput.PressedDown &&\r
237                                 (event.KeyInput.Key == KEY_DOWN ||\r
238                                 event.KeyInput.Key == KEY_UP   ||\r
239                                 event.KeyInput.Key == KEY_HOME ||\r
240                                 event.KeyInput.Key == KEY_END  ||\r
241                                 event.KeyInput.Key == KEY_NEXT ||\r
242                                 event.KeyInput.Key == KEY_PRIOR ) )\r
243                         {\r
244                                 s32 oldSelected = Selected;\r
245                                 switch (event.KeyInput.Key)\r
246                                 {\r
247                                         case KEY_DOWN:\r
248                                                 Selected += 1;\r
249                                                 break;\r
250                                         case KEY_UP:\r
251                                                 Selected -= 1;\r
252                                                 break;\r
253                                         case KEY_HOME:\r
254                                                 Selected = 0;\r
255                                                 break;\r
256                                         case KEY_END:\r
257                                                 Selected = (s32)Items.size()-1;\r
258                                                 break;\r
259                                         case KEY_NEXT:\r
260                                                 Selected += AbsoluteRect.getHeight() / ItemHeight;\r
261                                                 break;\r
262                                         case KEY_PRIOR:\r
263                                                 Selected -= AbsoluteRect.getHeight() / ItemHeight;\r
264                                                 break;\r
265                                         default:\r
266                                                 break;\r
267                                 }\r
268                                 if (Selected<0)\r
269                                         Selected = 0;\r
270                                 if (Selected >= (s32)Items.size())\r
271                                         Selected = Items.size() - 1;    // will set Selected to -1 for empty listboxes which is correct\r
272 \r
273 \r
274                                 recalculateScrollPos();\r
275 \r
276                                 // post the news\r
277 \r
278                                 if (oldSelected != Selected && Parent && !Selecting && !MoveOverSelect)\r
279                                 {\r
280                                         SEvent e;\r
281                                         e.EventType = EET_GUI_EVENT;\r
282                                         e.GUIEvent.Caller = this;\r
283                                         e.GUIEvent.Element = 0;\r
284                                         e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;\r
285                                         Parent->OnEvent(e);\r
286                                 }\r
287 \r
288                                 return true;\r
289                         }\r
290                         else\r
291                         if (!event.KeyInput.PressedDown && ( event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE ) )\r
292                         {\r
293                                 if (Parent)\r
294                                 {\r
295                                         SEvent e;\r
296                                         e.EventType = EET_GUI_EVENT;\r
297                                         e.GUIEvent.Caller = this;\r
298                                         e.GUIEvent.Element = 0;\r
299                                         e.GUIEvent.EventType = EGET_LISTBOX_SELECTED_AGAIN;\r
300                                         Parent->OnEvent(e);\r
301                                 }\r
302                                 return true;\r
303                         }\r
304                         else if (event.KeyInput.Key == KEY_TAB )\r
305                         {\r
306                                 return false;\r
307                         }\r
308                         else if (event.KeyInput.PressedDown && event.KeyInput.Char)\r
309                         {\r
310                                 // change selection based on text as it is typed.\r
311                                 u32 now = os::Timer::getTime();\r
312 \r
313                                 if (now - LastKeyTime < 500)\r
314                                 {\r
315                                         // add to key buffer if it isn't a key repeat\r
316                                         if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char))\r
317                                         {\r
318                                                 KeyBuffer += L" ";\r
319                                                 KeyBuffer[KeyBuffer.size()-1] = event.KeyInput.Char;\r
320                                         }\r
321                                 }\r
322                                 else\r
323                                 {\r
324                                         KeyBuffer = L" ";\r
325                                         KeyBuffer[0] = event.KeyInput.Char;\r
326                                 }\r
327                                 LastKeyTime = now;\r
328 \r
329                                 // find the selected item, starting at the current selection\r
330                                 s32 start = Selected;\r
331                                 // dont change selection if the key buffer matches the current item\r
332                                 if (Selected > -1 && KeyBuffer.size() > 1)\r
333                                 {\r
334                                         if (Items[Selected].Text.size() >= KeyBuffer.size() &&\r
335                                                 KeyBuffer.equals_ignore_case(Items[Selected].Text.subString(0,KeyBuffer.size())))\r
336                                                 return true;\r
337                                 }\r
338 \r
339                                 s32 current;\r
340                                 for (current = start+1; current < (s32)Items.size(); ++current)\r
341                                 {\r
342                                         if (Items[current].Text.size() >= KeyBuffer.size())\r
343                                         {\r
344                                                 if (KeyBuffer.equals_ignore_case(Items[current].Text.subString(0,KeyBuffer.size())))\r
345                                                 {\r
346                                                         if (Parent && Selected != current && !Selecting && !MoveOverSelect)\r
347                                                         {\r
348                                                                 SEvent e;\r
349                                                                 e.EventType = EET_GUI_EVENT;\r
350                                                                 e.GUIEvent.Caller = this;\r
351                                                                 e.GUIEvent.Element = 0;\r
352                                                                 e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;\r
353                                                                 Parent->OnEvent(e);\r
354                                                         }\r
355                                                         setSelected(current);\r
356                                                         return true;\r
357                                                 }\r
358                                         }\r
359                                 }\r
360                                 for (current = 0; current <= start; ++current)\r
361                                 {\r
362                                         if (Items[current].Text.size() >= KeyBuffer.size())\r
363                                         {\r
364                                                 if (KeyBuffer.equals_ignore_case(Items[current].Text.subString(0,KeyBuffer.size())))\r
365                                                 {\r
366                                                         if (Parent && Selected != current && !Selecting && !MoveOverSelect)\r
367                                                         {\r
368                                                                 Selected = current;\r
369                                                                 SEvent e;\r
370                                                                 e.EventType = EET_GUI_EVENT;\r
371                                                                 e.GUIEvent.Caller = this;\r
372                                                                 e.GUIEvent.Element = 0;\r
373                                                                 e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;\r
374                                                                 Parent->OnEvent(e);\r
375                                                         }\r
376                                                         setSelected(current);\r
377                                                         return true;\r
378                                                 }\r
379                                         }\r
380                                 }\r
381 \r
382                                 return true;\r
383                         }\r
384                         break;\r
385 \r
386                 case EET_GUI_EVENT:\r
387                         switch(event.GUIEvent.EventType)\r
388                         {\r
389                         case gui::EGET_SCROLL_BAR_CHANGED:\r
390                                 if (event.GUIEvent.Caller == ScrollBar)\r
391                                         return true;\r
392                                 break;\r
393                         case gui::EGET_ELEMENT_FOCUS_LOST:\r
394                                 {\r
395                                         if (event.GUIEvent.Caller == this)\r
396                                                 Selecting = false;\r
397                                 }\r
398                         default:\r
399                         break;\r
400                         }\r
401                         break;\r
402 \r
403                 case EET_MOUSE_INPUT_EVENT:\r
404                         {\r
405                                 core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);\r
406 \r
407                                 switch(event.MouseInput.Event)\r
408                                 {\r
409                                 case EMIE_MOUSE_WHEEL:\r
410                                         ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-ItemHeight/2);\r
411                                         return true;\r
412 \r
413                                 case EMIE_LMOUSE_PRESSED_DOWN:\r
414                                 {\r
415                                         Selecting = true;\r
416                                         return true;\r
417                                 }\r
418 \r
419                                 case EMIE_LMOUSE_LEFT_UP:\r
420                                 {\r
421                                         Selecting = false;\r
422 \r
423                                         if (isPointInside(p))\r
424                                                 selectNew(event.MouseInput.Y);\r
425 \r
426                                         return true;\r
427                                 }\r
428 \r
429                                 case EMIE_MOUSE_MOVED:\r
430                                         if (Selecting || MoveOverSelect)\r
431                                         {\r
432                                                 if (isPointInside(p))\r
433                                                 {\r
434                                                         selectNew(event.MouseInput.Y, true);\r
435                                                         return true;\r
436                                                 }\r
437                                         }\r
438                                 default:\r
439                                 break;\r
440                                 }\r
441                         }\r
442                         break;\r
443                 default:\r
444                         break;\r
445                 }\r
446         }\r
447 \r
448         return IGUIElement::OnEvent(event);\r
449 }\r
450 \r
451 \r
452 void CGUIListBox::selectNew(s32 ypos, bool onlyHover)\r
453 {\r
454         u32 now = os::Timer::getTime();\r
455         s32 oldSelected = Selected;\r
456 \r
457         Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos);\r
458         if (Selected<0 && !Items.empty())\r
459                 Selected = 0;\r
460 \r
461         recalculateScrollPos();\r
462 \r
463         gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED;\r
464         selectTime = now;\r
465         // post the news\r
466         if (Parent && !onlyHover)\r
467         {\r
468                 SEvent event;\r
469                 event.EventType = EET_GUI_EVENT;\r
470                 event.GUIEvent.Caller = this;\r
471                 event.GUIEvent.Element = 0;\r
472                 event.GUIEvent.EventType = eventType;\r
473                 Parent->OnEvent(event);\r
474         }\r
475 }\r
476 \r
477 \r
478 //! Update the position and size of the listbox, and update the scrollbar\r
479 void CGUIListBox::updateAbsolutePosition()\r
480 {\r
481         IGUIElement::updateAbsolutePosition();\r
482 \r
483         recalculateItemHeight();\r
484 }\r
485 \r
486 \r
487 //! draws the element and its children\r
488 void CGUIListBox::draw()\r
489 {\r
490         if (!IsVisible)\r
491                 return;\r
492 \r
493         recalculateItemHeight(); // if the font changed\r
494 \r
495         IGUISkin* skin = Environment->getSkin();\r
496         updateScrollBarSize(skin->getSize(EGDS_SCROLLBAR_SIZE));\r
497 \r
498         core::rect<s32>* clipRect = 0;\r
499 \r
500         // draw background\r
501         core::rect<s32> frameRect(AbsoluteRect);\r
502 \r
503         // draw items\r
504 \r
505         core::rect<s32> clientClip(AbsoluteRect);\r
506         clientClip.UpperLeftCorner.Y += 1;\r
507         clientClip.UpperLeftCorner.X += 1;\r
508         if (ScrollBar->isVisible())\r
509                 clientClip.LowerRightCorner.X -= ScrollBar->getRelativePosition().getWidth();\r
510         clientClip.LowerRightCorner.Y -= 1;\r
511         clientClip.clipAgainst(AbsoluteClippingRect);\r
512 \r
513         skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true,\r
514                 DrawBack, frameRect, &AbsoluteClippingRect);\r
515 \r
516         if (clipRect)\r
517                 clientClip.clipAgainst(*clipRect);\r
518 \r
519         frameRect = AbsoluteRect;\r
520         frameRect.UpperLeftCorner.X += 1;\r
521         if (ScrollBar->isVisible())\r
522                 frameRect.LowerRightCorner.X -= ScrollBar->getRelativePosition().getWidth();\r
523 \r
524         frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight;\r
525 \r
526         frameRect.UpperLeftCorner.Y -= ScrollBar->getPos();\r
527         frameRect.LowerRightCorner.Y -= ScrollBar->getPos();\r
528 \r
529         bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar));\r
530 \r
531         for (s32 i=0; i<(s32)Items.size(); ++i)\r
532         {\r
533                 if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&\r
534                         frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)\r
535                 {\r
536                         if (i == Selected && hl)\r
537                                 skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip);\r
538 \r
539                         core::rect<s32> textRect = frameRect;\r
540                         textRect.UpperLeftCorner.X += 3;\r
541 \r
542                         if (Font)\r
543                         {\r
544                                 if (IconBank && (Items[i].Icon > -1))\r
545                                 {\r
546                                         core::position2di iconPos = textRect.UpperLeftCorner;\r
547                                         iconPos.Y += textRect.getHeight() / 2;\r
548                                         iconPos.X += ItemsIconWidth/2;\r
549 \r
550                                         if ( i==Selected && hl )\r
551                                         {\r
552                                                 IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip,\r
553                                                         hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ?\r
554                                                         getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),\r
555                                                         selectTime, os::Timer::getTime(), false, true);\r
556                                         }\r
557                                         else\r
558                                         {\r
559                                                 IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip,\r
560                                                         hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),\r
561                                                         0 , (i==Selected) ? os::Timer::getTime() : 0, false, true);\r
562                                         }\r
563                                 }\r
564 \r
565                                 textRect.UpperLeftCorner.X += ItemsIconWidth+3;\r
566 \r
567                                 if ( i==Selected && hl )\r
568                                 {\r
569                                         Font->draw(Items[i].Text.c_str(), textRect,\r
570                                                 hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ?\r
571                                                 getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT),\r
572                                                 false, true, &clientClip);\r
573                                 }\r
574                                 else\r
575                                 {\r
576                                         Font->draw(Items[i].Text.c_str(), textRect,\r
577                                                 hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT),\r
578                                                 false, true, &clientClip);\r
579                                 }\r
580 \r
581                                 textRect.UpperLeftCorner.X -= ItemsIconWidth+3;\r
582                         }\r
583                 }\r
584 \r
585                 frameRect.UpperLeftCorner.Y += ItemHeight;\r
586                 frameRect.LowerRightCorner.Y += ItemHeight;\r
587         }\r
588 \r
589         IGUIElement::draw();\r
590 }\r
591 \r
592 \r
593 //! adds an list item with an icon\r
594 u32 CGUIListBox::addItem(const wchar_t* text, s32 icon)\r
595 {\r
596         ListItem i;\r
597         i.Text = text;\r
598         i.Icon = icon;\r
599 \r
600         Items.push_back(i);\r
601         recalculateItemHeight();\r
602         recalculateItemWidth(icon);\r
603 \r
604         return Items.size() - 1;\r
605 }\r
606 \r
607 \r
608 void CGUIListBox::setSpriteBank(IGUISpriteBank* bank)\r
609 {\r
610         if ( bank == IconBank )\r
611                 return;\r
612         if (IconBank)\r
613                 IconBank->drop();\r
614 \r
615         IconBank = bank;\r
616         if (IconBank)\r
617                 IconBank->grab();\r
618 }\r
619 \r
620 \r
621 void CGUIListBox::recalculateScrollPos()\r
622 {\r
623         if (!AutoScroll)\r
624                 return;\r
625 \r
626         const s32 selPos = (Selected == -1 ? TotalItemHeight : Selected * ItemHeight) - ScrollBar->getPos();\r
627 \r
628         if (selPos < 0)\r
629         {\r
630                 ScrollBar->setPos(ScrollBar->getPos() + selPos);\r
631         }\r
632         else\r
633         if (selPos > AbsoluteRect.getHeight() - ItemHeight)\r
634         {\r
635                 ScrollBar->setPos(ScrollBar->getPos() + selPos - AbsoluteRect.getHeight() + ItemHeight);\r
636         }\r
637 }\r
638 \r
639 void CGUIListBox::updateScrollBarSize(s32 size)\r
640 {\r
641         if ( size != ScrollBar->getRelativePosition().getWidth() )\r
642         {\r
643                 core::recti r(RelativeRect.getWidth() - size, 0, RelativeRect.getWidth(), RelativeRect.getHeight());\r
644                 ScrollBar->setRelativePosition(r);\r
645         }\r
646 }\r
647 \r
648 void CGUIListBox::setAutoScrollEnabled(bool scroll)\r
649 {\r
650         AutoScroll = scroll;\r
651 }\r
652 \r
653 \r
654 bool CGUIListBox::isAutoScrollEnabled() const\r
655 {\r
656         return AutoScroll;\r
657 }\r
658 \r
659 \r
660 bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const\r
661 {\r
662         switch ( colorType )\r
663         {\r
664         case EGUI_LBC_TEXT:\r
665                 useColorLabel = "UseColText";\r
666                 colorLabel = "ColText";\r
667                 break;\r
668         case EGUI_LBC_TEXT_HIGHLIGHT:\r
669                 useColorLabel = "UseColTextHl";\r
670                 colorLabel = "ColTextHl";\r
671                 break;\r
672         case EGUI_LBC_ICON:\r
673                 useColorLabel = "UseColIcon";\r
674                 colorLabel = "ColIcon";\r
675                 break;\r
676         case EGUI_LBC_ICON_HIGHLIGHT:\r
677                 useColorLabel = "UseColIconHl";\r
678                 colorLabel = "ColIconHl";\r
679                 break;\r
680         default:\r
681                 return false;\r
682         }\r
683         return true;\r
684 }\r
685 \r
686 \r
687 void CGUIListBox::recalculateItemWidth(s32 icon)\r
688 {\r
689         if (IconBank && icon > -1 &&\r
690                 IconBank->getSprites().size() > (u32)icon &&\r
691                 IconBank->getSprites()[(u32)icon].Frames.size())\r
692         {\r
693                 u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber;\r
694                 if (IconBank->getPositions().size() > rno)\r
695                 {\r
696                         const s32 w = IconBank->getPositions()[rno].getWidth();\r
697                         if (w > ItemsIconWidth)\r
698                                 ItemsIconWidth = w;\r
699                 }\r
700         }\r
701 }\r
702 \r
703 \r
704 void CGUIListBox::setItem(u32 index, const wchar_t* text, s32 icon)\r
705 {\r
706         if ( index >= Items.size() )\r
707                 return;\r
708 \r
709         Items[index].Text = text;\r
710         Items[index].Icon = icon;\r
711 \r
712         recalculateItemHeight();\r
713         recalculateItemWidth(icon);\r
714 }\r
715 \r
716 \r
717 //! Insert the item at the given index\r
718 //! Return the index on success or -1 on failure.\r
719 s32 CGUIListBox::insertItem(u32 index, const wchar_t* text, s32 icon)\r
720 {\r
721         ListItem i;\r
722         i.Text = text;\r
723         i.Icon = icon;\r
724 \r
725         Items.insert(i, index);\r
726         recalculateItemHeight();\r
727         recalculateItemWidth(icon);\r
728 \r
729         return index;\r
730 }\r
731 \r
732 \r
733 void CGUIListBox::swapItems(u32 index1, u32 index2)\r
734 {\r
735         if ( index1 >= Items.size() || index2 >= Items.size() )\r
736                 return;\r
737 \r
738         ListItem dummmy = Items[index1];\r
739         Items[index1] = Items[index2];\r
740         Items[index2] = dummmy;\r
741 }\r
742 \r
743 \r
744 void CGUIListBox::setItemOverrideColor(u32 index, video::SColor color)\r
745 {\r
746         for ( u32 c=0; c < EGUI_LBC_COUNT; ++c )\r
747         {\r
748                 Items[index].OverrideColors[c].Use = true;\r
749                 Items[index].OverrideColors[c].Color = color;\r
750         }\r
751 }\r
752 \r
753 \r
754 void CGUIListBox::setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color)\r
755 {\r
756         if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )\r
757                 return;\r
758 \r
759         Items[index].OverrideColors[colorType].Use = true;\r
760         Items[index].OverrideColors[colorType].Color = color;\r
761 }\r
762 \r
763 \r
764 void CGUIListBox::clearItemOverrideColor(u32 index)\r
765 {\r
766         for (u32 c=0; c < (u32)EGUI_LBC_COUNT; ++c )\r
767         {\r
768                 Items[index].OverrideColors[c].Use = false;\r
769         }\r
770 }\r
771 \r
772 \r
773 void CGUIListBox::clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType)\r
774 {\r
775         if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )\r
776                 return;\r
777 \r
778         Items[index].OverrideColors[colorType].Use = false;\r
779 }\r
780 \r
781 \r
782 bool CGUIListBox::hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const\r
783 {\r
784         if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )\r
785                 return false;\r
786 \r
787         return Items[index].OverrideColors[colorType].Use;\r
788 }\r
789 \r
790 \r
791 video::SColor CGUIListBox::getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const\r
792 {\r
793         if ( (u32)index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )\r
794                 return video::SColor();\r
795 \r
796         return Items[index].OverrideColors[colorType].Color;\r
797 }\r
798 \r
799 \r
800 video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const\r
801 {\r
802         IGUISkin* skin = Environment->getSkin();\r
803         if ( !skin )\r
804                 return video::SColor();\r
805 \r
806         switch ( colorType )\r
807         {\r
808                 case EGUI_LBC_TEXT:\r
809                         return skin->getColor(EGDC_BUTTON_TEXT);\r
810                 case EGUI_LBC_TEXT_HIGHLIGHT:\r
811                         return skin->getColor(EGDC_HIGH_LIGHT_TEXT);\r
812                 case EGUI_LBC_ICON:\r
813                         return skin->getColor(EGDC_ICON);\r
814                 case EGUI_LBC_ICON_HIGHLIGHT:\r
815                         return skin->getColor(EGDC_ICON_HIGH_LIGHT);\r
816                 default:\r
817                         return video::SColor();\r
818         }\r
819 }\r
820 \r
821 //! set global itemHeight\r
822 void CGUIListBox::setItemHeight( s32 height )\r
823 {\r
824         ItemHeight = height;\r
825         ItemHeightOverride = 1;\r
826 }\r
827 \r
828 \r
829 //! Sets whether to draw the background\r
830 void CGUIListBox::setDrawBackground(bool draw)\r
831 {\r
832     DrawBack = draw;\r
833 }\r
834 \r
835 //! Access the vertical scrollbar\r
836 IGUIScrollBar* CGUIListBox::getVerticalScrollBar() const\r
837 {\r
838         return ScrollBar;\r
839 }\r
840 \r
841 } // end namespace gui\r
842 } // end namespace irr\r