1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639 |
- //-----------------------------------------------------------------------------
- // 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"
- #include "console/script.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()
- {
- docsURL;
- 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 ).value, 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;
- }
- }
- }
|