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