12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "gui/controls/guiListBoxCtrl.h"
- #include "gfx/gfxDrawUtil.h"
- #include "console/engineAPI.h"
- IMPLEMENT_CONOBJECT(GuiListBoxCtrl);
- ConsoleDocClass( GuiListBoxCtrl,
- "@brief A list of text items.\n\n"
- "A list of text items where each individual entry can have its own text value, text color and associated SimObject.\n\n"
- "@tsexample\n"
- "new GuiListBoxCtrl(GuiMusicPlayerMusicList)\n"
- "{\n"
- " allowMultipleSelections = \"true\";\n"
- " fitParentWidth = \"true\";\n"
- " mirrorSet = \"AnotherGuiListBoxCtrl\";\n"
- " makeNameCallback = \"\";\n"
- " colorBullet = \"1\";\n"
- " //Properties not specific to this control have been omitted from this example.\n"
- "};\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- "@ingroup GuiCore\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onMouseDragged, void, (),(),
- "@brief Called whenever the mouse is dragged across the control.\n\n"
- "@tsexample\n"
- "// Mouse is dragged across the control, causing the callback to occur.\n"
- "GuiListBoxCtrl::onMouseDragged(%this)\n"
- " {\n"
- " // Code to run whenever the mouse is dragged across the control\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onClearSelection, void, (),(),
- "@brief Called whenever a selected item in the list is cleared.\n\n"
- "@tsexample\n"
- "// A selected item is cleared, causing the callback to occur.\n"
- "GuiListBoxCtrl::onClearSelection(%this)\n"
- " {\n"
- " // Code to run whenever a selected item is cleared\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onUnSelect, void, ( S32 index, const char* itemText),( index, itemText ),
- "@brief Called whenever a selected item in the list has been unselected.\n\n"
- "@param index Index id of the item that was unselected\n"
- "@param itemText Text for the list entry at the index id that was unselected\n\n"
- "@tsexample\n"
- "// A selected item is unselected, causing the callback to occur\n"
- "GuiListBoxCtrl::onUnSelect(%this, %indexId, %itemText)\n"
- " {\n"
- " // Code to run whenever a selected list item is unselected\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onSelect, void, ( S32 index , const char* itemText ),( index, itemText ),
- "@brief Called whenever an item in the list is selected.\n\n"
- "@param index Index id for the item in the list that was selected.\n"
- "@param itemText Text for the list item at the index that was selected.\n\n"
- "@tsexample\n"
- "// An item in the list is selected, causing the callback to occur\n"
- "GuiListBoxCtrl::onSelect(%this, %index, %itemText)\n"
- " {\n"
- " // Code to run whenever an item in the list is selected\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onDoubleClick, void, (),(),
- "@brief Called whenever an item in the list has been double clicked.\n\n"
- "@tsexample\n"
- "// An item in the list is double clicked, causing the callback to occur.\n"
- "GuiListBoxCtrl::onDoubleClick(%this)\n"
- " {\n"
- " // Code to run whenever an item in the control has been double clicked\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onMouseUp, void, ( S32 itemHit, S32 mouseClickCount ),( itemHit,mouseClickCount ),
- "@brief Called whenever the mouse has previously been clicked down (onMouseDown) and has now been raised on the control.\n"
- "If an item in the list was hit during the click cycle, then the index id of the clicked object along with how many clicks occured are passed\n"
- "into the callback.\n\n"
- "Detailed description\n\n"
- "@param itemHit Index id for the list item that was hit\n"
- "@param mouseClickCount How many mouse clicks occured on this list item\n\n"
- "@tsexample\n"
- "// Mouse was previously clicked down, and now has been released, causing the callback to occur.\n"
- "GuiListBoxCtrl::onMouseUp(%this, %itemHit, %mouseClickCount)\n"
- " {\n"
- " // Code to call whenever the mouse has been clicked and released on the control\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, onDeleteKey, void, (),(),
- "@brief Called whenever the Delete key on the keyboard has been pressed while in this control.\n\n"
- "@tsexample\n"
- "// The delete key on the keyboard has been pressed while this control is in focus, causing the callback to occur.\n"
- "GuiListBoxCtrl::onDeleteKey(%this)\n"
- " {\n"
- " // Code to call whenever the delete key is pressed\n"
- " }\n"
- "@endtsexample\n\n"
- "@see GuiControl\n\n"
- );
- IMPLEMENT_CALLBACK( GuiListBoxCtrl, isObjectMirrored, bool, ( const char* indexIdString ),( indexIdString ),
- "@brief Checks if a list item at a defined index id is mirrored, and returns the result.\n\n"
- "@param indexIdString Index id of the list to check.\n"
- "@tsexample\n"
- "// Engine has requested of the script level to determine if a list entry is mirrored or not.\n"
- "GuiListBoxCtrl::isObjectMirrored(%this, %indexIdString)\n"
- " {\n"
- " // Perform code required to check and see if the list item at the index id is mirrored or not.\n"
- " return %isMirrored;\n"
- " }\n"
- "@endtsexample\n\n"
- "@return A boolean value on if the list item is mirrored or not.\n\n"
- "@see GuiControl\n\n"
- );
- GuiListBoxCtrl::GuiListBoxCtrl()
- {
- mItems.clear();
- mSelectedItems.clear();
- mMultipleSelections = true;
- mFitParentWidth = true;
- mColorBullet = true;
- mItemSize = Point2I(10,20);
- mLastClickItem = NULL;
-
- mRenderTooltipDelegate.bind( this, &GuiListBoxCtrl::renderTooltip );
- }
- GuiListBoxCtrl::~GuiListBoxCtrl()
- {
- clearItems();
- }
- void GuiListBoxCtrl::initPersistFields()
- {
- addField( "allowMultipleSelections", TypeBool, Offset( mMultipleSelections, GuiListBoxCtrl), "If true, will allow the selection of multiple items in the listbox.\n");
- addField( "fitParentWidth", TypeBool, Offset( mFitParentWidth, GuiListBoxCtrl), "If true, the width of the listbox will match the width of its parent control.\n");
- addField( "colorBullet", TypeBool, Offset( mColorBullet, GuiListBoxCtrl), "If true, colored items will render a colored rectangular bullet next to the item text.\n");
- addField( "mirrorSet", TypeRealString, Offset( mMirrorSetName, GuiListBoxCtrl ), "If populated with the name of another GuiListBoxCtrl, then this list box will mirror the contents of the mirrorSet listbox.\n");
- addField( "makeNameCallback", TypeRealString, Offset( mMakeNameCallback, GuiListBoxCtrl ), "A script snippet to control what is displayed in the list for a SimObject. Within this snippet, $ThisControl is bound to the guiListBoxCtrl and $ThisObject to the contained object in question.\n");
- Parent::initPersistFields();
- }
- bool GuiListBoxCtrl::onWake()
- {
- if( !Parent::onWake() )
- return false;
- updateSize();
- return true;
- }
- //-----------------------------------------------------------------------------
- // Item Accessors
- //-----------------------------------------------------------------------------
- DefineEngineMethod( GuiListBoxCtrl, setMultipleSelection, void, (bool allowMultSelections),,
- "@brief Enable or disable multiple selections for this GuiListBoxCtrl object.\n\n"
- "@param allowMultSelections Boolean variable to set the use of multiple selections or not.\n"
- "@tsexample\n"
- "// Define the multiple selection use state.\n"
- "%allowMultSelections = \"true\";\n\n"
- "// Set the allow multiple selection state on the GuiListBoxCtrl object.\n"
- "%thisGuiListBoxCtrl.setMultipleSelection(%allowMultSelections);\n"
- "@endtsexample\n\n"
- "@see GuiControl\n")
- {
- object->setMultipleSelection( allowMultSelections );
- }
- DefineEngineMethod( GuiListBoxCtrl, clearItems, void, (),,
- "@brief Clears all the items in the listbox.\n\n"
- "@tsexample\n"
- "// Inform the GuiListBoxCtrl object to clear all items from its list.\n"
- "%thisGuiListBoxCtrl.clearItems();\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->clearItems();
- }
- void GuiListBoxCtrl::clearItems()
- {
- // Free item list allocated memory
- while( mItems.size() )
- deleteItem( 0 );
- // Free our vector lists
- mItems.clear();
- mSelectedItems.clear();
- mFilteredItems.clear();
- }
- DefineEngineMethod( GuiListBoxCtrl, clearSelection, void, (),,
- "@brief Sets all currently selected items to unselected.\n\n"
- "Detailed description\n\n"
- "@tsexample\n"
- "// Inform the GuiListBoxCtrl object to set all of its items to unselected./n"
- "%thisGuiListBoxCtrl.clearSelection();\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->clearSelection();
- }
- void GuiListBoxCtrl::clearSelection()
- {
- if( !mSelectedItems.size() )
- return;
- VectorPtr<LBItem*>::iterator i = mSelectedItems.begin();
- for( ; i != mSelectedItems.end(); i++ )
- (*i)->isSelected = false;
- mSelectedItems.clear();
- onClearSelection_callback();
- }
- DefineEngineMethod( GuiListBoxCtrl, setSelected, void, (S32 index, bool setSelected), (true),
- "@brief Sets the item at the index specified to selected or not.\n\n"
- "Detailed description\n\n"
- "@param index Item index to set selected or unselected.\n"
- "@param setSelected Boolean selection state to set the requested item index.\n"
- "@tsexample\n"
- "// Define the index\n"
- "%index = \"5\";\n\n"
- "// Define the selection state\n"
- "%selected = \"true\"\n\n"
- "// Inform the GuiListBoxCtrl object of the new selection state for the requested index entry.\n"
- "%thisGuiListBoxCtrl.setSelected(%index,%selected);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- if( setSelected == true )
- object->addSelection( index );
- else
- object->removeSelection( index );
- }
- void GuiListBoxCtrl::removeSelection( S32 index )
- {
- // Range Check
- if( index >= mItems.size() || index < 0 )
- {
- Con::warnf("GuiListBoxCtrl::removeSelection - index out of range!" );
- return;
- }
- removeSelection( mItems[index], index );
- }
- void GuiListBoxCtrl::removeSelection( LBItem *item, S32 index )
- {
- if( !mSelectedItems.size() )
- return;
- if( !item )
- return;
- for( S32 i = 0 ; i < mSelectedItems.size(); i++ )
- {
- if( mSelectedItems[i] == item )
- {
- mSelectedItems.erase( &mSelectedItems[i] );
- item->isSelected = false;
- onUnSelect_callback(index, item->itemText);
- return;
- }
- }
- }
- void GuiListBoxCtrl::addSelection( S32 index )
- {
- // Range Check
- if( index >= mItems.size() || index < 0 )
- {
- Con::warnf("GuiListBoxCtrl::addSelection- index out of range!" );
- return;
- }
- addSelection( mItems[index], index );
- }
- void GuiListBoxCtrl::addSelection( LBItem *item, S32 index )
- {
- if( !mMultipleSelections )
- {
- if( !mSelectedItems.empty() )
- {
- LBItem* selItem = mSelectedItems.front();
- if( selItem != item )
- clearSelection();
- else
- return;
- }
- }
- else
- {
- if( !mSelectedItems.empty() )
- {
- for( S32 i = 0; i < mSelectedItems.size(); i++ )
- {
- if( mSelectedItems[ i ] == item )
- return;
- }
- }
- }
- item->isSelected = true;
- mSelectedItems.push_front( item );
- onSelect_callback(index, item->itemText);
- }
- S32 GuiListBoxCtrl::getItemIndex( LBItem *item )
- {
- if( mItems.empty() )
- return -1;
- // Lookup the index of an item in our list, by the pointer to the item
- for( S32 i = 0; i < mItems.size(); i++ )
- if( mItems[i] == item )
- return i;
- return -1;
- }
- DefineEngineMethod( GuiListBoxCtrl, getItemCount, S32, (),,
- "@brief Returns the number of items in the list.\n\n"
- "@tsexample\n"
- "// Request the number of items in the list of the GuiListBoxCtrl object.\n"
- "%listItemCount = %thisGuiListBoxCtrl.getItemCount();\n"
- "@endtsexample\n\n"
- "@return The number of items in the list.\n\n"
- "@see GuiControl")
- {
- return object->getItemCount();
- }
- S32 GuiListBoxCtrl::getItemCount()
- {
- return mItems.size();
- }
- DefineEngineMethod( GuiListBoxCtrl, getSelCount, S32, (),,
- "@brief Returns the number of items currently selected.\n\n"
- "@tsexample\n"
- "// Request the number of currently selected items\n"
- "%selectedItemCount = %thisGuiListBoxCtrl.getSelCount();\n"
- "@endtsexample\n\n"
- "@return Number of currently selected items.\n\n"
- "@see GuiControl")
- {
- return object->getSelCount();
- }
- S32 GuiListBoxCtrl::getSelCount()
- {
- return mSelectedItems.size();
- }
- DefineEngineMethod( GuiListBoxCtrl, getSelectedItem, S32, (),,
- "@brief Returns the selected items index or -1 if none selected. If multiple selections exist it returns the first selected item. \n\n"
- "@tsexample\n"
- "// Request the index id of the currently selected item\n"
- "%selectedItemId = %thisGuiListBoxCtrl.getSelectedItem();\n"
- "@endtsexample\n\n"
- "@return The selected items index or -1 if none selected.\n\n"
- "@see GuiControl")
- {
- return object->getSelectedItem();
- }
- S32 GuiListBoxCtrl::getSelectedItem()
- {
- if( mSelectedItems.empty() || mItems.empty() )
- return -1;
- for( S32 i = 0 ; i < mItems.size(); i++ )
- if( mItems[i]->isSelected )
- return i;
- return -1;
- }
- DefineEngineMethod( GuiListBoxCtrl, getSelectedItems, const char*, (),,
- "@brief Returns a space delimited list of the selected items indexes in the list.\n\n"
- "@tsexample\n"
- "// Request a space delimited list of the items in the GuiListBoxCtrl object.\n"
- "%selectionList = %thisGuiListBoxCtrl.getSelectedItems();\n"
- "@endtsexample\n\n"
- "@return Space delimited list of the selected items indexes in the list\n\n"
- "@see GuiControl")
- {
- S32 selCount = object->getSelCount();
- if( selCount == -1 || selCount == 0 )
- return StringTable->lookup("-1");
- else if( selCount == 1 )
- return Con::getIntArg(object->getSelectedItem());
- Vector<S32> selItems;
- object->getSelectedItems( selItems );
- if( selItems.empty() )
- return StringTable->lookup("-1");
- static const U32 bufSize = selItems.size() * 4;
- UTF8 *retBuffer = Con::getReturnBuffer( bufSize );
- dMemset( retBuffer, 0, bufSize );
- Vector<S32>::iterator i = selItems.begin();
- for( ; i != selItems.end(); i++ )
- {
- UTF8 retFormat[12];
- dSprintf( retFormat, 12, "%d ", (*i) );
- dStrcat( retBuffer, retFormat, 12 );
- }
- return retBuffer;
- }
- void GuiListBoxCtrl::getSelectedItems( Vector<S32> &Items )
- {
- // Clear our return vector
- Items.clear();
-
- // If there are no selected items, return an empty vector
- if( mSelectedItems.empty() )
- return;
-
- for( S32 i = 0; i < mItems.size(); i++ )
- if( mItems[i]->isSelected )
- Items.push_back( i );
- }
- DefineEngineMethod( GuiListBoxCtrl, findItemText, S32, (const char* findText, bool bCaseSensitive), (false),
- "@brief Returns index of item with matching text or -1 if none found.\n\n"
- "@param findText Text in the list to find.\n"
- "@param isCaseSensitive If true, the search will be case sensitive.\n"
- "@tsexample\n"
- "// Define the text we wish to find in the list.\n"
- "%findText = \"Hickory Smoked Gideon\"/n/n"
- "// Define if this is a case sensitive search or not.\n"
- "%isCaseSensitive = \"false\";\n\n"
- "// Ask the GuiListBoxCtrl object what item id in the list matches the requested text.\n"
- "%matchingId = %thisGuiListBoxCtrl.findItemText(%findText,%isCaseSensitive);\n"
- "@endtsexample\n\n"
- "@return Index id of item with matching text or -1 if none found.\n\n"
- "@see GuiControl")
- {
- return object->findItemText( findText, bCaseSensitive );
- }
- S32 GuiListBoxCtrl::findItemText( StringTableEntry text, bool caseSensitive )
- {
- // Check Proper Arguments
- if( !text || !text[0] || text == StringTable->lookup("") )
- {
- Con::warnf("GuiListBoxCtrl::findItemText - No Text Specified!");
- return -1;
- }
- // Check Items Exist.
- if( mItems.empty() )
- return -1;
- // Lookup the index of an item in our list, by the pointer to the item
- for( S32 i = 0; i < mItems.size(); i++ )
- {
- // Case Sensitive Compare?
- if( caseSensitive && ( String::compare( mItems[i]->itemText, text ) == 0 ) )
- return i;
- else if (!caseSensitive && ( dStricmp( mItems[i]->itemText, text ) == 0 ))
- return i;
- }
- // Not Found!
- return -1;
- }
- DefineEngineMethod( GuiListBoxCtrl, setCurSel, void, (S32 indexId),,
- "@brief Sets the currently selected item at the specified index.\n\n"
- "@param indexId Index Id to set selected.\n"
- "@tsexample\n"
- "// Define the index id that we wish to select.\n"
- "%selectId = \"4\";\n\n"
- "// Inform the GuiListBoxCtrl object to set the requested index as selected.\n"
- "%thisGuiListBoxCtrl.setCurSel(%selectId);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->setCurSel( indexId );
- }
- void GuiListBoxCtrl::setCurSel( S32 index )
- {
- // Range Check
- if( index >= mItems.size() )
- {
- Con::warnf("GuiListBoxCtrl::setCurSel - index out of range!" );
- return;
- }
- // If index -1 is specified, we clear the selection
- if( index == -1 )
- {
- mSelectedItems.clear();
- return;
- }
- // Add the selection
- addSelection( mItems[ index ], index );
- }
- DefineEngineMethod( GuiListBoxCtrl, setCurSelRange, void, (S32 indexStart, S32 indexStop), (999999),
- "@brief Sets the current selection range from index start to stop. If no stop is specified it sets from start index to the end of the list\n\n"
- "@param indexStart Index Id to start selection.\n"
- "@param indexStop Index Id to end selection.\n"
- "@tsexample\n"
- "// Set start id\n"
- "%indexStart = \"3\";\n\n"
- "// Set end id\n"
- "%indexEnd = \"6\";\n\n"
- "// Request the GuiListBoxCtrl object to select the defined range.\n"
- "%thisGuiListBoxCtrl.setCurSelRange(%indexStart,%indexEnd);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->setCurSelRange( indexStart , indexStop );
- }
- void GuiListBoxCtrl::setCurSelRange( S32 start, S32 stop )
- {
- // Verify Selection Range
- if( start < 0 )
- start = 0;
- else if( start > mItems.size() )
- start = mItems.size();
- if( stop < 0 )
- stop = 0;
- else if( stop > mItems.size() )
- stop = mItems.size();
- S32 iterStart = ( start < stop ) ? start : stop;
- S32 iterStop = ( start < stop ) ? stop : start;
- for( ; iterStart <= iterStop; iterStart++ )
- addSelection( mItems[iterStart], iterStart );
- }
- DefineEngineMethod( GuiListBoxCtrl, addItem, S32, (const char* newItem, const char* color), ( "" ),
- "@brief Adds an item to the end of the list with an optional color.\n\n"
- "@param newItem New item to add to the list.\n"
- "@param color Optional color parameter to add to the new item.\n"
- "@tsexample\n"
- "// Define the item to add to the list.\n"
- "%newItem = \"Gideon's Blue Coat\";\n\n"
- "// Define the optional color for the new list item.\n"
- "%color = \"0.0 0.0 1.0\";\n\n"
- "// Inform the GuiListBoxCtrl object to add the item to the end of the list with the defined color.\n"
- "%thisGuiListBoxCtrl.addItem(%newItem,%color);\n"
- "@endtsexample\n\n"
- "@return If not void, return value and description\n\n"
- "@see GuiControl\n"
- "@hide")
- {
- if(dStricmp(color,"") == 0)
- {
- return object->addItem( newItem );
- }
- else
- {
- U32 elementCount = GuiListBoxCtrl::getStringElementCount(color);
- if(elementCount == 3)
- {
- F32 red, green, blue;
- red = dAtof(GuiListBoxCtrl::getStringElement( color, 0 ));
- green = dAtof(GuiListBoxCtrl::getStringElement( color, 1 ));
- blue = dAtof(GuiListBoxCtrl::getStringElement( color, 2 ));
- return object->addItemWithColor( newItem, LinearColorF(red, green, blue) );
- }
- else if(elementCount == 1)
- {
- U32 objId = dAtoi( color );
- return object->addItem( newItem, (void*)(uintptr_t)objId );
- }
- else
- {
- Con::warnf("GuiListBoxCtrl::addItem() - Invalid number of parameters for the color!");
- return -1;
- }
- }
- }
- static ConsoleDocFragment sGuiControlSetExtent1(
- "@brief Adds an item to the control with the specific text.\n\n"
- "@param text Text item to add to the list.\n"
- "GuiListBoxCtrl", // The class to place the method in; use NULL for functions.
- "void addItem( const char* text );" );
- S32 GuiListBoxCtrl::addItem( StringTableEntry text, void *itemData )
- {
- // This just calls insert item at the end of the list
- return insertItem( mItems.size(), text, itemData );
- }
- S32 GuiListBoxCtrl::addItemWithColor( StringTableEntry text, LinearColorF color, void *itemData )
- {
- // This just calls insert item at the end of the list
- return insertItemWithColor( mItems.size(), text, color, itemData );
- }
- DefineEngineMethod( GuiListBoxCtrl, setItemColor, void, (S32 index, LinearColorF color),,
- "@brief Sets the color of a single list entry at the specified index id.\n\n"
- "@param index Index id to modify the color of in the list.\n"
- "@param color Color value to set the list entry to.\n"
- "@tsexample\n"
- "// Define the index id value\n"
- "%index = \"5\";\n\n"
- "// Define the color value\n"
- "%color = \"1.0 0.0 0.0\";\n\n"
- "// Inform the GuiListBoxCtrl object to change the color of the requested index\n"
- "%thisGuiListBoxCtrl.setItemColor(%index,%color);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->setItemColor( index, color );
- }
- void GuiListBoxCtrl::setItemColor(S32 index, const LinearColorF& color)
- {
- if ((index >= mItems.size()) || index < 0)
- {
- Con::warnf("GuiListBoxCtrl::setItemColor - invalid index");
- return;
- }
- LBItem* item = mItems[index];
- item->hasColor = true;
- item->color = color;
- }
- DefineEngineMethod( GuiListBoxCtrl, clearItemColor, void, (S32 index),,
- "@brief Removes any custom coloring from an item at the defined index id in the list.\n\n"
- "@param index Index id for the item to clear any custom color from.\n"
- "@tsexample\n"
- "// Define the index id\n"
- "%index = \"4\";\n\n"
- "// Request the GuiListBoxCtrl object to remove any custom coloring from the defined index entry\n"
- "%thisGuiListBoxCtrl.clearItemColor(%index);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->clearItemColor(index);
- }
- void GuiListBoxCtrl::clearItemColor( S32 index )
- {
- if ((index >= mItems.size()) || index < 0)
- {
- Con::warnf("GuiListBoxCtrl::setItemColor - invalid index");
- return;
- }
- LBItem* item = mItems[index];
- item->hasColor = false;
- }
- DefineEngineMethod( GuiListBoxCtrl, insertItem, void, (const char* text, S32 index),,
- "@brief Inserts an item into the list at the specified index and returns the index assigned or -1 on error.\n\n"
- "@param text Text item to add.\n"
- "@param index Index id to insert the list item text at.\n"
- "@tsexample\n"
- "// Define the text to insert\n"
- "%text = \"Secret Agent Gideon\";\n\n"
- "// Define the index entry to insert the text at\n"
- "%index = \"14\";\n\n"
- "// In form the GuiListBoxCtrl object to insert the text at the defined index.\n"
- "%assignedId = %thisGuiListBoxCtrl.insertItem(%text,%index);\n"
- "@endtsexample\n\n"
- "@return If successful will return the index id assigned. If unsuccessful, will return -1.\n\n"
- "@see GuiControl")
- {
- object->insertItem( index, text );
- }
- S32 GuiListBoxCtrl::insertItem( S32 index, StringTableEntry text, void *itemData )
- {
- // If the index is greater than our list size, insert it at the end
- if( index >= mItems.size() )
- index = mItems.size();
- // Sanity checking
- if( !text )
- {
- Con::warnf("GuiListBoxCtrl::insertItem - cannot add NULL string" );
- return -1;
- }
- LBItem *newItem = new LBItem;
- // Assign item data
- newItem->itemText = StringTable->insert(text, true);
- newItem->itemData = itemData;
- newItem->isSelected = false;
- newItem->hasColor = false;
- // Add to list
- mItems.insert(index);
- mItems[index] = newItem;
- // Resize our list to fit our items
- updateSize();
- // Return our index in list (last)
- return index;
- }
- S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, LinearColorF color, void *itemData )
- {
- // If the index is greater than our list size, insert it at the end
- if( index >= mItems.size() )
- index = mItems.size();
- // Sanity checking
- if( !text )
- {
- Con::warnf("GuiListBoxCtrl::insertItem - cannot add NULL string" );
- return -1;
- }
- if( color == LinearColorF(-1, -1, -1) )
- {
- Con::warnf("GuiListBoxCtrl::insertItem - cannot add NULL color" );
- return -1;
- }
- LBItem *newItem = new LBItem;
- // Assign item data
- newItem->itemText = StringTable->insert(text, true);
- newItem->itemData = itemData;
- newItem->isSelected = false;
- newItem->hasColor = true;
- newItem->color = color;
- // Add to list
- mItems.insert(index);
- mItems[index] = newItem;
- // Resize our list to fit our items
- updateSize();
- // Return our index in list (last)
- return index;
- }
- DefineEngineMethod( GuiListBoxCtrl, deleteItem, void, (S32 itemIndex),,
- "@brief Removes the list entry at the requested index id from the control and clears the memory associated with it.\n\n"
- "@param itemIndex Index id location to remove the item from.\n"
- "@tsexample\n"
- "// Define the index id we want to remove from the list\n"
- "%itemIndex = \"8\";\n\n"
- "// Inform the GuiListBoxCtrl object to remove the item at the defined index id.\n"
- "%thisGuiListBoxCtrl.deleteItem(%itemIndex);\n"
- "@endtsexample\n\n"
- "@see References")
- {
- object->deleteItem( itemIndex );
- }
- void GuiListBoxCtrl::deleteItem( S32 index )
- {
- // Range Check
- if( index >= mItems.size() || index < 0 )
- {
- Con::warnf("GuiListBoxCtrl::deleteItem - index out of range!" );
- return;
- }
- // Grab our item
- LBItem* item = mItems[ index ];
- if( !item )
- {
- Con::warnf("GuiListBoxCtrl::deleteItem - Bad Item Data!" );
- return;
- }
- // Remove it from the selected list.
- if( item->isSelected )
- {
- for( VectorPtr<LBItem*>::iterator i = mSelectedItems.begin(); i != mSelectedItems.end(); i++ )
- {
- if( item == *i )
- {
- mSelectedItems.erase_fast( i );
- break;
- }
- }
- }
- // Remove it from the list
- mItems.erase( &mItems[ index ] );
- // Free the memory associated with it
- delete item;
- }
- DefineEngineMethod( GuiListBoxCtrl, getItemText, const char*, (S32 index),,
- "@brief Returns the text of the item at the specified index.\n\n"
- "@param index Index id to return the item text from.\n"
- "@tsexample\n"
- "// Define the index id entry to request the text from\n"
- "%index = \"12\";\n\n"
- "// Request the item id text from the GuiListBoxCtrl object.\n"
- "%text = %thisGuiListBoxCtrl.getItemText(%index);\n"
- "@endtsexample\n\n"
- "@return The text of the requested index id.\n\n"
- "@see GuiControl")
- {
- return object->getItemText( index );
- }
- StringTableEntry GuiListBoxCtrl::getItemText( S32 index )
- {
- // Range Checking
- if( index > mItems.size() || index < 0 )
- {
- Con::warnf( "GuiListBoxCtrl::getItemText - index out of range!" );
- return StringTable->lookup("");
- }
-
- return mItems[ index ]->itemText;
- }
- DefineEngineMethod( GuiListBoxCtrl, getItemObject, const char*, (S32 index),,
- "@brief Returns the object associated with an item. This only makes sense if you are mirroring a simset.\n\n"
- "@param index Index id to request the associated item from.\n"
- "@tsexample\n"
- "// Define the index id\n"
- "%index = \"12\";\n\n"
- "// Request the item from the GuiListBoxCtrl object\n"
- "%object = %thisGuiListBoxCtrl.getItemObject(%index);\n"
- "@endtsexample\n\n"
- "@return The object associated with the item in the list.\n\n"
- "@see References")
- {
- SimObject *outObj = object->getItemObject( index );
- if ( !outObj )
- return NULL;
- return outObj->getIdString();
- }
- SimObject* GuiListBoxCtrl::getItemObject( S32 index )
- {
- // Range Checking
- if( index > mItems.size() || index < 0 )
- {
- Con::warnf( "GuiListBoxCtrl::getItemObject - index out of range!" );
- return NULL;
- }
- SimObject *outObj;
- Sim::findObject( (SimObjectId)(uintptr_t)(mItems[ index ]->itemData), outObj );
- return outObj;
- }
- DefineEngineMethod( GuiListBoxCtrl, setItemText, void, (S32 index, const char* newtext),,
- "@brief Sets the items text at the specified index.\n\n"
- "@param index Index id to set the item text at.\n"
- "@param newtext Text to change the list item at index id to.\n"
- "@tsexample\n"
- "// Define the index id/n"
- "%index = \"12\";\n\n"
- "// Define the text to set the list item to\n"
- "%newtext = \"Gideon's Fancy Goggles\";\n\n"
- "// Inform the GuiListBoxCtrl object to change the text at the requested index\n"
- "%thisGuiListBoxCtrl.setItemText(%index,%newText);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- object->setItemText(index, newtext );
- }
- void GuiListBoxCtrl::setItemText( S32 index, StringTableEntry text )
- {
- // Sanity Checking
- if( !text )
- {
- Con::warnf("GuiListBoxCtrl::setItemText - Invalid Text Specified!" );
- return;
- }
- // Range Checking
- if( index > mItems.size() || index < 0 )
- {
- Con::warnf( "GuiListBoxCtrl::getItemText - index out of range!" );
- return;
- }
- mItems[ index ]->itemText = StringTable->insert( text, true );
- }
- DefineEngineMethod( GuiListBoxCtrl, setItemTooltip, void, (S32 index, const char* text),,
- "@brief Set the tooltip text to display for the given list item.\n\n"
- "@param index Index id to change the tooltip text\n"
- "@param text Text for the tooltip.\n"
- "@tsexample\n"
- "// Define the index id\n"
- "%index = \"12\";\n\n"
- "// Define the tooltip text\n"
- "%tooltip = \"Gideon's goggles can see through space and time.\"\n\n"
- "// Inform the GuiListBoxCtrl object to set the tooltop for the item at the defined index id\n"
- "%thisGuiListBoxCtrl.setItemToolTip(%index,%tooltip);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- if( index > object->mItems.size() || index < 0 )
- {
- Con::errorf( "GuiListBoxCtrl::setItemTooltip - index '%i' out of range", index );
- return;
- }
-
- object->mItems[ index ]->itemTooltip = text;
- }
- DefineEngineMethod( GuiListBoxCtrl, getLastClickItem, S32, (),,
- "@brief Request the item index for the item that was last clicked.\n\n"
- "@tsexample\n"
- "// Request the item index for the last clicked item in the list\n"
- "%lastClickedIndex = %thisGuiListBoxCtrl.getLastClickItem();\n"
- "@endtsexample\n\n"
- "@return Index id for the last clicked item in the list.\n\n"
- "@see GuiControl")
- {
- GuiListBoxCtrl::LBItem *lastItem = object->mLastClickItem;
- if ( !lastItem )
- return -1;
- return object->getItemIndex( lastItem );
- }
- //-----------------------------------------------------------------------------
- // Sizing Functions
- //-----------------------------------------------------------------------------
- void GuiListBoxCtrl::updateSize()
- {
- if( !mProfile || !mProfile->mFont )
- return;
- GFont *font = mProfile->mFont;
- GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl *>(getParent());
- if ( mFitParentWidth && parent )
- mItemSize.x = parent->getContentExtent().x;
- else
- {
- // Find the maximum width cell:
- S32 maxWidth = 1;
- for ( U32 i = 0; i < mItems.size(); i++ )
- {
- S32 width = font->getStrWidth( mItems[i]->itemText );
- if( width > maxWidth )
- maxWidth = width;
- }
- mItemSize.x = maxWidth + 6;
- }
- mItemSize.y = font->getHeight() + 2;
- Point2I newExtent( mItemSize.x, mItemSize.y * mItems.size() );
- setExtent( newExtent );
- }
- void GuiListBoxCtrl::parentResized(const RectI &oldParentRect, const RectI &newParentRect)
- {
- Parent::parentResized( oldParentRect, newParentRect );
- updateSize();
- }
- //-----------------------------------------------------------------------------
- // Overrides
- //-----------------------------------------------------------------------------
- void GuiListBoxCtrl::onRender( Point2I offset, const RectI &updateRect )
- {
- RectI clipRect(updateRect.point, updateRect.extent);
- if( !mProfile )
- return;
- _mirror();
- // Save our original clip rect
- RectI oldClipRect = clipRect;
- for ( S32 i = 0; i < mItems.size(); i++)
- {
- S32 colorBoxSize = 0;
- ColorI boxColor = ColorI(0, 0, 0);
- // Only render visible items
- if ((i + 1) * mItemSize.y + offset.y < updateRect.point.y)
- continue;
- // Break our once we're no longer in visible item range
- if( i * mItemSize.y + offset.y >= updateRect.point.y + updateRect.extent.y)
- break;
- // Render color box if needed
- if(mColorBullet && mItems[i]->hasColor)
- {
- // Set the size of the color box to be drawn next to the item text
- colorBoxSize = 3;
- boxColor = ColorI(mItems[i]->color.toColorI());
- // Draw the box first
- ColorI black = ColorI(0, 0, 0);
- drawBox( Point2I(offset.x + mProfile->mTextOffset.x + colorBoxSize, offset.y + ( i * mItemSize.y ) + 8), colorBoxSize, black, boxColor );
- }
- RectI itemRect = RectI( offset.x + mProfile->mTextOffset.x + (colorBoxSize * 3), offset.y + ( i * mItemSize.y ), mItemSize.x, mItemSize.y );
- // Render our item
- onRenderItem( itemRect, mItems[i] );
- }
- GFX->setClipRect( oldClipRect );
- }
- void GuiListBoxCtrl::onRenderItem(const RectI& itemRect, LBItem *item)
- {
- if( item->isSelected )
- GFX->getDrawUtil()->drawRectFill( itemRect, mProfile->mFillColorSEL );
- GFX->getDrawUtil()->setBitmapModulation( item->hasColor ? item->color.toColorI() : mProfile->mFontColor);
- renderJustifiedText(itemRect.point + Point2I( 2, 0 ), itemRect.extent, item->itemText);
- }
- void GuiListBoxCtrl::drawBox(const Point2I &box, S32 size, ColorI &outlineColor, ColorI &boxColor)
- {
- RectI r(box.x - size, box.y - size, 2 * size + 1, 2 * size + 1);
- r.inset(1, 1);
- GFX->getDrawUtil()->drawRectFill(r, boxColor);
- r.inset(-1, -1);
- GFX->getDrawUtil()->drawRect(r, outlineColor);
- }
- bool GuiListBoxCtrl::renderTooltip( const Point2I &hoverPos, const Point2I& cursorPos, const char* tipText )
- {
- S32 hitItemIndex;
- if( hitTest( hoverPos, hitItemIndex ) )
- tipText = mItems[ hitItemIndex ]->itemTooltip;
-
- return defaultTooltipRender( hoverPos, cursorPos, tipText );
- }
- //-----------------------------------------------------------------------------
- // Hit Detection
- //-----------------------------------------------------------------------------
- bool GuiListBoxCtrl::hitTest( const Point2I& point, S32& outItem )
- {
- Point2I localPoint = globalToLocalCoord( point );
-
- S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
- if ( itemHit >= mItems.size() || itemHit == -1 )
- return false;
- LBItem *hitItem = mItems[ itemHit ];
- if ( hitItem == NULL )
- return false;
-
- outItem = itemHit;
- return true;
- }
- //-----------------------------------------------------------------------------
- // Mouse Events
- //-----------------------------------------------------------------------------
- void GuiListBoxCtrl::onMouseDragged(const GuiEvent &event)
- {
- Parent::onMouseDragged(event);
- onMouseDragged_callback();
- }
- void GuiListBoxCtrl::onMouseDown( const GuiEvent &event )
- {
- S32 itemHit;
- if( !hitTest( event.mousePoint, itemHit ) )
- return;
-
- LBItem* hitItem = mItems[ itemHit ];
- // If we're not a multiple selection listbox, we simply select/unselect an item
- if( !mMultipleSelections )
- {
- // No current selection? Just select the cell and move on
- S32 selItem = getSelectedItem();
- if ( selItem != itemHit && selItem != -1 )
- clearSelection();
- // Set the current selection
- setCurSel( itemHit );
- if( itemHit == selItem && event.mouseClickCount == 2 )
- onDoubleClick_callback();
- // Store the clicked item
- mLastClickItem = hitItem;
- // Evaluate the console command if we clicked the same item twice
- if( selItem == itemHit && event.mouseClickCount > 1 )
- execAltConsoleCallback();
- return;
- }
-
- // Deal with multiple selections
- if( event.modifier & SI_MULTISELECT)
- {
- // Ctrl-Click toggles selection
- if( hitItem->isSelected )
- {
- removeSelection( hitItem, itemHit );
- // We return here when we deselect an item because we don't store last clicked when we deselect
- return;
- }
- else
- addSelection( hitItem, itemHit );
- }
- else if( event.modifier & SI_RANGESELECT )
- {
- if( !mLastClickItem )
- addSelection( hitItem, itemHit );
- else
- setCurSelRange( getItemIndex( mLastClickItem ), itemHit );
- }
- else
- {
- if( getSelCount() != 0 )
- {
- S32 selItem = getSelectedItem();
- if( selItem != -1 && mItems[selItem] != hitItem )
- clearSelection();
- }
- addSelection( hitItem, itemHit );
- }
- if( hitItem == mLastClickItem && event.mouseClickCount == 2 )
- onDoubleClick_callback();
- mLastClickItem = hitItem;
- }
- void GuiListBoxCtrl::onMouseUp( const GuiEvent& event )
- {
- S32 itemHit = -1;
- if( hitTest( event.mousePoint, itemHit ) )
- onMouseUp_callback( itemHit, event.mouseClickCount );
- // Execute console command
- execConsoleCallback();
-
- Parent::onMouseUp( event );
- }
- bool GuiListBoxCtrl::onKeyDown( const GuiEvent &event )
- {
- if ( event.keyCode == KEY_DELETE )
- {
- onDeleteKey_callback();
- return true;
- }
- return Parent::onKeyDown( event );
- }
- U32 GuiListBoxCtrl::getStringElementCount( const char* inString )
- {
- // Non-whitespace chars.
- static const char* set = " \t\n";
- // End of string.
- if ( *inString == 0 )
- return 0;
- U32 wordCount = 0;
- U8 search = 0;
- // Search String.
- while( *inString )
- {
- // Get string element.
- search = *inString;
- // End of string?
- if ( search == 0 )
- break;
- // Move to next element.
- inString++;
- // Search for seperators.
- for( U32 i = 0; set[i]; i++ )
- {
- // Found one?
- if( search == set[i] )
- {
- // Yes...
- search = 0;
- break;
- }
- }
- // Found a seperator?
- if ( search == 0 )
- continue;
- // We've found a non-seperator.
- wordCount++;
- // Search for end of non-seperator.
- while( 1 )
- {
- // Get string element.
- search = *inString;
- // End of string?
- if ( search == 0 )
- break;
- // Move to next element.
- inString++;
- // Search for seperators.
- for( U32 i = 0; set[i]; i++ )
- {
- // Found one?
- if( search == set[i] )
- {
- // Yes...
- search = 0;
- break;
- }
- }
- // Found Seperator?
- if ( search == 0 )
- break;
- }
- // End of string?
- if ( *inString == 0 )
- {
- // Bah!
- break;
- }
- }
- // We've finished.
- return wordCount;
- }
- //------------------------------------------------------------------------------
- // Get String Element.
- //------------------------------------------------------------------------------
- const char* GuiListBoxCtrl::getStringElement( const char* inString, const U32 index )
- {
- // Non-whitespace chars.
- static const char* set = " \t\n";
- U32 wordCount = 0;
- U8 search = 0;
- const char* pWordStart = NULL;
- // End of string?
- if ( *inString != 0 )
- {
- // No, so search string.
- while( *inString )
- {
- // Get string element.
- search = *inString;
- // End of string?
- if ( search == 0 )
- break;
- // Move to next element.
- inString++;
- // Search for seperators.
- for( U32 i = 0; set[i]; i++ )
- {
- // Found one?
- if( search == set[i] )
- {
- // Yes...
- search = 0;
- break;
- }
- }
- // Found a seperator?
- if ( search == 0 )
- continue;
- // Found are word?
- if ( wordCount == index )
- {
- // Yes, so mark it.
- pWordStart = inString-1;
- }
- // We've found a non-seperator.
- wordCount++;
- // Search for end of non-seperator.
- while( 1 )
- {
- // Get string element.
- search = *inString;
- // End of string?
- if ( search == 0 )
- break;
- // Move to next element.
- inString++;
- // Search for seperators.
- for( U32 i = 0; set[i]; i++ )
- {
- // Found one?
- if( search == set[i] )
- {
- // Yes...
- search = 0;
- break;
- }
- }
- // Found Seperator?
- if ( search == 0 )
- break;
- }
- // Have we found our word?
- if ( pWordStart )
- {
- // Yes, so we've got our word...
- // Result Buffer.
- static char buffer[4096];
- // Calculate word length.
- const U32 length = inString - pWordStart - ((*inString)?1:0);
- // Copy Word.
- dStrncpy( buffer, pWordStart, length);
- buffer[length] = '\0';
- // Return Word.
- return buffer;
- }
- // End of string?
- if ( *inString == 0 )
- {
- // Bah!
- break;
- }
- }
- }
- // Sanity!
- AssertFatal( false, "t2dSceneObject::getStringElement() - Couldn't find specified string element!" );
- // Didn't find it
- return " ";
- }
- void GuiListBoxCtrl::_mirror()
- {
- SimSet *mirrorSet;
- if ( !Sim::findObject( mMirrorSetName, mirrorSet ) )
- return;
- // Allow script to filter out objects if desired.
- Vector<SimObjectId> workingSet;
- // If the method is not defined we assume user wants us to add
- // all objects.
- bool isObjMirroredDefined = isMethod( "isObjectMirrored" );
-
- for ( S32 i = 0; i < mirrorSet->size(); i++ )
- {
- bool addObj = true;
-
- if ( isObjMirroredDefined )
- addObj = isObjectMirrored_callback(mirrorSet->at(i)->getIdString());
-
- if ( addObj )
- workingSet.push_back( mirrorSet->at(i)->getId() );
- }
- // Remove existing items that are no longer in the SimSet.
- // Or are no longer valid objects.
- SimObjectId curId;
- SimObject *curObj;
- for ( U32 i = 0; i < mItems.size(); i++ )
- {
- curId = (SimObjectId)(uintptr_t)mItems[i]->itemData;
- Sim::findObject( curId, curObj );
- bool keep = false;
- if ( curObj )
- {
- if ( workingSet.contains( curId ) )
- {
- mItems[i]->itemText = _makeMirrorItemName( curObj );
- keep = true;
- }
- }
- if ( !keep )
- {
- deleteItem( i );
- i--;
- }
- }
- // Add items that are in the SimSet but not yet in the list.
- for ( U32 i = 0; i < workingSet.size(); i++ )
- {
- curId = workingSet[i];
- Sim::findObject( curId, curObj );
- bool found = false;
- for ( U32 j = 0; j < mItems.size(); j++ )
- {
- if ( (SimObjectId)(uintptr_t)(mItems[j]->itemData) == curId )
- {
- found = true;
- break;
- }
- }
-
- for ( U32 j = 0; j < mFilteredItems.size(); j++ )
- {
- if ( (SimObjectId)(uintptr_t)(mFilteredItems[j]->itemData) == curId )
- {
- found = true;
- break;
- }
- }
- if ( !found )
- {
- addItem( _makeMirrorItemName( curObj ), (void*)(uintptr_t)curId );
- }
- }
- }
- StringTableEntry GuiListBoxCtrl::_makeMirrorItemName( SimObject *inObj )
- {
- StringTableEntry outName = StringTable->EmptyString();
- if ( mMakeNameCallback.isNotEmpty() )
- {
- Con::setIntVariable( "$ThisControl", getId() );
- Con::setIntVariable( "$ThisObject", inObj->getId() );
-
- outName = StringTable->insert( Con::evaluate( mMakeNameCallback ), true );
- }
- else if ( inObj->getName() )
- outName = StringTable->insert( inObj->getName() );
-
- if ( !outName || !outName[0] )
- outName = StringTable->insert( "(no name)" );
- return outName;
- }
- DefineEngineMethod( GuiListBoxCtrl, doMirror, void, (),,
- "@brief Informs the GuiListBoxCtrl object to mirror the contents of the GuiListBoxCtrl stored in the mirrorSet field.\n\n"
- "@tsexample\n"
- "\\ Inform the object to mirror the object located at %thisGuiListBox.mirrorSet\n"
- "%thisGuiListBox.doMirror();\n"
- "@endtsexample\n\n"
- "@see GuiCore")
- {
- object->_mirror();
- }
- DefineEngineMethod( GuiListBoxCtrl, addFilteredItem, void, (const char* newItem),,
- "@brief Checks if there is an item with the exact text of what is passed in, and if so\n"
- "the item is removed from the list and adds that item's data to the filtered list.\n\n"
- "@param itemName Name of the item that we wish to add to the filtered item list of the GuiListBoxCtrl.\n"
- "@tsexample\n"
- "// Define the itemName that we wish to add to the filtered item list.\n"
- "%itemName = \"This Item Name\";\n\n"
- "// Add the item name to the filtered item list.\n"
- "%thisGuiListBoxCtrl.addFilteredItem(%filteredItemName);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- String item(newItem);
- if( item == String::EmptyString )
- return;
- object->addFilteredItem( item );
- }
- void GuiListBoxCtrl::addFilteredItem( String item )
- {
- // Delete from selected items list
- for ( S32 i = 0; i < mSelectedItems.size(); i++ )
- {
- String itemText = mSelectedItems[i]->itemText;
- if ( String::compare( itemText.c_str(), item.c_str() ) == 0 )
- {
- mSelectedItems.erase_fast( i );
- break;
- }
- }
- for ( S32 i = 0; i < mItems.size(); i++ )
- {
- String itemText = mItems[i]->itemText;
- if( String::compare( itemText.c_str(), item.c_str() ) == 0 )
- {
- mItems[i]->isSelected = false;
- mFilteredItems.push_front( mItems[i] );
- mItems.erase( &mItems[i] );
- break;
- }
- }
- }
- DefineEngineMethod( GuiListBoxCtrl, removeFilteredItem, void, ( const char* itemName ),,
- "@brief Removes an item of the entered name from the filtered items list.\n\n"
- "@param itemName Name of the item to remove from the filtered list.\n"
- "@tsexample\n"
- "// Define the itemName that you wish to remove.\n"
- "%itemName = \"This Item Name\";\n\n"
- "// Remove the itemName from the GuiListBoxCtrl\n"
- "%thisGuiListBoxCtrl.removeFilteredItem(%itemName);\n"
- "@endtsexample\n\n"
- "@see GuiControl")
- {
- String item(itemName);
- if( item == String::EmptyString )
- return;
- object->removeFilteredItem( item );
- }
- void GuiListBoxCtrl::removeFilteredItem( String item )
- {
- for ( S32 i = 0; i < mFilteredItems.size(); i++ )
- {
- String itemText = mFilteredItems[i]->itemText;
- if( String::compare( itemText.c_str(), item.c_str() ) == 0 )
- {
- mItems.push_front( mFilteredItems[i] );
- mFilteredItems.erase( &mFilteredItems[i] );
- break;
- }
- }
- }
|