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