GadgetListBox.cpp 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: GadgetListBox.cpp ////////////////////////////////////////////////////
  24. //-----------------------------------------------------------------------------
  25. //
  26. // Westwood Studios Pacific.
  27. //
  28. // Confidential Information
  29. // Copyright (C) 2001 - All Rights Reserved
  30. //
  31. //-----------------------------------------------------------------------------
  32. //
  33. // Project: RTS3
  34. //
  35. // File name: ListBox.cpp
  36. //
  37. // Created: Dean Iverson, March 1998
  38. // Colin Day, June 2001
  39. //
  40. // Desc: ListBox GUI control
  41. //
  42. //-----------------------------------------------------------------------------
  43. ///////////////////////////////////////////////////////////////////////////////
  44. // SYSTEM INCLUDES ////////////////////////////////////////////////////////////
  45. // USER INCLUDES //////////////////////////////////////////////////////////////
  46. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  47. #include "Common/AudioEventRTS.h"
  48. #include "Common/Language.h"
  49. #include "Common/Debug.h"
  50. #include "Common/GameAudio.h"
  51. #include "GameClient/DisplayStringManager.h"
  52. #include "GameClient/GameWindow.h"
  53. #include "GameClient/Gadget.h"
  54. #include "GameClient/GameWindowManager.h"
  55. #include "GameClient/GadgetListBox.h"
  56. #include "GameClient/GadgetPushButton.h"
  57. #include "GameClient/GadgetSlider.h"
  58. #include "GameClient/GameWindowGlobal.h"
  59. #include "GameClient/Keyboard.h"
  60. #ifdef _INTERNAL
  61. // for occasional debugging...
  62. //#pragma optimize("", off)
  63. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  64. #endif
  65. // DEFINES ////////////////////////////////////////////////////////////////////
  66. // Sets up the user's OS set doubleclick time so if they don't like it... they can
  67. // change it in their OS.
  68. static UnsignedInt doubleClickTime = GetDoubleClickTime();
  69. // PRIVATE TYPES //////////////////////////////////////////////////////////////
  70. typedef struct _AddMessageStruct
  71. {
  72. Int row; // The row to add the data to
  73. Int column; // The column to add the data to
  74. const void *data; // void pointer, can be either an DisplayString or an Image
  75. Int type; // Can either be set to LISTBOX_TEXT or LISTBOX_IMAGE
  76. Bool overwrite; // Do we overwrite existing data?
  77. Int width; // set to -1 if we want the defaults
  78. Int height; // set to -1 if we want the defaults
  79. } AddMessageStruct;
  80. typedef struct _TextAndColor
  81. {
  82. UnicodeString string; // Holds a unicode String
  83. Color color; // holds a text's color
  84. } TextAndColor;
  85. ///////////////////////////////////////////////////////////////////////////////
  86. // PRIVATE DATA ///////////////////////////////////////////////////////////////
  87. ///////////////////////////////////////////////////////////////////////////////
  88. static void doAudioFeedback(GameWindow *window)
  89. {
  90. if (!window)
  91. return;
  92. ListboxData *lData = (ListboxData *)window->winGetUserData();
  93. if (!lData)
  94. return;
  95. if (lData->audioFeedback)
  96. {
  97. AudioEventRTS buttonClick("GUIComboBoxClick");
  98. if( TheAudio )
  99. {
  100. TheAudio->addAudioEvent( &buttonClick );
  101. } // end if
  102. }
  103. }
  104. static Int getListboxEntryBasedOnCoord(GameWindow *window, Int x, Int y, Int &row, Int &column)
  105. {
  106. Int pos;
  107. Int winx, winy, i;
  108. WinInstanceData *instData = window->winGetInstanceData();
  109. ListboxData *list = (ListboxData *)window->winGetUserData();
  110. window->winGetScreenPosition( &winx, &winy );
  111. // Adjust for title if present
  112. if( instData->getTextLength() )
  113. winy += TheWindowManager->winFontHeight( instData->getFont() ) + 1;
  114. pos = -2;
  115. for( i=0; ; i++ )
  116. {
  117. if( i > 0 )
  118. if( list->listData[ i - 1 ].listHeight >
  119. (list->displayPos + list->displayHeight ) )
  120. {
  121. pos = -1;
  122. break;
  123. }
  124. if( i == list->endPos )
  125. {
  126. pos = -1;
  127. break;
  128. }
  129. if( list->listData[i].listHeight > (y - winy + list->displayPos) )
  130. break;
  131. }
  132. column = -1;
  133. if( pos == -2 )
  134. {
  135. pos = i;
  136. Int total = 0;
  137. for( i = 0; i < list->columns ;i++)
  138. {
  139. total += list->columnWidth[i];
  140. if(x - winx < total)
  141. {
  142. column = i;
  143. break;
  144. }
  145. }
  146. }
  147. row = pos;
  148. return pos;
  149. }
  150. Int GadgetListBoxGetEntryBasedOnXY( GameWindow *listbox, Int x, Int y, Int &row, Int &column)
  151. {
  152. return getListboxEntryBasedOnCoord( listbox, x, y, row, column );
  153. }
  154. // getListboxTopEntry =========================================================
  155. //=============================================================================
  156. static Int getListboxTopEntry( ListboxData *list )
  157. {
  158. Int entry;
  159. // determin which entry is at the top of the display area
  160. for( entry=0; ; entry++ )
  161. {
  162. if( list->listData[entry].listHeight > list->displayPos )
  163. return entry;
  164. if( entry >= list->endPos )
  165. return 0;
  166. }
  167. return 0;
  168. }
  169. // getListboxTopEntry =========================================================
  170. //=============================================================================
  171. static Int getListboxBottomEntry( ListboxData *list )
  172. {
  173. Int entry;
  174. // determin which entry is at the top of the display area
  175. for( entry=list->endPos - 1; ; entry-- )
  176. {
  177. if( list->listData[entry].listHeight == list->displayPos + list->displayHeight )
  178. return entry;
  179. if( list->listData[entry].listHeight < list->displayPos + list->displayHeight && entry != list->endPos - 1)
  180. return entry + 1;
  181. if( list->listData[entry].listHeight < list->displayPos + list->displayHeight)
  182. return entry;
  183. if( entry < 0 )
  184. return 0;
  185. }
  186. return 0;
  187. }
  188. // removeSelection ============================================================
  189. /** Remove Selection from a multiple selection list */
  190. //=============================================================================
  191. static void removeSelection( ListboxData *list, Int i )
  192. {
  193. memcpy( &list->selections[i], &list->selections[(i+1)],
  194. ((list->listLength - i) * sizeof(Int)) );
  195. // put -1 at end of list just for safety
  196. list->selections[(list->listLength - 1)] = -1;
  197. }
  198. // adjustDisplay ==============================================================
  199. /** Update Display List information inlcuding scrollbar */
  200. //=============================================================================
  201. static void adjustDisplay( GameWindow *window, Int adjustment,
  202. Bool updateSlider )
  203. {
  204. Int entry;
  205. SliderData *sData;
  206. ListboxData *list = (ListboxData *)window->winGetUserData();
  207. // determin which entry is at the top of the display area
  208. entry = getListboxTopEntry( list ) + adjustment;
  209. if( entry < 0 )
  210. entry = 0;
  211. else if( entry >= list->endPos )
  212. entry = list->endPos - 1;
  213. if( updateSlider )
  214. {
  215. if( entry > 0 )
  216. list->displayPos = list->listData[(entry - 1)].listHeight + 1;
  217. else
  218. list->displayPos = 0;
  219. }
  220. if( list->slider != NULL )
  221. {
  222. ICoord2D sliderSize, sliderChildSize;
  223. GameWindow *child;
  224. sData = (SliderData *)list->slider->winGetUserData();
  225. list->slider->winGetSize( &sliderSize.x, &sliderSize.y );
  226. // Take into account that there is a line-drawn outline surrounding listbox
  227. sData->maxVal = list->totalHeight - ( list->displayHeight - TOTAL_OUTLINE_HEIGHT ) + 1;
  228. if( sData->maxVal < 0 )
  229. {
  230. sData->maxVal = 0;
  231. }
  232. child = list->slider->winGetChild();
  233. child->winGetSize( &sliderChildSize.x, &sliderChildSize.y );
  234. sData->numTicks = (float)((sliderSize.y - sliderChildSize.y) / (float)sData->maxVal);
  235. if( updateSlider )
  236. TheWindowManager->winSendSystemMsg( list->slider,
  237. GSM_SET_SLIDER,
  238. (sData->maxVal - list->displayPos),
  239. 0 );
  240. }
  241. } // end adjustDisplay
  242. // computeTotalHeight =========================================================
  243. /** Compute Total Height and fill in listHeight values */
  244. //=============================================================================
  245. static void computeTotalHeight( GameWindow *window )
  246. {
  247. Int i, height = 0;
  248. Int tempHeight;
  249. ListboxData *list = (ListboxData *)window->winGetUserData();
  250. WinInstanceData *instData = window->winGetInstanceData();
  251. for( i=0; i<list->endPos; i++ )
  252. {
  253. if(!list->listData[i].cell)
  254. continue;
  255. tempHeight = 0;
  256. for (Int j = 0; j < list->columns; j++)
  257. {
  258. Int cellHeight = 0;
  259. if(list->listData[i].cell[j].cellType == LISTBOX_TEXT)
  260. {
  261. if( BitTest( window->winGetStatus(), WIN_STATUS_ONE_LINE ) == TRUE )
  262. {
  263. cellHeight = TheWindowManager->winFontHeight( instData->getFont() );
  264. }
  265. else
  266. {
  267. DisplayString *displayString = (DisplayString *)list->listData[i].cell[j].data;
  268. if(displayString)
  269. displayString->getSize( NULL, &cellHeight );
  270. }//else
  271. }//if
  272. else if(list->listData[i].cell[j].cellType == LISTBOX_IMAGE)
  273. {
  274. if(list->listData[i].cell[j].height > 0)
  275. cellHeight = list->listData[i].cell[j].height + 1;
  276. else
  277. cellHeight = TheWindowManager->winFontHeight( instData->getFont() );
  278. }
  279. if(cellHeight > tempHeight)
  280. tempHeight = cellHeight;
  281. }//for
  282. list->listData[i].height = tempHeight;
  283. height += (list->listData[i].height + 1);
  284. list->listData[i].listHeight = height;
  285. }
  286. list->totalHeight = height;
  287. adjustDisplay( window, 0, TRUE );
  288. }
  289. // addImageEntry ==============================================================
  290. /** Add Images to position and column. Row and Column are both based from starting
  291. Position 0 */
  292. //=============================================================================
  293. static Int addImageEntry( const Image *image, Color color, Int row, Int column, GameWindow *window, Bool overwrite, Int width, Int height )
  294. {
  295. // WinInstanceData *instData = window->winGetInstanceData();
  296. ListboxData *list = (ListboxData *)window->winGetUserData();
  297. if( column >= list->columns || row >= list->listLength )
  298. {
  299. DEBUG_ASSERTCRASH(false, ("Tried to add Image to Listbox at invalid position"));
  300. return -1;
  301. }
  302. // If we want to just add an entry to the bottom, set the defaults
  303. if (row == -1)
  304. {
  305. row = list->insertPos;
  306. list->insertPos++;
  307. list->endPos++;
  308. }
  309. if( column == -1 )
  310. column = 0;
  311. ListEntryRow *listRow = &list->listData[row];
  312. // Check and see if we have allocated cells for that row yet, if not, allocate them
  313. if(!listRow->cell)
  314. {
  315. listRow->cell = NEW ListEntryCell[list->columns];
  316. memset(listRow->cell,0,list->columns * sizeof(ListEntryCell));
  317. }
  318. // if we're copying over strings, then lets first deallocate them.
  319. if(listRow->cell[column].cellType == LISTBOX_TEXT)
  320. {
  321. TheDisplayStringManager->freeDisplayString((DisplayString *)listRow->cell[column].data);
  322. }
  323. //add Image to selected row/cell
  324. listRow->cell[column].cellType = LISTBOX_IMAGE;
  325. listRow->cell[column].data = (void *)image;
  326. listRow->cell[column].color = color;
  327. listRow->cell[column].height = height;
  328. listRow->cell[column].width = width;
  329. computeTotalHeight( window );
  330. return (row);
  331. }// static Int addImageEntry( Image image, Int column, GameWindow *window)
  332. // startingRow will get moved to startingRow+1, etc. This assumes there is space!!!!!
  333. static Int moveRowsDown(ListboxData *list, Int startingRow)
  334. {
  335. //
  336. // copy the cells down
  337. //
  338. Int copyLen = (list->endPos - startingRow) * sizeof(ListEntryRow);
  339. char *buf = NEW char[copyLen];
  340. memcpy(buf, list->listData + startingRow, copyLen);
  341. memcpy(list->listData + startingRow + 1, buf, copyLen );
  342. delete buf;
  343. list->endPos ++;
  344. list->insertPos = list->endPos;
  345. //
  346. // remove the display or links to images after the shift
  347. //
  348. list->listData[startingRow].cell = NULL;
  349. list->listData[startingRow].height = 0;
  350. list->listData[startingRow].listHeight = 0;
  351. if( list->multiSelect )
  352. {
  353. Int i = 0;
  354. while( list->selections[i] >= 0 )
  355. {
  356. if( startingRow <= list->selections[i] )
  357. list->selections[i]++;
  358. i++;
  359. }
  360. }
  361. else
  362. {
  363. if( list->selectPos >= startingRow )
  364. list->selectPos++;
  365. }
  366. /*
  367. if( list->displayPos > 0 )
  368. adjustDisplay( window, (-1 * mData1), TRUE );
  369. computeTotalHeight( window );
  370. */
  371. return 1;
  372. }
  373. // addEntry ===================================================================
  374. /** Add and process one string at insertPos */
  375. //=============================================================================
  376. static Int addEntry( UnicodeString *string, Int color, Int row, Int column, GameWindow *window, Bool overwrite )
  377. {
  378. // WinInstanceData *instData = window->winGetInstanceData();
  379. ListboxData *list = (ListboxData *)window->winGetUserData();
  380. Int width;
  381. DisplayString *displayString;
  382. // make sure our params are good
  383. if( column >= list->columns || row >= list->listLength )
  384. {
  385. DEBUG_ASSERTCRASH(false, ("Tried to add text to Listbox at invalid position"));
  386. return -1;
  387. }
  388. // If we want to just add an entry to the bottom, set the defaults
  389. if (row == -1)
  390. {
  391. row = list->insertPos;
  392. list->insertPos++;
  393. list->endPos++;
  394. }
  395. if( column == -1 )
  396. column = 0;
  397. width = list->columnWidth[column] - TEXT_WIDTH_OFFSET;
  398. Int rowsAdded = 0;
  399. ListEntryRow *listRow = &list->listData[row];
  400. // Here I've decided to just overright what's in the row, if that's not what we want, change it here
  401. // Check and see if we have allocated cells for that row yet, if not, allocate them
  402. if(!listRow->cell)
  403. {
  404. listRow->cell = NEW ListEntryCell[list->columns];
  405. memset(listRow->cell,0,list->columns * sizeof(ListEntryCell));
  406. rowsAdded = 1;
  407. }
  408. else if (!overwrite)
  409. {
  410. // Shove things down
  411. moveRowsDown(list, row);
  412. listRow->cell = NEW ListEntryCell[list->columns];
  413. memset(listRow->cell,0,list->columns * sizeof(ListEntryCell));
  414. rowsAdded = 1;
  415. }
  416. //add Image to selected row/cell
  417. listRow->cell[column].cellType = LISTBOX_TEXT;
  418. // assign the color to the list data element
  419. listRow->cell[column].color = color;
  420. // copy text
  421. if( !listRow->cell[column].data )
  422. listRow->cell[column].data = (void *) TheDisplayStringManager->newDisplayString();
  423. displayString = (DisplayString *) listRow->cell[column].data;
  424. if ( BitTest( window->winGetStatus(), WIN_STATUS_ONE_LINE ) == FALSE )
  425. displayString->setWordWrap( width );
  426. displayString->setText( *string );
  427. /** @todo we need for formalize this, but for now just set the font
  428. of this listbox entry to the font of the window */
  429. displayString->setFont( window->winGetFont() );
  430. if (overwrite)
  431. {
  432. Int oldRowHeight = listRow->height;
  433. Int oldTotalHeight = listRow->listHeight;
  434. Int rowHeight;
  435. Int totalHeight;
  436. if (!oldTotalHeight && row)
  437. {
  438. oldTotalHeight = list->listData[row-1].listHeight;
  439. }
  440. displayString->getSize( NULL, &rowHeight );
  441. if (rowHeight > oldRowHeight)
  442. {
  443. totalHeight = oldTotalHeight + (rowHeight - oldRowHeight);
  444. listRow->height = rowHeight;
  445. listRow->listHeight = totalHeight + rowsAdded;
  446. list->totalHeight += (rowHeight - oldRowHeight) + rowsAdded;
  447. adjustDisplay( window, 0, TRUE );
  448. }
  449. }
  450. else
  451. {
  452. computeTotalHeight( window );
  453. }
  454. return (row);
  455. } // end addEntry
  456. // PUBLIC DATA ////////////////////////////////////////////////////////////////
  457. // PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
  458. // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
  459. ///////////////////////////////////////////////////////////////////////////////
  460. // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
  461. ///////////////////////////////////////////////////////////////////////////////
  462. // GadgetListBoxInput =========================================================
  463. /** Handle input for list box */
  464. //=============================================================================
  465. WindowMsgHandledType GadgetListBoxInput( GameWindow *window, UnsignedInt msg,
  466. WindowMsgData mData1, WindowMsgData mData2 )
  467. {
  468. ListboxData *list = (ListboxData *)window->winGetUserData();
  469. WinInstanceData *instData = window->winGetInstanceData();
  470. switch (msg)
  471. {
  472. // ------------------------------------------------------------------------
  473. case GWM_CHAR:
  474. {
  475. switch (mData1)
  476. {
  477. // --------------------------------------------------------------------
  478. case KEY_ENTER:
  479. case KEY_SPACE:
  480. {
  481. if( BitTest( mData2, KEY_STATE_UP ) )
  482. {
  483. doAudioFeedback(window);
  484. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  485. GLM_DOUBLE_CLICKED,
  486. (WindowMsgData)window,
  487. list->selectPos );
  488. } // end if
  489. break;
  490. } // end enter or space
  491. // --------------------------------------------------------------------
  492. case KEY_DOWN:
  493. {
  494. if( BitTest( mData2, KEY_STATE_DOWN ) )
  495. {
  496. if( list->selectPos == -1 )
  497. {
  498. list->selectPos = 0;
  499. adjustDisplay( window, 0, TRUE );
  500. }
  501. else if( list->selectPos < list->endPos - 1 )
  502. {
  503. list->selectPos++;
  504. while (1)
  505. {
  506. Int cellBottom = list->listData[list->selectPos].listHeight;
  507. Int cellTop = cellBottom - list->listData[list->selectPos].height;
  508. Int displayTop = list->displayPos;
  509. Int displayBottom = list->displayPos + list->displayHeight - 1; // account for the border
  510. if ( cellTop < displayTop )
  511. {
  512. adjustDisplay(window, -1, TRUE );
  513. }
  514. else if ( cellBottom < displayBottom )
  515. {
  516. adjustDisplay(window, 0, TRUE );
  517. break;
  518. }
  519. else
  520. {
  521. adjustDisplay(window, 1, TRUE );
  522. }
  523. }
  524. }
  525. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  526. GLM_SELECTED,
  527. (WindowMsgData)window,
  528. list->selectPos );
  529. } // end if
  530. break;
  531. } // end key down
  532. // --------------------------------------------------------------------
  533. case KEY_UP:
  534. {
  535. if( BitTest( mData2, KEY_STATE_DOWN ) )
  536. {
  537. if( list->selectPos == -1 )
  538. {
  539. list->selectPos = 0;
  540. adjustDisplay( window, 0, TRUE );
  541. }
  542. else if( list->selectPos > 0 )
  543. {
  544. list->selectPos--;
  545. while (1)
  546. {
  547. if( list->listData[list->selectPos].listHeight - list->listData[list->selectPos].height < list->displayPos )
  548. {
  549. list->displayPos = list->listData[list->selectPos].listHeight +1;
  550. adjustDisplay( window, -1, TRUE );
  551. }
  552. else if( list->listData[list->selectPos].listHeight > list->displayPos + list->displayHeight)
  553. {
  554. list->displayPos = list->listData[list->selectPos].listHeight - list->displayHeight;
  555. adjustDisplay(window, 1, TRUE);
  556. }
  557. else
  558. {
  559. adjustDisplay(window, 0, TRUE);
  560. break;
  561. }
  562. }
  563. }
  564. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  565. GLM_SELECTED,
  566. (WindowMsgData)window,
  567. list->selectPos );
  568. }
  569. break;
  570. } // end key up
  571. // --------------------------------------------------------------------
  572. case KEY_RIGHT:
  573. case KEY_TAB:
  574. if( BitTest( mData2, KEY_STATE_DOWN ) )
  575. TheWindowManager->winNextTab(window);
  576. break;
  577. // --------------------------------------------------------------------
  578. case KEY_LEFT:
  579. if( BitTest( mData2, KEY_STATE_DOWN ) )
  580. TheWindowManager->winPrevTab(window);
  581. break;
  582. // --------------------------------------------------------------------
  583. default:
  584. {
  585. Bool foundIt = false;
  586. if( BitTest( mData2, KEY_STATE_DOWN ) )
  587. {
  588. // set the position to start looking for the line of text with this character
  589. Int position = list->selectPos;
  590. // only search the max number of times so that we're not looping over and over
  591. for(Int i = 0; i < list->endPos; ++i)
  592. {
  593. // start at the next position
  594. ++position;
  595. // if we've reached the end of the list, start at the beginning
  596. if( position >= list->endPos)
  597. position = 0;
  598. ListEntryCell *cell = NULL;
  599. // go through the columns until we find a column with text
  600. for(Int j = 0; j < list->columns; ++j)
  601. {
  602. cell = &list->listData[position].cell[j];
  603. if(cell && cell->cellType == LISTBOX_TEXT && cell->data)
  604. {
  605. break;
  606. }
  607. }
  608. if(!cell || cell->cellType != LISTBOX_TEXT)
  609. continue;
  610. DisplayString *dString = (DisplayString *)cell->data;
  611. if(!dString)
  612. continue;
  613. for(j = 0; j < TheKeyboard->MAX_KEY_STATES; ++j)
  614. {
  615. if(dString->getText().getCharAt(0) == TheKeyboard->getPrintableKey(mData1, j))
  616. {
  617. list->selectPos = position;
  618. Int prevPos = getListboxTopEntry(list);
  619. //list->displayPos = list->listData[position].listHeight - list->displayHeight;
  620. adjustDisplay(window, position - prevPos, TRUE);
  621. foundIt = TRUE;
  622. break;
  623. }
  624. }
  625. if(foundIt)
  626. {
  627. doAudioFeedback(window);
  628. break;
  629. }
  630. }
  631. }
  632. if (!foundIt)
  633. return MSG_IGNORED;
  634. }
  635. } // end switch( mData1 )
  636. break;
  637. } // end case char
  638. // ------------------------------------------------------------------------
  639. case GWM_WHEEL_DOWN:
  640. {
  641. if( list->endPos <= 0)
  642. break;
  643. if (list->listData[list->endPos - 1].listHeight > list->displayHeight + list->displayPos)
  644. adjustDisplay( window, 1, TRUE );
  645. break;
  646. } // end wheel down
  647. // ------------------------------------------------------------------------
  648. case GWM_WHEEL_UP:
  649. {
  650. if( list->endPos <= 0)
  651. break;
  652. adjustDisplay( window, -1, TRUE );
  653. break;
  654. } // end wheel up
  655. // ------------------------------------------------------------------------
  656. case GWM_LEFT_UP:
  657. {
  658. TheWindowManager->winSetFocus( window );
  659. // Int mousex = mData1 & 0xFFFF;
  660. Int mousey = mData1 >> 16;
  661. Int x, y, i;
  662. Int oldPos = list->selectPos;
  663. window->winGetScreenPosition( &x, &y );
  664. // Adjust for title if present
  665. if( instData->getTextLength() )
  666. y += TheWindowManager->winFontHeight( instData->getFont() ) + 1;
  667. list->selectPos = -2;
  668. for( i=0; ; i++ )
  669. {
  670. if( i > 0 )
  671. if( list->listData[ i - 1 ].listHeight >
  672. (list->displayPos + list->displayHeight) )
  673. {
  674. list->selectPos = -1;
  675. break;
  676. }
  677. if( i == list->endPos )
  678. {
  679. list->selectPos = -1;
  680. break;
  681. }
  682. if( list->listData[i].listHeight > (mousey - y + list->displayPos) )
  683. break;
  684. }
  685. //Bool dblClicked = FALSE;
  686. if( list->doubleClickTime + doubleClickTime > timeGetTime() &&
  687. (i == oldPos || (oldPos == -1 && ( i>=0 && i<list->endPos ) )) )
  688. {
  689. int temp;
  690. list->doubleClickTime = 0;
  691. if( oldPos == -1 )
  692. temp = i;
  693. else
  694. temp = oldPos;
  695. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  696. GLM_DOUBLE_CLICKED,
  697. (WindowMsgData)window,
  698. temp );
  699. //break;
  700. }
  701. if( (i == oldPos) && (list->forceSelect == FALSE) )
  702. {
  703. list->selectPos = -1;
  704. }
  705. if( (list->selectPos == -2) && (i < list->endPos) )
  706. {
  707. list->selectPos = i;
  708. }
  709. if( (list->selectPos < 0) && (list->forceSelect) )
  710. {
  711. list->selectPos = oldPos;
  712. }
  713. list->doubleClickTime = timeGetTime();
  714. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  715. GLM_SELECTED,
  716. (WindowMsgData)window,
  717. list->selectPos );
  718. break;
  719. } // end left click, left up
  720. // ------------------------------------------------------------------------
  721. case GWM_RIGHT_DOWN:
  722. doAudioFeedback(window);
  723. break; // if we're in game, we want to eat this message because we're right clicking on a listbox
  724. case GWM_RIGHT_UP:
  725. {
  726. TheWindowManager->winSetFocus( window );
  727. Int pos;
  728. Int mousex = mData1 & 0xFFFF;
  729. Int mousey = mData1 >> 16;
  730. Int x, y, i;
  731. RightClickStruct rc;
  732. window->winGetScreenPosition( &x, &y );
  733. // Adjust for title if present
  734. if( instData->getTextLength() )
  735. y += TheWindowManager->winFontHeight( instData->getFont() ) + 1;
  736. pos = -2;
  737. for( i=0; ; i++ )
  738. {
  739. if( i > 0 )
  740. if( list->listData[ i - 1 ].listHeight >
  741. (list->displayPos + list->displayHeight ) )
  742. {
  743. pos = -1;
  744. break;
  745. }
  746. if( i == list->endPos )
  747. {
  748. pos = -1;
  749. break;
  750. }
  751. if( list->listData[i].listHeight > (mousey - y + list->displayPos) )
  752. break;
  753. }
  754. if( pos == -2 )
  755. pos = i;
  756. rc.pos = pos;
  757. rc.mouseX = mousex;
  758. rc.mouseY = mousey;
  759. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  760. GLM_RIGHT_CLICKED,
  761. (WindowMsgData)window,
  762. (WindowMsgData)&rc );
  763. break;
  764. } // end right up, right click
  765. // ------------------------------------------------------------------------
  766. case GWM_MOUSE_ENTERING:
  767. {
  768. if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  769. {
  770. BitSet( instData->m_state, WIN_STATE_HILITED );
  771. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  772. GBM_MOUSE_ENTERING,
  773. (WindowMsgData)window,
  774. 0 );
  775. //TheWindowManager->winSetFocus( window );
  776. } // end if
  777. break;
  778. } // end mouse entering
  779. // ------------------------------------------------------------------------
  780. case GWM_MOUSE_LEAVING:
  781. {
  782. if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ))
  783. {
  784. BitClear( instData->m_state, WIN_STATE_HILITED );
  785. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  786. GBM_MOUSE_LEAVING,
  787. (WindowMsgData)window,
  788. 0 );
  789. } // end if
  790. break;
  791. } // end mouse leaving
  792. // ------------------------------------------------------------------------
  793. case GWM_LEFT_DRAG:
  794. if (BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  795. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  796. GGM_LEFT_DRAG,
  797. (WindowMsgData)window,
  798. 0 );
  799. break;
  800. // ------------------------------------------------------------------------
  801. case GWM_LEFT_DOWN:
  802. doAudioFeedback(window);
  803. // we want to eat the down... so we may receive the up.
  804. return MSG_HANDLED;
  805. //-------------------------------------------------------------------------
  806. default:
  807. return MSG_IGNORED;
  808. } // end switch msg
  809. return MSG_HANDLED;
  810. } // end GadgetListBoxInput
  811. // GadgetListBoxMultiInput ====================================================
  812. /** Handle input for multiple selection list box */
  813. //=============================================================================
  814. WindowMsgHandledType GadgetListBoxMultiInput( GameWindow *window, UnsignedInt msg,
  815. WindowMsgData mData1, WindowMsgData mData2 )
  816. {
  817. ListboxData *list = (ListboxData *)window->winGetUserData();
  818. WinInstanceData *instData = window->winGetInstanceData();
  819. switch( msg )
  820. {
  821. // ------------------------------------------------------------------------
  822. case GWM_CHAR:
  823. {
  824. switch( mData1 )
  825. {
  826. // --------------------------------------------------------------------
  827. case KEY_TAB:
  828. if( BitTest( mData2, KEY_STATE_DOWN ) )
  829. window->winNextTab();
  830. break;
  831. // --------------------------------------------------------------------
  832. default:
  833. return MSG_IGNORED;
  834. }
  835. break;
  836. } // end char
  837. // ------------------------------------------------------------------------
  838. case GWM_LEFT_UP:
  839. //case GWM_LEFT_CLICK:
  840. {
  841. TheWindowManager->winSetFocus( window );
  842. // Int *selections = list->selections;
  843. Int selectPos = -2;
  844. // Int mousex = mData1 & 0xFFFF;
  845. Int mousey = mData1 >> 16;
  846. Int x, y, i;
  847. Bool removed = FALSE;
  848. window->winGetScreenPosition( &x, &y );
  849. // Adjust for title if present
  850. if( instData->getTextLength() )
  851. y += TheWindowManager->winFontHeight( instData->getFont() ) + 1;
  852. for( i = 0; ; i++ )
  853. {
  854. if( i > 0 )
  855. if( list->listData[ i - 1 ].listHeight >
  856. (list->displayPos + list->displayHeight ) )
  857. {
  858. selectPos = -1;
  859. break;
  860. }
  861. if( i == list->endPos )
  862. {
  863. selectPos = -1;
  864. break;
  865. }
  866. if( list->listData[i].listHeight > (mousey - y + list->displayPos) )
  867. break;
  868. }
  869. if( selectPos == -2 )
  870. selectPos = i;
  871. i = 0;
  872. while( list->selections[i] >= 0 )
  873. {
  874. if( list->selections[i] == selectPos )
  875. {
  876. removeSelection( list, i );
  877. removed = TRUE;
  878. break;
  879. }
  880. i++;
  881. }
  882. if( removed == FALSE )
  883. {
  884. list->selections[ i] = selectPos;
  885. list->selections[ i + 1 ] = -1;
  886. }
  887. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  888. GLM_SELECTED,
  889. (WindowMsgData)window,
  890. selectPos );
  891. break;
  892. } // end left up, left click
  893. // ------------------------------------------------------------------------
  894. case GWM_RIGHT_UP:
  895. {
  896. /*
  897. Int selectPos = -2;
  898. // Int mousex = mData1 & 0xFFFF;
  899. Int mousey = mData1 >> 16;
  900. Int x, y, i;
  901. window->winGetScreenPosition( &x, &y );
  902. // Adjust for title if present
  903. if( instData->getTextLength() )
  904. y += TheWindowManager->winFontHeight( instData->getFont() ) + 1;
  905. for( i = 0; ; i++ )
  906. {
  907. if( i > 0 )
  908. if( list->listData[ i - 1 ].listHeight >
  909. (list->displayPos + list->displayHeight ) )
  910. {
  911. selectPos = -1;
  912. break;
  913. }
  914. if( i == list->endPos )
  915. {
  916. selectPos = -1;
  917. break;
  918. }
  919. if( list->listData[i].listHeight > (mousey - y + list->displayPos) )
  920. break;
  921. }
  922. if( selectPos == -2 )
  923. selectPos = i;
  924. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  925. GLM_RIGHT_CLICKED,
  926. (WindowMsgData)window,
  927. selectPos );*/
  928. TheWindowManager->winSetFocus( window );
  929. Int pos;
  930. Int mousex = mData1 & 0xFFFF;
  931. Int mousey = mData1 >> 16;
  932. Int x, y, i;
  933. RightClickStruct rc;
  934. window->winGetScreenPosition( &x, &y );
  935. // Adjust for title if present
  936. if( instData->getTextLength() )
  937. y += TheWindowManager->winFontHeight( instData->getFont() ) + 1;
  938. pos = -2;
  939. for( i=0; ; i++ )
  940. {
  941. if( i > 0 )
  942. if( list->listData[ i - 1 ].listHeight >
  943. (list->displayPos + list->displayHeight ) )
  944. {
  945. pos = -1;
  946. break;
  947. }
  948. if( i == list->endPos )
  949. {
  950. pos = -1;
  951. break;
  952. }
  953. if( list->listData[i].listHeight > (mousey - y + list->displayPos) )
  954. break;
  955. }
  956. if( pos == -2 )
  957. pos = i;
  958. rc.pos = pos;
  959. rc.mouseX = mousex;
  960. rc.mouseY = mousey;
  961. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  962. GLM_RIGHT_CLICKED,
  963. (WindowMsgData)window,
  964. (WindowMsgData)&rc );
  965. break;
  966. } // end right up, right click
  967. // ------------------------------------------------------------------------
  968. case GWM_WHEEL_DOWN:
  969. // Simulate the down button if it exists
  970. if( list->downButton )
  971. {
  972. if( list->displayPos + list->displayHeight <= list->totalHeight )
  973. adjustDisplay( window, 1, TRUE );
  974. }
  975. break;
  976. // ------------------------------------------------------------------------
  977. case GWM_WHEEL_UP:
  978. // Simulate the up button if it exists
  979. if( list->upButton )
  980. {
  981. if( list->displayPos > 0 )
  982. adjustDisplay( window, -1, TRUE );
  983. }
  984. break;
  985. // ------------------------------------------------------------------------
  986. case GWM_MOUSE_ENTERING:
  987. {
  988. if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  989. {
  990. BitSet( instData->m_state, WIN_STATE_HILITED );
  991. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  992. GBM_MOUSE_ENTERING,
  993. (WindowMsgData)window,
  994. 0 );
  995. //TheWindowManager->winSetFocus( window );
  996. } // end if
  997. break;
  998. } // end mouse entering
  999. // ------------------------------------------------------------------------
  1000. case GWM_MOUSE_LEAVING:
  1001. {
  1002. if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ))
  1003. {
  1004. BitClear( instData->m_state, WIN_STATE_HILITED );
  1005. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  1006. GBM_MOUSE_LEAVING,
  1007. (WindowMsgData)window,
  1008. 0 );
  1009. } // end if
  1010. break;
  1011. } // end mouse leaving
  1012. // ------------------------------------------------------------------------
  1013. case GWM_LEFT_DRAG:
  1014. if (BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  1015. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  1016. GGM_LEFT_DRAG,
  1017. (WindowMsgData)window,
  1018. 0 );
  1019. break;
  1020. // ------------------------------------------------------------------------
  1021. case GWM_LEFT_DOWN:
  1022. doAudioFeedback(window);
  1023. // we want to eat the down... so we may receive the up.
  1024. return MSG_HANDLED;
  1025. // ------------------------------------------------------------------------
  1026. default:
  1027. return MSG_IGNORED;
  1028. } // end switch( msg )
  1029. return MSG_HANDLED;
  1030. } // end GadgetListBoxMultiInput
  1031. // GadgetListBoxSystem ========================================================
  1032. /** Handle system messages for list box */
  1033. //=============================================================================
  1034. WindowMsgHandledType GadgetListBoxSystem( GameWindow *window, UnsignedInt msg,
  1035. WindowMsgData mData1, WindowMsgData mData2 )
  1036. {
  1037. ListboxData *list = (ListboxData *)window->winGetUserData();
  1038. WinInstanceData *instData = window->winGetInstanceData();
  1039. ICoord2D *pos;
  1040. switch( msg )
  1041. {
  1042. // ------------------------------------------------------------------------
  1043. case GGM_SET_LABEL:
  1044. {
  1045. instData->setText(*(UnicodeString*)mData1);
  1046. break;
  1047. } // end set lavel
  1048. // ------------------------------------------------------------------------
  1049. case GLM_GET_TEXT:
  1050. {
  1051. pos = (ICoord2D *)mData1;
  1052. TextAndColor *tAndC = (TextAndColor *)mData2;
  1053. if(pos->x >= list->columns || pos->y >= list->listLength ||
  1054. list->listData[pos->y].cell[pos->x].cellType != LISTBOX_TEXT)
  1055. {
  1056. tAndC->string = UnicodeString.TheEmptyString;
  1057. tAndC->color = 0;
  1058. }
  1059. else
  1060. {
  1061. tAndC->string = ((DisplayString *)list->listData[ pos->y ].cell[pos->x].data)->getText();
  1062. tAndC->color = list->listData[ pos->y ].cell[pos->x].color;
  1063. }
  1064. break;
  1065. }
  1066. // ------------------------------------------------------------------------
  1067. case GBM_SELECTED:
  1068. {
  1069. // See if the up button was selected
  1070. if( (GameWindow *)mData1 == list->upButton )
  1071. {
  1072. if( list->displayPos > 0 )
  1073. adjustDisplay( window, -1, TRUE );
  1074. }
  1075. else if( (GameWindow *)mData1 == list->downButton )
  1076. {
  1077. if( list->displayPos + list->displayHeight <= list->totalHeight )
  1078. adjustDisplay( window, 1, TRUE );
  1079. }
  1080. break;
  1081. } // end selected
  1082. // ------------------------------------------------------------------------
  1083. case GGM_LEFT_DRAG:
  1084. {
  1085. if( (GameWindow *)mData1 == list->upButton )
  1086. {
  1087. if( list->displayPos > 0 )
  1088. adjustDisplay( window, -1, TRUE );
  1089. }
  1090. else if( (GameWindow *)mData1 == list->downButton )
  1091. {
  1092. if( list->displayPos + list->displayHeight <= list->totalHeight )
  1093. adjustDisplay( window, 1, TRUE );
  1094. }
  1095. break;
  1096. } // end left drag
  1097. // ------------------------------------------------------------------------
  1098. case GLM_DEL_ALL:
  1099. {
  1100. //
  1101. // Reset the listbox by freeing all the display string stuff and setting
  1102. // everything else to zero
  1103. //
  1104. // Loop through and destroy any display strings we've allocated that aren't used
  1105. for( Int i = 0; i < list->listLength; i++ )
  1106. {
  1107. // Loop though
  1108. ListEntryCell *cells = list->listData[i].cell;
  1109. for (int j = list->columns - 1; j >=0; j-- )
  1110. {
  1111. if(!cells)
  1112. break;
  1113. if( cells[j].cellType == LISTBOX_TEXT )
  1114. {
  1115. if ( cells[j].data )
  1116. {
  1117. TheDisplayStringManager->freeDisplayString((DisplayString *) cells[j].data );
  1118. }
  1119. }
  1120. cells[j].userData = NULL;
  1121. cells[j].data = NULL;
  1122. }
  1123. delete(list->listData[i].cell);
  1124. list->listData[i].cell = NULL;
  1125. }
  1126. //zero out the header structure
  1127. memset(list->listData,0,list->listLength * sizeof(ListEntryRow));
  1128. if( mData1 != GP_DONT_UPDATE )
  1129. {
  1130. list->displayPos = 0;
  1131. }
  1132. if( list->multiSelect )
  1133. memset( list->selections, -1, list->listLength * sizeof( Int ) );
  1134. else
  1135. list->selectPos = -1;
  1136. list->insertPos = 0;
  1137. list->endPos = 0;
  1138. list->totalHeight = 0;
  1139. adjustDisplay( window, 0, TRUE );
  1140. break;
  1141. } // end delete all
  1142. // ------------------------------------------------------------------------
  1143. case GLM_DEL_ENTRY:
  1144. {
  1145. Int i;
  1146. if( list->endPos <= (Int)mData1 )
  1147. break;
  1148. ListEntryCell *cells = list->listData[mData1].cell;
  1149. if(cells)
  1150. for( i = 0; i <= list->columns; i ++ )
  1151. {
  1152. if( cells[i].cellType == LISTBOX_TEXT && cells[i].data )
  1153. TheDisplayStringManager->freeDisplayString((DisplayString *) cells[i].data );
  1154. cells[i].data = NULL;
  1155. cells[i].userData = NULL;
  1156. }
  1157. delete [](list->listData[mData1].cell);
  1158. memcpy( &list->listData[mData1], &list->listData[(mData1+1)],
  1159. (list->endPos - mData1 - 1) * sizeof(ListEntryRow) );
  1160. list->endPos--;
  1161. list->insertPos = list->endPos;
  1162. if( list->multiSelect )
  1163. {
  1164. i = 0;
  1165. while( list->selections[i] >= 0 )
  1166. {
  1167. if( (Int)mData1 < list->selections[i] )
  1168. list->selections[i]--;
  1169. else if ( (Int)mData1 == list->selections[i] )
  1170. {
  1171. removeSelection( list, i );
  1172. i--; // compensate for lost entry
  1173. }
  1174. i++;
  1175. }
  1176. }
  1177. else
  1178. {
  1179. if( (Int)mData1 < list->selectPos )
  1180. list->selectPos--;
  1181. else if ( (Int)mData1 == list->selectPos )
  1182. list->selectPos = -1;
  1183. }
  1184. computeTotalHeight( window );
  1185. break;
  1186. } // end delete entry
  1187. // ------------------------------------------------------------------------
  1188. case GLM_ADD_ENTRY:
  1189. {
  1190. Bool success = TRUE;
  1191. Int addedIndex = -1;
  1192. AddMessageStruct *addInfo = (AddMessageStruct*)mData1;
  1193. if (addInfo->row >= list->insertPos)
  1194. addInfo->row = -1;
  1195. Int row = addInfo->row;
  1196. // Special case, we're just appending and we've reached the end.
  1197. if( addInfo->row == -1 && list->insertPos == list->listLength )
  1198. {
  1199. row = list->insertPos;
  1200. // Check to see if we've filled our buffer and need to scroll the window
  1201. if( list->insertPos == list->listLength )
  1202. {
  1203. if( list->autoPurge )
  1204. TheWindowManager->winSendSystemMsg( window, GLM_SCROLL_BUFFER, 1, 0 );
  1205. else
  1206. success = FALSE;
  1207. }
  1208. }
  1209. else if (addInfo->row != -1 && !addInfo->overwrite && list->insertPos == list->listLength)
  1210. {
  1211. // We're inserting into the middle with no space - see if we can scroll the window
  1212. if( list->autoPurge )
  1213. TheWindowManager->winSendSystemMsg( window, GLM_SCROLL_BUFFER, 1, 0 );
  1214. else
  1215. success = FALSE;
  1216. }
  1217. if(success)
  1218. {
  1219. if( addInfo->type == LISTBOX_TEXT )
  1220. {
  1221. addedIndex = addEntry( (UnicodeString *)addInfo->data, mData2, addInfo->row, addInfo->column, window, addInfo->overwrite );
  1222. }
  1223. else if ( addInfo->type == LISTBOX_IMAGE )
  1224. {
  1225. addedIndex = addImageEntry( (const Image *)addInfo->data, mData2, addInfo->row, addInfo->column, window, addInfo->overwrite,addInfo->width, addInfo->height );
  1226. }
  1227. else
  1228. success = FALSE;
  1229. }
  1230. if( success )
  1231. {
  1232. if( list->autoScroll )
  1233. {
  1234. while( TRUE )
  1235. {
  1236. // If off bottom of screen, scroll and try again.
  1237. // we use -1 because insertPos was increased in addEntry
  1238. if( row == -1 )
  1239. {
  1240. if( list->listData[(list->insertPos - 1)].listHeight >=
  1241. (list->displayPos + list->displayHeight) )
  1242. adjustDisplay( window, 1, TRUE );
  1243. else
  1244. break;
  1245. }
  1246. else
  1247. {
  1248. if( list->listData[( row )].listHeight >=
  1249. (list->displayPos + list->displayHeight) )
  1250. adjustDisplay( window, 1, TRUE );
  1251. else
  1252. break;
  1253. }
  1254. }
  1255. }
  1256. if( list->multiSelect )
  1257. {
  1258. Int i = 0;
  1259. while( list->selections[i] >= 0 )
  1260. {
  1261. if( (row = list->selections[i]) != 0 )
  1262. list->selections[i] = -1;
  1263. i++;
  1264. } // end while
  1265. } // end if
  1266. else
  1267. {
  1268. if( row == list->selectPos )
  1269. list->selectPos = -1;
  1270. }
  1271. } // end success
  1272. return((WindowMsgHandledType) addedIndex );
  1273. } // end add entry
  1274. // ------------------------------------------------------------------------
  1275. case GLM_TOGGLE_MULTI_SELECTION:
  1276. {
  1277. if( (Int)mData1 < 0 )
  1278. {
  1279. // a negative number will purge the entire list.
  1280. if( list->multiSelect )
  1281. memset( list->selections, -1, list->listLength * sizeof(Int) );
  1282. else
  1283. {
  1284. // this message has no effect in a non-multi listbox
  1285. }
  1286. break;
  1287. }
  1288. // if there is no cells we shouldn't be selecting this entry
  1289. if( !list->listData[ mData1 ].cell )
  1290. break;
  1291. if( list->multiSelect )
  1292. {
  1293. Int i = 0;
  1294. Bool removed = FALSE;
  1295. while( list->selections[i] >= 0 )
  1296. {
  1297. if( list->selections[i] == (Int)mData1 )
  1298. {
  1299. removeSelection( list, i );
  1300. removed = TRUE;
  1301. break;
  1302. }
  1303. i++;
  1304. }
  1305. if( removed == FALSE )
  1306. {
  1307. list->selections[i] = (Int)mData1;
  1308. list->selections[i+1] = -1;
  1309. }
  1310. }
  1311. else
  1312. {
  1313. // this message has no effect in a non-multi listbox
  1314. }
  1315. break;
  1316. } // end toggle multi-select
  1317. // ------------------------------------------------------------------------
  1318. case GLM_SET_SELECTION:
  1319. {
  1320. const Int *selectList = (const Int *)mData1;
  1321. Int selectCount = (Int)mData2;
  1322. DEBUG_ASSERTCRASH( list->multiSelect || selectCount == 1, ("Bad selection size"));
  1323. if( selectList[0] < 0 || list->listLength <= selectList[0] )
  1324. {
  1325. if( list->multiSelect )
  1326. memset( list->selections, -1, list->listLength * sizeof(Int) );
  1327. else
  1328. list->selectPos = -1;
  1329. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  1330. GLM_SELECTED,
  1331. (WindowMsgData)window,
  1332. list->selectPos );
  1333. break;
  1334. }
  1335. if( list->multiSelect )
  1336. {
  1337. // forced selections override the entire selection list.
  1338. for (Int i=0; i<selectCount && i<list->endPos; ++i)
  1339. {
  1340. // don't select off the end
  1341. if (list->listLength <= selectList[i])
  1342. {
  1343. break;
  1344. }
  1345. // if there is no cells we shouldn't be selecting this entry
  1346. if( !list->listData[ selectList[i] ].cell )
  1347. {
  1348. break;
  1349. }
  1350. list->selections[i] = selectList[i];
  1351. }
  1352. list->selections[i] = -1;
  1353. }
  1354. else
  1355. {
  1356. // if there is no cells we shouldn't be selecting this entry
  1357. if( !list->listData[ selectList[0] ].cell )
  1358. {
  1359. break;
  1360. }
  1361. list->selectPos = selectList[0];
  1362. GameWindow *parent = window->winGetParent();
  1363. if( parent && BitTest( parent->winGetStyle(), GWS_COMBO_BOX ) )
  1364. {
  1365. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  1366. GLM_SELECTED,
  1367. (WindowMsgData)window,
  1368. list->selectPos );
  1369. break;
  1370. }
  1371. if( list->listData[list->selectPos].listHeight < list->displayPos )
  1372. {
  1373. TheWindowManager->winSendSystemMsg( window, GLM_UPDATE_DISPLAY,
  1374. list->selectPos, 0 );
  1375. }
  1376. else if( list->listData[list->selectPos].listHeight >
  1377. (list->displayPos + list->displayHeight) )
  1378. {
  1379. if( list->selectPos > 0 )
  1380. list->displayPos =
  1381. list->listData[list->selectPos].listHeight - list->displayHeight;
  1382. else
  1383. list->displayPos = 0;
  1384. adjustDisplay( window, 0, TRUE );
  1385. } // end else if
  1386. } // end else
  1387. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  1388. GLM_SELECTED,
  1389. (WindowMsgData)window,
  1390. list->selectPos );
  1391. break;
  1392. } // end set selection
  1393. // ------------------------------------------------------------------------
  1394. case GLM_SCROLL_BUFFER:
  1395. {
  1396. if( list->endPos < (Int)mData1 )
  1397. break;
  1398. //
  1399. // scroll buffer literally scrolls the entire list data buffer
  1400. // up one entry, effectively removing the top entry.
  1401. //
  1402. //
  1403. // Loop through and remove all the entries from the top up until we reach
  1404. // the position mData1 contains
  1405. //
  1406. ListEntryCell *cells = NULL;
  1407. for (Int i = 0; i < (Int)mData1; i++)
  1408. {
  1409. cells = list->listData[i].cell;
  1410. if(cells)
  1411. for( Int j = 0; j < list->columns; j++ )
  1412. {
  1413. if( cells[j].cellType == LISTBOX_TEXT && cells[j].data )
  1414. TheDisplayStringManager->freeDisplayString((DisplayString *) cells[j].data );
  1415. // if (cells[i].userData)
  1416. // free(cells[i].userData);
  1417. cells[j].data = NULL;
  1418. cells[j].userData = NULL;
  1419. cells[j].color = 0;
  1420. cells[j].cellType = 0;
  1421. }
  1422. delete(list->listData[i].cell);
  1423. list->listData[i].cell = NULL;
  1424. }
  1425. //
  1426. // copy the cells up
  1427. //
  1428. memcpy(list->listData, &list->listData[mData1],
  1429. (list->endPos - mData1) * sizeof(ListEntryRow) );
  1430. list->endPos -= mData1;
  1431. list->insertPos = list->endPos;
  1432. //
  1433. // remove the display or links to images after the shift
  1434. //
  1435. for(i = 0; i < (Int)mData1; i ++)
  1436. {
  1437. list->listData[list->endPos + i].cell = NULL;
  1438. }
  1439. if( list->multiSelect )
  1440. {
  1441. Int i = 0;
  1442. while( list->selections[i] >= 0 )
  1443. {
  1444. if( (Int)mData1 >= list->selections[i] )
  1445. list->selections[i] -= (Int)mData1;
  1446. else
  1447. {
  1448. removeSelection( list, i );
  1449. i--; // compensate for lost entry
  1450. }
  1451. i++;
  1452. }
  1453. }
  1454. else
  1455. {
  1456. if( list->selectPos > 0 )
  1457. list->selectPos -= mData1;
  1458. }
  1459. if( list->displayPos > 0 )
  1460. adjustDisplay( window, (-1 * mData1), TRUE );
  1461. computeTotalHeight( window );
  1462. break;
  1463. } // end scroll buffer
  1464. // ------------------------------------------------------------------------
  1465. case GLM_GET_SELECTION:
  1466. {
  1467. if( list->multiSelect )
  1468. *(Int*)mData2 = (Int)list->selections;
  1469. else
  1470. *(Int*)mData2 = list->selectPos;
  1471. break;
  1472. } // end get selection
  1473. // ------------------------------------------------------------------------
  1474. case GLM_SET_UP_BUTTON:
  1475. list->upButton = (GameWindow *)mData1;
  1476. break;
  1477. // ------------------------------------------------------------------------
  1478. case GLM_SET_DOWN_BUTTON:
  1479. list->downButton = (GameWindow *)mData1;
  1480. break;
  1481. // ------------------------------------------------------------------------
  1482. case GLM_SET_SLIDER:
  1483. list->slider = (GameWindow *)mData1;
  1484. break;
  1485. // ------------------------------------------------------------------------
  1486. case GWM_CREATE:
  1487. break;
  1488. // ------------------------------------------------------------------------
  1489. case GGM_RESIZED:
  1490. {
  1491. Int width = (Int)mData1;
  1492. Int height = (Int)mData2;
  1493. ICoord2D downSize = {0, 0};
  1494. ICoord2D upSize = {0, 0};
  1495. ICoord2D sliderSize = {0, 0};
  1496. GameWindow *child = NULL;
  1497. ICoord2D sliderChildSize = {0, 0};
  1498. // get needed window sizes
  1499. if (list->downButton)
  1500. list->downButton->winGetSize( &downSize.x, &downSize.y );
  1501. if (list->upButton)
  1502. list->upButton->winGetSize( &upSize.x, &upSize.y );
  1503. if (list->slider)
  1504. {
  1505. list->slider->winGetSize( &sliderSize.x, &sliderSize.y );
  1506. child = list->slider->winGetChild();
  1507. if (child)
  1508. child->winGetSize( &sliderChildSize.x, &sliderChildSize.y );
  1509. }
  1510. if( list->upButton )
  1511. {
  1512. list->upButton->winSetPosition( width - upSize.x - 2, 2 );
  1513. }
  1514. if( list->downButton )
  1515. {
  1516. list->downButton->winSetPosition( width - downSize.x - 2,
  1517. height - downSize.y - 2 );
  1518. }
  1519. if( list->slider )
  1520. {
  1521. list->slider->winSetSize( sliderSize.x,
  1522. height - (2 * upSize.y) -6 );
  1523. list->slider->winSetPosition( width - sliderSize.x -2, upSize.y + 3 );
  1524. }
  1525. list->displayHeight = height;
  1526. // store display height
  1527. if( instData->getTextLength() )
  1528. {
  1529. list->displayHeight -= TheWindowManager->winFontHeight( instData->getFont() );
  1530. }
  1531. //
  1532. // Setup listbox Columns
  1533. //
  1534. if( list->columns == 1 )
  1535. {
  1536. list->columnWidth[0] = width;
  1537. if( list->slider )
  1538. {
  1539. ICoord2D sliderSize;
  1540. list->slider->winGetSize( &sliderSize.x, &sliderSize.y );
  1541. list->columnWidth[0] -= sliderSize.x;
  1542. } // end if
  1543. }// if
  1544. else
  1545. {
  1546. if( !list->columnWidthPercentage )
  1547. break;
  1548. if(!list->columnWidth)
  1549. break;
  1550. Int totalWidth = width;
  1551. if( list->slider )
  1552. {
  1553. ICoord2D sliderSize;
  1554. list->slider->winGetSize( &sliderSize.x, &sliderSize.y );
  1555. totalWidth -= sliderSize.x;
  1556. } // end if
  1557. for(Int i = 0; i < list->columns; i++ )
  1558. {
  1559. list->columnWidth[i] = list->columnWidthPercentage[i] * totalWidth / 100;
  1560. }// for
  1561. }// else
  1562. //reset the total height
  1563. computeTotalHeight(window);
  1564. break;
  1565. } // end resized
  1566. // ------------------------------------------------------------------------
  1567. case GLM_UPDATE_DISPLAY:
  1568. {
  1569. if( mData1 > 0 )
  1570. // set the display to the top of a specific entry
  1571. // which is the previous listHeight + 1
  1572. list->displayPos = list->listData[(mData1 - 1)].listHeight + 1;
  1573. else
  1574. list->displayPos = 0;
  1575. if( list->displayPos + list->displayHeight >= list->totalHeight )
  1576. {
  1577. list->displayPos = list->totalHeight - list->displayHeight;
  1578. }
  1579. adjustDisplay( window, 0, TRUE );
  1580. break;
  1581. } // end update display
  1582. // ------------------------------------------------------------------------
  1583. case GWM_DESTROY:
  1584. {
  1585. Int i;
  1586. // Loop through and destroy any display strings we've allocated
  1587. for( i = 0; i < list->listLength; i++ )
  1588. {
  1589. //We're now onto a row of cells we are not using anymore Pull off the cells and loop through them
  1590. ListEntryCell *cells = list->listData[i].cell;
  1591. for (int j = list->columns - 1; j >=0; j-- )
  1592. {
  1593. if(!cells)
  1594. break;
  1595. if( cells[j].cellType == LISTBOX_TEXT )
  1596. {
  1597. // If we can delete the stuff that won't be showing up in the new listData struture
  1598. if ( cells[j].data )
  1599. {
  1600. TheDisplayStringManager->freeDisplayString((DisplayString *) cells[j].data );
  1601. }
  1602. }
  1603. // if ( cells[j].userData )
  1604. // free(cells[j].userData);
  1605. // Null out the data pointers so they're not destroyed when we free up this listdata
  1606. cells[j].userData = NULL;
  1607. cells[j].data = NULL;
  1608. }
  1609. delete[](list->listData[i].cell);
  1610. list->listData[i].cell = NULL;
  1611. }
  1612. delete[]( list->listData );
  1613. if( list->columnWidth )
  1614. delete[]( list->columnWidth );
  1615. if( list->columnWidthPercentage )
  1616. delete[]( list->columnWidthPercentage );
  1617. if( list->multiSelect )
  1618. delete[]( list->selections );
  1619. delete( list );
  1620. break;
  1621. } // end destroy
  1622. // ------------------------------------------------------------------------
  1623. case GWM_INPUT_FOCUS:
  1624. {
  1625. // If we're losing focus
  1626. if( mData1 == FALSE )
  1627. {
  1628. BitClear( instData->m_state, WIN_STATE_HILITED );
  1629. }
  1630. else
  1631. {
  1632. BitSet( instData->m_state, WIN_STATE_HILITED );
  1633. }
  1634. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  1635. GGM_FOCUS_CHANGE,
  1636. mData1,
  1637. window->winGetWindowId() );
  1638. *(Bool*)mData2 = TRUE;
  1639. break;
  1640. } // end input focus
  1641. // ------------------------------------------------------------------------
  1642. case GSM_SLIDER_TRACK:
  1643. {
  1644. SliderData *sData = (SliderData *)list->slider->winGetUserData();
  1645. list->displayPos = sData->maxVal - mData2;
  1646. if( list->displayPos > (list->totalHeight - list->displayHeight + 1) )
  1647. list->displayPos = (list->totalHeight - list->displayHeight + 1);
  1648. if( list->displayPos < 0)
  1649. list->displayPos = 0;
  1650. adjustDisplay( window, 0, FALSE );
  1651. break;
  1652. } // end slider track
  1653. // ------------------------------------------------------------------------
  1654. case GLM_SET_ITEM_DATA:
  1655. {
  1656. void *data = (void *)mData2;
  1657. pos = (ICoord2D *)mData1;
  1658. if (pos->y >= 0 && pos->y < list->endPos && list->listData[pos->y].cell)
  1659. list->listData[pos->y].cell[pos->x].userData = data;
  1660. break;
  1661. }//case GLM_SET_ITEM_DATA:
  1662. // ------------------------------------------------------------------------
  1663. case GLM_GET_ITEM_DATA:
  1664. {
  1665. pos = (ICoord2D *)mData1;
  1666. void **data = (void **)mData2;
  1667. *data = NULL; // initialize to NULL
  1668. if (pos->y >= 0 && pos->y < list->endPos && list->listData[pos->y].cell)
  1669. *data = list->listData[pos->y].cell[pos->x].userData;
  1670. break;
  1671. }//case GLM_GET_ITEM_DATA:
  1672. default:
  1673. return MSG_IGNORED;
  1674. } // end switch( msg )
  1675. return MSG_HANDLED;
  1676. } // end GadgetListBoxSystem
  1677. // GadgetListBoxSetColors =====================================================
  1678. /** Set the colors for a list box, note that this will also automatically
  1679. * change the colors of any attached slider, slider thumb, and slider
  1680. * buttons */
  1681. //=============================================================================
  1682. void GadgetListBoxSetColors( GameWindow *listbox,
  1683. Color enabledColor,
  1684. Color enabledBorderColor,
  1685. Color enabledSelectedItemColor,
  1686. Color enabledSelectedItemBorderColor,
  1687. Color disabledColor,
  1688. Color disabledBorderColor,
  1689. Color disabledSelectedItemColor,
  1690. Color disabledSelectedItemBorderColor,
  1691. Color hiliteColor,
  1692. Color hiliteBorderColor,
  1693. Color hiliteSelectedItemColor,
  1694. Color hiliteSelectedItemBorderColor )
  1695. {
  1696. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  1697. // enabled
  1698. GadgetListBoxSetEnabledColor( listbox, enabledColor );
  1699. GadgetListBoxSetEnabledBorderColor( listbox, enabledBorderColor );
  1700. GadgetListBoxSetEnabledSelectedItemColor( listbox, enabledSelectedItemColor );
  1701. GadgetListBoxSetEnabledSelectedItemBorderColor( listbox, enabledSelectedItemBorderColor );
  1702. // disabled
  1703. GadgetListBoxSetDisabledColor( listbox, disabledColor );
  1704. GadgetListBoxSetDisabledBorderColor( listbox, disabledBorderColor );
  1705. GadgetListBoxSetDisabledSelectedItemColor( listbox, disabledSelectedItemColor );
  1706. GadgetListBoxSetDisabledSelectedItemBorderColor( listbox, disabledSelectedItemBorderColor );
  1707. // hilited
  1708. GadgetListBoxSetHiliteColor( listbox, hiliteColor );
  1709. GadgetListBoxSetHiliteBorderColor( listbox, hiliteBorderColor );
  1710. GadgetListBoxSetHiliteSelectedItemColor( listbox, hiliteSelectedItemColor );
  1711. GadgetListBoxSetHiliteSelectedItemBorderColor( listbox, hiliteSelectedItemBorderColor );
  1712. // assign default slider colors and images as part of the list box
  1713. GameWindow *slider = listboxData->slider;
  1714. if( slider )
  1715. {
  1716. GameWindow *upButton = listboxData->upButton;
  1717. GameWindow *downButton = listboxData->downButton;
  1718. // slider and slider thumb ----------------------------------------------
  1719. // enabled
  1720. GadgetSliderSetEnabledColor( slider, GadgetListBoxGetEnabledColor( listbox ) );
  1721. GadgetSliderSetEnabledBorderColor( slider, GadgetListBoxGetEnabledBorderColor( listbox ) );
  1722. // Disabled
  1723. GadgetSliderSetDisabledColor( slider, GadgetListBoxGetDisabledColor( listbox ) );
  1724. GadgetSliderSetDisabledBorderColor( slider, GadgetListBoxGetDisabledBorderColor( listbox ) );
  1725. // Hilite
  1726. GadgetSliderSetHiliteColor( slider, GadgetListBoxGetHiliteColor( listbox ) );
  1727. GadgetSliderSetHiliteBorderColor( slider, GadgetListBoxGetHiliteBorderColor( listbox ) );
  1728. // up button ------------------------------------------------------------
  1729. // enabled
  1730. GadgetButtonSetEnabledColor( upButton, GadgetSliderGetEnabledColor( slider ) );
  1731. GadgetButtonSetEnabledBorderColor( upButton, GadgetSliderGetEnabledBorderColor( slider ) );
  1732. GadgetButtonSetEnabledSelectedColor( upButton, GadgetSliderGetEnabledSelectedThumbColor( slider ) );
  1733. GadgetButtonSetEnabledSelectedBorderColor( upButton, GadgetSliderGetEnabledSelectedThumbBorderColor( slider ) );
  1734. // disabled
  1735. GadgetButtonSetDisabledColor( upButton, GadgetSliderGetDisabledColor( slider ) );
  1736. GadgetButtonSetDisabledBorderColor( upButton, GadgetSliderGetDisabledBorderColor( slider ) );
  1737. GadgetButtonSetDisabledSelectedColor( upButton, GadgetSliderGetDisabledSelectedThumbColor( slider ) );
  1738. GadgetButtonSetDisabledSelectedBorderColor( upButton, GadgetSliderGetDisabledSelectedThumbBorderColor( slider ) );
  1739. // hilite
  1740. GadgetButtonSetHiliteColor( upButton, GadgetSliderGetHiliteColor( slider ) );
  1741. GadgetButtonSetHiliteBorderColor( upButton, GadgetSliderGetHiliteBorderColor( slider ) );
  1742. GadgetButtonSetHiliteSelectedColor( upButton, GadgetSliderGetHiliteSelectedThumbColor( slider ) );
  1743. GadgetButtonSetHiliteSelectedBorderColor( upButton, GadgetSliderGetHiliteSelectedThumbBorderColor( slider ) );
  1744. // down button ----------------------------------------------------------
  1745. // enabled
  1746. GadgetButtonSetEnabledColor( downButton, GadgetSliderGetEnabledColor( slider ) );
  1747. GadgetButtonSetEnabledBorderColor( downButton, GadgetSliderGetEnabledBorderColor( slider ) );
  1748. GadgetButtonSetEnabledSelectedColor( downButton, GadgetSliderGetEnabledSelectedThumbColor( slider ) );
  1749. GadgetButtonSetEnabledSelectedBorderColor( downButton, GadgetSliderGetEnabledSelectedThumbBorderColor( slider ) );
  1750. // disabled
  1751. GadgetButtonSetDisabledColor( downButton, GadgetSliderGetDisabledColor( slider ) );
  1752. GadgetButtonSetDisabledBorderColor( downButton, GadgetSliderGetDisabledBorderColor( slider ) );
  1753. GadgetButtonSetDisabledSelectedColor( downButton, GadgetSliderGetDisabledSelectedThumbColor( slider ) );
  1754. GadgetButtonSetDisabledSelectedBorderColor( downButton, GadgetSliderGetDisabledSelectedThumbBorderColor( slider ) );
  1755. // hilite
  1756. GadgetButtonSetHiliteColor( downButton, GadgetSliderGetHiliteColor( slider ) );
  1757. GadgetButtonSetHiliteBorderColor( downButton, GadgetSliderGetHiliteBorderColor( slider ) );
  1758. GadgetButtonSetHiliteSelectedColor( downButton, GadgetSliderGetHiliteSelectedThumbColor( slider ) );
  1759. GadgetButtonSetHiliteSelectedBorderColor( downButton, GadgetSliderGetHiliteSelectedThumbBorderColor( slider ) );
  1760. } // end if
  1761. } // end GadgetListBoxSetColors
  1762. // GadgetListBoxGetText =======================================================
  1763. /** Get the text for a list box entry */
  1764. //=============================================================================
  1765. UnicodeString GadgetListBoxGetText( GameWindow *listbox, Int row, Int column)
  1766. {
  1767. Color color;
  1768. return GadgetListBoxGetTextAndColor( listbox,&color,row,column );
  1769. } // end GadgetListBoxGetText
  1770. // GadgetListBoxGetText =======================================================
  1771. /** Get the text for a list box entry */
  1772. //=============================================================================
  1773. UnicodeString GadgetListBoxGetTextAndColor( GameWindow *listbox, Color *color, Int row, Int column)
  1774. {
  1775. *color = 0;
  1776. // sanity
  1777. if( listbox == NULL || row == -1 || column == -1)
  1778. return UnicodeString::TheEmptyString;
  1779. // verify that this is a list box
  1780. if( BitTest( listbox->winGetStyle(), GWS_SCROLL_LISTBOX ) == FALSE )
  1781. return UnicodeString::TheEmptyString;
  1782. TextAndColor tAndC;
  1783. //UnicodeString result;
  1784. ICoord2D pos;
  1785. pos.x = column;
  1786. pos.y = row;
  1787. TheWindowManager->winSendSystemMsg( listbox, GLM_GET_TEXT, (WindowMsgData)&pos, (WindowMsgData)&tAndC );
  1788. *color = tAndC.color;
  1789. return tAndC.string;
  1790. //return UnicodeString::TheEmptyString;
  1791. } // end GadgetListBoxGetText
  1792. // GadgetListBoxAddEntryText ==================================================
  1793. /** Add a new string entry into the listbox at the insert position */
  1794. //=============================================================================
  1795. Int GadgetListBoxAddEntryText( GameWindow *listbox,
  1796. UnicodeString text,
  1797. Color color, Int row, Int column, Bool overwrite )
  1798. {
  1799. if (!listbox)
  1800. return -1;
  1801. if (text.isEmpty())
  1802. text = UnicodeString(L" ");
  1803. Int index;
  1804. AddMessageStruct addInfo;
  1805. addInfo.row = row;
  1806. addInfo.column = column;
  1807. addInfo.type = LISTBOX_TEXT;
  1808. addInfo.data = &text;
  1809. addInfo.overwrite = overwrite;
  1810. addInfo.height = -1;
  1811. addInfo.width = -1;
  1812. ListboxData *listData = (ListboxData *)listbox->winGetUserData();
  1813. Bool wasFull = (listData->listLength <= listData->endPos);
  1814. Int newEntryOffset = (wasFull)?0:1;
  1815. Int oldBottomIndex = GadgetListBoxGetBottomVisibleEntry(listbox);
  1816. /// @TODO: Don't do this type cast!
  1817. index = (Int) TheWindowManager->winSendSystemMsg( listbox, GLM_ADD_ENTRY, (WindowMsgData)&addInfo, color );
  1818. //DEBUG_ASSERTLOG(!listData->scrollIfAtEnd, ("Adding line %d (orig end was %d, newEntryOffset is %d, (%d-%d)?=%d, isFull=%d/%d ll=%d, end=%d\n",
  1819. //index, oldBottomIndex, newEntryOffset, index, oldBottomIndex, newEntryOffset, wasFull, GadgetListBoxIsFull(listbox), listData->listLength, listData->endPos));
  1820. if(listData->scrollIfAtEnd && index - oldBottomIndex == newEntryOffset && GadgetListBoxIsFull(listbox))
  1821. {
  1822. GadgetListBoxSetBottomVisibleEntry( listbox, index );
  1823. }
  1824. return (index);
  1825. } // end GadgetListBoxAddEntry
  1826. // GadgetListBoxAddEntryImage =================================================
  1827. /** Add a new string entry into the listbox at the insert position */
  1828. //=============================================================================
  1829. Int GadgetListBoxAddEntryImage( GameWindow *listbox, const Image *image,
  1830. Int row, Int column,
  1831. Int hight, Int width,
  1832. Bool overwrite, Color color )
  1833. {
  1834. Int index;
  1835. AddMessageStruct addInfo;
  1836. addInfo.row = row;
  1837. addInfo.column = column;
  1838. addInfo.type = LISTBOX_IMAGE;
  1839. addInfo.data = image;
  1840. addInfo.overwrite = overwrite;
  1841. addInfo.height = hight;
  1842. addInfo.width = width;
  1843. /// @TODO: Don't do this type cast!
  1844. index = (Int) TheWindowManager->winSendSystemMsg( listbox, GLM_ADD_ENTRY, (WindowMsgData)&addInfo, color );
  1845. return (index);
  1846. } // end GadgetListBoxAddEntryImage
  1847. Int GadgetListBoxAddEntryImage( GameWindow *listbox, const Image *image,
  1848. Int row, Int column,
  1849. Bool overwrite, Color color )
  1850. {
  1851. return GadgetListBoxAddEntryImage(listbox, image, row, column, -1, -1, overwrite, color);
  1852. }
  1853. // GadgetListBoxSetFont =======================================================
  1854. /** Set the font for a listbox control, we need to set the window
  1855. * text font, the tooltip font, and the edit text display strings for
  1856. * the text data itself and the secret text */
  1857. //=============================================================================
  1858. void GadgetListBoxSetFont( GameWindow *g, GameFont *font )
  1859. {
  1860. ListboxData *listData = (ListboxData *)g->winGetUserData();
  1861. DisplayString *dString;
  1862. // set the font for the display strings all windows have
  1863. dString = g->winGetInstanceData()->getTextDisplayString();
  1864. if( dString )
  1865. dString->setFont( font );
  1866. dString = g->winGetInstanceData()->getTooltipDisplayString();
  1867. if( dString )
  1868. dString->setFont( font );
  1869. // listbox specific
  1870. if( listData )
  1871. for( Int i = 0; i < listData->listLength; i++ )
  1872. {
  1873. if(listData->listData[i].cell)
  1874. for( Int j = 0; j < listData->columns; j++ )
  1875. {
  1876. if( listData->listData[i].cell[j].cellType == LISTBOX_TEXT && listData->listData[i].cell[j].data )
  1877. {
  1878. dString = (DisplayString *)listData->listData[i].cell[j].data;
  1879. dString->setFont( font );
  1880. }
  1881. }
  1882. } // end for i
  1883. } // end GadgetListBoxSetFont
  1884. // GadgetListboxCreateScrollbar ===============================================
  1885. /** Create the scroll bar using a slider and two buttons for a listbox */
  1886. //=============================================================================
  1887. void GadgetListboxCreateScrollbar( GameWindow *listbox )
  1888. {
  1889. ListboxData *listData = (ListboxData *)listbox->winGetUserData();
  1890. WinInstanceData winInstData;
  1891. SliderData sData = { 0 };
  1892. Int buttonWidth, buttonHeight;
  1893. Int sliderButtonWidth, sliderButtonHeight;
  1894. Int fontHeight;
  1895. Int top;
  1896. Int bottom;
  1897. UnsignedInt status = listbox->winGetStatus();
  1898. Bool title = FALSE;
  1899. Int width, height;
  1900. // get width and height of listbox
  1901. listbox->winGetSize( &width, &height );
  1902. // do we have a title
  1903. if( listbox->winGetTextLength() )
  1904. title = TRUE;
  1905. // remove unwanted status bits.
  1906. status &= ~(WIN_STATUS_BORDER | WIN_STATUS_HIDDEN | WIN_STATUS_NO_INPUT);
  1907. fontHeight = TheWindowManager->winFontHeight( listbox->winGetFont() );
  1908. top = title ? (fontHeight + 1):0;
  1909. bottom = title ? (height - (fontHeight + 1)):height;
  1910. // intialize instData
  1911. winInstData.init();
  1912. // size of button
  1913. buttonWidth = 21;//GADGET_SIZE;
  1914. buttonHeight = 22;//GADGET_SIZE;
  1915. // ----------------------------------------------------------------------
  1916. // Create Top Button
  1917. // ----------------------------------------------------------------------
  1918. status |= WIN_STATUS_IMAGE;
  1919. winInstData.m_owner = listbox;
  1920. winInstData.m_style = GWS_PUSH_BUTTON;
  1921. // if listbox tracks, so will this sub control
  1922. if( BitTest( listbox->winGetStyle(), GWS_MOUSE_TRACK ) )
  1923. BitSet( winInstData.m_style, GWS_MOUSE_TRACK );
  1924. listData->upButton =
  1925. TheWindowManager->gogoGadgetPushButton( listbox,
  1926. status | WIN_STATUS_ACTIVE | WIN_STATUS_ENABLED,
  1927. width - buttonWidth -2, top+2,
  1928. buttonWidth, buttonHeight,
  1929. &winInstData, NULL, TRUE );
  1930. // ----------------------------------------------------------------------
  1931. // Create Bottom Button
  1932. // ----------------------------------------------------------------------
  1933. winInstData.init();
  1934. winInstData.m_style = GWS_PUSH_BUTTON;
  1935. winInstData.m_owner = listbox;
  1936. // if listbox tracks, so will this sub control
  1937. if( BitTest( listbox->winGetStyle(), GWS_MOUSE_TRACK ) )
  1938. BitSet( winInstData.m_style, GWS_MOUSE_TRACK );
  1939. listData->downButton =
  1940. TheWindowManager->gogoGadgetPushButton( listbox,
  1941. status | WIN_STATUS_ACTIVE | WIN_STATUS_ENABLED,
  1942. width - buttonWidth -2,
  1943. (top + bottom - buttonHeight -2),
  1944. buttonWidth, buttonHeight,
  1945. &winInstData, NULL, TRUE );
  1946. // ----------------------------------------------------------------------
  1947. // create the slider
  1948. // ----------------------------------------------------------------------
  1949. // size of button
  1950. sliderButtonWidth = buttonWidth;//GADGET_SIZE;
  1951. sliderButtonHeight = GADGET_SIZE;
  1952. // intialize instData
  1953. winInstData.init();
  1954. winInstData.m_style = GWS_VERT_SLIDER;
  1955. winInstData.m_owner = listbox;
  1956. // if listbox tracks, so will this sub control
  1957. if( BitTest( listbox->winGetStyle(), GWS_MOUSE_TRACK ) )
  1958. BitSet( winInstData.m_style, GWS_MOUSE_TRACK );
  1959. // intialize sData
  1960. memset( &sData, 0, sizeof(SliderData) );
  1961. // Create Slider
  1962. listData->slider =
  1963. TheWindowManager->gogoGadgetSlider( listbox,
  1964. status | WIN_STATUS_ACTIVE | WIN_STATUS_ENABLED,
  1965. width - sliderButtonWidth - 2,
  1966. (top + buttonHeight + 3),
  1967. sliderButtonWidth, bottom - (2 * buttonHeight) - 6,
  1968. &winInstData, &sData, NULL, TRUE );
  1969. // we now have all the scrollbar parts, this better be set :)
  1970. listData->scrollBar = TRUE;
  1971. } // end GadgetListBoxCreateScrollbar
  1972. // GadgetListBoxAddMultiSelect ================================================
  1973. /** Enable multi selections for a listbox
  1974. *
  1975. * ASSUMPTION: The listLength must already be set at this time so
  1976. * that we can make enough space to hold all the selection data, if you
  1977. * change the list length you must also change the selection array
  1978. * for multi select listboxes
  1979. */
  1980. //=============================================================================
  1981. void GadgetListBoxAddMultiSelect( GameWindow *listbox )
  1982. {
  1983. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  1984. DEBUG_ASSERTCRASH(listboxData && listboxData->selections == NULL, ("selections is not NULL"));
  1985. listboxData->selections = NEW Int [listboxData->listLength];
  1986. DEBUG_LOG(( "Enable list box multi select: listLength (select) = %d * %d = %d bytes;\n",
  1987. listboxData->listLength, sizeof(Int),
  1988. listboxData->listLength *sizeof(Int) ));
  1989. if( listboxData->selections == NULL )
  1990. {
  1991. delete( listboxData->listData );
  1992. return;
  1993. } // end if
  1994. memset( listboxData->selections, -1,
  1995. listboxData->listLength * sizeof(Int) );
  1996. // set mutliselect flag
  1997. listboxData->multiSelect = TRUE;
  1998. // adjust the input procedure for the listbox
  1999. listbox->winSetInputFunc( GadgetListBoxMultiInput );
  2000. } // end GadgetListBoxEnableMultiSelect
  2001. // GadgetListBoxRemoveMultiSelect =============================================
  2002. /** Remove multi select capability from a listbox */
  2003. //=============================================================================
  2004. void GadgetListBoxRemoveMultiSelect( GameWindow *listbox )
  2005. {
  2006. ListboxData *listData = (ListboxData *)listbox->winGetUserData();
  2007. if( listData->selections )
  2008. {
  2009. delete( listData->selections );
  2010. listData->selections = NULL;
  2011. } // end if
  2012. listData->multiSelect = FALSE;
  2013. // adjust the input procedure for the listbox
  2014. listbox->winSetInputFunc( GadgetListBoxInput );
  2015. } // end GadgetListBoxRemoveMultiSelect
  2016. // GadgetListBoxSetListLength =================================================
  2017. /** Set OR reset the list length data contained in the listboxData
  2018. * parameter. When adjusting the size of lists we also have to
  2019. * adjust multiselection lists if present and any display
  2020. * strings present */
  2021. //=============================================================================
  2022. void GadgetListBoxSetListLength( GameWindow *listbox, Int newLength )
  2023. {
  2024. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2025. // ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2026. // ListEntry *newData = (ListEntry *)malloc(newLength * sizeof(ListEntry));
  2027. DEBUG_ASSERTCRASH(listboxData, ("We don't have our needed listboxData!"));
  2028. if( !listboxData )
  2029. return;
  2030. DEBUG_ASSERTCRASH(listboxData->columns > 0,("We need at least one Column in the listbox"));
  2031. if( listboxData->columns < 1 )
  2032. return;
  2033. Int columns = listboxData->columns;
  2034. ListEntryRow *newData = NEW ListEntryRow[ newLength ];
  2035. DEBUG_ASSERTCRASH(newData, ("Unable to allocate new data structures for the Listbox"));
  2036. if( !newData )
  2037. return;
  2038. Int i;
  2039. // zero out the new Data structure
  2040. memset( newData, 0, newLength * sizeof( ListEntryRow ) );
  2041. // we want to copy over different amounts of data depending on if we're adding
  2042. // to the list box or removing from the listbox
  2043. if(newLength >= listboxData->listLength)
  2044. {
  2045. memcpy(newData,listboxData->listData,listboxData->listLength * sizeof( ListEntryRow ) );
  2046. }
  2047. else
  2048. {
  2049. // If we're removing entries from the listbox, we need to reset the length,
  2050. // position, and selection to their new places
  2051. if( listboxData->displayPos >newLength)
  2052. listboxData->displayPos = newLength;
  2053. //if we're multiselect, just select no position
  2054. if(listboxData->selectPos > newLength || listboxData->multiSelect)
  2055. listboxData->selectPos = -1;
  2056. if(listboxData->insertPos > newLength)
  2057. listboxData->insertPos = newLength;
  2058. listboxData->endPos = newLength;
  2059. //copy only the data that we'll be needing.
  2060. memcpy(newData,listboxData->listData,newLength * sizeof( ListEntryRow ) );
  2061. }
  2062. // Loop through and destroy any display strings we've allocated that aren't used
  2063. for( i = 0; i < listboxData->listLength; i++ )
  2064. {
  2065. //We're now onto a row of cells we are not using anymore Pull off the cells and loop through them
  2066. ListEntryCell *cells = listboxData->listData[i].cell;
  2067. for (int j = columns - 1; j >=0; j-- )
  2068. {
  2069. if(!cells)
  2070. break;
  2071. if ( i >= newLength )
  2072. {
  2073. if( cells[j].cellType == LISTBOX_TEXT && i >= newLength)
  2074. {
  2075. // If we can delete the stuff that won't be showing up in the new listData struture
  2076. if ( cells[j].data )
  2077. {
  2078. TheDisplayStringManager->freeDisplayString((DisplayString *) cells[j].data );
  2079. }
  2080. }
  2081. // if ( cells[j].userData )
  2082. // free(cells[j].userData);
  2083. }
  2084. }
  2085. if ( i >= newLength )
  2086. delete(listboxData->listData[i].cell);
  2087. listboxData->listData[i].cell = NULL;
  2088. }
  2089. listboxData->listLength = newLength;
  2090. if( listboxData->listData )
  2091. delete( listboxData->listData );
  2092. listboxData->listData = newData;
  2093. //reset the total height
  2094. computeTotalHeight(listbox);
  2095. // Sanity check that everything was created properly
  2096. if( listboxData->listData == NULL )
  2097. {
  2098. DEBUG_LOG(( "Unable to allocate listbox data pointer\n" ));
  2099. assert( 0 );
  2100. return;
  2101. } // end if
  2102. // adjust the selection array for multi select listboxes
  2103. if( listboxData->multiSelect )
  2104. {
  2105. GadgetListBoxRemoveMultiSelect( listbox );
  2106. GadgetListBoxAddMultiSelect( listbox );
  2107. } // end if
  2108. } // end GadgetListBoxSetListLength
  2109. // GadgetListBoxGetListLength =================================================
  2110. /** Get the list length data contained in the listboxData
  2111. * parameter. */
  2112. //=============================================================================
  2113. Int GadgetListBoxGetListLength( GameWindow *listbox )
  2114. {
  2115. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2116. if (listboxData->multiSelect)
  2117. {
  2118. return listboxData->listLength;
  2119. }
  2120. else
  2121. {
  2122. return 1;
  2123. }
  2124. } // end GadgetListBoxGetListLength
  2125. // GadgetListBoxGetNumEntries =================================================
  2126. /** Get the list length data contained in the listboxData
  2127. * parameter. */
  2128. //=============================================================================
  2129. Int GadgetListBoxGetNumEntries( GameWindow *listbox )
  2130. {
  2131. if (!listbox)
  2132. return 0;
  2133. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2134. if (listboxData)
  2135. return listboxData->endPos;
  2136. return 0;
  2137. } // end GadgetListBoxGetNumEntries
  2138. //-------------------------------------------------------------------------------------------------
  2139. /** Get the selected item(s) of a listbox. For a single select listbox the parameter
  2140. * should be a single integer pointer. For a multi select listbox the parameter
  2141. * should be an (Int *), this array returned will be an array of indices of the selected items
  2142. * of the list box. An entry of -1 in this array is the "end" of the selected list,
  2143. * and this list will never be larger than the max items in the list box */
  2144. //-------------------------------------------------------------------------------------------------
  2145. void GadgetListBoxGetSelected( GameWindow *listbox, Int *selectList )
  2146. {
  2147. // sanity
  2148. if( listbox == NULL )
  2149. return;
  2150. // get selected indeces via system message
  2151. TheWindowManager->winSendSystemMsg( listbox, GLM_GET_SELECTION, 0, (WindowMsgData)selectList );
  2152. } // end GadgetListBoxGetSelected
  2153. //-------------------------------------------------------------------------------------------------
  2154. /** Set the selected item of a listbox. The parameter is a single integer. If
  2155. * the selected index is less than 0, nothing is selected. */
  2156. //-------------------------------------------------------------------------------------------------
  2157. void GadgetListBoxSetSelected( GameWindow *listbox, Int selectIndex )
  2158. {
  2159. // sanity
  2160. if( listbox == NULL )
  2161. return;
  2162. // set selected index via system message
  2163. TheWindowManager->winSendSystemMsg( listbox, GLM_SET_SELECTION, (WindowMsgData)(&selectIndex), 1 );
  2164. } // end GadgetListBoxSetSelected
  2165. //-------------------------------------------------------------------------------------------------
  2166. /** Set the selected item of a listbox. */
  2167. //-------------------------------------------------------------------------------------------------
  2168. void GadgetListBoxSetSelected( GameWindow *listbox, const Int *selectList, Int selectCount )
  2169. {
  2170. // sanity
  2171. if( listbox == NULL )
  2172. return;
  2173. // set selected index via system message
  2174. TheWindowManager->winSendSystemMsg( listbox, GLM_SET_SELECTION, (WindowMsgData)selectList, selectCount );
  2175. }
  2176. //-------------------------------------------------------------------------------------------------
  2177. /** Reset the content of the listbox */
  2178. //-------------------------------------------------------------------------------------------------
  2179. void GadgetListBoxReset( GameWindow *listbox )
  2180. {
  2181. // sanity
  2182. if( listbox == NULL )
  2183. return;
  2184. // reset via system message
  2185. TheWindowManager->winSendSystemMsg( listbox, GLM_DEL_ALL, 0, 0 );
  2186. } // end GadgetListBoxReset
  2187. //-------------------------------------------------------------------------------------------------
  2188. //-------------------------------------------------------------------------------------------------
  2189. void GadgetListBoxSetItemData( GameWindow *listbox, void *data, Int row, Int column )
  2190. {
  2191. ICoord2D pos;
  2192. pos.x = column;
  2193. pos.y = row;
  2194. if (listbox)
  2195. TheWindowManager->winSendSystemMsg( listbox, GLM_SET_ITEM_DATA, (WindowMsgData)&pos, (WindowMsgData)data);
  2196. }// void GadgetListBoxSetItemData( Int index, void *data )
  2197. //-------------------------------------------------------------------------------------------------
  2198. //-------------------------------------------------------------------------------------------------
  2199. void *GadgetListBoxGetItemData( GameWindow *listbox, Int row, Int column)
  2200. {
  2201. void *data = NULL;
  2202. ICoord2D pos;
  2203. pos.x = column;
  2204. pos.y = row;
  2205. if (listbox)
  2206. {
  2207. TheWindowManager->winSendSystemMsg( listbox, GLM_GET_ITEM_DATA, (WindowMsgData)&pos, (WindowMsgData)&data);
  2208. }
  2209. return (data);
  2210. }
  2211. //-------------------------------------------------------------------------------------------------
  2212. //-------------------------------------------------------------------------------------------------
  2213. Int GadgetListBoxGetBottomVisibleEntry( GameWindow *window )
  2214. {
  2215. if (!window)
  2216. return 0;
  2217. ListboxData *listData = (ListboxData *)window->winGetUserData();
  2218. if (!listData)
  2219. return 0;
  2220. return getListboxBottomEntry(listData);
  2221. }
  2222. //-------------------------------------------------------------------------------------------------
  2223. //-------------------------------------------------------------------------------------------------
  2224. bool GadgetListBoxIsFull(GameWindow *window)
  2225. {
  2226. if (!window)
  2227. return FALSE;
  2228. ListboxData *listData = (ListboxData *)window->winGetUserData();
  2229. if (!listData)
  2230. return FALSE;
  2231. Int entry = getListboxBottomEntry(listData);
  2232. if(listData->listData[entry].listHeight >= listData->displayPos + listData->displayHeight - 5)
  2233. return TRUE;
  2234. else
  2235. return FALSE;
  2236. }
  2237. //-------------------------------------------------------------------------------------------------
  2238. //-------------------------------------------------------------------------------------------------
  2239. void GadgetListBoxSetBottomVisibleEntry( GameWindow *window, Int newPos )
  2240. {
  2241. if (!window)
  2242. return;
  2243. ListboxData *listData = (ListboxData *)window->winGetUserData();
  2244. if (!listData)
  2245. return;
  2246. int prevPos = GadgetListBoxGetBottomVisibleEntry( window );
  2247. adjustDisplay(window, newPos - prevPos + 1, true);
  2248. } // void GadgetListBoxSetTopVisibleEntry( GameWindow *window, Int newPos )
  2249. //-------------------------------------------------------------------------------------------------
  2250. //-------------------------------------------------------------------------------------------------
  2251. Int GadgetListBoxGetTopVisibleEntry( GameWindow *window )
  2252. {
  2253. if (!window)
  2254. return 0;
  2255. ListboxData *listData = (ListboxData *)window->winGetUserData();
  2256. if (!listData)
  2257. return 0;
  2258. return getListboxTopEntry(listData);
  2259. } // Int GadgetListBoxGetTopVisibleEntry( GameWindow *window )
  2260. //-------------------------------------------------------------------------------------------------
  2261. //-------------------------------------------------------------------------------------------------
  2262. void GadgetListBoxSetTopVisibleEntry( GameWindow *window, Int newPos )
  2263. {
  2264. if (!window)
  2265. return;
  2266. ListboxData *listData = (ListboxData *)window->winGetUserData();
  2267. if (!listData)
  2268. return;
  2269. int prevPos = GadgetListBoxGetTopVisibleEntry( window );
  2270. adjustDisplay(window, newPos - prevPos, true);
  2271. } // void GadgetListBoxSetTopVisibleEntry( GameWindow *window, Int newPos )
  2272. //-------------------------------------------------------------------------------------------------
  2273. //-------------------------------------------------------------------------------------------------
  2274. void GadgetListBoxSetAudioFeedback( GameWindow *listbox, Bool enable )
  2275. {
  2276. if (!listbox)
  2277. return;
  2278. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2279. if (!listboxData)
  2280. return;
  2281. listboxData->audioFeedback = enable;
  2282. } // end GadgetListBoxSetAudioFeedback
  2283. //-------------------------------------------------------------------------------------------------
  2284. //-------------------------------------------------------------------------------------------------
  2285. Int GadgetListBoxGetNumColumns( GameWindow *listbox )
  2286. {
  2287. if (!listbox)
  2288. return 0;
  2289. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2290. if (!listboxData)
  2291. return 0;
  2292. return listboxData->columns;
  2293. } // end GadgetListBoxGetNumColumns
  2294. //-------------------------------------------------------------------------------------------------
  2295. //-------------------------------------------------------------------------------------------------
  2296. Int GadgetListBoxGetColumnWidth( GameWindow *listbox, Int column )
  2297. {
  2298. if (!listbox)
  2299. return 0;
  2300. ListboxData *listboxData = (ListboxData *)listbox->winGetUserData();
  2301. if (!listboxData)
  2302. return 0;
  2303. if (listboxData->columns <= column || column < 0)
  2304. return 0;
  2305. return listboxData->columnWidth[column];
  2306. } // end GadgetListBoxGetNumColumns