CGUIListBox.cpp 22 KB

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