Torque3D Documentation / _generateds / guiTreeViewCtrl.cpp

guiTreeViewCtrl.cpp

Engine/source/gui/controls/guiTreeViewCtrl.cpp

More...

Public Functions

ConsoleDocClass(GuiTreeViewCtrl , "@brief Hierarchical list of text items with optional <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icons.\n\n</a>" "Can also be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> inspect <a href="/coding/class/classsimobject/">SimObject</a> hierarchies, primarily within <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editors.\n\n</a>" "GuiTreeViewCtrls can either display arbitrary user-defined trees or can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display <a href="/coding/class/classsimobject/">SimObject</a> hierarchies where " "each parent node in the tree is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimset/">SimSet</a> or <a href="/coding/class/classsimgroup/">SimGroup</a> and each leaf node is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimObject.\n\n</a>" "Each item in the tree has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> text and <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> value. For trees that display <a href="/coding/class/classsimobject/">SimObject</a> hierarchies, the text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each item " "is automatically derived from objects <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each item is the ID of the respective SimObject. For trees " "that are not tied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> SimObjects, both text and <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of each item are set by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">user.\n\n</a>" " Additionally, items in the tree can have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icons.\n\n</a>" "Each item in the tree has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> distinct numeric ID that is unique within its tree. The ID of the root item, which is always " "present on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> tree, is 0.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguitreeviewctrl/">GuiTreeViewCtrl</a>(DatablockEditorTree)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " tabSize=\"16\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  textOffset = \"2\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  fullRowSelect = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  itemHeight = \"21\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  destroyTreeOnSleep = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  MouseDragging = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  MultipleSelections = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  DeleteObjectAllowed = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  DragToItemAllowed = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  ClearAllOnSingleSelection = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  showRoot = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  internalNamesOnly = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  objectNamesOnly = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  compareToObjectID = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  Profile = \"GuiTreeViewProfile\";\n" "  tooltipprofile = \"GuiToolTipProfile\";\n" "  hovertime = \"1000\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiContainers\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , addChildSelectionByValue , void , (S32 parentId, const char *value) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child selection by it's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "@param parentId Parent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TreeItemId.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> search <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , addSelection , void , (S32 id, bool isLastSelection) , (true) , "Add an item/object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n\n</a>" "@param <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> ID of item/object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n</a>" "@param isLastSelection Whether there are more pending items/objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the selection. If false, " "the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> will defer refreshing the tree and wait until addSelection() is called with this parameter set " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true." )
DefineEngineMethod(GuiTreeViewCtrl , buildIconTable , bool , (const char *icons) , "Builds an icon <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">table.\n\n</a>" "@param icons Name of icons <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> build, Icons should be designated by the bitmap/png <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> names(minus the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> extensions)" "and separated by colons(:). This list should be synchronized with the Icons <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enum\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , buildVisibleTree , void , (bool forceFullUpdate) , (false) , "Build the visible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param forceFullUpdate True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> force <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> full update of the tree, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> only update the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">stuff.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , cancelRename , void , () , "Cancel renaming an item (For internal use)." )
DefineEngineMethod(GuiTreeViewCtrl , clear , void , () , "Empty the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , clearFilterText , void , () , "Clear the current item filtering <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pattern.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setFilterText\n</a>" "@see getFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , clearHiddenItems , void , () , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , clearSelection , void , () , "Unselect all currently selected items." )
DefineEngineMethod(GuiTreeViewCtrl , deleteSelection , void , () , "Delete all items/objects in the current selection." )
DefineEngineMethod(GuiTreeViewCtrl , editItem , bool , (S32 itemId, const char *newText, const char *newValue) , "Edits the text and <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given tree <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">edit.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , expandItem , bool , (S32 itemID, bool expand) , (true) , "Expand/contract item, item 's sub-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" " @param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expand or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">contract.\n</a>" " @param expand True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expand the item, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> contract <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , findChildItemByName , S32 , (S32 parentId, const char *childName) , "Get the child item of the given parent item whose text matches @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">childName.\n\n</a>" "@param parentId <a href="/coding/class/classitem/">Item</a> ID of the parent in which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">child.\n</a>" "@param childName Text of the child item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">find.\n</a>" "@return ID of the child item or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no child in @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> parentId has the given text @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">childName.\n\n</a>" "@note This method does not recurse, i.e. it only looks <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> direct children." )
DefineEngineMethod(GuiTreeViewCtrl , findItemByName , S32 , (const char *text) , "Get the ID of the item whose text matches the given @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">text.\n\n</a>" "@param text <a href="/coding/class/classitem/">Item</a> text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">match.\n</a>" "@return ID of the item or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no item matches the given text." )
DefineEngineMethod(GuiTreeViewCtrl , findItemByObjectId , S32 , (S32 objectId) , "Find an item by its object <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> and returns the Tree <a href="/coding/class/classitem/">Item</a> ID <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "@param objectId <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> you want the item <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> for." "@return Tree <a href="/coding/class/classitem/">Item</a> Id <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given object ID." )
DefineEngineMethod(GuiTreeViewCtrl , findItemByValue , S32 , (const char *value) , "Get the ID of the item whose <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> matches @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">match.\n</a>" "@return ID of the item or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no item has the given value." )
DefineEngineMethod(GuiTreeViewCtrl , getChild , S32 , (S32 itemId) , "Get the child of the parent with the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param itemId TreeItemID of item that <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child we should <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">get.\n</a>" "@return Id of child of given item." )
DefineEngineMethod(GuiTreeViewCtrl , getFilterText , const char * , () , "Get the current filter expression. Only tree items whose text matches this expression " "are displayed. By default, the expression is empty and all items are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">shown.\n\n</a>" " @return The current filter pattern or an empty string <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no filter pattern is currently <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">active.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setFilterText\n</a>" " @see clearFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , getFirstRootItem , S32 , () , "Get <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> root <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n</a>" "@return Id <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> root item." )
DefineEngineMethod(GuiTreeViewCtrl , getItemAtPosition , S32 , (Point2I position) , (Point2I::Zero) , "Get the tree item at the passed in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n\n</a>" "@param position The position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> what item is below <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the item under the position." )
DefineEngineMethod(GuiTreeViewCtrl , getItemCount , S32 , () , "Get the total number of items in the tree or item <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">count.\n\n</a>" "@return total number of items in the tree." )
DefineEngineMethod(GuiTreeViewCtrl , getItemObject , S32 , (S32 itemId) , "Gets the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> particular <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId <a href="/coding/class/classitem/">Item</a> <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> you want the object <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> for." "@return <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> Id <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given tree item ID." )
DefineEngineMethod(GuiTreeViewCtrl , getItemText , const char * , (S32 itemId) , "Gets the text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return Text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given item." )
DefineEngineMethod(GuiTreeViewCtrl , getItemValue , const char * , (S32 itemId) , "Gets the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given item." )
DefineEngineMethod(GuiTreeViewCtrl , getNextSibling , S32 , (S32 itemId) , "Get the next sibling of the given item <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemID of item that we want the next sibling <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return Id of next sibling of the given item." )
DefineEngineMethod(GuiTreeViewCtrl , getParentItem , S32 , (S32 itemId) , "Get the parent of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemID of item that has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> parent we should <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">get.\n</a>" "@return Id of parent of given item." )
DefineEngineMethod(GuiTreeViewCtrl , getPrevSibling , S32 , (S32 itemId) , "Get the previous sibling of the given item <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemID of item that we want the previous sibling <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return Id of previous sibling of the given item." )
DefineEngineMethod(GuiTreeViewCtrl , getSelectedItem , S32 , (S32 index) , (0) , "Return the selected item at the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n\n</a>" "@param index Given index <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> selected item." "@return selected item at the given index." )
DefineEngineMethod(GuiTreeViewCtrl , getSelectedItemList , const char * , () , "Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> space separated list <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> ids of all selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@return space separated list of selected item ids." )
DefineEngineMethod(GuiTreeViewCtrl , getSelectedItemsCount , S32 , () , "Get the selected number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@return number of selected items." )
DefineEngineMethod(GuiTreeViewCtrl , getSelectedObject , S32 , (S32 index) , (0) , "Return the currently selected <a href="/coding/class/classsimobject/">SimObject</a> at the given index in inspector <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> or -1.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@param index Given index <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> selected object." "@return currently selected <a href="/coding/class/classsimobject/">SimObject</a> at the given index in inspector <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> or -1." )
DefineEngineMethod(GuiTreeViewCtrl , getSelectedObjectList , const char * , () , "Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> space separated list of all selected object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ids.\n\n</a>" "@return space separated list of all selected object ids." )
DefineEngineMethod(GuiTreeViewCtrl , getTabLevel , S32 , (S32 itemId) , (0) , "Get the tree item at the passed in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n\n</a>" "@param position The position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> what item is below <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the item under the position." )
DefineEngineMethod(GuiTreeViewCtrl , getTextToRoot , const char * , (S32 itemId, const char *delimiter) , ("") , "Gets the text from the current node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the root, concatenating at each branch upward, with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specified delimiter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">optionally.\n\n</a>" " @param itemId TreeItemId of node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> start at." " @param delimiter(Optional) delimiter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use between each branch concatenation." " @return text from the current node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the root." )
DefineEngineMethod(GuiTreeViewCtrl , hideSelection , void , (bool state) , (true) , "Call <a href="/coding/class/classsimobject/#classsimobject_1a68c9d8dc400ba765c987d9c917e7880f">SimObject::setHidden</a>( @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> state ) on all objects in the current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n\n</a>" "@param state Visibility state <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set objects in selection to." )
DefineEngineMethod(GuiTreeViewCtrl , insertItem , S32 , (S32 parentId, const char *text, const char *value, const char *icon, S32 normalImage, S32 expandedImage) , ("", "", 0, 0) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param parentId <a href="/coding/class/classitem/">Item</a> ID of parent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add the item as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child. 0 is root <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n</a>" "@param text Text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the item in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> Behind-the-scenes <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n</a>" "@param <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icon\n</a>" "@param <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">normalImage\n</a>" "@param <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">expandedImage\n</a>" "@return The ID of the newly added item." )
DefineEngineMethod(GuiTreeViewCtrl , insertObject , S32 , (S32 parentId, SimObject *obj, bool OKToEdit) , (false) , "Inserts object as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given parent." )
DefineEngineMethod(GuiTreeViewCtrl , isItemSelected , bool , (S32 id) , "Check whether the given item is currently selected in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/class/classitem/">Item</a>/object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item/object is currently selected in the tree." )
DefineEngineMethod(GuiTreeViewCtrl , isParentItem , bool , (S32 itemId) , "Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item contains child <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">children.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item contains child items, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , lockSelection , void , (bool lock) , (true) , "Set whether the current selection can be changed by the user or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">not.\n\n</a>" "@param lock If true, the current selection is frozen and cannot be changed. If false, " "the selection may be modified." )
DefineEngineMethod(GuiTreeViewCtrl , markItem , bool , (S32 itemID, bool mark) , (true) , "Mark/unmark <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> Mark or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">unmark.\n</a>" "@param mark True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> Mark the item, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> unmark <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , moveItemDown , void , (S32 itemId) , "Move the specified item down in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move down in the tree." )
DefineEngineMethod(GuiTreeViewCtrl , moveItemUp , void , (S32 itemId) , "Move the specified item up in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move up in the tree." )
DefineEngineMethod(GuiTreeViewCtrl , onRenameValidate , void , () , "Validate the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> name <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an object (For internal use)." )
DefineEngineMethod(GuiTreeViewCtrl , open , void , (const char *objName, bool okToEdit) , (true) , "Set the root of the tree view <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the specified object, or <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the root <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" " @param objName Name or <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of <a href="/coding/class/classsimset/">SimSet</a> or object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the tree root equal <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , removeAllChildren , void , (S32 itemId) , "Remove all children of an item from the tree with the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param itemId TreeItemID of item that has children we should <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">remove.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , removeChildSelectionByValue , void , (S32 parentId, const char *value) , "Deselect <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child item or remove it from the selection based on its parent and its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "@param parentId Parent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TreeItemId.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> search <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param performCallback True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> script of the change, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">not.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , removeItem , bool , (S32 itemId, bool deleteObjects) , (0, true) , "Remove an item from the tree with the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param itemId TreeItemID of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">remove.\n</a>" "@param deleteObjects Whether the object on the item is deleted when the item <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">is.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , removeSelection , void , (S32 itemId) , "Deselect an item or remove it from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n\n</a>" "@param itemId <a href="/coding/class/classitem/">Item</a> Id <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deselect.\n</a>" )
DefineEngineMethod(GuiTreeViewCtrl , reparentItem , void , (S32 itemId, S32 parentId) , (0, 0) , "Check whether the given item is currently selected in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/class/classitem/">Item</a>/object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item/object is currently selected in the tree." )
DefineEngineMethod(GuiTreeViewCtrl , scrollVisible , bool , (S32 itemID) , "Make the given item <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" "@param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> scroll <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a>/make <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , scrollVisibleByObjectId , S32 , (S32 objectId) , "Show item by object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param objectId <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> you want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> scroll to." "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , selectItem , bool , (S32 itemID, bool select) , (true) , "Select or deselect and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> select or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deselect.\n</a>" "@param select True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> select the item, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> deselect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
DefineEngineMethod(GuiTreeViewCtrl , setDebug , void , (bool value) , (true) , "Enable/disable debug output." "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> enable debug output, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> disable it." )
DefineEngineMethod(GuiTreeViewCtrl , setFilterChildren , void , (bool doFilterChildren) , (true) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , setFilterText , void , (const char *pattern) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , setItemFilterException , void , (U32 item, bool isExempt) , (0, true) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , setItemHidden , void , (U32 item, bool hidden) , (0, true) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )
DefineEngineMethod(GuiTreeViewCtrl , setItemImages , void , (S32 itemId, S8 normalImage, S8 expandedImage) , "Sets the normal and expanded images <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set images <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param normalImage Normal image <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given item." "@param expandedImage Expanded image <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given item." )
DefineEngineMethod(GuiTreeViewCtrl , setItemTooltip , bool , (S32 itemId, const char *tooltip) , "Set the tooltip <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the tooltip <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param tooltip <a href="/coding/class/classstring/">String</a> tooltip <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the item." "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successfully found the item, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not" )
DefineEngineMethod(GuiTreeViewCtrl , showItemRenameCtrl , void , (S32 itemId) , "Show the rename text field <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given item (only one at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> time)." "@param itemId TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show rename text field for." )
DefineEngineMethod(GuiTreeViewCtrl , sort , void , (S32 parentId, bool traverseHierarchy, bool parentsFirst, bool caseSensitive) , (0, false, false, true) , "Sorts all items of the given parent (or root). With 'hierarchy' , traverses hierarchy." " @param parentId TreeItemID of parent/root <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> sort all the items under. Use 0 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> sort the entire tree." " @param traverseHierarchy True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> traverse the hierarchy, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> not." " @param parentsFirst True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> sort the parents first." " @param caseSensitive True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> pay attention <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> case, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore it." )
DefineEngineMethod(GuiTreeViewCtrl , toggleHideSelection , void , () , "Toggle the hidden state of all objects in the current selection." )
DefineEngineMethod(GuiTreeViewCtrl , toggleLockSelection , void , () , "Toggle the locked state of all objects in the current selection." )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , canRenameObject , bool , (SimObject *object) , (object) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , handleRenameObject , bool , (const char *newName, SimObject *object) , (newName, object) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , isValidDragTarget , bool , (S32 id, const char *value) , (id, value) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddGroupSelected , void , (SimGroup *group) , (group) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddMultipleSelectionBegin , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddMultipleSelectionEnd , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddSelection , void , (S32 itemOrObjectId, bool isLastSelection) , (itemOrObjectId, isLastSelection) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onBeginReparenting , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onClearSelection , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDefineIcons , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDeleteObject , bool , (SimObject *object) , (object) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDeleteSelection , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDragDropped , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onEndReparenting , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onInspect , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onKeyDown , void , (S32 modifier, S32 keyCode) , (modifier, keyCode) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onMouseDragged , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onMouseUp , void , (S32 hitItemId, S32 mouseClickCount) , (hitItemId, mouseClickCount) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onObjectDeleteCompleted , void , () , () , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onRemoveSelection , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onReparent , void , (S32 itemOrObjectId, S32 oldParentItemOrObjectId, S32 newParentItemOrObjectId) , (itemOrObjectId, oldParentItemOrObjectId, newParentItemOrObjectId) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onRightMouseDown , void , (S32 itemId, const Point2I &mousePos, SimObject *object) , (itemId, mousePos, object) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onRightMouseUp , void , (S32 itemId, const Point2I &mousePos, SimObject *object) , (itemId, mousePos, object) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onSelect , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )
IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onUnselect , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )
itemSortList(GuiTreeViewCtrl::Item *& firstChild, bool caseSensitive, bool traverseHierarchy, bool parentsFirst)

Detailed Description

Public Functions

ConsoleDocClass(GuiTreeViewCtrl , "@brief Hierarchical list of text items with optional <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icons.\n\n</a>" "Can also be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> inspect <a href="/coding/class/classsimobject/">SimObject</a> hierarchies, primarily within <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editors.\n\n</a>" "GuiTreeViewCtrls can either display arbitrary user-defined trees or can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display <a href="/coding/class/classsimobject/">SimObject</a> hierarchies where " "each parent node in the tree is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimset/">SimSet</a> or <a href="/coding/class/classsimgroup/">SimGroup</a> and each leaf node is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimObject.\n\n</a>" "Each item in the tree has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> text and <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> value. For trees that display <a href="/coding/class/classsimobject/">SimObject</a> hierarchies, the text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each item " "is automatically derived from objects <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each item is the ID of the respective SimObject. For trees " "that are not tied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> SimObjects, both text and <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of each item are set by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">user.\n\n</a>" " Additionally, items in the tree can have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icons.\n\n</a>" "Each item in the tree has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> distinct numeric ID that is unique within its tree. The ID of the root item, which is always " "present on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> tree, is 0.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguitreeviewctrl/">GuiTreeViewCtrl</a>(DatablockEditorTree)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " tabSize=\"16\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  textOffset = \"2\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  fullRowSelect = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  itemHeight = \"21\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  destroyTreeOnSleep = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  MouseDragging = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  MultipleSelections = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  DeleteObjectAllowed = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  DragToItemAllowed = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  ClearAllOnSingleSelection = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  showRoot = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  internalNamesOnly = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  objectNamesOnly = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  compareToObjectID = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  Profile = \"GuiTreeViewProfile\";\n" "  tooltipprofile = \"GuiToolTipProfile\";\n" "  hovertime = \"1000\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiContainers\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , addChildSelectionByValue , void , (S32 parentId, const char *value) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child selection by it's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "@param parentId Parent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TreeItemId.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> search <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , addSelection , void , (S32 id, bool isLastSelection) , (true) , "Add an item/object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n\n</a>" "@param <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> ID of item/object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n</a>" "@param isLastSelection Whether there are more pending items/objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the selection. If false, " "the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> will defer refreshing the tree and wait until addSelection() is called with this parameter set " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true." )

DefineEngineMethod(GuiTreeViewCtrl , buildIconTable , bool , (const char *icons) , "Builds an icon <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">table.\n\n</a>" "@param icons Name of icons <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> build, Icons should be designated by the bitmap/png <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> names(minus the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> extensions)" "and separated by colons(:). This list should be synchronized with the Icons <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enum\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , buildVisibleTree , void , (bool forceFullUpdate) , (false) , "Build the visible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param forceFullUpdate True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> force <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> full update of the tree, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> only update the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">stuff.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , cancelRename , void , () , "Cancel renaming an item (For internal use)." )

DefineEngineMethod(GuiTreeViewCtrl , clear , void , () , "Empty the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , clearFilterText , void , () , "Clear the current item filtering <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pattern.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setFilterText\n</a>" "@see getFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , clearHiddenItems , void , () , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , clearSelection , void , () , "Unselect all currently selected items." )

DefineEngineMethod(GuiTreeViewCtrl , deleteSelection , void , () , "Delete all items/objects in the current selection." )

DefineEngineMethod(GuiTreeViewCtrl , editItem , bool , (S32 itemId, const char *newText, const char *newValue) , "Edits the text and <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given tree <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">edit.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , expandItem , bool , (S32 itemID, bool expand) , (true) , "Expand/contract item, item 's sub-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" " @param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expand or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">contract.\n</a>" " @param expand True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> expand the item, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> contract <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , findChildItemByName , S32 , (S32 parentId, const char *childName) , "Get the child item of the given parent item whose text matches @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">childName.\n\n</a>" "@param parentId <a href="/coding/class/classitem/">Item</a> ID of the parent in which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">child.\n</a>" "@param childName Text of the child item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">find.\n</a>" "@return ID of the child item or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no child in @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> parentId has the given text @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">childName.\n\n</a>" "@note This method does not recurse, i.e. it only looks <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> direct children." )

DefineEngineMethod(GuiTreeViewCtrl , findItemByName , S32 , (const char *text) , "Get the ID of the item whose text matches the given @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">text.\n\n</a>" "@param text <a href="/coding/class/classitem/">Item</a> text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">match.\n</a>" "@return ID of the item or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no item matches the given text." )

DefineEngineMethod(GuiTreeViewCtrl , findItemByObjectId , S32 , (S32 objectId) , "Find an item by its object <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> and returns the Tree <a href="/coding/class/classitem/">Item</a> ID <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "@param objectId <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> you want the item <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> for." "@return Tree <a href="/coding/class/classitem/">Item</a> Id <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given object ID." )

DefineEngineMethod(GuiTreeViewCtrl , findItemByValue , S32 , (const char *value) , "Get the ID of the item whose <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> matches @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">match.\n</a>" "@return ID of the item or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no item has the given value." )

DefineEngineMethod(GuiTreeViewCtrl , getChild , S32 , (S32 itemId) , "Get the child of the parent with the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param itemId TreeItemID of item that <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child we should <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">get.\n</a>" "@return Id of child of given item." )

DefineEngineMethod(GuiTreeViewCtrl , getFilterText , const char * , () , "Get the current filter expression. Only tree items whose text matches this expression " "are displayed. By default, the expression is empty and all items are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">shown.\n\n</a>" " @return The current filter pattern or an empty string <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no filter pattern is currently <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">active.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setFilterText\n</a>" " @see clearFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , getFirstRootItem , S32 , () , "Get <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> root <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n</a>" "@return Id <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> root item." )

DefineEngineMethod(GuiTreeViewCtrl , getItemAtPosition , S32 , (Point2I position) , (Point2I::Zero) , "Get the tree item at the passed in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n\n</a>" "@param position The position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> what item is below <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the item under the position." )

DefineEngineMethod(GuiTreeViewCtrl , getItemCount , S32 , () , "Get the total number of items in the tree or item <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">count.\n\n</a>" "@return total number of items in the tree." )

DefineEngineMethod(GuiTreeViewCtrl , getItemObject , S32 , (S32 itemId) , "Gets the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> particular <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId <a href="/coding/class/classitem/">Item</a> <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> you want the object <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> for." "@return <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> Id <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given tree item ID." )

DefineEngineMethod(GuiTreeViewCtrl , getItemText , const char * , (S32 itemId) , "Gets the text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return Text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given item." )

DefineEngineMethod(GuiTreeViewCtrl , getItemValue , const char * , (S32 itemId) , "Gets the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given item." )

DefineEngineMethod(GuiTreeViewCtrl , getNextSibling , S32 , (S32 itemId) , "Get the next sibling of the given item <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemID of item that we want the next sibling <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return Id of next sibling of the given item." )

DefineEngineMethod(GuiTreeViewCtrl , getParentItem , S32 , (S32 itemId) , "Get the parent of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemID of item that has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> parent we should <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">get.\n</a>" "@return Id of parent of given item." )

DefineEngineMethod(GuiTreeViewCtrl , getPrevSibling , S32 , (S32 itemId) , "Get the previous sibling of the given item <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemID of item that we want the previous sibling <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return Id of previous sibling of the given item." )

DefineEngineMethod(GuiTreeViewCtrl , getSelectedItem , S32 , (S32 index) , (0) , "Return the selected item at the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n\n</a>" "@param index Given index <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> selected item." "@return selected item at the given index." )

DefineEngineMethod(GuiTreeViewCtrl , getSelectedItemList , const char * , () , "Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> space separated list <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> ids of all selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@return space separated list of selected item ids." )

DefineEngineMethod(GuiTreeViewCtrl , getSelectedItemsCount , S32 , () , "Get the selected number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@return number of selected items." )

DefineEngineMethod(GuiTreeViewCtrl , getSelectedObject , S32 , (S32 index) , (0) , "Return the currently selected <a href="/coding/class/classsimobject/">SimObject</a> at the given index in inspector <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> or -1.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@param index Given index <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> selected object." "@return currently selected <a href="/coding/class/classsimobject/">SimObject</a> at the given index in inspector <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> or -1." )

DefineEngineMethod(GuiTreeViewCtrl , getSelectedObjectList , const char * , () , "Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> space separated list of all selected object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ids.\n\n</a>" "@return space separated list of all selected object ids." )

DefineEngineMethod(GuiTreeViewCtrl , getTabLevel , S32 , (S32 itemId) , (0) , "Get the tree item at the passed in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n\n</a>" "@param position The position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> what item is below <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the item under the position." )

DefineEngineMethod(GuiTreeViewCtrl , getTextToRoot , const char * , (S32 itemId, const char *delimiter) , ("") , "Gets the text from the current node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the root, concatenating at each branch upward, with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specified delimiter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">optionally.\n\n</a>" " @param itemId TreeItemId of node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> start at." " @param delimiter(Optional) delimiter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use between each branch concatenation." " @return text from the current node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the root." )

DefineEngineMethod(GuiTreeViewCtrl , hideSelection , void , (bool state) , (true) , "Call <a href="/coding/class/classsimobject/#classsimobject_1a68c9d8dc400ba765c987d9c917e7880f">SimObject::setHidden</a>( @<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> state ) on all objects in the current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n\n</a>" "@param state Visibility state <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set objects in selection to." )

DefineEngineMethod(GuiTreeViewCtrl , insertItem , S32 , (S32 parentId, const char *text, const char *value, const char *icon, S32 normalImage, S32 expandedImage) , ("", "", 0, 0) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param parentId <a href="/coding/class/classitem/">Item</a> ID of parent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add the item as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child. 0 is root <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n</a>" "@param text Text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the item in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> Behind-the-scenes <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n</a>" "@param <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icon\n</a>" "@param <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">normalImage\n</a>" "@param <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">expandedImage\n</a>" "@return The ID of the newly added item." )

DefineEngineMethod(GuiTreeViewCtrl , insertObject , S32 , (S32 parentId, SimObject *obj, bool OKToEdit) , (false) , "Inserts object as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given parent." )

DefineEngineMethod(GuiTreeViewCtrl , isItemSelected , bool , (S32 id) , "Check whether the given item is currently selected in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/class/classitem/">Item</a>/object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item/object is currently selected in the tree." )

DefineEngineMethod(GuiTreeViewCtrl , isParentItem , bool , (S32 itemId) , "Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item contains child <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@param itemId TreeItemID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">children.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item contains child items, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , lockSelection , void , (bool lock) , (true) , "Set whether the current selection can be changed by the user or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">not.\n\n</a>" "@param lock If true, the current selection is frozen and cannot be changed. If false, " "the selection may be modified." )

DefineEngineMethod(GuiTreeViewCtrl , markItem , bool , (S32 itemID, bool mark) , (true) , "Mark/unmark <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> Mark or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">unmark.\n</a>" "@param mark True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> Mark the item, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> unmark <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , moveItemDown , void , (S32 itemId) , "Move the specified item down in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move down in the tree." )

DefineEngineMethod(GuiTreeViewCtrl , moveItemUp , void , (S32 itemId) , "Move the specified item up in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param itemId TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move up in the tree." )

DefineEngineMethod(GuiTreeViewCtrl , onRenameValidate , void , () , "Validate the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> name <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an object (For internal use)." )

DefineEngineMethod(GuiTreeViewCtrl , open , void , (const char *objName, bool okToEdit) , (true) , "Set the root of the tree view <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the specified object, or <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the root <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" " @param objName Name or <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of <a href="/coding/class/classsimset/">SimSet</a> or object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the tree root equal <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , removeAllChildren , void , (S32 itemId) , "Remove all children of an item from the tree with the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param itemId TreeItemID of item that has children we should <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">remove.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , removeChildSelectionByValue , void , (S32 parentId, const char *value) , "Deselect <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child item or remove it from the selection based on its parent and its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "@param parentId Parent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TreeItemId.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> search <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param performCallback True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> script of the change, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">not.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , removeItem , bool , (S32 itemId, bool deleteObjects) , (0, true) , "Remove an item from the tree with the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param itemId TreeItemID of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">remove.\n</a>" "@param deleteObjects Whether the object on the item is deleted when the item <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">is.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , removeSelection , void , (S32 itemId) , "Deselect an item or remove it from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selection.\n\n</a>" "@param itemId <a href="/coding/class/classitem/">Item</a> Id <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deselect.\n</a>" )

DefineEngineMethod(GuiTreeViewCtrl , reparentItem , void , (S32 itemId, S32 parentId) , (0, 0) , "Check whether the given item is currently selected in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tree.\n\n</a>" "@param <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/class/classitem/">Item</a>/object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given item/object is currently selected in the tree." )

DefineEngineMethod(GuiTreeViewCtrl , scrollVisible , bool , (S32 itemID) , "Make the given item <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" "@param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> scroll <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a>/make <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , scrollVisibleByObjectId , S32 , (S32 objectId) , "Show item by object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">id.\n\n</a>" "@param objectId <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> you want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> scroll to." "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , selectItem , bool , (S32 itemID, bool select) , (true) , "Select or deselect and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemID TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> select or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deselect.\n</a>" "@param select True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> select the item, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> deselect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n</a>" " @return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it was successful, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

DefineEngineMethod(GuiTreeViewCtrl , setDebug , void , (bool value) , (true) , "Enable/disable debug output." "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> enable debug output, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> disable it." )

DefineEngineMethod(GuiTreeViewCtrl , setFilterChildren , void , (bool doFilterChildren) , (true) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , setFilterText , void , (const char *pattern) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , setItemFilterException , void , (U32 item, bool isExempt) , (0, true) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , setItemHidden , void , (U32 item, bool hidden) , (0, true) , "Set the pattern by which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> filter items in the tree. Only items in the tree whose text " "matches this pattern are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" "@param pattern New pattern based on which visible items in the tree should be filtered. If empty, all items become <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">visible.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">getFilterText\n</a>" " @see clearFilterText" )

DefineEngineMethod(GuiTreeViewCtrl , setItemImages , void , (S32 itemId, S8 normalImage, S8 expandedImage) , "Sets the normal and expanded images <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set images <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param normalImage Normal image <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given item." "@param expandedImage Expanded image <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given item." )

DefineEngineMethod(GuiTreeViewCtrl , setItemTooltip , bool , (S32 itemId, const char *tooltip) , "Set the tooltip <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item.\n\n</a>" "@param itemId TreeItemID of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the tooltip <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param tooltip <a href="/coding/class/classstring/">String</a> tooltip <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the item." "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successfully found the item, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> not" )

DefineEngineMethod(GuiTreeViewCtrl , showItemRenameCtrl , void , (S32 itemId) , "Show the rename text field <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given item (only one at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> time)." "@param itemId TreeItemId of item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show rename text field for." )

DefineEngineMethod(GuiTreeViewCtrl , sort , void , (S32 parentId, bool traverseHierarchy, bool parentsFirst, bool caseSensitive) , (0, false, false, true) , "Sorts all items of the given parent (or root). With 'hierarchy' , traverses hierarchy." " @param parentId TreeItemID of parent/root <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> sort all the items under. Use 0 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> sort the entire tree." " @param traverseHierarchy True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> traverse the hierarchy, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> not." " @param parentsFirst True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> sort the parents first." " @param caseSensitive True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> pay attention <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> case, false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore it." )

DefineEngineMethod(GuiTreeViewCtrl , toggleHideSelection , void , () , "Toggle the hidden state of all objects in the current selection." )

DefineEngineMethod(GuiTreeViewCtrl , toggleLockSelection , void , () , "Toggle the locked state of all objects in the current selection." )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , canRenameObject , bool , (SimObject *object) , (object) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , handleRenameObject , bool , (const char *newName, SimObject *object) , (newName, object) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , isValidDragTarget , bool , (S32 id, const char *value) , (id, value) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddGroupSelected , void , (SimGroup *group) , (group) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddMultipleSelectionBegin , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddMultipleSelectionEnd , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onAddSelection , void , (S32 itemOrObjectId, bool isLastSelection) , (itemOrObjectId, isLastSelection) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onBeginReparenting , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onClearSelection , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDefineIcons , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDeleteObject , bool , (SimObject *object) , (object) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDeleteSelection , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onDragDropped , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onEndReparenting , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onInspect , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onKeyDown , void , (S32 modifier, S32 keyCode) , (modifier, keyCode) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onMouseDragged , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onMouseUp , void , (S32 hitItemId, S32 mouseClickCount) , (hitItemId, mouseClickCount) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onObjectDeleteCompleted , void , () , () , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onRemoveSelection , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onReparent , void , (S32 itemOrObjectId, S32 oldParentItemOrObjectId, S32 newParentItemOrObjectId) , (itemOrObjectId, oldParentItemOrObjectId, newParentItemOrObjectId) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onRightMouseDown , void , (S32 itemId, const Point2I &mousePos, SimObject *object) , (itemId, mousePos, object) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onRightMouseUp , void , (S32 itemId, const Point2I &mousePos, SimObject *object) , (itemId, mousePos, object) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onSelect , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )

IMPLEMENT_CALLBACK(GuiTreeViewCtrl , onUnselect , void , (S32 itemOrObjectId) , (itemOrObjectId) , "" )

IMPLEMENT_CONOBJECT(GuiTreeViewCtrl )

itemCompareCaseInsensitive(const void * a, const void * b)

itemCompareCaseSensitive(const void * a, const void * b)

itemSortList(GuiTreeViewCtrl::Item *& firstChild, bool caseSensitive, bool traverseHierarchy, bool parentsFirst)

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "platform/platform.h"
  25#include "gui/controls/guiTreeViewCtrl.h"
  26
  27#include "core/frameAllocator.h"
  28#include "core/strings/findMatch.h"
  29#include "gui/containers/guiScrollCtrl.h"
  30#include "gui/worldEditor/editorIconRegistry.h"
  31#include "console/consoleTypes.h"
  32#include "console/console.h"
  33#include "gui/core/guiTypes.h"
  34#include "gfx/gfxDrawUtil.h"
  35#include "gui/controls/guiTextEditCtrl.h"
  36#ifdef TORQUE_TOOLS
  37   #include "gui/editor/editorFunctions.h"
  38#endif
  39#include "console/engineAPI.h"
  40
  41IMPLEMENT_CONOBJECT(GuiTreeViewCtrl);
  42
  43ConsoleDocClass( GuiTreeViewCtrl,
  44   "@brief Hierarchical list of text items with optional icons.\n\n"
  45
  46   "Can also be used to inspect SimObject hierarchies, primarily within editors.\n\n"
  47
  48   "GuiTreeViewCtrls can either display arbitrary user-defined trees or can be used to display SimObject hierarchies where "
  49   "each parent node in the tree is a SimSet or SimGroup and each leaf node is a SimObject.\n\n"
  50
  51   "Each item in the tree has a text and a value.  For trees that display SimObject hierarchies, the text for each item "
  52   "is automatically derived from objects while the value for each item is the ID of the respective SimObject.  For trees "
  53   "that are not tied to SimObjects, both text and value of each item are set by the user.\n\n"
  54
  55   "Additionally, items in the tree can have icons.\n\n"
  56
  57   "Each item in the tree has a distinct numeric ID that is unique within its tree.  The ID of the root item, which is always "
  58   "present on a tree, is 0.\n\n"
  59
  60   "@tsexample\n"
  61   "new GuiTreeViewCtrl(DatablockEditorTree)\n"
  62   "{\n"
  63   "  tabSize = \"16\";\n"
  64   "  textOffset = \"2\";\n"
  65   "  fullRowSelect = \"0\";\n"
  66   "  itemHeight = \"21\";\n"
  67   "  destroyTreeOnSleep = \"0\";\n"
  68   "  MouseDragging = \"0\";\n"
  69   "  MultipleSelections = \"1\";\n"
  70   "  DeleteObjectAllowed = \"1\";\n"
  71   "  DragToItemAllowed = \"0\";\n"
  72   "  ClearAllOnSingleSelection = \"1\";\n"
  73   "  showRoot = \"1\";\n"
  74   "  internalNamesOnly = \"0\";\n"
  75   "  objectNamesOnly = \"0\";\n"
  76   "  compareToObjectID = \"0\";\n"
  77   "  Profile = \"GuiTreeViewProfile\";\n"
  78   "  tooltipprofile = \"GuiToolTipProfile\";\n"
  79   "  hovertime = \"1000\";\n"
  80   "};\n"
  81   "@endtsexample\n\n"
  82
  83   "@ingroup GuiContainers\n");
  84
  85IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onDeleteObject, bool, ( SimObject* object ), ( object ), "" );
  86IMPLEMENT_CALLBACK( GuiTreeViewCtrl, isValidDragTarget, bool, ( S32 id, const char* value ), ( id, value ), "" );
  87IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onDefineIcons, void, (), (), "" );
  88IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onAddGroupSelected, void, ( SimGroup* group ), ( group ), "" );
  89IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onAddSelection, void, ( S32 itemOrObjectId, bool isLastSelection ), ( itemOrObjectId, isLastSelection ), "" );
  90IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onSelect, void, ( S32 itemOrObjectId ), ( itemOrObjectId ), "" );
  91IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onInspect, void, ( S32 itemOrObjectId ), ( itemOrObjectId ), "" );
  92IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onRemoveSelection, void, ( S32 itemOrObjectId ), ( itemOrObjectId ), "" );
  93IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onUnselect, void, ( S32 itemOrObjectId ), ( itemOrObjectId ), "" );
  94IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onDeleteSelection, void, (), (), "" );
  95IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onObjectDeleteCompleted, void, (), (), "" );
  96IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onKeyDown, void, ( S32 modifier, S32 keyCode ), ( modifier, keyCode ), "" );
  97IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onMouseUp, void, ( S32 hitItemId, S32 mouseClickCount ), ( hitItemId, mouseClickCount ), "" );
  98IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onMouseDragged, void, (), (), "" );
  99IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onRightMouseDown, void, ( S32 itemId, const Point2I& mousePos, SimObject* object ), ( itemId, mousePos, object ), "" );
 100IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onRightMouseUp, void, ( S32 itemId, const Point2I& mousePos, SimObject* object ), ( itemId, mousePos, object ), "" );
 101IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onBeginReparenting, void, (), (), "" );
 102IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onEndReparenting, void, (), (), "" );
 103IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onReparent, void, ( S32 itemOrObjectId, S32 oldParentItemOrObjectId, S32 newParentItemOrObjectId ), ( itemOrObjectId, oldParentItemOrObjectId, newParentItemOrObjectId ), "" );
 104IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onDragDropped, void, (), (), "" );
 105IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onAddMultipleSelectionBegin, void, (), (), "" );
 106IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onAddMultipleSelectionEnd, void, (), (), "" );
 107IMPLEMENT_CALLBACK( GuiTreeViewCtrl, canRenameObject, bool, ( SimObject* object ), ( object ), "" );
 108IMPLEMENT_CALLBACK( GuiTreeViewCtrl, handleRenameObject, bool, ( const char* newName, SimObject* object ), ( newName, object ), "" );
 109IMPLEMENT_CALLBACK( GuiTreeViewCtrl, onClearSelection, void, (), (), "" );
 110
 111
 112static S32 QSORT_CALLBACK itemCompareCaseSensitive( const void *a, const void *b )
 113{
 114   GuiTreeViewCtrl::Item* itemA = *( ( GuiTreeViewCtrl::Item** ) a );
 115   GuiTreeViewCtrl::Item* itemB = *( ( GuiTreeViewCtrl::Item** ) b );
 116
 117   char bufferA[ 1024 ];
 118   char bufferB[ 1024 ];
 119
 120   itemA->getDisplayText( sizeof( bufferA ), bufferA );
 121   itemB->getDisplayText( sizeof( bufferB ), bufferB );
 122
 123   return dStrnatcmp( bufferA, bufferB );
 124}
 125
 126static S32 QSORT_CALLBACK itemCompareCaseInsensitive( const void *a, const void *b )
 127{
 128   GuiTreeViewCtrl::Item* itemA = *( ( GuiTreeViewCtrl::Item** ) a );
 129   GuiTreeViewCtrl::Item* itemB = *( ( GuiTreeViewCtrl::Item** ) b );
 130
 131   char bufferA[ 1024 ];
 132   char bufferB[ 1024 ];
 133
 134   itemA->getDisplayText( sizeof( bufferA ), bufferA );
 135   itemB->getDisplayText( sizeof( bufferB ), bufferB );
 136
 137   return dStrnatcasecmp( bufferA, bufferB );
 138}
 139
 140static void itemSortList( GuiTreeViewCtrl::Item*& firstChild, bool caseSensitive, bool traverseHierarchy, bool parentsFirst )
 141{
 142   // Sort the children.
 143   // Do this in a separate scope, so we release the buffers before
 144   // recursing.
 145
 146   {
 147      Vector< GuiTreeViewCtrl::Item*> parents;
 148      Vector< GuiTreeViewCtrl::Item*> items;
 149
 150      // Put all items into the two vectors.
 151
 152      for( GuiTreeViewCtrl::Item* item = firstChild; item != NULL; item = item->mNext )
 153         if( parentsFirst && item->isParent() )
 154            parents.push_back( item );
 155         else
 156            items.push_back( item );
 157
 158      // Sort both vectors.
 159
 160      dQsort( parents.address(), parents.size(), sizeof( GuiTreeViewCtrl::Item* ), caseSensitive ? itemCompareCaseSensitive : itemCompareCaseInsensitive );
 161      dQsort( items.address(), items.size(), sizeof( GuiTreeViewCtrl::Item* ), caseSensitive ? itemCompareCaseSensitive : itemCompareCaseInsensitive );
 162
 163      // Wipe current child chain then reconstruct it in reverse
 164      // as we prepend items.
 165
 166      firstChild = NULL;
 167
 168      // Add child items.
 169
 170      for( U32 i = items.size(); i > 0; -- i )
 171      {
 172         GuiTreeViewCtrl::Item* child = items[ i - 1 ];
 173
 174         child->mNext = firstChild;         
 175         if( firstChild )
 176            firstChild->mPrevious = child;
 177
 178         firstChild = child;
 179      }
 180
 181      // Add parent child items, if requested.
 182
 183      for( U32 i = parents.size(); i > 0; -- i )
 184      {
 185         GuiTreeViewCtrl::Item* child = parents[ i - 1 ];
 186
 187         child->mNext = firstChild;
 188         if( firstChild )
 189            firstChild->mPrevious = child;
 190
 191         firstChild = child;
 192      }
 193
 194      firstChild->mPrevious = NULL;
 195   }
 196
 197   // Traverse hierarchy, if requested.
 198
 199   if( traverseHierarchy )
 200   {
 201      GuiTreeViewCtrl::Item* child = firstChild;
 202      while( child )
 203      {
 204         if( child->isParent() )
 205            child->sort( caseSensitive, traverseHierarchy, parentsFirst );
 206
 207         child = child->mNext;
 208      }
 209   }
 210}
 211
 212
 213//=============================================================================
 214//    GuiTreeViewCtrl::Item.
 215//=============================================================================
 216// MARK: ---- GuiTreeViewCtrl::Item ----
 217
 218//-----------------------------------------------------------------------------
 219
 220GuiTreeViewCtrl::Item::Item( GuiTreeViewCtrl* parent, GuiControlProfile *pProfile )
 221{
 222   AssertFatal( pProfile != NULL , "Cannot create a tree item without a valid tree and control profile!");
 223   mParentControl       = parent;
 224   mState               = 0;
 225   mId                  = -1;
 226   mTabLevel            = 0;
 227   mIcon                = 0;
 228   mDataRenderWidth     = 0;
 229   mParent              = NULL;
 230   mChild               = NULL;
 231   mNext                = NULL;
 232   mPrevious            = NULL;
 233   mProfile             = pProfile;
 234
 235   mScriptInfo.mNormalImage   = BmpCon;
 236   mScriptInfo.mExpandedImage = BmpExp;
 237   mScriptInfo.mText          = NULL;
 238   mScriptInfo.mValue         = NULL;
 239}
 240
 241//-----------------------------------------------------------------------------
 242
 243GuiTreeViewCtrl::Item::~Item()
 244{
 245   _disconnectMonitors();
 246}
 247
 248//-----------------------------------------------------------------------------
 249
 250void GuiTreeViewCtrl::Item::_connectMonitors()
 251{
 252   if( mInspectorInfo.mObject != NULL )
 253   {
 254      SimSet* set = dynamic_cast< SimSet* >( mInspectorInfo.mObject.getPointer() );
 255      if( set )
 256         set->getSetModificationSignal().notify( mParentControl, &GuiTreeViewCtrl::_onInspectorSetObjectModified );
 257   }
 258}
 259
 260//-----------------------------------------------------------------------------
 261
 262void GuiTreeViewCtrl::Item::_disconnectMonitors()
 263{
 264   if( mInspectorInfo.mObject != NULL )
 265   {
 266      SimSet* set = dynamic_cast< SimSet* >( mInspectorInfo.mObject.getPointer() );
 267      if( set )
 268         set->getSetModificationSignal().remove( mParentControl, &GuiTreeViewCtrl::_onInspectorSetObjectModified );
 269   }
 270}
 271
 272//-----------------------------------------------------------------------------
 273
 274void GuiTreeViewCtrl::Item::setNormalImage(S8 id)
 275{
 276   if(mState.test(InspectorData))
 277   {
 278      Con::errorf("Tried to set normal image %d for item %d, which is InspectorData!", id, mId);
 279      return;
 280   }
 281
 282   mScriptInfo.mNormalImage = id;
 283}
 284
 285//-----------------------------------------------------------------------------
 286
 287void GuiTreeViewCtrl::Item::setExpandedImage(S8 id)
 288{
 289   if(mState.test(InspectorData))
 290   {
 291      Con::errorf("Tried to set expanded image %d for item %d, which is InspectorData!", id, mId);
 292      return;
 293   }
 294
 295   mScriptInfo.mExpandedImage = id;
 296}
 297
 298//-----------------------------------------------------------------------------
 299
 300void GuiTreeViewCtrl::Item::setText(StringTableEntry txt)
 301{
 302   if(mState.test(InspectorData))
 303   {
 304      Con::errorf("Tried to set text for item %d, which is InspectorData!", mId);
 305      return;
 306   }
 307
 308   mScriptInfo.mText = txt;
 309
 310
 311   // Update Render Data
 312   if( !mProfile.isNull() )
 313      mDataRenderWidth = getDisplayTextWidth( mProfile->mFont );
 314
 315}
 316
 317//-----------------------------------------------------------------------------
 318
 319void GuiTreeViewCtrl::Item::setValue(StringTableEntry val)
 320{
 321   if(mState.test(InspectorData))
 322   {
 323      Con::errorf("Tried to set value for item %d, which is InspectorData!", mId);
 324      return;
 325   }
 326
 327   mScriptInfo.mValue = const_cast<char*>(val); // mValue really ought to be a StringTableEntry
 328
 329   // Update Render Data
 330   if( !mProfile.isNull() )
 331      mDataRenderWidth = getDisplayTextWidth( mProfile->mFont );
 332
 333}
 334
 335//-----------------------------------------------------------------------------
 336
 337S8 GuiTreeViewCtrl::Item::getNormalImage() const
 338{
 339   if(mState.test(InspectorData))
 340   {
 341      Con::errorf("Tried to get the normal image for item %d, which is InspectorData!", mId);
 342      return 0; // fail safe for width determinations
 343   }
 344
 345   return mScriptInfo.mNormalImage;
 346}
 347
 348//-----------------------------------------------------------------------------
 349
 350S8 GuiTreeViewCtrl::Item::getExpandedImage() const
 351{
 352   if(mState.test(InspectorData))
 353   {
 354      Con::errorf("Tried to get the expanded image for item %d, which is InspectorData!", mId);
 355      return 0; // fail safe for width determinations
 356   }
 357
 358   return mScriptInfo.mExpandedImage;
 359}
 360
 361//-----------------------------------------------------------------------------
 362
 363StringTableEntry GuiTreeViewCtrl::Item::getText()
 364{
 365   if(mState.test(InspectorData))
 366   {
 367      Con::errorf("Tried to get the text for item %d, which is InspectorData!", mId);
 368      return NULL;
 369   }
 370
 371   return ( mScriptInfo.mText ) ? mScriptInfo.mText : StringTable->EmptyString();
 372}
 373
 374//-----------------------------------------------------------------------------
 375
 376StringTableEntry GuiTreeViewCtrl::Item::getValue()
 377{
 378   if(mState.test(InspectorData))
 379   {
 380      Con::errorf("Tried to get the value for item %d, which is InspectorData!", mId);
 381      return NULL;
 382   }
 383
 384   return ( mScriptInfo.mValue ) ? mScriptInfo.mValue : StringTable->EmptyString();
 385}
 386
 387//-----------------------------------------------------------------------------
 388
 389void GuiTreeViewCtrl::Item::setObject(SimObject *obj)
 390{
 391   if(!mState.test(InspectorData))
 392   {
 393      return;
 394   }
 395   
 396   _disconnectMonitors();
 397   mInspectorInfo.mObject = obj;
 398   _connectMonitors();
 399
 400   // Update Render Data
 401   if( !mProfile.isNull() )
 402      mDataRenderWidth = getDisplayTextWidth( mProfile->mFont );
 403}
 404
 405//-----------------------------------------------------------------------------
 406
 407SimObject *GuiTreeViewCtrl::Item::getObject()
 408{
 409   if(!mState.test(InspectorData))
 410   {
 411      return NULL;
 412   }
 413
 414   return mInspectorInfo.mObject;
 415}
 416
 417//-----------------------------------------------------------------------------
 418
 419U32 GuiTreeViewCtrl::Item::getDisplayTextLength()
 420{
 421   if( mState.test( InspectorData ) )
 422   {
 423      SimObject *obj = getObject();
 424      if( !obj )
 425         return 0;
 426
 427      StringTableEntry name = obj->getName();
 428      StringTableEntry internalName = obj->getInternalName();
 429      StringTableEntry className = obj->getClassName();      
 430
 431      if( showInternalNameOnly() )
 432      {
 433         if( internalName && internalName[ 0 ] )
 434            return dStrlen( internalName );
 435         else
 436            return dStrlen( "(none)" );
 437      }
 438      else if( showObjectNameOnly() )
 439      {
 440         if( name && name[ 0 ] )
 441            return dStrlen( name );
 442         else if( mState.test( ShowClassNameForUnnamed ) )
 443            return dStrlen( className );
 444         else
 445            return dStrlen( "(none)" );
 446      }
 447
 448      dsize_t len = 0;
 449      if( mState.test( ShowObjectId ) )
 450         len += dStrlen( obj->getIdString() ) + 2; // '<id>: '
 451      if( mState.test( ShowClassName ) )
 452      {
 453         if( name && name[ 0 ] )
 454            len += dStrlen( className ) + 3; // '<class> - '
 455         else
 456            len += dStrlen( className );
 457      }
 458      if( mState.test( ShowObjectName ) )
 459      {
 460         if( name && name[ 0 ] )
 461            len += dStrlen( name );
 462         else if( mState.test( ShowClassNameForUnnamed ) )
 463            len += dStrlen( className );
 464      }
 465      if( mState.test( ShowInternalName ) )
 466      {
 467         if( internalName && internalName[ 0 ] )
 468            len += dStrlen( internalName ) + 3; // ' [<internalname>]'
 469      }
 470
 471      return len;
 472   }
 473
 474   StringTableEntry pText = getText();
 475   if( pText == NULL )
 476      return 0;
 477
 478   return dStrlen( pText );
 479}
 480
 481//-----------------------------------------------------------------------------
 482
 483void GuiTreeViewCtrl::Item::getDisplayText(U32 bufLen, char *buf)
 484{
 485   FrameAllocatorMarker txtAlloc;
 486
 487   //if we're doing the special case of forcing the item text, just skip the rest of this junk
 488   if (mState.test(ForceItemName))
 489   {
 490      StringTableEntry text = (mScriptInfo.mText) ? mScriptInfo.mText : StringTable->EmptyString();
 491      dStrncpy(buf, text, bufLen);
 492      return;
 493   }
 494
 495   if( mState.test( InspectorData ) )
 496   {
 497      SimObject *pObject = getObject();
 498      if( pObject )
 499      {
 500         const char* pObjName = pObject->getName();
 501         const char* pInternalName = pObject->getInternalName();
 502
 503         bool hasInternalName = pInternalName && pInternalName[0];
 504         bool hasObjectName = pObjName && pObjName[0];
 505
 506         const char* pClassName = pObject->getClassName();
 507
 508         if( showInternalNameOnly() )
 509            dSprintf( buf, bufLen, "%s", hasInternalName ? pInternalName : "(none)" );
 510         else if( showObjectNameOnly() )
 511         {
 512            if( !hasObjectName && mState.test( ShowClassNameForUnnamed ) )
 513               dSprintf( buf, bufLen, "%s", pClassName );
 514            else
 515               dSprintf( buf, bufLen, "%s", hasObjectName ? pObjName : "(none)" );
 516         }
 517         else
 518         {
 519            char* ptr = buf;
 520            int len = bufLen;
 521            
 522            if( mState.test( ShowObjectId ) )
 523            {
 524               S32 n = dSprintf( ptr, len, "%d: ", pObject->getId() );
 525               ptr += n;
 526               len -= n;
 527            }
 528            
 529            if( mState.test( ShowClassName ) )
 530            {
 531               S32 n;
 532               if( hasObjectName && mState.test( ShowObjectName ) )
 533                  n = dSprintf( ptr, len, "%s - ", pClassName );
 534               else
 535                  n = dSprintf( ptr, len, "%s", pClassName );
 536               
 537               ptr += n;
 538               len -= n;
 539            }
 540            
 541            if( mState.test( ShowObjectName ) )
 542            {
 543               S32 n = 0;
 544               if (hasObjectName)
 545               {
 546                  //If it's been marked, reflect that
 547                  if (mState.test(Item::Marked))
 548                     n = dSprintf(ptr, len, "*%s", pObjName);
 549                  else
 550                     n = dSprintf(ptr, len, "%s", pObjName);                  
 551               }
 552               else if( mState.test( ShowClassNameForUnnamed ) )
 553                  n = dSprintf( ptr, len, "%s", pClassName );
 554                  
 555               ptr += n;
 556               len -= n;
 557            }
 558            
 559            if (hasInternalName && mState.test(ShowInternalName))
 560            {
 561               if (mState.test(Item::Marked))
 562                  dSprintf(ptr, len, " *[%s]", pInternalName);
 563               else
 564                  dSprintf(ptr, len, " [%s]", pInternalName);
 565            }
 566         }
 567      }
 568      else
 569         buf[ 0 ] = '\0';
 570   }
 571   else
 572   {
 573      // Script data! (copy it in)
 574      dStrncpy(buf, getText(), bufLen);
 575   }
 576}
 577
 578//-----------------------------------------------------------------------------
 579
 580S32 GuiTreeViewCtrl::Item::getDisplayTextWidth(GFont *font)
 581{
 582   if( !font )
 583      return 0;
 584
 585   FrameAllocatorMarker txtAlloc;
 586   U32 bufLen = getDisplayTextLength();
 587   if( bufLen == 0 )
 588      return 0;
 589
 590   // Add space for the string terminator
 591   bufLen++;
 592
 593   char *buf = (char*)txtAlloc.alloc(bufLen);
 594   getDisplayText(bufLen, buf);
 595
 596   return font->getStrWidth(buf);
 597}
 598
 599//-----------------------------------------------------------------------------
 600
 601bool GuiTreeViewCtrl::Item::hasObjectBasedTooltip()
 602{
 603   if(mState.test(Item::InspectorData))
 604   {
 605      SimObject *pObject = getObject();
 606      if(pObject)
 607      {
 608         const char* pClassName = pObject->getClassName();
 609
 610         // Retrieve custom tooltip string
 611         String method("GetTooltip");
 612         method += pClassName;
 613         if(mParentControl->isMethod(method.c_str()))
 614         {
 615            return true;
 616         }
 617      }
 618   }
 619
 620   return false;
 621}
 622
 623//-----------------------------------------------------------------------------
 624
 625void GuiTreeViewCtrl::Item::getTooltipText(U32 bufLen, char *buf)
 626{
 627   getDisplayText(bufLen, buf);
 628
 629   if(mState.test(Item::InspectorData))
 630   {
 631      SimObject *pObject = getObject();
 632      if(pObject)
 633      {
 634         const char* pClassName = pObject->getClassName();
 635
 636         // Retrieve custom tooltip string
 637         String method("GetTooltip");
 638         method += pClassName;
 639         if(mParentControl->isMethod(method.c_str()))
 640         {
 641            const char* tooltip = Con::executef( mParentControl, method.c_str(), pObject->getIdString() );
 642            dsize_t len = dStrlen(buf);
 643            S32 newBufLen = bufLen-len;
 644            if(dStrlen(tooltip) > 0 && newBufLen > 0)
 645            {
 646               dSprintf(buf+len, newBufLen, "\n%s", tooltip);
 647            }
 648         }
 649      }
 650   }
 651}
 652
 653//-----------------------------------------------------------------------------
 654
 655bool GuiTreeViewCtrl::Item::isParent() const
 656{
 657   if(mState.test(VirtualParent))
 658   {
 659      if( !isInspectorData() )
 660         return true;
 661
 662      // Does our object have any children?
 663      if(mInspectorInfo.mObject)
 664      {
 665         SimSet *pSimSet = dynamic_cast<SimSet*>( (SimObject*)mInspectorInfo.mObject);
 666         if ( pSimSet != NULL && pSimSet->size() > 0)
 667            return pSimSet->size();
 668      }
 669   }
 670
 671   // Otherwise, just return whether the child list is populated.
 672   return mChild;
 673}
 674
 675//-----------------------------------------------------------------------------
 676
 677bool GuiTreeViewCtrl::Item::isExpanded() const
 678{
 679   if(mState.test(InspectorData))
 680      return mInspectorInfo.mObject ? mInspectorInfo.mObject->isExpanded() : false;
 681   else
 682      return mState.test(Expanded);
 683}
 684
 685//-----------------------------------------------------------------------------
 686
 687void GuiTreeViewCtrl::Item::setExpanded(bool f)
 688{
 689   if( mState.test(InspectorData) )
 690   {
 691      if( !mInspectorInfo.mObject.isNull() )
 692         mInspectorInfo.mObject->setExpanded(f);
 693   }
 694   else
 695      mState.set(Expanded, f);
 696}
 697
 698//-----------------------------------------------------------------------------
 699
 700void GuiTreeViewCtrl::Item::setVirtualParent( bool value )
 701{
 702   mState.set(VirtualParent, value);
 703}
 704
 705//-----------------------------------------------------------------------------
 706
 707GuiTreeViewCtrl::Item* GuiTreeViewCtrl::Item::findChildByName( const char* name )
 708{
 709   Item* child = mChild;
 710   while( child )
 711   {
 712      if( dStricmp( child->mScriptInfo.mText, name ) == 0 )
 713         return child;
 714         
 715      child = child->mNext;
 716   }
 717   
 718   return NULL;
 719}
 720
 721//-----------------------------------------------------------------------------
 722
 723GuiTreeViewCtrl::Item *GuiTreeViewCtrl::Item::findChildByValue(const SimObject *obj)
 724{
 725   // Iterate over our children and try to find the given
 726   // SimObject
 727
 728   Item *pResultObj = mChild;
 729
 730   while(pResultObj)
 731   {
 732      // CodeReview this check may need to be removed
 733      // if we want to use the tree for data that
 734      // isn't related to SimObject based objects with
 735      // arbitrary values associated with them [5/5/2007 justind]
 736
 737      // Skip non-inspector data stuff.
 738      if(pResultObj->mState.test(InspectorData))
 739      {
 740         if(pResultObj->getObject() == obj)
 741            break; // Whoa.
 742      }
 743      pResultObj = pResultObj->mNext;
 744   }
 745   // If the loop terminated we are NULL, otherwise we have the result in res.
 746   return pResultObj;
 747}
 748
 749//-----------------------------------------------------------------------------
 750
 751GuiTreeViewCtrl::Item *GuiTreeViewCtrl::Item::findChildByValue( StringTableEntry Value )
 752{
 753   // Iterate over our children and try to find the given Value
 754   // Note : This is a case-insensitive search
 755   Item *pResultObj = mChild;
 756
 757   while(pResultObj)
 758   {
 759
 760      // check the script value of the item against the specified value
 761      if( pResultObj->mScriptInfo.mValue != NULL && dStricmp( pResultObj->mScriptInfo.mValue, Value ) == 0 )
 762         return pResultObj;
 763      pResultObj = pResultObj->mNext;
 764   }
 765   // If the loop terminated we didn't find an item with the specified script value
 766   return NULL;
 767}
 768
 769//-----------------------------------------------------------------------------
 770
 771void GuiTreeViewCtrl::Item::sort( bool caseSensitive, bool traverseHierarchy, bool parentsFirst )
 772{
 773   itemSortList( mChild, caseSensitive, traverseHierarchy, parentsFirst );
 774}
 775
 776//=============================================================================
 777//    GuiTreeViewCtrl.
 778//=============================================================================
 779// MARK: ---- GuiTreeViewCtrl ----
 780
 781//-----------------------------------------------------------------------------
 782
 783GuiTreeViewCtrl::GuiTreeViewCtrl()
 784{
 785   VECTOR_SET_ASSOCIATION(mItems);
 786   VECTOR_SET_ASSOCIATION(mVisibleItems);
 787   VECTOR_SET_ASSOCIATION(mSelectedItems);
 788   VECTOR_SET_ASSOCIATION(mSelected);
 789
 790   mItemFreeList  =  NULL;
 791   mRoot          =  NULL;
 792   mItemCount     =  0;
 793   mSelectedItem  =  0;
 794   mStart         =  0;
 795   mPossibleRenameItem = NULL;
 796   mRenamingItem = NULL;
 797   mTempItem = NULL;
 798   mRenameCtrl = NULL;
 799
 800   mDraggedToItem =  0;
 801   mCurrentDragCell = 0;
 802   mPreviousDragCell = 0;
 803   mDragMidPoint = NomDragMidPoint;
 804   mMouseDragged = false;
 805   mDebug = false;
 806
 807   // persist info..
 808   mTabSize = 16;
 809   mTextOffset = 2;
 810   mFullRowSelect = false;
 811   mItemHeight = 20;
 812
 813   //
 814   setSize(Point2I(1, 0));
 815
 816   // Set up default state
 817   mFlags.set(ShowTreeLines);
 818   mFlags.set(IsEditable, false);
 819
 820   mDestroyOnSleep = true;
 821   mSupportMouseDragging = true;
 822   mMultipleSelections = true;
 823   mDeleteObjectAllowed = true;
 824   mDragToItemAllowed = true;
 825   mShowRoot = true;
 826   mUseInspectorTooltips = false;
 827   mTooltipOnWidthOnly = false;
 828   mCompareToObjectID = true;
 829   mShowObjectIds = true;
 830   mShowClassNames = true;
 831   mShowObjectNames = true;
 832   mShowInternalNames = true;
 833   mShowClassNameForUnnamedObjects = false;
 834   mFlags.set(RebuildVisible);
 835
 836   mCanRenameObjects = true;
 837   mRenameInternal = false;
 838
 839   mClearAllOnSingleSelection = true;
 840
 841   mBitmapBase       = StringTable->EmptyString();
 842   mTexRollover      = NULL;
 843   mTexSelected      = NULL;
 844   
 845   mRenderTooltipDelegate.bind( this, &GuiTreeViewCtrl::renderTooltip );
 846
 847   mDoFilterChildren = true;
 848}
 849
 850//-----------------------------------------------------------------------------
 851
 852GuiTreeViewCtrl::~GuiTreeViewCtrl()
 853{
 854   _destroyTree();
 855}
 856
 857//------------------------------------------------------------------------------
 858
 859void GuiTreeViewCtrl::initPersistFields()
 860{
 861   addGroup( "TreeView" );
 862
 863      addField( "tabSize",              TypeS32,    Offset(mTabSize,              GuiTreeViewCtrl));
 864      addField( "textOffset",           TypeS32,    Offset(mTextOffset,           GuiTreeViewCtrl));
 865      addField( "fullRowSelect",        TypeBool,   Offset(mFullRowSelect,        GuiTreeViewCtrl));
 866      addField( "itemHeight",           TypeS32,    Offset(mItemHeight,           GuiTreeViewCtrl));
 867      addField( "destroyTreeOnSleep",   TypeBool,   Offset(mDestroyOnSleep,       GuiTreeViewCtrl),
 868         "If true, the entire tree item hierarchy is deleted when the control goes to sleep." );
 869      addField( "mouseDragging",        TypeBool,   Offset(mSupportMouseDragging, GuiTreeViewCtrl));
 870      addField( "multipleSelections",   TypeBool,   Offset(mMultipleSelections,   GuiTreeViewCtrl),
 871         "If true, multiple items can be selected concurrently." );
 872      addField( "deleteObjectAllowed",  TypeBool,   Offset(mDeleteObjectAllowed,  GuiTreeViewCtrl));
 873      addField( "dragToItemAllowed",    TypeBool,   Offset(mDragToItemAllowed,    GuiTreeViewCtrl));
 874      addField( "clearAllOnSingleSelection",  TypeBool,   Offset(mClearAllOnSingleSelection,  GuiTreeViewCtrl));
 875      addField( "showRoot",             TypeBool,   Offset(mShowRoot,             GuiTreeViewCtrl),
 876         "If true, the root item is shown in the tree." );
 877      addField( "useInspectorTooltips", TypeBool,   Offset(mUseInspectorTooltips,    GuiTreeViewCtrl));
 878      addField( "tooltipOnWidthOnly",   TypeBool,   Offset(mTooltipOnWidthOnly,    GuiTreeViewCtrl));
 879
 880   endGroup( "TreeView" );
 881   
 882   addGroup( "Inspector Trees" );
 883   
 884      addField( "showObjectIds", TypeBool, Offset( mShowObjectIds, GuiTreeViewCtrl ),
 885         "If true, item text labels for objects will include object IDs." );
 886      addField( "showClassNames", TypeBool, Offset( mShowClassNames, GuiTreeViewCtrl ),
 887         "If true, item text labels for objects will include class names." );
 888      addField( "showObjectNames", TypeBool, Offset( mShowObjectNames, GuiTreeViewCtrl ),
 889         "If true, item text labels for objects will include object names." );
 890      addField( "showInternalNames", TypeBool, Offset( mShowInternalNames, GuiTreeViewCtrl ),
 891         "If true, item text labels for obje ts will include internal names." );
 892      addField( "showClassNameForUnnamedObjects", TypeBool, Offset( mShowClassNameForUnnamedObjects, GuiTreeViewCtrl ),
 893         "If true, class names will be used as object names for unnamed objects." );
 894      addField( "compareToObjectID",    TypeBool,   Offset(mCompareToObjectID,    GuiTreeViewCtrl));
 895      addField( "canRenameObjects",     TypeBool,   Offset(mCanRenameObjects,     GuiTreeViewCtrl),       
 896         "If true clicking on a selected item ( that is an object and not the root ) will allow you to rename it." );
 897      addField( "renameInternal",       TypeBool,   Offset(mRenameInternal,       GuiTreeViewCtrl),
 898         "If true then object renaming operates on the internalName rather than the object name." );
 899
 900   endGroup( "Inspector Trees" );
 901
 902   Parent::initPersistFields();
 903}
 904
 905//------------------------------------------------------------------------------
 906
 907GuiTreeViewCtrl::Item * GuiTreeViewCtrl::getItem(S32 itemId) const
 908{
 909   if ( itemId > 0 && itemId <= mItems.size() )
 910      return mItems[itemId-1];
 911   return NULL;
 912}
 913
 914//------------------------------------------------------------------------------
 915
 916GuiTreeViewCtrl::Item * GuiTreeViewCtrl::createItem(S32 icon)
 917{
 918   Item * pNewItem = NULL;
 919
 920   // grab from the free list?
 921   if( mItemFreeList )
 922   {
 923      pNewItem = mItemFreeList;
 924      mItemFreeList = pNewItem->mNext;
 925
 926      // re-add to vector
 927      mItems[ pNewItem->mId - 1 ] = pNewItem;
 928   }
 929   else
 930   {
 931      pNewItem = new Item( this, mProfile );
 932
 933      AssertFatal( pNewItem != NULL, "Fatal : unable to allocate tree item!");
 934
 935      mItems.push_back( pNewItem );
 936
 937      // set the id
 938      pNewItem->mId = mItems.size();
 939   }
 940
 941   // reset
 942   if (icon)
 943      pNewItem->mIcon = icon;
 944   else
 945      pNewItem->mIcon = Default; //default icon to stick next to an item
 946
 947   pNewItem->mState = Item::ShowObjectId | Item::ShowClassName | Item::ShowObjectName | Item::ShowInternalName;
 948   pNewItem->mTabLevel = 0;
 949
 950   // Null out item pointers
 951   pNewItem->mNext = 0;
 952   pNewItem->mPrevious = 0;
 953   pNewItem->mChild = 0;
 954   pNewItem->mParent = 0;
 955
 956   mItemCount++;
 957
 958   return pNewItem;
 959}
 960
 961//------------------------------------------------------------------------------
 962
 963void GuiTreeViewCtrl::_destroyChildren( Item* item, Item* parent, bool deleteObjects )
 964{
 965   if ( !item  || item == parent || !mItems[item->mId-1] )
 966      return;
 967
 968   // destroy depth first, then siblings from last to first
 969   if ( item->isParent() && item->mChild )
 970      _destroyChildren(item->mChild, item, deleteObjects);
 971   if( item->mNext )
 972      _destroyChildren(item->mNext, parent, deleteObjects);
 973
 974   // destroy the item
 975   _destroyItem( item, deleteObjects );
 976}
 977
 978//-----------------------------------------------------------------------------
 979
 980void GuiTreeViewCtrl::_destroyItem( Item* item, bool deleteObject )
 981{
 982   if(!item)
 983      return;
 984
 985   if(item->isInspectorData())
 986   {
 987      // make sure the SimObjectPtr is clean!
 988      SimObject *pObject = item->getObject();
 989      if( pObject && pObject->isProperlyAdded() )
 990      {
 991         bool skipDelete = !deleteObject;
 992
 993         if( !skipDelete && isMethod( "onDeleteObject" ) )
 994            skipDelete = onDeleteObject_callback( pObject );
 995
 996         if ( !skipDelete )
 997            pObject->deleteObject();
 998      }
 999
1000      item->setObject( NULL );
1001   }
1002
1003   // Remove item from the selection
1004   if (mSelectedItem == item->mId)
1005      mSelectedItem = 0;
1006   for ( S32 i = 0; i < mSelectedItems.size(); i++ ) 
1007   {
1008      if ( mSelectedItems[i] == item ) 
1009      {
1010         mSelectedItems.erase( i );
1011         break;
1012      }
1013   }
1014   item->mState.clear();
1015
1016   // unlink
1017   if( item->mPrevious )
1018      item->mPrevious->mNext = item->mNext;
1019   if( item->mNext )
1020      item->mNext->mPrevious = item->mPrevious;
1021   if( item->mParent && ( item->mParent->mChild == item ) )
1022      item->mParent->mChild = item->mNext;
1023
1024   // remove from vector
1025   mItems[item->mId-1] = 0;
1026
1027   // set as root free item
1028   item->mNext = mItemFreeList;
1029   mItemFreeList = item;
1030   mItemCount--;
1031}
1032
1033//------------------------------------------------------------------------------
1034
1035void GuiTreeViewCtrl::_deleteItem(Item *item)
1036{
1037   removeItem(item->mId);
1038}
1039
1040//------------------------------------------------------------------------------
1041
1042void GuiTreeViewCtrl::_destroyTree()
1043{
1044   // clear the item list
1045   for(U32 i = 0; i < mItems.size(); i++)
1046   {
1047      Item *pFreeItem = mItems[ i ];
1048      if( pFreeItem != NULL )
1049         delete pFreeItem;
1050   }
1051
1052   mItems.clear();
1053
1054   // clear the free list
1055   while(mItemFreeList)
1056   {
1057      Item *next = mItemFreeList->mNext;
1058      delete mItemFreeList;
1059      mItemFreeList = next;
1060   }
1061
1062   mVisibleItems.clear();
1063   mSelectedItems.clear();
1064
1065   //
1066   mRoot          = NULL;
1067   mItemFreeList  = NULL;
1068   mItemCount     = 0;
1069   mSelectedItem  = 0;
1070   mDraggedToItem = 0;
1071
1072   mRenamingItem = NULL;
1073   mTempItem = NULL;
1074   mPossibleRenameItem = NULL;
1075}
1076
1077//------------------------------------------------------------------------------
1078
1079void GuiTreeViewCtrl::_onInspectorSetObjectModified( SetModification modification, SimSet* set, SimObject* object )
1080{
1081   // Don't bother searching for the Item to see if it is actually visible and instead just
1082   // mark our tree state as dirty so we get a rebuild on the next render.
1083
1084   mFlags.set( RebuildVisible );
1085}
1086
1087//------------------------------------------------------------------------------
1088
1089GuiTreeViewCtrl::Item* GuiTreeViewCtrl::_findItemByAmbiguousId( S32 itemOrObjectId, bool buildVirtual )
1090{
1091   Item* item = getItem( itemOrObjectId );
1092   if( item )
1093      return item;
1094
1095   SimObject* object = Sim::findObject( itemOrObjectId );
1096   if( object )
1097   {
1098      // If we should expand virtual trees in order to find the item,
1099      // do so now.
1100      if( buildVirtual )
1101      {
1102         if( mFlags.test( RebuildVisible ) )
1103            buildVisibleTree();
1104
1105         SimGroup* group = object->getGroup();
1106         if( group )
1107            _expandObjectHierarchy( group );
1108      }
1109
1110      if( objectSearch( object, &item ) )
1111         return item;
1112   }
1113
1114   return NULL;
1115}
1116
1117//------------------------------------------------------------------------------
1118
1119void GuiTreeViewCtrl::_expandObjectHierarchy( SimGroup* group )
1120{
1121   SimGroup* parent = group->getGroup();
1122   if( parent && !parent->isExpanded() )
1123      _expandObjectHierarchy( parent );
1124
1125   if( !group->isExpanded() )
1126   {
1127      Item* item;
1128      if( objectSearch( group, &item ) )
1129      {
1130         item->setExpanded();
1131         onVirtualParentBuild( item, false );
1132      }
1133   }
1134}
1135
1136//------------------------------------------------------------------------------
1137
1138void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdate, bool skipFlter )
1139{
1140   if (!item || !mActive || !isVisible() || !mProfile  )
1141      return;
1142
1143   // If it's inspector data, make sure we still have it, if not, kill it.
1144   if(item->isInspectorData() && !item->getObject() )
1145   {
1146      removeItem(item->mId);
1147      return;
1148   }
1149
1150   // If it's a virtual parent, give a chance to update itself...
1151   if(item->mState.test( Item::VirtualParent) )
1152   {
1153      // If it returns false the item has been removed.
1154
1155      if( !onVirtualParentBuild( item, bForceFullUpdate ) )
1156         return;
1157   }
1158
1159   // If we have a filter pattern, sync the item's filtering status to it.
1160
1161   if( !getFilterText().isEmpty() && !skipFlter)
1162   {
1163      // Determine the filtering status by looking for the filter
1164      // text in the item's display text.
1165
1166      char displayText[ 2048 ];
1167      item->getDisplayText( sizeof( displayText ), displayText );
1168      if( !dStristr( displayText, mFilterText ) )
1169      {
1170         //Last check, see if we special-exception this item
1171         if (!mItemFilterExceptionList.contains(item->mId))
1172            item->mState.set(Item::Filtered);
1173         else
1174            item->mState.clear(Item::Filtered);
1175
1176         // If it's not a parent, we're done.  Otherwise, there may be children
1177         // that are not filtered so we need to process them first.
1178
1179         if( !item->isParent() )
1180            return;
1181      }
1182      else
1183      {
1184         item->mState.clear(Item::Filtered);
1185      }
1186   }
1187   else
1188      item->mState.clear( Item::Filtered );
1189
1190   //If the item should be hidden from view, check now
1191   if (mHiddenItemsList.contains(item->mId))
1192      item->mState.set(Item::Filtered);
1193
1194   // Is this the root item?
1195   const bool isRoot = item == mRoot;
1196
1197   // Add non-root items or the root if we're supposed to show it.
1198
1199   if( ( mShowRoot || !isRoot ) &&
1200       !item->isFiltered() )
1201   {
1202      item->mTabLevel = tabLevel;
1203      mVisibleItems.push_back( item );
1204
1205      if( mProfile != NULL )
1206      {
1207         mProfile->incLoadCount();
1208         
1209         S32 width = mTextOffset + ( mTabSize * item->mTabLevel ) + getInspectorItemIconsWidth( item ) + item->getDisplayTextWidth( mProfile->mFont );
1210
1211         // check image
1212         S32 image = BmpChild;
1213         if ( item->isInspectorData() )
1214            image = item->isExpanded() ? BmpExp : BmpCon;
1215         else
1216            image = item->isExpanded() ? item->getExpandedImage() : item->getNormalImage();
1217
1218         if ( ( image >= 0 ) && ( image < mProfile->mBitmapArrayRects.size() ) )
1219            width += mProfile->mBitmapArrayRects[image].extent.x;
1220
1221         if ( width > mMaxWidth )
1222            mMaxWidth = width;
1223            
1224         mProfile->decLoadCount();
1225      }
1226   }
1227
1228   // If expanded or a hidden root, add all the
1229   // children items as well.
1230
1231   if (  item->isExpanded() || 
1232         bForceFullUpdate ||
1233         ( isRoot && !mShowRoot ) )
1234   {
1235      Item* child = item->mChild;
1236      while ( child )
1237      {
1238         // Bit of a hack so we can safely remove items as we
1239         // traverse.
1240         Item *pChildTemp = child;
1241         child = child->mNext;
1242
1243         if (!mItemFilterExceptionList.contains(item->mId) && !mDoFilterChildren && !item->isFiltered())
1244            _buildItem( pChildTemp, tabLevel + 1, bForceFullUpdate, true );
1245         else
1246            _buildItem(pChildTemp, tabLevel + 1, bForceFullUpdate, false);
1247      }
1248   }
1249}
1250
1251//------------------------------------------------------------------------------
1252
1253void GuiTreeViewCtrl::buildVisibleTree(bool bForceFullUpdate)
1254{
1255   // Recursion Prevention.
1256   if( mFlags.test( BuildingVisTree ) )
1257      return;
1258   mFlags.set( BuildingVisTree, true );
1259
1260   if( mDebug )
1261      Con::printf( "Rebuilding visible tree" );
1262
1263   mMaxWidth = 0;
1264   mVisibleItems.clear();
1265
1266   // If we're filtering, force a full update.
1267
1268   if( !mFilterText.isEmpty() )
1269      bForceFullUpdate = true;
1270
1271   // Update the flags.
1272   mFlags.clear(RebuildVisible);
1273
1274   // build the root items
1275   Item *traverse = mRoot;
1276   while(traverse)
1277   {
1278      _buildItem(traverse, 0, bForceFullUpdate);
1279      traverse = traverse->mNext;
1280   }
1281
1282   // adjust the GuiArrayCtrl
1283   mCellSize.set( mMaxWidth + mTextOffset, mItemHeight );
1284   setSize(Point2I(1, mVisibleItems.size()));
1285   syncSelection();
1286
1287   // Done Recursing.
1288   mFlags.clear( BuildingVisTree );
1289}
1290
1291//------------------------------------------------------------------------------
1292
1293bool GuiTreeViewCtrl::scrollVisible( S32 itemId )
1294{
1295   Item* item = getItem(itemId);
1296   if(item)
1297      return scrollVisible(item);
1298
1299   return false;
1300}
1301
1302//-----------------------------------------------------------------------------
1303
1304bool GuiTreeViewCtrl::scrollVisible( Item *item )
1305{
1306   // Now, make sure it's visible (ie, all parents expanded)
1307   Item *parent = item->mParent;
1308
1309   if( !item->isInspectorData() && item->mState.test(Item::VirtualParent) )
1310      onVirtualParentExpand(item);
1311
1312   while(parent)
1313   {
1314      parent->setExpanded(true);
1315
1316      if( !parent->isInspectorData() && parent->mState.test(Item::VirtualParent) )
1317         onVirtualParentExpand(parent);
1318
1319      parent = parent->mParent;
1320   }
1321
1322   // Get our scroll-pappy, if any.
1323   GuiScrollCtrl *pScrollParent = dynamic_cast<GuiScrollCtrl*>( getParent() );
1324
1325   if ( !pScrollParent )
1326   {
1327      Con::warnf("GuiTreeViewCtrl::scrollVisible - parent control is not a GuiScrollCtrl!");
1328      return false;
1329   }
1330
1331   // And now, build the visible tree so we know where we have to scroll.
1332   if( mFlags.test( RebuildVisible ) )
1333      buildVisibleTree();
1334
1335   // All done, let's figure out where we have to scroll...
1336   for(S32 i=0; i<mVisibleItems.size(); i++)
1337   {
1338      if(mVisibleItems[i] == item)
1339      {
1340         // Fetch X Details.
1341         const S32 xPos   = pScrollParent->getChildRelPos().x;
1342         const S32 xWidth = ( mMaxWidth - xPos );
1343
1344         // Scroll to View the Item.
1345         // Note: Delta X should be 0 so that we maintain the X axis position.
1346         pScrollParent->scrollRectVisible( RectI( xPos, i * mItemHeight, xWidth, mItemHeight ) );
1347         return true;
1348      }
1349   }
1350
1351   // If we got here, it's probably bad...
1352   Con::errorf("GuiTreeViewCtrl::scrollVisible - was unable to find specified item in visible list!");
1353   return false;
1354}
1355
1356//------------------------------------------------------------------------------
1357
1358S32 GuiTreeViewCtrl::insertItem(S32 parentId, const char * text, const char * value, const char * iconString, S16 normalImage, S16 expandedImage)
1359{
1360   if( ( parentId < 0 ) || ( parentId > mItems.size() ) )
1361   {
1362      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::insertItem: invalid parent id!");
1363      return 0;
1364   }
1365
1366   if((parentId != 0) && (mItems[parentId-1] == 0))
1367   {
1368      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::insertItem: parent item invalid!");
1369      return 0;
1370   }
1371
1372
1373   const char * pItemText  = ( text != NULL ) ? text : "";
1374   const char * pItemValue = ( value != NULL ) ? value : "";
1375
1376   S32 icon = getIcon(iconString);
1377
1378   // create an item (assigns id)
1379   Item * pNewItem = createItem(icon);
1380   if( pNewItem == NULL )
1381      return 0;
1382
1383   pNewItem->setText( StringTable->insert( pItemText, true ) );
1384   pNewItem->setValue( StringTable->insert( pItemValue, true ) );
1385   
1386   pNewItem->setNormalImage( normalImage );
1387   pNewItem->setExpandedImage( expandedImage );
1388
1389   // root level?
1390   if(parentId == 0)
1391   {
1392      // insert back
1393      if( mRoot != NULL )
1394      {
1395         Item * pTreeTraverse = mRoot;
1396         while( pTreeTraverse != NULL && pTreeTraverse->mNext != NULL )
1397            pTreeTraverse = pTreeTraverse->mNext;
1398
1399         pTreeTraverse->mNext = pNewItem;
1400         pNewItem->mPrevious = pTreeTraverse;
1401      }
1402      else
1403         mRoot = pNewItem;
1404
1405      mFlags.set(RebuildVisible);
1406   }
1407   else if( mItems.size() >= ( parentId - 1 ) )
1408   {
1409      Item * pParentItem = mItems[parentId-1];
1410
1411      // insert back
1412      if( pParentItem != NULL && pParentItem->mChild)
1413      {
1414         Item * pTreeTraverse = pParentItem->mChild;
1415         while( pTreeTraverse != NULL && pTreeTraverse->mNext != NULL )
1416            pTreeTraverse = pTreeTraverse->mNext;
1417
1418         pTreeTraverse->mNext = pNewItem;
1419         pNewItem->mPrevious = pTreeTraverse;
1420      }
1421      else
1422         pParentItem->mChild = pNewItem;
1423
1424      pNewItem->mParent = pParentItem;
1425
1426      if( pParentItem->isExpanded() )
1427         mFlags.set(RebuildVisible);
1428   }
1429
1430   return pNewItem->mId;
1431}
1432
1433//------------------------------------------------------------------------------
1434
1435bool GuiTreeViewCtrl::removeItem( S32 itemId, bool deleteObjects )
1436{
1437   if( isSelected( itemId ) )
1438      removeSelection( itemId );
1439      
1440   // tree?
1441   if(itemId == 0)
1442   {
1443      //RD: this does not delete objects and thus isn't coherent with the semantics of this method
1444      
1445      _destroyTree();
1446      return(true);
1447   }
1448
1449   Item * item = getItem(itemId);
1450   if(!item)
1451   {
1452      //Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::removeItem: invalid item id!");
1453      return false;
1454   }
1455
1456   // root?
1457   if(item == mRoot)
1458      mRoot = item->mNext;
1459
1460   // Dispose of any children...
1461   if (item->mChild)
1462      _destroyChildren( item->mChild, item, deleteObjects );
1463
1464   // Kill the item...
1465   _destroyItem( item, deleteObjects );
1466
1467   // Update the rendered tree...
1468   mFlags.set(RebuildVisible);
1469
1470   return true;
1471}
1472
1473
1474//-----------------------------------------------------------------------------
1475
1476void GuiTreeViewCtrl::removeAllChildren(S32 itemId)
1477{
1478   Item * item = getItem(itemId);
1479   if(item)
1480   {
1481      _destroyChildren(item->mChild, item);
1482   }
1483}
1484//------------------------------------------------------------------------------
1485
1486const S32 GuiTreeViewCtrl::getFirstRootItem() const
1487{
1488   return (mRoot ? mRoot->mId : 0);
1489}
1490
1491//------------------------------------------------------------------------------
1492
1493S32 GuiTreeViewCtrl::getChildItem(S32 itemId)
1494{
1495   Item * item = getItem(itemId);
1496   if(!item)
1497   {
1498      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getChild: invalid item id!");
1499      return(0);
1500   }
1501
1502   return(item->mChild ? item->mChild->mId : 0);
1503}
1504
1505//-----------------------------------------------------------------------------
1506
1507S32 GuiTreeViewCtrl::getParentItem(S32 itemId)
1508{
1509   Item * item = getItem(itemId);
1510   if(!item)
1511   {
1512      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getParent: invalid item id!");
1513      return(0);
1514   }
1515
1516   return(item->mParent ? item->mParent->mId : 0);
1517}
1518
1519//-----------------------------------------------------------------------------
1520
1521S32 GuiTreeViewCtrl::getNextSiblingItem(S32 itemId)
1522{
1523   Item * item = getItem(itemId);
1524   if(!item)
1525   {
1526      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getNextSibling: invalid item id!");
1527      return(0);
1528   }
1529
1530   return(item->mNext ? item->mNext->mId : 0);
1531}
1532
1533//-----------------------------------------------------------------------------
1534
1535S32 GuiTreeViewCtrl::getPrevSiblingItem(S32 itemId)
1536{
1537   Item * item = getItem(itemId);
1538   if(!item)
1539   {
1540      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getPrevSibling: invalid item id!");
1541      return(0);
1542   }
1543
1544   return(item->mPrevious ? item->mPrevious->mId : 0);
1545}
1546
1547//------------------------------------------------------------------------------
1548
1549bool GuiTreeViewCtrl::isValidDragTarget( Item* item )
1550{
1551   bool isValid = true;
1552   
1553   // First, check if we're just going to override this from manually setting the ForceAllowDrag flag
1554   // If that's set, we're assuming special circumstances and will just let it go on it's way
1555   if (item->isDragTargetAllowed())
1556      return true;
1557   
1558   // If this is inspector data, first make sure the item accepts all
1559   // selected objects as children.  This prevents bad surprises when
1560   // certain SimSet subclasses reject children and start shoving them
1561   // off to places of their own choosing.
1562
1563   if( item->isInspectorData() )
1564   {
1565      if( mDebug )
1566         Con::printf( "Checking %i:%s as drag-parent",
1567            item->getObject()->getId(), item->getObject()->getClassName() );
1568      
1569      SimSet* set = dynamic_cast< SimSet*>( item->getObject() );
1570      if( set )
1571      {
1572         for( U32 i = 0; i < mSelectedItems.size(); ++ i )
1573         {
1574            Item* selectedItem = mSelectedItems[ i ];
1575            
1576            if( mDebug )
1577               Con::printf( "Checking %i:%s as drag-object",
1578                  selectedItem->getObject()->getId(),
1579                  selectedItem->getObject()->getClassName() );
1580            
1581            if(    selectedItem->isInspectorData()
1582                && !set->acceptsAsChild( selectedItem->getObject() ) )
1583               return false;
1584         }
1585      }
1586   }
1587      
1588   if( isMethod( "isValidDragTarget" ) )
1589   {
1590      // We have a callback.  Exclusively leave the decision whether
1591      // the item is a valid drag target to it.
1592      
1593      isValid = isValidDragTarget_callback( item->mId, getItemValue( item->mId ) );
1594   }
1595   else
1596   {
1597      // Make the item a valid drag target if it either already is
1598      // a parent (including VirtualParents) or if dragging to non-parent
1599      // items is explicitly allowed.
1600      
1601      isValid = item->isParent() || mDragToItemAllowed;
1602   }
1603   
1604   return isValid;
1605}
1606
1607//------------------------------------------------------------------------------
1608
1609S32 GuiTreeViewCtrl::getItemCount()
1610{
1611   return(mItemCount);
1612}
1613
1614//-----------------------------------------------------------------------------
1615
1616S32 GuiTreeViewCtrl::getSelectedItem()
1617{
1618   return mSelectedItem;
1619}
1620
1621//------------------------------------------------------------------------------
1622
1623void GuiTreeViewCtrl::moveItemUp( S32 itemId )
1624{
1625   GuiTreeViewCtrl::Item* pItem = getItem( itemId );
1626   if ( !pItem )
1627   {
1628      Con::errorf( ConsoleLogEntry::General, "GuiTreeViewCtrl::moveItemUp: invalid item id!");
1629      return;
1630   }
1631
1632   Item * pParent   = pItem->mParent;
1633   Item * pPrevItem = pItem->mPrevious;
1634   if ( pPrevItem == NULL || pParent == NULL )
1635   {
1636      Con::errorf( ConsoleLogEntry::General, "GuiTreeViewCtrl::moveItemUp: Unable to move item up, bad data!");
1637      return;
1638   }
1639
1640   //  Diddle the linked list!
1641   if ( pPrevItem->mPrevious )
1642      pPrevItem->mPrevious->mNext = pItem;
1643   else if ( pItem->mParent )
1644      pItem->mParent->mChild = pItem;
1645
1646   if ( pItem->mNext )
1647      pItem->mNext->mPrevious = pPrevItem;
1648
1649   pItem->mPrevious = pPrevItem->mPrevious;
1650   pPrevItem->mNext = pItem->mNext;
1651   pItem->mNext = pPrevItem;
1652   pPrevItem->mPrevious = pItem;
1653
1654   // Update SimObjects if Appropriate.
1655   SimObject * pSimObject = NULL;
1656   SimSet    * pParentSet = NULL;
1657
1658   // Fetch Current Add Set
1659   if( pParent->isInspectorData() )
1660      pParentSet = dynamic_cast<SimSet*>( pParent->getObject() );
1661   else
1662   {
1663      // parent is probably script data so we search up the tree for a
1664      // set to put our object in
1665      Item * pTraverse = pItem->mParent;
1666      while ( pTraverse != NULL && !pTraverse->isInspectorData() )
1667         pTraverse = pTraverse->mParent;
1668
1669      // found an ancestor who is an inspectorData?
1670      if (pTraverse != NULL)
1671         pParentSet = pTraverse->isInspectorData() ? dynamic_cast<SimSet*>( pTraverse->getObject() ) : NULL;
1672   }
1673
1674   // Reorder the item and make sure that the children of the item get updated
1675   // correctly prev item may be script... so find a prevItem if there is.
1676   // We only need to reorder if there you move it above an inspector item.
1677   if ( pSimObject != NULL && pParentSet != NULL )
1678   {
1679      Item * pTraverse = pItem->mNext;
1680
1681      while(pTraverse)
1682      {
1683         if (pTraverse->isInspectorData())
1684            break;
1685         pTraverse = pTraverse->mNext;
1686      }
1687
1688      if (pTraverse && pItem->getObject() &&  pTraverse->getObject())
1689         pParentSet->reOrder(pItem->getObject(), pTraverse->getObject());
1690   }
1691
1692   mFlags.set(RebuildVisible);
1693}
1694//-----------------------------------------------------------------------------
1695
1696void GuiTreeViewCtrl::moveItemDown( S32 itemId )
1697{
1698   GuiTreeViewCtrl::Item* item = getItem( itemId );
1699   if ( !item )
1700   {
1701      Con::errorf( ConsoleLogEntry::General, "GuiTreeViewCtrl::moveItemDown: invalid item id!");
1702      return;
1703   }
1704
1705   Item* nextItem = item->mNext;
1706   if ( !nextItem )
1707   {
1708      Con::errorf( ConsoleLogEntry::General, "GuiTreeViewCtrl::moveItemDown: no next sibling?");
1709      return;
1710   }
1711
1712   //  Diddle the linked list!
1713   if ( nextItem->mNext )
1714      nextItem->mNext->mPrevious = item;
1715
1716   if ( item->mPrevious )
1717      item->mPrevious->mNext = nextItem;
1718   else if ( item->mParent )
1719      item->mParent->mChild = nextItem;
1720
1721   item->mNext = nextItem->mNext;
1722   nextItem->mPrevious = item->mPrevious;
1723   item->mPrevious = nextItem;
1724   nextItem->mNext = item;
1725
1726   // And update the simobjects if apppropriate...
1727   SimObject * simobj = NULL;
1728   if (item->isInspectorData())
1729      simobj = item->getObject();
1730
1731   SimSet *parentSet = NULL;
1732
1733   // grab the current parentSet if there is any...
1734   if(item->mParent->isInspectorData())
1735      parentSet = dynamic_cast<SimSet*>(item->mParent->getObject());
1736   else
1737   {
1738      // parent is probably script data so we search up the tree for a
1739      // set to put our object in
1740      Item * temp = item->mParent;
1741      while (temp && !temp->isInspectorData())
1742         temp = temp->mParent;
1743
1744      // found an ancestor who is an inspectorData?
1745      parentSet = (temp && temp->isInspectorData()) ? dynamic_cast<SimSet*>(temp->getObject()) : NULL;
1746   }
1747
1748   // Reorder the item and make sure that the children of the item get updated
1749   // correctly prev item may be script... so find a prevItem if there is.
1750   // We only need to reorder if there you move it above an inspector item.
1751   if (simobj && parentSet)
1752   {
1753      Item * temp = item->mPrevious;
1754
1755      while(temp)
1756      {
1757         if (temp->isInspectorData())
1758            break;
1759         temp = temp->mPrevious;
1760      }
1761
1762      if (temp && item->getObject() && temp->getObject())
1763         parentSet->reOrder(temp->getObject(), item->getObject());
1764   }
1765
1766   mFlags.set(RebuildVisible);
1767}
1768
1769//------------------------------------------------------------------------------
1770
1771bool GuiTreeViewCtrl::onAdd()
1772{
1773   if( !Parent::onAdd() )
1774      return false;
1775      
1776   // If we have dynamic fields, convert the "internalNamesOnly" and "objectNamesOnly"
1777   // legacy fields.
1778      
1779   if( getFieldDictionary() )
1780   {
1781      static StringTableEntry sInternalNamesOnly = StringTable->insert( "internalNamesOnly" );
1782      static StringTableEntry sObjectNamesOnly = StringTable->insert( "objectNamesOnly" );
1783      
1784      const char* internalNamesOnly = getDataField( sInternalNamesOnly, NULL );
1785      if( internalNamesOnly && internalNamesOnly[ 0 ] && dAtob( internalNamesOnly ) )
1786      {
1787         mShowObjectIds = false;
1788         mShowClassNames = false;
1789         mShowObjectNames = false;
1790         mShowInternalNames = true;
1791      }
1792
1793      const char* objectNamesOnly = getDataField( sObjectNamesOnly, NULL );
1794      if( objectNamesOnly && objectNamesOnly[ 0 ] && dAtob( objectNamesOnly ) )
1795      {
1796         mShowObjectIds = false;
1797         mShowClassNames = false;
1798         mShowObjectNames = true;
1799         mShowInternalNames = false;
1800      }
1801   }
1802      
1803   return true;
1804}
1805
1806//------------------------------------------------------------------------------
1807
1808bool GuiTreeViewCtrl::onWake()
1809{
1810   if(!Parent::onWake() || !mProfile->constructBitmapArray())
1811      return false;
1812
1813   // If destroy on sleep, then we have to give things a chance to rebuild.
1814   if(mDestroyOnSleep)
1815   {
1816      onDefineIcons_callback();
1817   }
1818
1819   // Update the row height, if appropriate.
1820   if(mProfile->mAutoSizeHeight)
1821   {
1822      // make sure it's big enough for both bitmap AND font...
1823      mItemHeight = getMax((S32)mFont->getHeight(), (S32)mProfile->mBitmapArrayRects[0].extent.y);
1824   }
1825   
1826   mFlags.set(RebuildVisible);
1827
1828   return true;
1829}
1830
1831//-----------------------------------------------------------------------------
1832
1833void GuiTreeViewCtrl::onSleep()
1834{
1835   Parent::onSleep();
1836
1837   // If appropriate, blast the tree. (We probably rebuild it on wake.)
1838   if( mDestroyOnSleep )
1839      _destroyTree();
1840
1841   if ( mRenameCtrl )
1842   {
1843      mRenameCtrl->deleteObject();
1844      mRenameCtrl = NULL;
1845   }
1846}
1847
1848//-----------------------------------------------------------------------------
1849
1850bool GuiTreeViewCtrl::buildIconTable(const char * icons)
1851{
1852   // Icons should be designated by the bitmap/png file names (minus the file extensions)
1853   // and separated by colons (:). This list should be synchronized with the Icons enum.
1854
1855   // Figure the size of the buffer we need...
1856   const char* temp = dStrchr( icons, '\t' );
1857   U32 textLen = temp ? ( temp - icons ) : dStrlen( icons );
1858
1859   // Allocate temporary space.
1860   FrameAllocatorMarker txtBuff;
1861   char* drawText = (char*)txtBuff.alloc(sizeof(char) * (textLen + 4));
1862   dStrncpy( drawText, icons, textLen );
1863   drawText[textLen] = '\0';
1864
1865   U32 numIcons = 0;
1866   char buf[ 1024 ];
1867   char* pos = drawText;
1868
1869   // Count the number of icons and store them.
1870   while( *pos && numIcons < MaxIcons )
1871   {
1872      char* start = pos;
1873      while( *pos && *pos != ':' )
1874         pos ++;
1875      
1876      const U32 len = pos - start;
1877      if( len )
1878      {
1879         dStrncpy( buf, start, getMin( sizeof( buf ) / sizeof( buf[ 0 ] ) - 1, len ) );
1880         buf[ len ] = '\0';
1881                  
1882         mIconTable[ numIcons ] = GFXTexHandle( buf, &GFXTexturePersistentProfile, avar( "%s() - mIconTable[%d] (line %d)", __FUNCTION__, numIcons, __LINE__ ) );
1883      }
1884      else
1885         mIconTable[ numIcons ] = GFXTexHandle();
1886      
1887      numIcons ++;
1888      if( *pos )
1889         pos ++;
1890   }
1891
1892   return true;
1893}
1894
1895//------------------------------------------------------------------------------
1896
1897void GuiTreeViewCtrl::onPreRender()
1898{
1899   Parent::onPreRender();
1900
1901   S32 nRootItemId = getFirstRootItem();
1902   if( nRootItemId == 0 )
1903      return;
1904
1905   Item *pRootItem = getItem( nRootItemId );
1906   if( pRootItem == NULL )
1907      return;
1908
1909   // Update every render in case new objects are added
1910   if(mFlags.test(RebuildVisible))
1911   {
1912      buildVisibleTree();
1913     mFlags.clear(RebuildVisible);
1914   }
1915}
1916
1917//------------------------------------------------------------------------------
1918
1919bool GuiTreeViewCtrl::_hitTest(const Point2I & pnt, Item* & item, BitSet32 & flags)
1920{
1921   // Initialize some things.
1922   const Point2I pos = globalToLocalCoord(pnt);
1923   flags.clear();
1924   item = 0;
1925
1926   // get the hit cell
1927   Point2I cell((pos.x < 0 ? -1 : pos.x / mCellSize.x),
1928                (pos.y < 0 ? -1 : pos.y / mCellSize.y));
1929
1930   // valid?
1931   if((cell.x < 0 || cell.x >= mSize.x) ||
1932      (cell.y < 0 || cell.y >= mSize.y))
1933      return false;
1934
1935   flags.set(OnRow);
1936
1937   // Grab the cell.
1938   if (cell.y >= mVisibleItems.size())
1939      return false; //Invalid cell, so don't do anything
1940
1941   item = mVisibleItems[cell.y];
1942
1943   S32 min = mTabSize * item->mTabLevel;
1944
1945   // left of icon/text?
1946   if(pos.x < min)
1947   {
1948      flags.set(OnIndent);
1949      return true;
1950   }
1951
1952   // check image
1953   S32 image = BmpChild;
1954
1955   if(item->isInspectorData())
1956      image = item->isExpanded() ? BmpExp : BmpCon;
1957   else
1958      image = item->isExpanded() ? item->getExpandedImage() : item->getNormalImage();
1959
1960   if((image >= 0) && (image < mProfile->mBitmapArrayRects.size()))
1961      min += mProfile->mBitmapArrayRects[image].extent.x;
1962
1963   // Is it on the image?
1964   if(pos.x < min)
1965   {
1966      flags.set(OnImage);
1967      return(true);
1968   }
1969
1970   // Check the icon.
1971   min += getInspectorItemIconsWidth( item );
1972
1973   if ( pos.x < min )
1974   {
1975      flags.set(OnIcon);
1976      return true;
1977   }
1978
1979   // Check the text.
1980
1981   min += mProfile->mTextOffset.x;
1982
1983   FrameAllocatorMarker txtAlloc;
1984   U32 bufLen = item->getDisplayTextLength() + 1;
1985   char *buf = (char*)txtAlloc.alloc(bufLen);
1986   item->getDisplayText(bufLen, buf);
1987
1988   min += mProfile->mFont->getStrWidth(buf);
1989   if(pos.x < min)
1990      flags.set(OnText);
1991
1992   return true;
1993}
1994
1995//-----------------------------------------------------------------------------
1996
1997S32 GuiTreeViewCtrl::getInspectorItemIconsWidth(Item* & item)
1998{
1999   S32 width = 0;
2000
2001   if( item->isInspectorData() )
2002   {
2003      // Based on code in onRenderCell()
2004
2005      S32 icon = Lock1;
2006      S32 icon2 = Hidden;
2007
2008      if (item->getObject() && item->getObject()->isLocked())
2009      {
2010         if (mIconTable[icon])
2011         {
2012            width += mIconTable[icon].getWidth();
2013         }
2014      }
2015
2016      if (item->getObject() && item->getObject()->isHidden())
2017      {
2018         if (mIconTable[icon2])
2019         {
2020            width += mIconTable[icon2].getWidth();
2021         }
2022      }
2023
2024      GFXTexHandle iconHandle;
2025      if ( ( item->mIcon != -1 ) && mIconTable[item->mIcon] )
2026         iconHandle = mIconTable[item->mIcon];
2027   #ifdef TORQUE_TOOLS
2028      else
2029         iconHandle = gEditorIcons.findIcon( item->getObject() );
2030   #endif
2031
2032      if ( iconHandle.isValid() )
2033      {
2034         width += iconHandle.getWidth();
2035      }
2036   }
2037   else
2038   {
2039      S32 icon = item->isExpanded() ? item->mScriptInfo.mExpandedImage : item->mScriptInfo.mNormalImage;
2040      if ( ( icon != -1 ) && mIconTable[icon] )
2041      {
2042         width += mIconTable[icon].getWidth();
2043      }
2044   }
2045
2046   return width;
2047}
2048
2049//-----------------------------------------------------------------------------
2050
2051bool GuiTreeViewCtrl::setAddGroup(SimObject * obj)
2052{
2053   // make sure we're talking about a group.
2054   SimGroup * grp = dynamic_cast<SimGroup*>(obj);
2055
2056   if(grp)
2057   {
2058      onAddGroupSelected_callback( grp );
2059      return true;
2060   }
2061   return false;
2062}
2063
2064//-----------------------------------------------------------------------------
2065
2066void GuiTreeViewCtrl::syncSelection()
2067{
2068   // for each visible item check to see if it is on the mSelected list.
2069   // if it is then make sure that it is on the mSelectedItems list as well.
2070   for (S32 i = 0; i < mVisibleItems.size(); i++) 
2071   {
2072      for (S32 j = 0; j < mSelected.size(); j++) 
2073      {
2074         if (mVisibleItems[i]->mId == mSelected[j]) 
2075         {
2076            // check to see if it is on the visible items list.
2077            bool addToSelectedItems = true;
2078            for (S32 k = 0; k < mSelectedItems.size(); k++) 
2079            {
2080               if (mSelected[j] == mSelectedItems[k]->mId) 
2081               {
2082                  // don't add it
2083                  addToSelectedItems = false;
2084               }
2085            }
2086            if (addToSelectedItems) 
2087            {
2088               mVisibleItems[i]->mState.set(Item::Selected, true);
2089               mSelectedItems.push_front(mVisibleItems[i]);
2090               break;
2091            }
2092         } 
2093         else if (mVisibleItems[i]->isInspectorData()) 
2094         {
2095         if(mCompareToObjectID)
2096         {
2097            if (mVisibleItems[i]->getObject() && mVisibleItems[i]->getObject()->getId() == mSelected[j]) 
2098            {
2099              // check to see if it is on the visible items list.
2100              bool addToSelectedItems = true;
2101              for (S32 k = 0; k < mSelectedItems.size(); k++) 
2102              {
2103                if (mSelectedItems[k]->isInspectorData() && mSelectedItems[k]->getObject() )
2104                {
2105                  if (mSelected[j] == mSelectedItems[k]->getObject()->getId()) 
2106                  {
2107                     // don't add it
2108                     addToSelectedItems = false;
2109                  }
2110                } 
2111                else 
2112                {
2113                  if (mSelected[j] == mSelectedItems[k]->mId) 
2114                  {
2115                     // don't add it
2116                     addToSelectedItems = false;
2117                  }
2118                }
2119              }
2120              if (addToSelectedItems) 
2121              {
2122                mVisibleItems[i]->mState.set(Item::Selected, true);
2123                mSelectedItems.push_front(mVisibleItems[i]);
2124                break;
2125              }
2126            }
2127         }
2128         }
2129
2130      }
2131
2132   }
2133}
2134
2135//-----------------------------------------------------------------------------
2136
2137void GuiTreeViewCtrl::removeSelection( S32 itemOrObjectId )
2138{
2139   if (mDebug)
2140      Con::printf( "removeSelection %i", itemOrObjectId );
2141
2142   Item* item = _findItemByAmbiguousId( itemOrObjectId, false ); 
2143   if (!item) 
2144      return;
2145
2146   // Make sure we have a true item ID even if we started with
2147   // an object ID.
2148   S32 itemId = item->getID();
2149
2150   S32 objectId = -1;
2151   if ( item->isInspectorData() && item->getObject() )   
2152      objectId = item->getObject()->getId();   
2153
2154   // Remove from vector of selected object ids if it exists there
2155   if ( objectId != -1 )
2156   {
2157      for ( S32 i = 0; i < mSelected.size(); i++ ) 
2158      {
2159         if ( objectId == mSelected[i] || itemId == mSelected[i] ) 
2160         {
2161            mSelected.erase( i );
2162            break;
2163         }
2164      }
2165   }
2166   else
2167   {
2168      for ( S32 i = 0; i < mSelected.size(); i++ ) 
2169      {
2170         if ( itemId == mSelected[i] ) 
2171         {
2172            mSelected.erase( i );
2173            break;
2174         }
2175      }
2176   }
2177
2178   item->mState.set(Item::Selected, false);
2179   
2180   // Remove from vector of selected items if it exists there.
2181   for ( S32 i = 0; i < mSelectedItems.size(); i++ ) 
2182   {
2183      if ( mSelectedItems[i] == item ) 
2184      {
2185         mSelectedItems.erase( i );
2186         break;
2187      }
2188   }
2189
2190   // Callback.
2191   onRemoveSelection( item );
2192}
2193
2194//-----------------------------------------------------------------------------
2195
2196void GuiTreeViewCtrl::addSelection( S32 itemOrObjectId, bool update, bool isLastSelection )
2197{
2198   if (mDebug)
2199      Con::printf( "addSelection %i", itemOrObjectId );
2200
2201   Item* item = _findItemByAmbiguousId( itemOrObjectId );
2202
2203   // Add Item?
2204   if ( !item || isSelected( item ) || !canAddSelection( item ) )
2205   {
2206      // Nope.
2207      return;
2208   }
2209
2210   const S32 itemId = item->getID();
2211   
2212   // Ok, we have an item to select which isn't already selected....
2213
2214   // Do we want to allow more than one selected item?
2215   if( !mMultipleSelections )
2216      clearSelection();
2217
2218   // Add this object id to the vector of selected objectIds
2219   // if it is not already.
2220   bool foundMatch = false;
2221   for ( S32 i = 0; i < mSelected.size(); i++)
2222   {
2223      if ( mSelected[i] == itemId )
2224         foundMatch = true;
2225   }
2226   
2227   if ( !foundMatch )
2228      mSelected.push_front(itemId);
2229
2230   item->mState.set(Item::Selected, true);
2231
2232   if( mSelected.size() == 1 )
2233   {
2234      onItemSelected( item );
2235   }
2236
2237   // Callback Start
2238   // Set and add the selection to the selected items group
2239   item->mState.set(Item::Selected, true);
2240   mSelectedItems.push_front(item);
2241
2242   if ( item->isInspectorData() && 
2243        item->getObject() )
2244   { 
2245      SimObject *obj = item->getObject();
2246      
2247      onAddSelection_callback( obj->getId(), isLastSelection );
2248   }
2249   else
2250   {
2251      onAddSelection_callback( item->mId, isLastSelection );
2252   }
2253   // Callback end
2254
2255   mFlags.set( RebuildVisible );
2256   if( update )
2257   {
2258      // Also make it so we can see it if we didn't already.
2259      scrollVisible( item );
2260   }
2261}
2262
2263
2264//-----------------------------------------------------------------------------
2265
2266void GuiTreeViewCtrl::onItemSelected( Item *item )
2267{
2268   mSelectedItem = item->getID();
2269
2270   if (item->isInspectorData())
2271   {
2272      SimObject* object = item->getObject();
2273      if( object )
2274         onSelect_callback( object->getId() );
2275      if( !item->isParent() && object )
2276         onInspect_callback( object->getId() );
2277   }
2278   else
2279   {
2280      onSelect_callback( item->mId );
2281      if( !item->isParent() )
2282         onInspect_callback( item->mId );
2283   }
2284}
2285
2286//-----------------------------------------------------------------------------
2287
2288void GuiTreeViewCtrl::onRemoveSelection( Item *item )
2289{
2290   S32 id = item->mId;
2291
2292   if( item->isInspectorData() &&
2293       item->getObject() )
2294   {      
2295      SimObject* obj = item->getObject();
2296      id = obj->getId();
2297      //obj->setSelected( false );
2298   }
2299
2300   if( isMethod( "onRemoveSelection" ) )
2301      onRemoveSelection_callback( id );
2302   else
2303      onUnselect_callback( id );
2304}
2305
2306//-----------------------------------------------------------------------------
2307
2308bool GuiTreeViewCtrl::setItemSelected(S32 itemId, bool select)
2309{
2310   Item * item = getItem(itemId);
2311   if( isSelected( item ) == select )
2312      return true;
2313
2314   if (select)
2315   {
2316      if (mDebug) Con::printf("setItemSelected called true");
2317
2318      mSelected.push_front(itemId);
2319   }
2320   else
2321   {
2322      if (mDebug) Con::printf("setItemSelected called false");
2323
2324      // remove it from the mSelected list
2325      for (S32 j = 0; j <mSelected.size(); j++)
2326      {
2327         if (item)
2328         {
2329            if (item->isInspectorData())
2330            {
2331               if (item->getObject())
2332               {
2333                  if(item->getObject()->getId() == mSelected[j])
2334                  {
2335                     mSelected.erase(j);
2336                     break;
2337                  }
2338               }
2339               else
2340               {
2341                  // Zombie, kill it!
2342                  mSelected.erase(j);
2343                  j--;
2344                  break;
2345               }
2346            }
2347         }
2348
2349         if (mSelected[j] == itemId)
2350         {
2351            mSelected.erase(j);
2352            break;
2353         }
2354      }
2355   }
2356
2357   if(!item)
2358   {
2359      // maybe what we were passed wasn't an item id but an object id.
2360      for (S32 i = 0; i <mItems.size(); i++)
2361      {
2362         if (mItems[i] != 0)
2363         {
2364            if (mItems[i]->isInspectorData())
2365            {
2366               if (mItems[i]->getObject())
2367               {
2368                  if(mItems[i]->getObject()->getId() == itemId)
2369                  {
2370                     item = mItems[i];
2371                     break;
2372                  }
2373               }
2374               else
2375               {
2376                  // It's a zombie, blast it.
2377                  mItems.erase(i);
2378                  i--;
2379               }
2380            }
2381         }
2382      }
2383
2384      if (!item)
2385      {
2386         //Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::setItemSelected: invalid item id! Perhaps it isn't visible yet.");
2387         return(false);
2388      }
2389   }
2390
2391   mFlags.set( RebuildVisible );
2392
2393   if(select)
2394   {
2395      addSelection( item->mId );
2396      onItemSelected( item );
2397   }
2398   else
2399   {
2400      // deselect the item, if it's present.
2401      item->mState.set(Item::Selected, false);
2402
2403      if (item->isInspectorData() && item->getObject())
2404         onUnselect_callback( item->getObject()->getId() );
2405      else
2406         onUnselect_callback( item->mId );
2407
2408      // remove it from the selected items list
2409      for (S32 i = 0; i < mSelectedItems.size(); i++)
2410      {
2411         if (mSelectedItems[i] == item)
2412         {
2413            mSelectedItems.erase(i);
2414            break;
2415         }
2416      }
2417   }
2418
2419   setUpdate();
2420   return(true);
2421}
2422
2423//-----------------------------------------------------------------------------
2424
2425// Given an item's index in the selection list, return its itemId
2426S32 GuiTreeViewCtrl::getSelectedItem(S32 index)
2427{
2428   if(index >= 0 && index < getSelectedItemsCount())
2429   {
2430      return mSelectedItems[index]->mId;
2431   }
2432
2433   return -1;
2434}
2435
2436//-----------------------------------------------------------------------------
2437
2438bool GuiTreeViewCtrl::setItemExpanded(S32 itemId, bool expand)
2439{
2440   Item * item = getItem(itemId);
2441   if(!item)
2442   {
2443      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::setItemExpanded: invalid item id!");
2444      return(false);
2445   }
2446
2447   if(item->isExpanded() == expand)
2448      return(true);
2449
2450   item->setExpanded(expand);
2451
2452   // expand parents
2453   if(expand)
2454   {
2455      while (item)
2456      {
2457         if (!item->isInspectorData() && item->mState.test(Item::VirtualParent))
2458            onVirtualParentExpand(item);
2459
2460         scrollVisible(item);
2461         item = item->mParent;
2462      }
2463   }
2464   else
2465   {
2466      if(item->mState.test(Item::VirtualParent))
2467         onVirtualParentCollapse(item);
2468
2469      item->setExpanded(false);
2470   }
2471
2472   //if (!item->isInspectorData() && item->mState.test(Item::VirtualParent))
2473   //   onVirtualParentExpand(item);
2474
2475   mFlags.set(RebuildVisible);
2476
2477   return(true);
2478}
2479
2480
2481//-----------------------------------------------------------------------------
2482
2483bool GuiTreeViewCtrl::setItemValue(S32 itemId, StringTableEntry Value)
2484{
2485   Item * item = getItem(itemId);
2486   if(!item)
2487   {
2488      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::setItemValue: invalid item id!");
2489      return(false);
2490   }
2491
2492   item->setValue( ( Value ) ? Value : "" );
2493
2494   return(true);
2495}
2496
2497//-----------------------------------------------------------------------------
2498
2499const char * GuiTreeViewCtrl::getItemText(S32 itemId)
2500{
2501   Item * item = getItem(itemId);
2502   if(!item)
2503   {
2504      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getItemText: invalid item id!");
2505      return("");
2506   }
2507
2508   return(item->getText() ? item->getText() : "");
2509}
2510
2511//-----------------------------------------------------------------------------
2512
2513const char * GuiTreeViewCtrl::getItemValue(S32 itemId)
2514{
2515   Item * item = getItem(itemId);
2516   if(!item)
2517   {
2518      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getItemValue: invalid item id!");
2519      return("");
2520   }
2521
2522   if(item->mState.test(Item::InspectorData))
2523   {
2524      // If it's InspectorData, we let people use this call to get an object reference.
2525      return item->mInspectorInfo.mObject->getIdString();
2526   }
2527   else
2528   {
2529      // Just return the script value...
2530      return item->getValue();
2531   }
2532}
2533
2534//-----------------------------------------------------------------------------
2535
2536S32 GuiTreeViewCtrl::getItemAtPosition(Point2I position)
2537{
2538   BitSet32 hitFlags = 0;
2539   Item* item;
2540
2541   if (_hitTest(position, item, hitFlags))
2542      return item->mId;
2543   else
2544      return -1;
2545}
2546
2547//-----------------------------------------------------------------------------
2548
2549bool GuiTreeViewCtrl::editItem( S32 itemId, const char* newText, const char* newValue )
2550{
2551   Item* item = getItem( itemId );
2552   if ( !item )
2553   {
2554      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::editItem: invalid item id: %d!", itemId);
2555      return false;
2556   }
2557
2558   if ( item->mState.test(Item::InspectorData) )
2559   {
2560      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::editItem: item %d is inspector data and may not be modified!", itemId);
2561      return false;
2562   }
2563
2564   item->setText( StringTable->insert( newText, true ) );
2565   item->setValue( StringTable->insert( newValue, true ) );
2566
2567   // Update the widths and such:
2568   mFlags.set(RebuildVisible);
2569   return true;
2570}
2571
2572//-----------------------------------------------------------------------------
2573
2574bool GuiTreeViewCtrl::markItem( S32 itemId, bool mark )
2575{
2576   Item *item = getItem( itemId );
2577   if ( !item )
2578   {
2579      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::markItem: invalid item id: %d!", itemId);
2580      return false;
2581   }
2582
2583   item->mState.set(Item::Marked, mark);
2584   return true;
2585}
2586
2587//-----------------------------------------------------------------------------
2588
2589bool GuiTreeViewCtrl::isItemSelected( S32 itemId )
2590{
2591   for( U32 i = 0, num = mSelectedItems.size(); i < num; ++ i )
2592      if( mSelectedItems[ i ]->mId == itemId )
2593         return true;
2594         
2595   return false;
2596}
2597
2598//-----------------------------------------------------------------------------
2599
2600void GuiTreeViewCtrl::deleteSelection()
2601{
2602   onDeleteSelection_callback();
2603
2604   if (mSelectedItems.empty())
2605   {
2606      for (S32 i = 0; i < mSelected.size(); i++)
2607      {
2608         S32 objectId = mSelected[i];
2609
2610         // find the object
2611         SimObject* obj = Sim::findObject(objectId);
2612         if ( !obj )
2613            continue;
2614
2615         bool skipDelete = onDeleteObject_callback( obj );
2616         if ( !skipDelete )
2617            obj->deleteObject();
2618      }
2619   }
2620   else
2621   {
2622     Vector<Item*> delSelection;
2623     delSelection = mSelectedItems;
2624     mSelectedItems.clear();
2625      while (!delSelection.empty())
2626      {
2627         Item * item = delSelection.front();
2628         setItemSelected(item->mId,false);
2629         if ( item->mParent )
2630            _deleteItem( item );
2631         
2632       delSelection.pop_front();      
2633      }
2634   }
2635
2636   mSelected.clear();
2637   mSelectedItems.clear();
2638   mSelectedItem = 0;
2639
2640   onObjectDeleteCompleted_callback();
2641}
2642
2643//------------------------------------------------------------------------------
2644
2645// keyboard movement of items is restricted to just one item at a time
2646// if more than one item is selected then movement operations are not performed
2647bool GuiTreeViewCtrl::onKeyDown( const GuiEvent& event )
2648{
2649   if ( !mVisible || !mActive || !mAwake )
2650      return false;
2651
2652   // All the keyboard functionality requires a selected item, so if none exists...
2653
2654   // Deal with enter and delete
2655   if ( event.modifier == 0 )
2656   {
2657      if ( event.keyCode == KEY_RETURN )
2658      {
2659         execAltConsoleCallback();
2660         return true;
2661      }
2662
2663      if ( event.keyCode == KEY_DELETE && mDeleteObjectAllowed )
2664      {
2665         // Don't delete the root!
2666         if (mSelectedItems.empty())
2667            return true;
2668
2669         //this may be fighting with the world editor delete
2670         deleteSelection();
2671         return true;
2672      }
2673 
2674     //call a generic bit of script that will let the subclass know that a key was pressed
2675     onKeyDown_callback( event.modifier, event.keyCode );
2676   }
2677
2678   // only do operations if only one item is selected
2679   if ( mSelectedItems.empty() || (mSelectedItems.size() > 1))
2680      return false;
2681
2682   Item* item = mSelectedItems.first();
2683
2684   if ( !item )
2685      return false;
2686
2687   // The Alt key lets you move items around!
2688   if ( mFlags.test(IsEditable) && event.modifier & SI_ALT )
2689   {
2690      switch ( event.keyCode )
2691      {
2692      case KEY_UP:
2693         // Move us up.
2694         if ( item->mPrevious )
2695         {
2696            moveItemUp( item->mId );
2697            scrollVisible(item);
2698         }
2699         return true;
2700
2701      case KEY_DOWN:
2702         // Move the item under us up.
2703         if ( item->mNext )
2704         {
2705            moveItemUp( item->mNext->mId );
2706            scrollVisible(item);
2707         }
2708         return true;
2709
2710      case KEY_LEFT:
2711         if ( item->mParent )
2712         {
2713            if ( item->mParent->mParent )
2714            {
2715               // Ok, we have both an immediate parent, and a grandparent.
2716
2717               // The goal of left-arrow alt is to become the child of our
2718               // grandparent, ie, to become a sibling of our parent.
2719
2720               // First, unlink item from its siblings.
2721               if ( item->mPrevious )
2722                  item->mPrevious->mNext = item->mNext;
2723               else
2724                  item->mParent->mChild = item->mNext;
2725
2726               if ( item->mNext )
2727                  item->mNext->mPrevious = item->mPrevious;
2728
2729               // Now, relink as the next sibling of our parent.
2730               item->mPrevious = item->mParent;
2731               item->mNext = item->mParent->mNext;
2732
2733               // If there was already a next sibling, deal with that case.
2734               if ( item->mNext )
2735                  item->mNext->mPrevious = item;
2736               item->mParent->mNext = item;
2737
2738               // Snag the current parent set if any...
2739               SimSet *parentSet = NULL;
2740
2741               if(item->mParent->isInspectorData())
2742                  parentSet = dynamic_cast<SimSet*>(item->mParent->getObject());
2743               else
2744               {
2745                  // parent is probably script data so we search up the tree for a
2746                  // set to put our object in
2747                  Item * temp = item->mParent;
2748                  while (!temp->isInspectorData())
2749                     temp = temp->mParent;
2750                  // found a ancestor who is an inspectorData
2751                  if (temp->isInspectorData())
2752                     parentSet = dynamic_cast<SimSet*>(temp->getObject());
2753                  else parentSet = NULL;
2754               }
2755
2756               // Get our active SimObject if any
2757               SimObject *simObj = NULL;
2758               if(item->isInspectorData())
2759                  simObj = item->getObject();
2760
2761               // Remove from the old parentset...
2762               if(simObj && parentSet) {
2763                  if (parentSet->size()>0)
2764                  {
2765                     SimObject *lastObject = parentSet->last();
2766                     parentSet->removeObject(simObj);
2767                     parentSet->reOrder(lastObject);
2768                  } else
2769                     parentSet->removeObject(simObj);
2770               }
2771
2772               // And finally, update our item
2773               item->mParent = item->mParent->mParent;
2774
2775               // Snag the newparent set if any...
2776               SimSet *newParentSet = NULL;
2777
2778               if(item->mParent->isInspectorData())
2779                  newParentSet = dynamic_cast<SimSet*>(item->mParent->getObject());
2780               else
2781               {
2782                  // parent is probably script data so we search up the tree for a
2783                  // set to put our object in
2784                  Item * temp = item->mParent;
2785                  while (!temp->isInspectorData())
2786                     temp = temp->mParent;
2787                  // found a ancestor who is an inspectorData
2788                  if (temp->isInspectorData())
2789                     newParentSet = dynamic_cast<SimSet*>(temp->getObject());
2790                  else newParentSet = NULL;
2791               }
2792               if(simObj && newParentSet)
2793               {
2794
2795                  newParentSet->addObject(simObj);
2796                  Item * temp = item->mNext;
2797                  // item->mNext may be script, so find an inspector item to reorder with if any
2798
2799                  if (temp) {
2800                     do {
2801                        if (temp->isInspectorData())
2802                           break;
2803                        temp = temp->mNext;
2804                     } while (temp);
2805                     if (temp && item->getObject() && temp->getObject()) //do we still have a item->mNext? If not then don't bother reordering
2806                        newParentSet->reOrder(item->getObject(), temp->getObject());
2807                  }
2808
2809               } else if (!simObj&&newParentSet) {
2810                  // our current item is script data. but it may have children who
2811                  // is inspector data who need an updated set
2812                  if (item->mChild)
2813                     inspectorSearch(item->mChild, item, parentSet, newParentSet);
2814
2815               }
2816
2817               // And update everything hurrah.
2818               buildVisibleTree();
2819               scrollVisible(item);
2820            }
2821         }
2822         return true;
2823
2824      case KEY_RIGHT:
2825         if ( item->mPrevious )
2826         {
2827            // Make the item the last child of its previous sibling.
2828
2829            // First, unlink from the current position in the list
2830            item->mPrevious->mNext = item->mNext;
2831
2832            if ( item->mNext )
2833               item->mNext->mPrevious = item->mPrevious;
2834
2835            // Get the object we're poking with.
2836            SimObject *simObj = NULL;
2837            SimSet *parentSet = NULL;
2838            if(item->isInspectorData())
2839               simObj = item->getObject();
2840            if(item->mParent->isInspectorData())
2841               parentSet = dynamic_cast<SimSet*>(item->mParent->getObject());
2842            else {
2843               // parent is probably script data so we search up the tree for a
2844               // set to put our object in
2845               Item * temp = item->mParent;
2846               while (!temp->isInspectorData())
2847                  temp = temp->mParent;
2848               // found an ancestor who is an inspectorData
2849               if (temp->isInspectorData())
2850                  parentSet = dynamic_cast<SimSet*>(temp->getObject());
2851            }
2852
2853            // If appropriate, remove from the current SimSet.
2854            if(parentSet && simObj) {
2855               if (parentSet->size()>0)
2856               {
2857                  SimObject *lastObject = parentSet->last();
2858                  parentSet->removeObject(simObj);
2859                  parentSet->reOrder(lastObject);
2860               } else
2861                  parentSet->removeObject(simObj);
2862            }
2863
2864
2865            // Now, make our previous sibling our parent...
2866            item->mParent = item->mPrevious;
2867            item->mNext = NULL;
2868
2869            // And sink us down to the end of its siblings, if appropriate.
2870            if ( item->mParent->mChild )
2871            {
2872               Item* temp = item->mParent->mChild;
2873               while ( temp->mNext )
2874                  temp = temp->mNext;
2875
2876               temp->mNext = item;
2877               item->mPrevious = temp;
2878            }
2879            else
2880            {
2881               // only child...<sniff>
2882               item->mParent->mChild = item;
2883               item->mPrevious = NULL;
2884            }
2885
2886            // Make sure the new parent is expanded:
2887            if ( !item->mParent->mState.test( Item::Expanded ) )
2888               setItemExpanded( item->mParent->mId, true );
2889
2890            // Snag the new parent simset if any.
2891            SimSet *newParentSet = NULL;
2892
2893            // new parent might be script. so figure out what set we need to add it to.
2894            if(item->mParent->isInspectorData())
2895               newParentSet = dynamic_cast<SimSet*>(item->mParent->getObject());
2896            else
2897            {
2898               // parent is probably script data so we search up the tree for a
2899               // set to put our object in
2900               if (mDebug) Con::printf("oh nos my parent is script!");
2901               Item * temp = item->mParent;
2902               while (!temp->isInspectorData())
2903                  temp = temp->mParent;
2904               // found a ancestor who is an inspectorData
2905               if (temp->isInspectorData())
2906                  newParentSet = dynamic_cast<SimSet*>(temp->getObject());
2907               else newParentSet = NULL;
2908            }
2909            // Add the item's SimObject to the new parent simset, at the end.
2910            if(newParentSet && simObj)
2911               newParentSet->addObject(simObj);
2912            else if (!simObj&&newParentSet&&parentSet) {
2913               // our current item is script data. but it may have children who
2914               // is inspector data who need an updated set
2915
2916               if (item->mChild) {
2917                  inspectorSearch(item->mChild, item, parentSet, newParentSet);
2918               }
2919
2920            }
2921            scrollVisible(item);
2922         }
2923         return true;
2924      
2925      default:
2926         break;
2927      }
2928   }
2929
2930   // Explorer-esque navigation...
2931   switch( event.keyCode )
2932   {
2933   case KEY_UP:
2934      // Select previous visible item:
2935      if ( item->mPrevious )
2936      {
2937         item = item->mPrevious;
2938         while ( item->isParent() && item->isExpanded() )
2939         {
2940            item = item->mChild;
2941            while ( item->mNext )
2942               item = item->mNext;
2943         }
2944         clearSelection();
2945         addSelection( item->mId );
2946         return true;
2947      }
2948
2949      // or select parent:
2950      if ( item->mParent )
2951      {
2952         clearSelection();
2953         addSelection( item->mParent->mId );
2954         return true;
2955      }
2956
2957      return false;
2958      break;
2959
2960   case KEY_DOWN:
2961      // Selected child if it is visible:
2962      if ( item->isParent() && item->isExpanded() )
2963      {
2964         clearSelection();
2965         addSelection( item->mChild->mId );
2966         return true;
2967      }
2968      // or select next sibling (recursively):
2969      do
2970      {
2971         if ( item->mNext )
2972         {
2973            clearSelection();
2974            addSelection( item->mNext->mId );
2975            return true;
2976         }
2977
2978         item = item->mParent;
2979      } while ( item );
2980
2981      return false;
2982      break;
2983
2984   case KEY_LEFT:
2985      // Contract current menu:
2986      if ( item->isExpanded() )
2987      {
2988         setItemExpanded( item->mId, false );
2989         scrollVisible(item);
2990         return true;
2991      }
2992      // or select parent:
2993      if ( item->mParent )
2994      {
2995         clearSelection();
2996         addSelection( item->mParent->mId );
2997         return true;
2998      }
2999
3000      return false;
3001      break;
3002
3003   case KEY_RIGHT:
3004      // Expand selected item:
3005      if ( item->isParent() )
3006      {
3007         if ( !item->isExpanded() )
3008         {
3009            setItemExpanded( item->mId, true );
3010            scrollVisible(item);
3011            return true;
3012         }
3013
3014         // or select child:
3015         clearSelection();
3016         addSelection( item->mChild->mId );
3017         return true;
3018      }
3019
3020      return false;
3021      break;
3022   
3023   default:
3024      break;
3025   }
3026
3027   // Not processed, so pass the event on:
3028   return Parent::onKeyDown( event );
3029}
3030
3031//------------------------------------------------------------------------------
3032
3033// on mouse up look at the current item and check to see if it is valid
3034// to move the selected item(s) to it.
3035void GuiTreeViewCtrl::onMouseUp(const GuiEvent &event)
3036{
3037   if( !mActive || !mAwake || !mVisible )
3038      return;
3039   
3040   BitSet32 hitFlags = 0;
3041   if( isMethod("onMouseUp") )
3042   {
3043      Item* item;
3044      
3045      S32 hitItemId = -1;
3046      if( _hitTest( event.mousePoint, item, hitFlags ) )
3047         hitItemId = item->mId;
3048         
3049      onMouseUp_callback( hitItemId, event.mouseClickCount );
3050   }
3051
3052   mouseUnlock();
3053
3054   if ( mSelectedItems.empty())
3055   {
3056      mDragMidPoint = NomDragMidPoint;
3057      return;
3058   }
3059
3060   hitFlags = 0;
3061   Item *hitItem;
3062   bool hitCheck = _hitTest( event.mousePoint, hitItem, hitFlags );
3063   mRenamingItem = NULL;
3064
3065   if( hitCheck )
3066   {
3067      if ( event.mouseClickCount == 1 && !mMouseDragged && mPossibleRenameItem != NULL )
3068      {
3069         if (hitItem == mPossibleRenameItem )
3070            showItemRenameCtrl(hitItem);
3071      }
3072      else // If mouseUp occurs on the same item as mouse down
3073      {
3074         bool wasSelected = isSelected(hitItem);
3075         bool multiSelect = getSelectedItemsCount() > 1;
3076         if( wasSelected && multiSelect && hitItem == mTempItem )
3077         {
3078            clearSelection();
3079            addSelection( hitItem->mId );
3080         }
3081      }
3082   }
3083
3084   mPossibleRenameItem = NULL;
3085   
3086   if (!mMouseDragged) 
3087      return;
3088
3089   Item* newItem = NULL;
3090   Item* newItem2 = NULL;
3091
3092   if (mFlags.test(IsEditable))
3093   {
3094      Parent::onMouseMove( event );
3095         
3096      hitFlags = 0;
3097      if( !_hitTest( event.mousePoint, newItem2, hitFlags ) )
3098      {
3099         if( !mShowRoot )
3100            newItem2 = mRoot;
3101         else
3102         {
3103            if( mDebug )
3104               Con::printf( "Nothing hit" );
3105               
3106            mDragMidPoint = NomDragMidPoint;
3107            return;
3108         }
3109      }
3110
3111      newItem2->mState.clear(Item::MouseOverBmp | Item::MouseOverText );
3112      
3113      // If the hit item is the visible root, make sure
3114      // we don't allow dragging above.
3115      
3116      if( newItem2 == mRoot && mDragMidPoint == AbovemDragMidPoint )
3117      {
3118         if( mDebug )
3119            Con::printf( "Rejecting to make child sibling of root" );
3120            
3121         mDragMidPoint = NomDragMidPoint;
3122         return;
3123      }
3124      
3125      // if the newItem isn't in the mSelectedItemList then continue.
3126
3127      Vector<Item *>::iterator k;
3128      for(k = mSelectedItems.begin(); k != mSelectedItems.end(); k++) 
3129      {
3130         newItem = newItem2;
3131         
3132         if (*(k) == newItem) 
3133         {
3134            mDragMidPoint = NomDragMidPoint;
3135            return;
3136         }
3137
3138         Item * temp = *(k);
3139         Item * grandpaTemp = newItem->mParent;
3140         
3141         // grandpa check, kick out if an item would be its own ancestor
3142         while (grandpaTemp)
3143         {
3144            if (temp == grandpaTemp)
3145            {
3146               if (mDebug)
3147               {
3148                  Con::printf("grandpa check");
3149
3150                  if (temp->isInspectorData())
3151                     Con::printf("temp's name: %s",temp->getObject()->getName());
3152
3153                  if (grandpaTemp->isInspectorData())
3154                     Con::printf("grandpa's name: %s",grandpaTemp->getObject()->getName());
3155               }
3156
3157               mDragMidPoint = NomDragMidPoint;
3158               return;
3159            }
3160
3161            grandpaTemp = grandpaTemp->mParent;
3162         }
3163      }
3164      
3165      // Notify script for undo.
3166
3167      onBeginReparenting_callback();
3168      
3169      // Reparent the items.
3170
3171      reparentItems(mSelectedItems, newItem2);
3172      
3173      onEndReparenting_callback();
3174
3175      // And update everything.
3176      scrollVisible(newItem);
3177
3178      onDragDropped_callback();
3179
3180      buildVisibleTree(false);
3181   }
3182
3183   mDragMidPoint = NomDragMidPoint;
3184}
3185
3186//------------------------------------------------------------------------------
3187
3188void GuiTreeViewCtrl::onMouseDragged(const GuiEvent &event)
3189{
3190   if( mDragStartInSelection )
3191      onMouseDragged_callback();
3192      
3193   if(!mSupportMouseDragging)
3194      return;
3195      
3196   if( !mActive || !mAwake || !mVisible )
3197      return;
3198
3199   if (mSelectedItems.size() == 0)
3200      return;
3201      
3202   //Check through to make sure all attempted dragged items even allow it
3203   for (U32 i = 0; i < mSelectedItems.size(); i++)
3204      if (!mSelectedItems[i]->isDragAllowed())
3205         return;
3206      
3207   // Give us a little delta before we actually start a mouse drag so that
3208   // if the user moves the mouse a little while clicking, he/she does not
3209   // accidentally trigger a drag.
3210      
3211   if( mFabs( ( mMouseDownPoint - event.mousePoint ).len() ) <= 4.f )
3212      return;
3213      
3214   Point2I pt = globalToLocalCoord(event.mousePoint);
3215   Parent::onMouseMove(event);
3216   mouseLock();
3217   mMouseDragged = true;
3218   
3219   // If the drag is outside of our visible area,
3220   // start scrolling.
3221   
3222   GuiScrollCtrl* scrollCtrl = dynamic_cast< GuiScrollCtrl* >( getParent() );
3223   if( scrollCtrl && !scrollCtrl->isPointVisible( pt ) )
3224   {
3225      S32 widthDelta = 0;
3226      S32 heightDelta = 0;
3227      
3228      if( pt.x < scrollCtrl->getChildRelPos().x )
3229         widthDelta = pt.x - scrollCtrl->getChildRelPos().x;
3230      else if( pt.x > scrollCtrl->getChildRelPos().x + scrollCtrl->getContentExtent().x )
3231         widthDelta = pt.x - scrollCtrl->getChildRelPos().x - scrollCtrl->getContentExtent().x;
3232
3233      if( pt.y < scrollCtrl->getChildRelPos().y )
3234         heightDelta = pt.y - scrollCtrl->getChildRelPos().y;
3235      else if( pt.y > scrollCtrl->getChildRelPos().y + scrollCtrl->getContentExtent().y )
3236         heightDelta = pt.y - scrollCtrl->getChildRelPos().y - scrollCtrl->getContentExtent().y;
3237         
3238      const F32 SCROLL_RATIO = 0.5f;
3239      scrollCtrl->scrollDelta( S32( F32( widthDelta ) * SCROLL_RATIO ), S32( F32( heightDelta ) * SCROLL_RATIO ) );
3240   }
3241   
3242   // whats our mDragMidPoint?
3243   mCurrentDragCell = mMouseOverCell.y;
3244   S32 midpCell = mCurrentDragCell * mItemHeight + (mItemHeight/2);
3245   S32 currentY = pt.y;
3246   S32 yDiff = currentY-midpCell;
3247   S32 variance = (mItemHeight/5);
3248   if( mPreviousDragCell >= 0 && mPreviousDragCell < mVisibleItems.size() )
3249      mVisibleItems[mPreviousDragCell]->mState.clear( Item::MouseOverBmp | Item::MouseOverText | Item::MouseOverIcon );
3250
3251   bool hoverItem = false;
3252
3253   if (mAbs(yDiff) <= variance)
3254   {
3255      mDragMidPoint = NomDragMidPoint;
3256      // highlight the current item
3257      // hittest to detect whether we are on an item
3258      // ganked from onMouseMouse
3259
3260      // used for tracking what our last cell was so we can clear it.
3261      mPreviousDragCell = mCurrentDragCell;
3262      if (mCurrentDragCell >= 0)
3263      {
3264
3265         Item* item = NULL;
3266         BitSet32 hitFlags = 0;
3267         if ( !_hitTest( event.mousePoint, item, hitFlags ) )
3268            return;
3269         
3270         // If the item is a valid drag target, activate the item
3271         // highlighting.
3272
3273         if( isValidDragTarget( item ) )
3274         {
3275            hoverItem = true;
3276
3277            if ( hitFlags.test( OnImage ) )
3278               item->mState.set( Item::MouseOverBmp );
3279
3280            if ( hitFlags.test( OnText ) )
3281               item->mState.set( Item::MouseOverText );
3282
3283            if ( hitFlags.test( OnIcon ) )
3284               item->mState.set( Item::MouseOverIcon );
3285
3286            // Always redraw the entire mouse over item, since we are distinguishing
3287            // between the bitmap and the text:
3288            setUpdateRegion( Point2I( mMouseOverCell.x * mCellSize.x, mMouseOverCell.y * mCellSize.y ), mCellSize );
3289         }
3290      }
3291   }
3292
3293   if ( !hoverItem )
3294   {
3295      //above or below an item?
3296      if (yDiff < 0)
3297         mDragMidPoint = AbovemDragMidPoint;
3298      else
3299         mDragMidPoint = BelowmDragMidPoint;
3300   }
3301}
3302
3303//-----------------------------------------------------------------------------
3304
3305void GuiTreeViewCtrl::onMiddleMouseDown(const GuiEvent & event)
3306{
3307   //for debugging items
3308   if (mDebug) {
3309      Item* item;
3310      BitSet32 hitFlags = 0;
3311      _hitTest( event.mousePoint, item, hitFlags );
3312      Con::printf("debugging %d", item->mId);
3313      Point2I pt = globalToLocalCoord(event.mousePoint);
3314      if (item->isInspectorData() && item->getObject()) {
3315         Con::printf("object data:");
3316         Con::printf("name:%s",item->getObject()->getName());
3317         Con::printf("className:%s",item->getObject()->getClassName());
3318      }
3319      Con::printf("contents of mSelectedItems:");
3320      for(S32 i = 0; i < mSelectedItems.size(); i++) {
3321         if (mSelectedItems[i]->isInspectorData()) {
3322            Con::printf("%d",mSelectedItems[i]->getObject()->getId());
3323         } else
3324            Con::printf("wtf %d", mSelectedItems[i]);
3325      }
3326      Con::printf("contents of mSelected");
3327      for (S32 j = 0; j < mSelected.size(); j++) {
3328         Con::printf("%d", mSelected[j]);
3329      }
3330      mCurrentDragCell = mMouseOverCell.y;
3331      S32 midpCell = (mCurrentDragCell) * mItemHeight + (mItemHeight/2);
3332      S32 currentY = pt.y;
3333      S32 yDiff = currentY-midpCell;
3334      Con::printf("cell info: (%d,%d) mCurrentDragCell=%d est=(%d,%d,%d) ydiff=%d",pt.x,pt.y,mCurrentDragCell,mCurrentDragCell*mItemHeight, midpCell, (mCurrentDragCell+1)*mItemHeight,yDiff);
3335   }
3336}
3337
3338//-----------------------------------------------------------------------------
3339
3340void GuiTreeViewCtrl::onMouseDown(const GuiEvent & event)
3341{
3342   if( !mActive || !mAwake || !mVisible )
3343   {
3344      Parent::onMouseDown(event);
3345      return;
3346   }
3347   if ( mProfile->mCanKeyFocus )
3348      setFirstResponder();
3349
3350   Item * item = 0;
3351   BitSet32 hitFlags;
3352   mDragMidPoint = NomDragMidPoint;
3353
3354   mMouseDragged = false;
3355   mMouseDownPoint = event.mousePoint;
3356
3357   //
3358   if(!_hitTest(event.mousePoint, item, hitFlags))
3359      return;
3360
3361   mPossibleRenameItem = NULL;
3362   mRenamingItem = NULL;
3363   mTempItem = NULL;
3364      
3365   //
3366   if( event.modifier & SI_MULTISELECT )
3367   {
3368      bool selectFlag = item->mState.test(Item::Selected);
3369      if (selectFlag == true)
3370      {
3371         // already selected, so unselect it and remove it
3372         removeSelection(item->mId);
3373      }
3374      else
3375      {
3376         addSelection(item->mId);
3377      }
3378   }
3379   else if( event.modifier & SI_RANGESELECT && mMultipleSelections )
3380   {
3381      // is something already selected?
3382      S32 firstSelectedIndex = 0;
3383      Item * firstItem = NULL;
3384      if (!mSelectedItems.empty())
3385      {
3386         firstItem = mSelectedItems.front();
3387         for (S32 i = 0; i < mVisibleItems.size();i++)
3388         {
3389            if (mVisibleItems[i] == mSelectedItems.front())
3390            {
3391               firstSelectedIndex = i;
3392               break;
3393            }
3394         }
3395         mCurrentDragCell = mMouseOverCell.y;
3396         if (mVisibleItems[firstSelectedIndex] != firstItem )
3397         {
3398            /*
3399            Con::printf("something isn't right...");
3400            if (mVisibleItems[firstSelectedIndex]->isInspectorData())
3401            Con::printf("visibleItem %s",mVisibleItems[firstSelectedIndex]->getObject()->getName());
3402            if (firstItem->isInspectorData())
3403            Con::printf("firstItem %s",firstItem->getObject()->getName());
3404            */
3405         }
3406         else
3407         {
3408            // select the cells
3409            onAddMultipleSelectionBegin_callback();
3410            if ((mCurrentDragCell) < firstSelectedIndex)
3411            {
3412               //select up
3413               for (S32 j = (mCurrentDragCell); j < firstSelectedIndex; j++)
3414               {
3415                  if( j != (firstSelectedIndex - 1) )
3416                     addSelection(mVisibleItems[j]->mId, false, false);
3417                  else
3418                     addSelection(mVisibleItems[j]->mId, false);
3419               }
3420            }
3421            else
3422            {
3423               // select down
3424               for (S32 j = firstSelectedIndex+1; j < (mCurrentDragCell+1); j++)
3425               {
3426                  if( j != mCurrentDragCell )
3427                     addSelection(mVisibleItems[j]->mId, false, false);
3428                  else
3429                     addSelection(mVisibleItems[j]->mId, false);
3430               }
3431            }
3432
3433            // Scroll to view the last selected cell.
3434            scrollVisible( mVisibleItems[mCurrentDragCell] );
3435
3436            onAddMultipleSelectionEnd_callback();
3437         }
3438      }
3439   }
3440   else if ( event.modifier & SI_PRIMARY_ALT )
3441   {
3442      if ( item->isInspectorData() && item->getObject() )
3443         setAddGroup(item->getObject());
3444   }
3445   else if ( !hitFlags.test(OnImage) )
3446   {      
3447      mTempItem = item;
3448
3449      bool wasSelected = isSelected( item );
3450      bool multiSelect = getSelectedItemsCount() > 1;
3451      
3452      if( !wasSelected || !multiSelect )
3453      {
3454         if ( mClearAllOnSingleSelection )
3455            clearSelection();
3456
3457         if ( !wasSelected || mClearAllOnSingleSelection )
3458            addSelection( item->mId );
3459
3460         if ( wasSelected &&
3461              !multiSelect &&
3462              mCanRenameObjects &&
3463              hitFlags.test(OnText) && 
3464              mFlags.test(IsEditable) && 
3465              item->isInspectorData() && 
3466              item->getObject() &&
3467              item->getObject()->isNameChangeAllowed() &&
3468              item != mRoot &&
3469              event.mouseClickCount == 1 )
3470         {
3471            mPossibleRenameItem = item;
3472
3473            if ( isMethod( "canRenameObject" ) )
3474            {
3475               if( canRenameObject_callback( item->getObject() ) )
3476                  mPossibleRenameItem = NULL;
3477            }
3478         }
3479      }
3480      
3481   }
3482
3483   if ( ( hitFlags.test( OnText ) || hitFlags.test( OnIcon ) ) && 
3484        event.mouseClickCount > 1 )
3485      execAltConsoleCallback();
3486
3487   // For dragging, note if hit is in selection.
3488   
3489   mDragStartInSelection = isItemSelected( item->mId );
3490
3491   if(!item->isParent())
3492      return;
3493
3494   //
3495   if ( mFullRowSelect || hitFlags.test( OnImage ) )
3496   {
3497      item->setExpanded(!item->isExpanded());
3498      if( !item->isInspectorData() && item->mState.test(Item::VirtualParent) )
3499         onVirtualParentExpand(item);
3500      
3501      mFlags.set( RebuildVisible );
3502      scrollVisible(item);
3503   }
3504}
3505
3506//------------------------------------------------------------------------------
3507
3508void GuiTreeViewCtrl::onMouseMove( const GuiEvent &event )
3509{
3510   if ( mMouseOverCell.y >= 0 && mVisibleItems.size() > mMouseOverCell.y)
3511      mVisibleItems[mMouseOverCell.y]->mState.clear( Item::MouseOverBmp | Item::MouseOverText | Item::MouseOverIcon);
3512
3513   Parent::onMouseMove( event );
3514
3515   if ( mMouseOverCell.y >= 0 )
3516   {
3517      Item* item = NULL;
3518      BitSet32 hitFlags = 0;
3519      if ( !_hitTest( event.mousePoint, item, hitFlags ) )
3520         return;
3521
3522      if ( hitFlags.test( OnImage ) )
3523         item->mState.set( Item::MouseOverBmp );
3524
3525      if ( hitFlags.test( OnText ) )
3526         item->mState.set( Item::MouseOverText );
3527
3528      if ( hitFlags.test( OnIcon ) )
3529         item->mState.set( Item::MouseOverIcon );
3530
3531      // Always redraw the entire mouse over item, since we are distinguishing
3532      // between the bitmap and the text:
3533      setUpdateRegion( Point2I( mMouseOverCell.x * mCellSize.x, mMouseOverCell.y * mCellSize.y ), mCellSize );
3534   }
3535}
3536
3537//------------------------------------------------------------------------------
3538
3539void GuiTreeViewCtrl::onMouseEnter( const GuiEvent &event )
3540{
3541   Parent::onMouseEnter( event );
3542   onMouseMove( event );
3543}
3544
3545//------------------------------------------------------------------------------
3546
3547void GuiTreeViewCtrl::onMouseLeave( const GuiEvent &event )
3548{
3549   if ( mMouseOverCell.y >= 0 && mVisibleItems.size() > mMouseOverCell.y)
3550      mVisibleItems[mMouseOverCell.y]->mState.clear( Item::MouseOverBmp | Item::MouseOverText | Item::MouseOverIcon );
3551
3552   Parent::onMouseLeave( event );
3553}
3554
3555//------------------------------------------------------------------------------
3556
3557void GuiTreeViewCtrl::onRightMouseDown(const GuiEvent & event)
3558{
3559   if(!mActive)
3560   {
3561      Parent::onRightMouseDown(event);
3562      return;
3563   }
3564
3565   Item * item = NULL;
3566   BitSet32 hitFlags;
3567
3568   //
3569   if(!_hitTest(event.mousePoint, item, hitFlags))
3570      return;
3571
3572   //
3573
3574   if (item->isInspectorData() && item->getObject())
3575      onRightMouseDown_callback( item->mId, event.mousePoint, item->getObject() );
3576   else
3577      onRightMouseDown_callback( item->mId, event.mousePoint );
3578}
3579
3580//-----------------------------------------------------------------------------
3581
3582void GuiTreeViewCtrl::onRightMouseUp(const GuiEvent & event)
3583{
3584   Item *item = NULL;
3585   BitSet32 hitFlags;
3586
3587   if ( !_hitTest( event.mousePoint, item, hitFlags ) )
3588      return;
3589
3590   if ( hitFlags.test( OnText ) || hitFlags.test( OnIcon ) )
3591   {
3592      if ( !isItemSelected( item->getID() ) )
3593      {
3594          clearSelection();
3595          addSelection( item->getID() );
3596      }
3597
3598      if (item->isInspectorData() && item->getObject())
3599         onRightMouseUp_callback( item->mId, event.mousePoint, item->getObject() );
3600      else
3601         onRightMouseUp_callback( item->mId, event.mousePoint );
3602   }
3603   else
3604   {
3605      clearSelection();
3606   }
3607
3608   Parent::onRightMouseUp(event);
3609}
3610
3611//------------------------------------------------------------------------------
3612
3613void GuiTreeViewCtrl::onRender(Point2I offset, const RectI &updateRect)
3614{
3615   if ( !mRenamingItem && mRenameCtrl )   
3616   {
3617      mRenameCtrl->deleteObject();
3618      mRenameCtrl = NULL;
3619   }
3620   
3621   // Get all our contents drawn!
3622   Parent::onRender(offset,updateRect);
3623
3624   // Deal with drawing the drag & drop line, if any...
3625   GFX->setClipRect(updateRect);
3626
3627   // only do it if we have a mDragMidPoint
3628   if (mDragMidPoint == NomDragMidPoint || !mSupportMouseDragging )
3629      return;
3630
3631   ColorI greyLine(128,128,128);
3632   Point2F squarePt;
3633
3634   // CodeReview: LineWidth is not supported in Direct3D. This is lame. [5/10/2007 Pat]
3635   // draw mDragMidPoint lines with a diamond
3636   if (mDragMidPoint == AbovemDragMidPoint)
3637   {
3638      S32 tempY = mItemHeight*mCurrentDragCell+offset.y ;
3639      squarePt.y = (F32)tempY;
3640      squarePt.x = 125.f+offset.x;
3641      GFX->getDrawUtil()->drawLine(0+offset.x, tempY, 250+offset.x, tempY,greyLine);
3642      GFX->getDrawUtil()->draw2DSquare(squarePt, 6, 90 );
3643
3644   }
3645   if (mDragMidPoint == BelowmDragMidPoint)
3646   {
3647      S32 tempY2 = mItemHeight*(mCurrentDragCell+1) +offset.y;
3648      squarePt.y = (F32)tempY2;
3649      squarePt.x = 125.f+offset.x;
3650      GFX->getDrawUtil()->drawLine(0+offset.x, tempY2, 250+offset.x, tempY2,greyLine);
3651      GFX->getDrawUtil()->draw2DSquare(squarePt,6, 90 );
3652   }
3653}
3654
3655//-----------------------------------------------------------------------------
3656
3657void GuiTreeViewCtrl::onRenderCell(Point2I offset, Point2I cell, bool, bool )
3658{
3659   if( !mVisibleItems.size() )
3660      return;
3661
3662   // Do some sanity checking and data retrieval.
3663   AssertFatal(cell.y < mVisibleItems.size(), "GuiTreeViewCtrl::onRenderCell: invalid cell");
3664   Item * item = mVisibleItems[cell.y];
3665
3666   // If there's no object, deal with it.
3667   if(item->isInspectorData())
3668      if(!item->getObject())
3669         return;
3670
3671   RectI drawRect( offset, mCellSize );
3672   GFXDrawUtil *drawer = GFX->getDrawUtil();
3673   drawer->clearBitmapModulation();
3674
3675   FrameAllocatorMarker txtBuff;
3676   
3677   // Ok, we have the item. There are a few possibilities at this point:
3678   //    - We need to draw inheritance lines and a treeview-chosen icon
3679   //       OR
3680   //    - We have to draw an item-dependent icon
3681   //    - If we're mouseover, we have to highlight it.
3682   //
3683   //    - We have to draw the text for the item
3684   //       - Taking into account various mouseover states
3685   //       - Taking into account the value (set or not)
3686   //       - If it's an inspector data, we have to do some custom rendering
3687   //       - ADDED: If it is being renamed, we also have custom rendering.
3688
3689   // Ok, first draw the tab and icon.
3690
3691   // Do we draw the tree lines?
3692   if( mFlags.test(ShowTreeLines) )
3693   {
3694      drawRect.point.x += ( mTabSize * item->mTabLevel );
3695      Item* parent = item->mParent;
3696      for ( S32 i = item->mTabLevel; ( parent && i > 0 ); i-- )
3697      {
3698         drawRect.point.x -= mTabSize;
3699         if ( parent->mNext )
3700            drawer->drawBitmapSR( mProfile->mTextureObject, drawRect.point, mProfile->mBitmapArrayRects[BmpLine] );
3701
3702         parent = parent->mParent;
3703      }
3704   }
3705
3706   // Now, the icon...
3707   drawRect.point.x = offset.x + mTabSize * item->mTabLevel;
3708
3709   // First, draw the rollover glow, if it's an inner node.
3710   if ( item->isParent() && item->mState.test( Item::MouseOverBmp ) )
3711      drawer->drawBitmapSR( mProfile->mTextureObject, drawRect.point, mProfile->mBitmapArrayRects[BmpGlow] );
3712
3713   // Now, do we draw a treeview-selected item or an item dependent one?
3714   S32 newOffset = 0; // This is stored so we can render glow, then update render pos.
3715
3716   S32 bitmap = 0;
3717
3718   // Ok, draw the treeview lines as appropriate.
3719   
3720   bool drawBitmap = true;
3721   if ( !item->isParent() )
3722   {
3723      if( mFlags.test( ShowTreeLines ) )
3724      {
3725         if(    ( item->mNext && item->mPrevious )
3726             || ( item->mNext && item->mParent && ( !_isRootLevelItem( item ) || mShowRoot ) ) )
3727            bitmap = BmpChild;
3728         else if( item->mNext && ( !item->mParent || !mShowRoot ) )
3729            bitmap = BmpFirstChild;
3730         else if( item->mPrevious || ( item->mParent && !_isRootLevelItem( item ) ) )
3731            bitmap = BmpLastChild;
3732         else
3733            drawBitmap = false;
3734      }
3735      else
3736         drawBitmap = false;
3737   }
3738   else
3739   {
3740      bitmap = item->isExpanded() ? BmpExp : BmpCon;
3741
3742      if( mFlags.test( ShowTreeLines ) )
3743      {
3744         // Shift indices to show versions with tree lines.
3745         
3746         if ( item->mParent || item->mPrevious )
3747            bitmap += ( item->mNext ? 3 : 2 );
3748         else
3749            bitmap += ( item->mNext ? 1 : 0 );
3750      }
3751   }
3752
3753   if( ( bitmap >= 0 ) && ( bitmap < mProfile->mBitmapArrayRects.size() ) )
3754   {
3755      if( drawBitmap )
3756         drawer->drawBitmapSR( mProfile->mTextureObject, drawRect.point, mProfile->mBitmapArrayRects[bitmap] );
3757      newOffset = mProfile->mBitmapArrayRects[bitmap].extent.x;
3758   }
3759
3760   if(item->isInspectorData())
3761   {
3762      // draw lock icon if need be
3763      S32 icon = Lock1;
3764      S32 icon2 = Hidden;
3765
3766      if (item->getObject() && item->getObject()->isLocked())
3767      {
3768         if (mIconTable[icon])
3769         {
3770            //drawRect.point.x = offset.x + mTabSize * item->mTabLevel + mIconTable[icon].getWidth();
3771            drawRect.point.x += mIconTable[icon].getWidth();
3772            drawer->drawBitmap( mIconTable[icon], drawRect.point );
3773         }
3774      }
3775
3776      if (item->getObject() && item->getObject()->isHidden())
3777      {
3778         if (mIconTable[icon2])
3779         {
3780            //drawRect.point.x = offset.x + mTabSize * item->mTabLevel + mIconTable[icon].getWidth();
3781            drawRect.point.x += mIconTable[icon2].getWidth();
3782            drawer->drawBitmap( mIconTable[icon2], drawRect.point );
3783         }
3784      }
3785
3786      SimObject * pObject = item->getObject();
3787      SimGroup  * pGroup  = ( pObject == NULL ) ? NULL : dynamic_cast<SimGroup*>( pObject );
3788
3789      // If this item is a VirtualParent we can use the generic SimGroup123 icons.
3790      // However if there is already an icon in the EditorIconRegistry for this
3791      // exact class (not counting parent class icons) we want to use that instead.
3792      bool hasClassIcon = false;
3793#ifdef TORQUE_TOOLS
3794      hasClassIcon = gEditorIcons.hasIconNoRecurse( pObject );
3795#endif
3796
3797      // draw the icon associated with the item
3798      if ( !hasClassIcon && item->mState.test(Item::VirtualParent))
3799      {
3800         if ( pGroup != NULL)
3801         {
3802            //Check if we're a SceneObject, and pick the default icon as appropriate
3803            
3804            if (pObject->getClassName() != String("SimGroup"))
3805            {
3806               item->mIcon = Icon31;
3807            }
3808            else
3809            {
3810               //If we're purely a SimGroup, pick our icon.
3811               if (item->isExpanded())
3812                  item->mIcon = SimGroup1;
3813               else
3814                  item->mIcon = SimGroup2;
3815            }
3816         }
3817         else
3818            item->mIcon = SimGroup2;
3819      }
3820      
3821      if ( !hasClassIcon && item->mState.test(Item::Marked))
3822      {
3823         if (item->isInspectorData())
3824         {
3825            if ( pGroup != NULL )
3826            {
3827               if (item->isExpanded())
3828                  item->mIcon = SimGroup3;
3829               else
3830                  item->mIcon = SimGroup4;
3831            }
3832         }
3833      }
3834
3835      GFXTexHandle iconHandle;
3836
3837      if ( ( item->mIcon != -1 ) && mIconTable[item->mIcon] )
3838         iconHandle = mIconTable[item->mIcon];
3839#ifdef TORQUE_TOOLS
3840      else
3841         iconHandle = gEditorIcons.findIcon( item->getObject() );
3842#endif
3843
3844      if ( iconHandle.isValid() )
3845      {
3846         S32 iconHeight = (mItemHeight - iconHandle.getHeight()) / 2;
3847         S32 oldHeight = drawRect.point.y;
3848         if(iconHeight > 0)
3849            drawRect.point.y += iconHeight;
3850         drawRect.point.x += iconHandle.getWidth();
3851         drawer->drawBitmap( iconHandle, drawRect.point );
3852         drawRect.point.y = oldHeight;
3853      }
3854   }
3855   else
3856   {
3857      S32 icon = item->isExpanded() ? item->mScriptInfo.mExpandedImage : item->mScriptInfo.mNormalImage;
3858      if ( icon )
3859      {
3860         if (mIconTable[icon])
3861         {
3862            S32 iconHeight = (mItemHeight - mIconTable[icon].getHeight()) / 2;
3863            S32 oldHeight = drawRect.point.y;
3864            if(iconHeight > 0)
3865               drawRect.point.y += iconHeight;
3866            drawRect.point.x += mIconTable[icon].getWidth();
3867            drawer->drawBitmap( mIconTable[icon], drawRect.point );
3868            drawRect.point.y = oldHeight;
3869         }
3870      }
3871   }
3872
3873   // Ok, update offset so we can render some text!
3874   drawRect.point.x += newOffset;
3875
3876   // Ok, now we're off to rendering the actual data for the treeview item.
3877
3878   U32 bufLen = 1024; //item->mDataRenderWidth + 1;
3879   char *displayText = (char *)txtBuff.alloc(bufLen);
3880   displayText[bufLen-1] = 0;
3881   item->getDisplayText(bufLen, displayText);
3882
3883   // Draw the rollover/selected bitmap, if one was specified.
3884   drawRect.extent.x = mProfile->mFont->getStrWidth( displayText ) + ( 2 * mTextOffset );
3885   if ( item->mState.test( Item::Selected ) && mTexSelected )
3886      drawer->drawBitmapStretch( mTexSelected, drawRect );
3887   else if ( item->mState.test( Item::MouseOverText ) && mTexRollover )
3888      drawer->drawBitmapStretch( mTexRollover, drawRect );
3889
3890   // Offset a bit so as to space text properly.
3891   drawRect.point.x += mTextOffset;
3892
3893   // Determine what color the font should be.
3894   ColorI fontColor;
3895
3896   fontColor = item->mState.test( Item::Selected ) ? mProfile->mFontColorSEL :
3897             ( item->mState.test( Item::MouseOverText ) ? mProfile->mFontColorHL : mProfile->mFontColor );
3898
3899   if (item->mState.test(Item::Selected))
3900   {
3901      drawer->drawRectFill(drawRect, mProfile->mFillColorSEL);
3902   }
3903   else if (item->mState.test(Item::MouseOverText))
3904   {
3905      drawer->drawRectFill(drawRect, mProfile->mFillColorHL);
3906   }
3907
3908   if( item->mState.test(Item::MouseOverText) )
3909   {
3910      fontColor   =  mProfile->mFontColorHL;
3911   }
3912
3913   drawer->setBitmapModulation( fontColor );
3914
3915   // Center the text horizontally.
3916   S32 height = (mItemHeight - mProfile->mFont->getHeight()) / 2;
3917
3918   if(height > 0)
3919      drawRect.point.y += height;
3920
3921   // JDD - offset by two pixels or so to keep the text from rendering RIGHT ONTOP of the outline
3922   drawRect.point.x += 2;
3923
3924   drawer->drawText( mProfile->mFont, drawRect.point, displayText, mProfile->mFontColors );
3925
3926   if ( mRenamingItem == item && mRenameCtrl )
3927   {
3928      Point2I ctrPos = globalToLocalCoord( drawRect.point );
3929      ctrPos.y -= height;
3930      ctrPos.x -= 2;
3931
3932      Point2I ctrExtent( getWidth() - ctrPos.x, drawRect.extent.y );
3933
3934      mRenameCtrl->setPosition( ctrPos );
3935      mRenameCtrl->setExtent( ctrExtent );
3936      mRenameCtrl->setVisible( true );
3937   }
3938}
3939
3940//------------------------------------------------------------------------------
3941
3942bool GuiTreeViewCtrl::renderTooltip( const Point2I &hoverPos, const Point2I& cursorPos, const char* tipText )
3943{
3944   Item* item;
3945   BitSet32 flags = 0;
3946   if( _hitTest( cursorPos, item, flags ) && (!item->mTooltip.isEmpty() || mUseInspectorTooltips) )
3947   {
3948      bool render = true;
3949
3950      if( mTooltipOnWidthOnly && !item->hasObjectBasedTooltip() )
3951      {
3952         // Only render tooltip if the item's text is cut off with its
3953         // parent scroll control, unless there is custom object-based
3954         // tooltip information.
3955         GuiScrollCtrl *pScrollParent = dynamic_cast<GuiScrollCtrl*>( getParent() );
3956         if ( pScrollParent )
3957         {
3958            Point2I textStart;
3959            Point2I textExt;
3960
3961            const Point2I pos = globalToLocalCoord(cursorPos);
3962            textStart.y = pos.y / mCellSize.y;
3963            textStart.y *= mCellSize.y;
3964
3965            // The following is taken from _hitTest()
3966            textStart.x = mTabSize * item->mTabLevel;
3967            S32 image = BmpChild;
3968            if((image >= 0) && (image < mProfile->mBitmapArrayRects.size()))
3969               textStart.x += mProfile->mBitmapArrayRects[image].extent.x;
3970            textStart.x += mTextOffset;
3971
3972            textStart.x += getInspectorItemIconsWidth( item );
3973
3974            FrameAllocatorMarker txtAlloc;
3975            U32 bufLen = item->getDisplayTextLength() + 1;
3976            char *buf = (char*)txtAlloc.alloc(bufLen);
3977            item->getDisplayText(bufLen, buf);
3978            textExt.x = mProfile->mFont->getStrWidth(buf);
3979            textExt.y = mProfile->mFont->getHeight();
3980
3981            if( pScrollParent->isRectCompletelyVisible(RectI(textStart, textExt)) )
3982               render = false;
3983         }
3984      }
3985
3986      if( render )
3987      {
3988         if( mUseInspectorTooltips )
3989         {
3990            char buf[2048];
3991            item->getTooltipText( sizeof( buf ), buf );
3992            tipText = buf;
3993         }
3994         else
3995         {
3996            tipText = item->mTooltip.c_str();
3997         }
3998      }
3999   }
4000      
4001   return defaultTooltipRender( cursorPos, cursorPos, tipText );
4002}
4003
4004//------------------------------------------------------------------------------
4005
4006void GuiTreeViewCtrl::clearSelection()
4007{
4008   if( mDebug ) Con::printf( "clearSelection called" );
4009   
4010   while ( !mSelectedItems.empty() )
4011   {
4012      removeSelection( mSelectedItems.last()->mId );
4013   }
4014
4015   mSelectedItems.clear();
4016   mSelected.clear();
4017
4018   onClearSelection();   
4019   onClearSelection_callback();
4020}
4021
4022//-----------------------------------------------------------------------------
4023
4024void GuiTreeViewCtrl::lockSelection(bool lock)
4025{
4026   for(U32 i = 0; i < mSelectedItems.size(); i++)
4027   {
4028      if(mSelectedItems[i]->isInspectorData())
4029         mSelectedItems[i]->getObject()->setLocked(lock);
4030   }
4031}
4032
4033//-----------------------------------------------------------------------------
4034
4035void GuiTreeViewCtrl::hideSelection(bool hide)
4036{
4037   for(U32 i = 0; i < mSelectedItems.size(); i++)
4038   {
4039      if(mSelectedItems[i]->isInspectorData())
4040         mSelectedItems[i]->getObject()->setHidden(hide);
4041   }
4042}
4043
4044//-----------------------------------------------------------------------------
4045
4046void GuiTreeViewCtrl::toggleLockSelection()
4047{
4048   for(U32 i = 0; i < mSelectedItems.size(); i++)
4049   {
4050      if( mSelectedItems[i]->isInspectorData() )
4051      {
4052         SimObject* object = mSelectedItems[ i ]->getObject();
4053         object->setLocked( !object->isLocked() );
4054      }
4055   }
4056}
4057
4058//-----------------------------------------------------------------------------
4059
4060void GuiTreeViewCtrl::toggleHideSelection()
4061{
4062   for(U32 i = 0; i < mSelectedItems.size(); i++)
4063   {
4064      if( mSelectedItems[i]->isInspectorData() )
4065      {
4066         SimObject* object = mSelectedItems[ i ]->getObject();
4067         object->setHidden( !object->isHidden() );
4068      }
4069   }
4070}
4071
4072//------------------------------------------------------------------------------
4073
4074// handles icon assignments
4075S32 GuiTreeViewCtrl::getIcon(const char * iconString)
4076{
4077   return -1;   
4078}
4079
4080//-----------------------------------------------------------------------------
4081
4082GuiTreeViewCtrl::Item* GuiTreeViewCtrl::addInspectorDataItem(Item *parent, SimObject *obj)
4083{
4084   S32 icon = getIcon(obj->getClassName());
4085   Item *item = createItem(icon);
4086   item->mState.set(Item::InspectorData);
4087
4088   // Set the item text label flags.
4089   
4090   if( !mShowObjectIds )
4091      item->mState.clear( Item::ShowObjectId );
4092   else
4093      item->mState.set( Item::ShowObjectId );
4094   if( !mShowClassNames )
4095      item->mState.clear( Item::ShowClassName );
4096   else
4097      item->mState.set( Item::ShowClassName );
4098   if( !mShowObjectNames )
4099      item->mState.clear( Item::ShowObjectName );
4100   else
4101      item->mState.set( Item::ShowObjectName );
4102   if( !mShowInternalNames )
4103      item->mState.clear( Item::ShowInternalName );
4104   else
4105      item->mState.set( Item::ShowInternalName );
4106   if( mShowClassNameForUnnamedObjects )
4107      item->mState.set( Item::ShowClassNameForUnnamed );
4108
4109   // Deal with child objects...
4110   if(dynamic_cast<SimSet*>(obj))
4111      item->mState.set(Item::VirtualParent);
4112
4113   // Actually store the data!
4114   item->setObject(obj);
4115
4116   // Now add us to the data structure...
4117   if(parent)
4118   {
4119      // Add as child of parent.
4120      if(parent->mChild)
4121      {
4122         Item * traverse = parent->mChild;
4123         while(traverse->mNext)
4124            traverse = traverse->mNext;
4125
4126         traverse->mNext = item;
4127         item->mPrevious = traverse;
4128      }
4129      else
4130         parent->mChild = item;
4131
4132      item->mParent = parent;
4133   }
4134   else
4135   {
4136      // If no parent, add to root.
4137      item->mNext = mRoot;
4138      mRoot = item;
4139      item->mParent = NULL;
4140   }
4141
4142   mFlags.set(RebuildVisible);
4143   return item;
4144}
4145
4146//-----------------------------------------------------------------------------
4147
4148void GuiTreeViewCtrl::unlinkItem(Item * item)
4149{
4150   if (item->mPrevious)
4151      item->mPrevious->mNext = item->mNext;
4152
4153   if (item->mNext)
4154      item->mNext->mPrevious = item->mPrevious;
4155}
4156
4157//-----------------------------------------------------------------------------
4158
4159bool GuiTreeViewCtrl::childSearch(Item * item, SimObject *obj, bool yourBaby)
4160{
4161   Item * temp = item->mChild;
4162   while (temp)
4163   {
4164      //do you have my baby?
4165      if (temp->isInspectorData())
4166      {
4167         if (temp->getObject() == obj)
4168            yourBaby = false; //probably a child of an inner script
4169      }
4170      yourBaby = childSearch(temp,obj, yourBaby);
4171      temp = temp->mNext;
4172   }
4173   return yourBaby;
4174}
4175
4176//-----------------------------------------------------------------------------
4177
4178void GuiTreeViewCtrl::inspectorSearch(Item * item, Item * parent, SimSet * parentSet, SimSet * newParentSet)
4179{
4180   if (!parentSet||!newParentSet)
4181      return;
4182
4183   if (item == parent->mNext)
4184      return;
4185
4186   if (item)
4187   {
4188      if (item->isInspectorData())
4189      {
4190         // remove the object from the parentSet and add it to the newParentSet
4191         SimObject* simObj = item->getObject();
4192
4193         if (parentSet->size())
4194         {
4195            SimObject *lastObject = parentSet->last();
4196            parentSet->removeObject(simObj);
4197            parentSet->reOrder(lastObject);
4198         }
4199         else
4200            parentSet->removeObject(simObj);
4201
4202         newParentSet->addObject(simObj);
4203
4204         if (item->mNext)
4205         {
4206            inspectorSearch(item->mNext, parent, parentSet, newParentSet);
4207            return;
4208         }
4209         else
4210         {
4211            // end of children so backing up
4212            if (item->mParent == parent)
4213               return;
4214            else
4215            {
4216               inspectorSearch(item->mParent->mNext, parent, parentSet, newParentSet);
4217               return;
4218            }
4219         }
4220      }
4221
4222      if (item->mChild)
4223      {
4224         inspectorSearch(item->mChild, parent, parentSet, newParentSet);
4225         return;
4226      }
4227
4228      if (item->mNext)
4229      {
4230         inspectorSearch(item->mNext, parent, parentSet, newParentSet);
4231         return;
4232      }
4233   }
4234}
4235
4236//-----------------------------------------------------------------------------
4237
4238bool GuiTreeViewCtrl::objectSearch( const SimObject *object, Item **item )
4239{
4240   for ( U32 i = 0; i < mItems.size(); i++ )
4241   {
4242      Item *pItem = mItems[i];
4243
4244      if ( !pItem )
4245         continue;
4246
4247      //A bit hackish, but we make a special exception here for items that are named 'Components', as they're merely
4248      //virtual parents to act as a container to an Entity's components
4249      if (pItem->mScriptInfo.mText == StringTable->insert("Components"))
4250         continue;
4251
4252      SimObject *pObj = pItem->getObject();
4253
4254      if ( pObj && pObj == object )
4255      {
4256         *item = pItem;
4257         return true;
4258      }
4259   }
4260
4261   return false;
4262}
4263
4264//-----------------------------------------------------------------------------
4265
4266bool GuiTreeViewCtrl::onVirtualParentBuild(Item *item, bool bForceFullUpdate)
4267{
4268   if(!item->mState.test(Item::InspectorData))
4269      return true;
4270
4271   // Blast an item if it doesn't have a corresponding SimObject...
4272   if(item->mInspectorInfo.mObject == NULL)
4273   {
4274      removeItem(item->mId);
4275      return false;
4276   }
4277
4278   // Skip the next stuff unless we're expanded...
4279    if(!item->isExpanded() && !bForceFullUpdate && !( item == mRoot && !mShowRoot ) )
4280      return true;
4281
4282   // Verify that we have all the kids we should in here...
4283   SimSet *srcObj = dynamic_cast<SimSet*>(&(*item->mInspectorInfo.mObject));
4284
4285   // If it's not a SimSet... WTF are we doing here?
4286   if(!srcObj)
4287      return true;
4288
4289   // This is slow but probably ok.
4290   for( SimSet::iterator i = srcObj->begin(); i != srcObj->end(); ++ i )
4291   {
4292      SimObject *obj = *i;
4293
4294      // If we can't find it, add it.
4295      // unless it has a parent that is a child that is a script
4296      Item *res = item->findChildByValue(obj);
4297
4298      bool foundChild = true;
4299
4300      // search the children. if any of them are the parent of the object then don't add it.
4301      foundChild = childSearch(item,obj,foundChild);
4302
4303      if(!res && foundChild)
4304      {
4305         if (mDebug) Con::printf( "adding object %i to item %i", obj->getId(), item->mId );
4306         res = addInspectorDataItem(item, obj);
4307      }
4308      
4309      if( res )
4310         res->mState.set( Item::RebuildVisited );
4311   }
4312   
4313   // Go through our items and purge those that have disappeared from
4314   // the set.
4315   for( Item* ptr = item->mChild; ptr != NULL; )
4316   {
4317      Item* next = ptr->mNext;
4318      if( !ptr->mState.test( Item::RebuildVisited ) )
4319      {
4320         if( mDebug ) Con::printf( "removing item %i for object %i that is no longer in the set",
4321            ptr->mId, ptr->getObject()->getId() );
4322            
4323         removeItem( ptr->mId, false );
4324      }
4325      else
4326         ptr->mState.clear( Item::RebuildVisited );
4327         
4328      ptr = next;
4329   }
4330
4331   return true;
4332}
4333
4334//-----------------------------------------------------------------------------
4335
4336bool GuiTreeViewCtrl::onVirtualParentExpand(Item *item)
4337{
4338   // Do nothing...
4339   return true;
4340}
4341
4342//-----------------------------------------------------------------------------
4343
4344bool GuiTreeViewCtrl::onVirtualParentCollapse(Item *item)
4345{
4346   // Do nothing...
4347   return true;
4348}
4349
4350//-----------------------------------------------------------------------------
4351
4352void GuiTreeViewCtrl::inspectObject( SimObject* obj, bool okToEdit )
4353{
4354   _destroyTree();
4355
4356   mFlags.set( IsEditable, okToEdit );
4357   mFlags.set( IsInspector );
4358
4359   onDefineIcons_callback();
4360
4361   addInspectorDataItem( NULL, obj );
4362}
4363
4364//-----------------------------------------------------------------------------
4365
4366S32 GuiTreeViewCtrl::insertObject( S32 parent, SimObject* obj, bool okToEdit )
4367{
4368   mFlags.set( IsEditable, okToEdit );
4369   mFlags.set( IsInspector );
4370
4371   //onDefineIcons_callback();
4372
4373   GuiTreeViewCtrl::Item *item = addInspectorDataItem( getItem(parent), obj );
4374   return item->getID();
4375}
4376
4377//-----------------------------------------------------------------------------
4378
4379S32 GuiTreeViewCtrl::findItemByName(const char *name)
4380{
4381   for (S32 i = 0; i < mItems.size(); i++) 
4382   {
4383      if ( !mItems[i] )
4384         continue;
4385      if( mItems[i]->mState.test( Item::InspectorData ) )
4386         continue;
4387      if (mItems[i] && String::compare(mItems[i]->getText(),name) == 0) 
4388         return mItems[i]->mId;
4389   }
4390
4391   return 0;
4392}
4393
4394//-----------------------------------------------------------------------------
4395
4396S32 GuiTreeViewCtrl::findItemByValue(const char *name)
4397{
4398   for (S32 i = 0; i < mItems.size(); i++) 
4399   {
4400      if (!mItems[i])
4401         continue;
4402      if( mItems[i]->mState.test( Item::InspectorData ) )
4403         continue;
4404      if (mItems[i] && String::compare(mItems[i]->getValue(),name) == 0) 
4405         return mItems[i]->mId;
4406   }
4407
4408   return 0;
4409}
4410
4411//-----------------------------------------------------------------------------
4412
4413void GuiTreeViewCtrl::sortTree( bool caseSensitive, bool traverseHierarchy, bool parentsFirst )
4414{
4415   itemSortList( mRoot, caseSensitive, traverseHierarchy, parentsFirst );
4416}
4417
4418//-----------------------------------------------------------------------------
4419
4420StringTableEntry GuiTreeViewCtrl::getTextToRoot( S32 itemId, const char * delimiter )
4421{
4422   Item * item = getItem(itemId);
4423
4424   if(!item)
4425   {
4426      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getTextToRoot: invalid start item id!");
4427      return StringTable->EmptyString();
4428   }
4429
4430   if(item->isInspectorData())
4431   {
4432      Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getTextToRoot: cannot get text to root of inspector data items");
4433      return StringTable->EmptyString();
4434   }
4435
4436   char bufferOne[1024];
4437   char bufferTwo[1024];
4438   char bufferNodeText[128];
4439
4440   dMemset( bufferOne, 0, sizeof(bufferOne) );
4441   dMemset( bufferTwo, 0, sizeof(bufferTwo) );
4442
4443   dStrcpy( bufferOne, item->getText(), 1024 );
4444
4445   Item *prevNode = item->mParent;
4446   while ( prevNode )
4447   {
4448      dMemset( bufferNodeText, 0, sizeof(bufferNodeText) );
4449      dStrcpy( bufferNodeText, prevNode->getText(), 128 );
4450      dSprintf( bufferTwo, 1024, "%s%s%s",bufferNodeText, delimiter, bufferOne );
4451      dStrcpy( bufferOne, bufferTwo, 1024 );
4452      dMemset( bufferTwo, 0, sizeof(bufferTwo) );
4453      prevNode = prevNode->mParent;
4454   }
4455
4456   // Return the result, StringTable-ized.
4457   return StringTable->insert( bufferOne, true );
4458}
4459
4460//-----------------------------------------------------------------------------
4461
4462void GuiTreeViewCtrl::setFilterText( const String& text )
4463{
4464   mFilterText = text;
4465
4466   // Trigger rebuild.
4467   mFlags.set( RebuildVisible );
4468}
4469
4470void GuiTreeViewCtrl::setItemFilterException(U32 item, bool isExempted)
4471{
4472   if (isExempted)
4473   {
4474      mItemFilterExceptionList.push_back(item);
4475   }
4476   else
4477   {
4478      mItemFilterExceptionList.remove(item);
4479   }
4480}
4481
4482void GuiTreeViewCtrl::setItemHidden(U32 item, bool isHidden)
4483{
4484   if (isHidden)
4485   {
4486      mHiddenItemsList.push_back(item);
4487   }
4488   else
4489   {
4490      mHiddenItemsList.remove(item);
4491   }
4492}
4493
4494void GuiTreeViewCtrl::reparentItems(Vector<Item*> selectedItems, Item* newParent)
4495{
4496   for (S32 i = 0; i < selectedItems.size(); i++)
4497   {
4498      Item* item = selectedItems[i];
4499
4500      if (mDebug)
4501         Con::printf("----------------------------");
4502
4503      // clear old highlighting of the item
4504      item->mState.clear(Item::MouseOverBmp | Item::MouseOverText);
4505
4506      // move the selected item to the newParent
4507      Item * oldParent = item->mParent;
4508      // Snag the current parent set if any for future reference
4509      SimSet * parentSet = NULL;
4510
4511      if (oldParent != nullptr && oldParent->isInspectorData())
4512      {
4513         parentSet = dynamic_cast<SimSet*>(oldParent->getObject());
4514      }
4515      else
4516      {
4517         // parent is probably script data so we search up the tree for a
4518         // set to put our object in
4519         Item* temp = oldParent;
4520         while (temp)
4521         {
4522            if (temp->isInspectorData())
4523               break;
4524            temp = temp->mParent;
4525         }
4526         // found an ancestor who is an inspectorData
4527         if (temp)
4528         {
4529            if (temp->isInspectorData())
4530               parentSet = dynamic_cast<SimSet*>(temp->getObject());
4531         }
4532      }
4533
4534      // unlink from the current position in the list
4535      unlinkItem(item);
4536
4537      // update the parent's children
4538
4539      // check if we an only child
4540      if (item->mParent && item->mParent->mChild == item)
4541      {
4542         if (item->mNext)
4543            item->mParent->mChild = item->mNext;
4544         else
4545            item->mParent->mChild = NULL;
4546      }
4547
4548      if (mDragMidPoint != NomDragMidPoint)
4549      {
4550
4551         //if it is below an expanded tree, place as last item in the tree
4552         //if it is below a parent who isn't expanded put below it
4553
4554         // position the item above or below another item
4555         if (mDragMidPoint == AbovemDragMidPoint)
4556         {
4557            // easier to treat everything as "Below the mDragMidPoint" so make some adjustments
4558            if (mDebug)
4559               Con::printf("adding item above mDragMidPoint");
4560
4561            // above the mid point of an item, so grab either the parent
4562            // or the previous sibling
4563
4564            // does the item have a previous sibling?
4565            if (newParent->mPrevious)
4566            {
4567               newParent = newParent->mPrevious;
4568
4569               if (mDebug)
4570                  Con::printf("treating as if below an item that isn't expanded");
4571
4572               // otherwise add below that item as a sibling
4573               item->mParent = newParent->mParent;
4574               item->mPrevious = newParent;
4575               item->mNext = newParent->mNext;
4576               if (newParent->mNext)
4577                  newParent->mNext->mPrevious = item;
4578               newParent->mNext = item;
4579            }
4580            else
4581            {
4582               if (mDebug)
4583                  Con::printf("treating as if adding below the parent of the item");
4584
4585               // instead we add as the first item below the newParent's parent
4586               item->mParent = newParent->mParent;
4587               item->mNext = newParent;
4588               item->mPrevious = NULL;
4589               newParent->mPrevious = item;
4590               item->mParent->mChild = item;
4591            }
4592         }
4593         else if (mDragMidPoint == BelowmDragMidPoint)
4594         {
4595            if ((newParent->isParent()) && (newParent->isExpanded()))
4596            {
4597               if (mDebug)
4598                  Con::printf("adding item to an expanded parent below the mDragMidPoint");
4599
4600               item->mParent = newParent;
4601
4602               // then add the new item as a child
4603               item->mNext = newParent->mChild;
4604               if (newParent->mChild)
4605                  newParent->mChild->mPrevious = item;
4606               item->mParent->mChild = item;
4607               item->mPrevious = NULL;
4608            }
4609            else if ((!newParent->mNext) && (newParent->mParent) && (newParent->mParent->mParent))
4610            {
4611               // add below it's parent.
4612               if (mDebug)
4613                  Con::printf("adding below a tree");
4614
4615               item->mParent = newParent->mParent->mParent;
4616               item->mNext = newParent->mParent->mNext;
4617               item->mPrevious = newParent->mParent;
4618
4619               if (newParent->mParent->mNext)
4620                  newParent->mParent->mNext->mPrevious = item;
4621
4622               newParent->mParent->mNext = item;
4623            }
4624            else
4625            {
4626               // adding below item not as a child
4627               if (mDebug)
4628                  Con::printf("adding item below the mDragMidPoint of an item");
4629
4630               item->mParent = newParent->mParent;
4631               // otherwise the item is a sibling
4632               if (newParent->mNext)
4633                  newParent->mNext->mPrevious = item;
4634               item->mNext = newParent->mNext;
4635               item->mPrevious = newParent;
4636               newParent->mNext = item;
4637            }
4638         }
4639      }
4640      // if we're not allowed to add to items, then try to add to the parent of the hit item.
4641      // if we are, just add to the item we hit.
4642      else
4643      {
4644         if (mDebug)
4645         {
4646            if (item->isInspectorData() && item->getObject())
4647               Con::printf("Item: %i", item->getObject()->getId());
4648            if (newParent->isInspectorData() && newParent->getObject())
4649               Con::printf("Parent: %i", newParent->getObject()->getId());
4650            Con::printf("dragged onto an item");
4651         }
4652
4653         // If the hit item is not a valid drag target,
4654         // then try to add to the parent.
4655
4656         if (!isValidDragTarget(newParent))
4657         {
4658            // add to the item's parent.
4659            if (!newParent->mParent || !newParent->mParent->isParent())
4660            {
4661               if (mDebug)
4662                  Con::printf("could not find the parent of that item. dragging to an item is not allowed, kicking out.");
4663               mDragMidPoint = NomDragMidPoint;
4664               continue;
4665            }
4666            newParent = newParent->mParent;
4667         }
4668
4669         // new parent is the item in the current cell
4670         item->mParent = newParent;
4671
4672         // adjust children if any
4673         if (newParent->mChild)
4674         {
4675            if (mDebug) Con::printf("not the first child");
4676
4677            // put it at the top of the list (easier to find if there are many children)
4678            if (newParent->mChild)
4679               newParent->mChild->mPrevious = item;
4680            item->mNext = newParent->mChild;
4681            newParent->mChild = item;
4682            item->mPrevious = NULL;
4683         }
4684         else
4685         {
4686            if (mDebug) Con::printf("first child");
4687
4688            // only child
4689            newParent->mChild = item;
4690            item->mNext = NULL;
4691            item->mPrevious = NULL;
4692         }
4693      }
4694
4695      // expand the item we added to, if it isn't expanded already
4696      if (!item->mParent->mState.test(Item::Expanded))
4697         setItemExpanded(item->mParent->mId, true);
4698
4699      //----------------------------------------------------------------
4700      // handle objects
4701
4702      // Get our active SimObject if any
4703      SimObject* simObj = NULL;
4704      if (item->isInspectorData())
4705      {
4706         simObj = item->getObject();
4707      }
4708
4709      // Remove from the old parentset
4710      if ((simObj && parentSet) && (oldParent != item->mParent))
4711      {
4712         if (mDebug)
4713            Con::printf("removing item from old parentset");
4714
4715         // hack to get around the way removeObject takes the last item of the set
4716         // and moves it into the place of the object we removed
4717         if (parentSet->size() > 0)
4718         {
4719            SimObject* lastObject = parentSet->last();
4720            parentSet->removeObject(simObj);
4721            parentSet->reOrder(lastObject);
4722         }
4723         else
4724         {
4725            parentSet->removeObject(simObj);
4726         }
4727      }
4728
4729      // Snag the newparent set if any...
4730      SimSet* newParentSet = NULL;
4731
4732      if (item->mParent->isInspectorData())
4733      {
4734         if (mDebug)
4735            Con::printf("getting a new parent set");
4736
4737         SimObject* tmpObj = item->mParent->getObject();
4738         newParentSet = dynamic_cast<SimSet*>(tmpObj);
4739      }
4740      else
4741      {
4742         // parent is probably script data so we search up the tree for a
4743         // set to put our object in
4744         if (mDebug)
4745            Con::printf("oh nos my parent is script!");
4746
4747         Item* temp = item->mParent;
4748         while (temp)
4749         {
4750            if (temp->isInspectorData())
4751               break;
4752            temp = temp->mParent;
4753         }
4754
4755         // found a ancestor who is an inspectorData
4756         if (temp)
4757         {
4758            if (temp->isInspectorData())
4759               newParentSet = dynamic_cast<SimSet*>(temp->getObject());
4760         }
4761         else
4762         {
4763            newParentSet = NULL;
4764         }
4765      }
4766
4767      if (simObj && newParentSet)
4768      {
4769         if (mDebug)
4770            Con::printf("simobj and new ParentSet");
4771
4772         if (oldParent != item->mParent)
4773            newParentSet->addObject(simObj);
4774
4775         //order the objects in the simset according to their
4776         //order in the tree view control
4777         if (!item->mNext)
4778         {
4779            if (item->mPrevious)
4780            {
4781               //bring to the end of the set
4782               SimObject* prevObject = item->mPrevious->getObject();
4783               if (prevObject && item->getObject())
4784               {
4785                  newParentSet->reOrder(item->getObject(), prevObject);
4786               }
4787            }
4788         }
4789         else
4790         {
4791            //reorder within the set
4792            SimObject* nextObject = item->mNext->getObject();
4793            if (nextObject && item->getObject())
4794            {
4795               newParentSet->reOrder(item->getObject(), nextObject);
4796            }
4797         }
4798      }
4799      else if (!simObj && newParentSet)
4800      {
4801         // our current item is script data. but it may have children who
4802         // is inspector data who need an updated set
4803         if (mDebug)
4804            Con::printf("no simobj but new parentSet");
4805         if (item->mChild)
4806            inspectorSearch(item->mChild, item, parentSet, newParentSet);
4807
4808      }
4809      else if (simObj && !newParentSet)
4810      {
4811         if (mDebug)
4812            Con::printf("simobject and no new parent set");
4813      }
4814      else
4815         if (mDebug)
4816            Con::printf("no simobject and no new parent set");
4817
4818      // Notify script.
4819
4820      if (item->isInspectorData())
4821      {
4822         if (item->getObject() && (oldParent && oldParent->getObject()) && item->mParent->getObject())
4823            onReparent_callback(
4824               item->getObject()->getId(),
4825               oldParent->getObject()->getId(),
4826               item->mParent->getObject()->getId()
4827            );
4828      }
4829      else
4830      {
4831         onReparent_callback(
4832            item->mId,
4833            oldParent->mId,
4834            item->mParent->mId
4835         );
4836      }
4837   }
4838}
4839
4840S32 GuiTreeViewCtrl::getTabLevel(S32 itemId)
4841{
4842   Item* item = getItem(itemId);
4843   if (item != nullptr)
4844   {
4845      return item->mTabLevel;
4846   }
4847
4848   return 0;
4849}
4850//=============================================================================
4851//    Console Methods.
4852//=============================================================================
4853// MARK: ---- Console Methods ----
4854
4855//-----------------------------------------------------------------------------
4856
4857DefineEngineMethod( GuiTreeViewCtrl, findItemByName, S32, ( const char* text ),,
4858   "Get the ID of the item whose text matches the given @a text.\n\n"
4859   "@param text Item text to match.\n"
4860   "@return ID of the item or -1 if no item matches the given text." )
4861{
4862   return object->findItemByName( text );
4863}
4864
4865//-----------------------------------------------------------------------------
4866
4867DefineEngineMethod( GuiTreeViewCtrl, findItemByValue, S32, ( const char* value ),,
4868   "Get the ID of the item whose value matches @a value.\n\n"
4869   "@param value Value text to match.\n"
4870   "@return ID of the item or -1 if no item has the given value." )
4871{
4872   return object->findItemByValue( value );
4873}
4874
4875//-----------------------------------------------------------------------------
4876
4877DefineEngineMethod( GuiTreeViewCtrl, findChildItemByName, S32, ( S32 parentId, const char* childName ),,
4878   "Get the child item of the given parent item whose text matches @a childName.\n\n"
4879   "@param parentId Item ID of the parent in which to look for the child.\n"
4880   "@param childName Text of the child item to find.\n"
4881   "@return ID of the child item or -1 if no child in @a parentId has the given text @a childName.\n\n"
4882   "@note This method does not recurse, i.e. it only looks for direct children." )
4883{
4884   if( parentId == 0 )
4885   {
4886      if( !object->getRootItem() )
4887         return 0;
4888         
4889      GuiTreeViewCtrl::Item* root = object->getRootItem();
4890      while( root )
4891      {
4892         if( dStricmp( root->getText(), childName ) == 0 )
4893            return root->getID();
4894            
4895         root = root->mNext;
4896      }
4897      
4898      return 0;
4899   }
4900   else
4901   {
4902      GuiTreeViewCtrl::Item* item = object->getItem( parentId );
4903      
4904      if( !item )
4905      {
4906         Con::errorf( "GuiTreeViewCtrl.findChildItemByName - invalid parent ID '%i'", parentId );
4907         return 0;
4908      }
4909      
4910      GuiTreeViewCtrl::Item* child = item->findChildByName( childName );
4911      if( !child )
4912         return 0;
4913      
4914      return child->mId;
4915   }
4916}
4917
4918//-----------------------------------------------------------------------------
4919
4920DefineEngineMethod( GuiTreeViewCtrl, insertItem, S32, ( S32 parentId, const char* text, const char* value, const char* icon, S32 normalImage, S32 expandedImage ), ( "", "", 0, 0 ),
4921   "Add a new item to the tree.\n\n"
4922   "@param parentId Item ID of parent to which to add the item as a child.  0 is root item.\n"
4923   "@param text Text to display on the item in the tree.\n"
4924   "@param value Behind-the-scenes value of the item.\n"
4925   "@param icon\n"
4926   "@param normalImage\n"
4927   "@param expandedImage\n"
4928   "@return The ID of the newly added item." )
4929{
4930   return object->insertItem( parentId, text, value, icon, normalImage, expandedImage );
4931}
4932
4933DefineEngineMethod( GuiTreeViewCtrl, insertObject, S32, ( S32 parentId, SimObject* obj, bool OKToEdit ), (false), "Inserts object as a child to the given parent." )
4934{
4935   return object->insertObject(parentId, obj, OKToEdit);
4936}
4937//-----------------------------------------------------------------------------
4938
4939DefineEngineMethod( GuiTreeViewCtrl, lockSelection, void, ( bool lock ), ( true ),
4940   "Set whether the current selection can be changed by the user or not.\n\n"
4941   "@param lock If true, the current selection is frozen and cannot be changed.  If false, "
4942      "the selection may be modified." )
4943{
4944   object->lockSelection( lock );
4945}
4946
4947//-----------------------------------------------------------------------------
4948
4949DefineEngineMethod( GuiTreeViewCtrl, hideSelection, void, ( bool state ), ( true ),
4950   "Call SimObject::setHidden( @a state ) on all objects in the current selection.\n\n"
4951   "@param state Visibility state to set objects in selection to." )
4952{
4953   object->hideSelection( state );
4954}
4955
4956//-----------------------------------------------------------------------------
4957
4958DefineEngineMethod( GuiTreeViewCtrl, toggleLockSelection, void, (),,
4959   "Toggle the locked state of all objects in the current selection." )
4960{
4961   object->toggleLockSelection();
4962
4963}
4964
4965//-----------------------------------------------------------------------------
4966
4967DefineEngineMethod( GuiTreeViewCtrl, toggleHideSelection, void, (),,
4968   "Toggle the hidden state of all objects in the current selection." )
4969{
4970   object->toggleHideSelection();
4971}
4972
4973//-----------------------------------------------------------------------------
4974
4975DefineEngineMethod( GuiTreeViewCtrl, clearSelection, void, (),,
4976   "Unselect all currently selected items." )
4977{
4978   object->clearSelection();
4979}
4980
4981//-----------------------------------------------------------------------------
4982
4983DefineEngineMethod( GuiTreeViewCtrl, deleteSelection, void, (),,
4984   "Delete all items/objects in the current selection." )
4985{
4986   object->deleteSelection();
4987}
4988
4989//-----------------------------------------------------------------------------
4990
4991DefineEngineMethod( GuiTreeViewCtrl, addSelection, void, ( S32 id, bool isLastSelection ), ( true ),
4992   "Add an item/object to the current selection.\n\n"
4993   "@param id ID of item/object to add to the selection.\n"
4994   "@param isLastSelection Whether there are more pending items/objects to be added to the selection.  If false, "
4995      "the control will defer refreshing the tree and wait until addSelection() is called with this parameter set "
4996      "to true." )
4997{
4998   object->addSelection( id, isLastSelection, isLastSelection );
4999}
5000
5001DefineEngineMethod( GuiTreeViewCtrl, addChildSelectionByValue, void, ( S32 parentId, const char* value), ,
5002   "Add a child selection by it's value.\n\n"
5003   "@param parentId Parent TreeItemId.\n"
5004   "@param value Value to search for.\n")
5005{
5006   GuiTreeViewCtrl::Item* parentItem = object->getItem(parentId);
5007   GuiTreeViewCtrl::Item* child = parentItem->findChildByValue(value);
5008   object->addSelection(child->getID());
5009}
5010
5011DefineEngineMethod( GuiTreeViewCtrl, removeSelection, void, ( S32 itemId), ,
5012   "Deselect an item or remove it from the selection.\n\n"
5013   "@param itemId Item Id to deselect.\n")
5014{
5015   object->removeSelection(itemId);
5016}
5017
5018DefineEngineMethod( GuiTreeViewCtrl, removeChildSelectionByValue, void, ( S32 parentId, const char* value), ,
5019   "Deselect a child item or remove it from the selection based on its parent and its value.\n\n"
5020   "@param parentId Parent TreeItemId.\n"
5021   "@param value Value to search for.\n"
5022   "@param performCallback True to notify script of the change, false to not.\n")
5023{
5024   GuiTreeViewCtrl::Item* parentItem = object->getItem(parentId);
5025   if(parentItem)
5026   {
5027      GuiTreeViewCtrl::Item* child = parentItem->findChildByValue(value);
5028     if(child)
5029     {
5030         object->removeSelection(child->getID());
5031     }
5032   }
5033}
5034
5035DefineEngineMethod( GuiTreeViewCtrl, selectItem, bool, ( S32 itemID, bool select), (true) ,
5036   "Select or deselect and item.\n\n"
5037   "@param itemID TreeItemId of item to select or deselect.\n"
5038   "@param select True to select the item, false to deselect it.\n"
5039   "@return True if it was successful, false if not.")
5040{
5041   return object->setItemSelected(itemID, select);
5042}
5043
5044DefineEngineMethod( GuiTreeViewCtrl, expandItem, bool, ( S32 itemID, bool expand), (true) ,
5045   "Expand/contract item, item's sub-tree.\n\n"
5046   "@param itemID TreeItemId of item to expand or contract.\n"
5047   "@param expand True to expand the item, false to contract it.\n"
5048   "@return True if it was successful, false if not.")
5049{
5050   return(object->setItemExpanded(itemID, expand));
5051}
5052
5053DefineEngineMethod( GuiTreeViewCtrl, markItem, bool, ( S32 itemID, bool mark), (true) ,
5054   "Mark/unmark item.\n\n"
5055   "@param itemID TreeItemId of item to Mark or unmark.\n"
5056   "@param mark True to Mark the item, false to unmark it.\n"
5057   "@return True if it was successful, false if not.")
5058{
5059   return object->markItem(itemID, mark);
5060}
5061
5062DefineEngineMethod( GuiTreeViewCtrl, scrollVisible, bool, ( S32 itemID), ,
5063   "Make the given item visible.\n\n"
5064   "@param itemID TreeItemId of item to scroll to/make visible.\n"
5065   "@return True if it was successful, false if not.")
5066{
5067   return object->scrollVisible(itemID);
5068}
5069
5070DefineEngineMethod( GuiTreeViewCtrl, buildIconTable, bool, ( const char* icons), ,
5071   "Builds an icon table.\n\n"
5072   "@param icons Name of icons to build, Icons should be designated by the bitmap/png file names (minus the file extensions)"
5073   "and separated by colons (:). This list should be synchronized with the Icons enum\n"
5074   "@return True if it was successful, false if not.")
5075{
5076   return object->buildIconTable(icons);
5077}
5078
5079DefineEngineMethod( GuiTreeViewCtrl, open, void, ( const char * objName, bool okToEdit), (true),
5080   "Set the root of the tree view to the specified object, or to the root set.\n\n"
5081   "@param objName Name or id of SimSet or object to set the tree root equal to.\n")
5082{
5083   SimSet *treeRoot = NULL;
5084   SimObject* target = Sim::findObject(objName);
5085
5086
5087   if (target)
5088      treeRoot = dynamic_cast<SimSet*>(target);
5089
5090   if (! treeRoot)
5091      Sim::findObject(RootGroupId, treeRoot);
5092
5093   object->inspectObject(treeRoot,okToEdit);
5094}
5095
5096DefineEngineMethod( GuiTreeViewCtrl, setItemTooltip, bool, ( S32 itemId, const char* tooltip), ,
5097   "Set the tooltip to show for the given item.\n\n"
5098   "@param itemId  TreeItemID of item to set the tooltip for.\n"
5099   "@param tooltip   String tooltip to set for the item."
5100   "@return True if successfully found the item, false if not")
5101{
5102   GuiTreeViewCtrl::Item* item = object->getItem( itemId );
5103   if( !item )
5104   {
5105      Con::errorf( "GuiTreeViewCtrl::setTooltip() - invalid item id '%i'", itemId );
5106      return false;
5107   }
5108
5109   item->mTooltip = tooltip;
5110
5111   return true;
5112}
5113
5114DefineEngineMethod( GuiTreeViewCtrl, setItemImages, void, ( S32 itemId, S8 normalImage, S8 expandedImage ), ,
5115   "Sets the normal and expanded images to show for the given item.\n\n"
5116   "@param itemId TreeItemID of item to set images for.\n"
5117   "@param normalImage Normal image to set for the given item."
5118   "@param expandedImage Expanded image to set for the given item.")
5119{
5120
5121   GuiTreeViewCtrl::Item* item = object->getItem( itemId );
5122   if( !item )
5123   {
5124      Con::errorf( "GuiTreeViewCtrl::setItemImages() - invalid item id '%i'", itemId );
5125      return;
5126   }
5127
5128   item->setNormalImage(normalImage);
5129   item->setExpandedImage(expandedImage);
5130}
5131
5132DefineEngineMethod( GuiTreeViewCtrl, isParentItem, bool, ( S32 itemId ), ,
5133   "Returns true if the given item contains child items.\n\n"
5134   "@param itemId TreeItemID to check for children.\n"
5135   "@return True if the given item contains child items, false if not.")
5136{
5137   if( !itemId && object->getItemCount() )
5138      return true;
5139   
5140   GuiTreeViewCtrl::Item* item = object->getItem( itemId );
5141   if( !item )
5142   {
5143      Con::errorf( "GuiTreeViewCtrl::isParentItem - invalid item id '%i'", itemId );
5144      return false;
5145   }
5146   
5147   return item->isParent();
5148}
5149
5150DefineEngineMethod( GuiTreeViewCtrl, getItemText, const char *, ( S32 itemId ), ,
5151   "Gets the text for a given item.\n\n"
5152   "@param itemId TreeItemID to get text of.\n"
5153   "@return Text for a given item.")
5154{
5155   return(object->getItemText(itemId));
5156}
5157
5158DefineEngineMethod( GuiTreeViewCtrl, getItemValue, const char *, ( S32 itemId ), ,
5159   "Gets the value for a given item.\n\n"
5160   "@param itemId TreeItemID to get value of.\n"
5161   "@return Value for a given item.")
5162{
5163   return object->getItemValue(itemId);
5164}
5165
5166DefineEngineMethod( GuiTreeViewCtrl, editItem, bool, ( S32 itemId, const char* newText, const char* newValue ), ,
5167   "Edits the text and value for a given tree item.\n\n"
5168   "@param itemId TreeItemID to edit.\n"
5169   "@return True if successful, false if not.")
5170{
5171   return(object->editItem(itemId, newText, newValue));
5172}
5173
5174DefineEngineMethod( GuiTreeViewCtrl, removeItem, bool, (S32 itemId, bool deleteObjects), (0, true),
5175   "Remove an item from the tree with the given id.\n\n"
5176   "@param itemId TreeItemID of item to remove.\n"
5177   "@param deleteObjects Whether the object on the item is deleted when the item is.\n"
5178   "@return True if successful, false if not.")
5179{
5180   return(object->removeItem(itemId, deleteObjects));
5181}
5182
5183DefineEngineMethod( GuiTreeViewCtrl, removeAllChildren, void, (S32 itemId), ,
5184   "Remove all children of an item from the tree with the given id.\n\n"
5185   "@param itemId TreeItemID of item that has children we should remove.\n")
5186{
5187   object->removeAllChildren(itemId);
5188}
5189
5190DefineEngineMethod( GuiTreeViewCtrl, clear, void, (), ,
5191   "Empty the tree.\n")
5192{
5193   object->removeItem(0);
5194}
5195
5196DefineEngineMethod( GuiTreeViewCtrl, getFirstRootItem, S32, (), ,
5197   "Get id for root item.\n"
5198   "@return Id for root item.")
5199{
5200   return(object->getFirstRootItem());
5201}
5202
5203DefineEngineMethod( GuiTreeViewCtrl, getChild, S32, (S32 itemId), ,
5204   "Get the child of the parent with the given id.\n\n"
5205   "@param itemId TreeItemID of item that a child we should get.\n"
5206   "@return Id of child of given item.")
5207{
5208   return(object->getChildItem(itemId));
5209}
5210
5211DefineEngineMethod( GuiTreeViewCtrl, buildVisibleTree, void, (bool forceFullUpdate), (false),
5212   "Build the visible tree.\n\n"
5213   "@param forceFullUpdate True to force a full update of the tree, false to only update the new stuff.\n")
5214{      
5215   object->buildVisibleTree( forceFullUpdate );
5216}
5217
5218//FIXME: [rene 11/09/09 - This clashes with GuiControl.getParent(); bad thing; should be getParentItem]
5219DefineEngineMethod( GuiTreeViewCtrl, getParentItem, S32, (S32 itemId), ,
5220   "Get the parent of a given id in the tree.\n\n"
5221   "@param itemId TreeItemID of item that has a parent we should get.\n"
5222   "@return Id of parent of given item.")
5223{      
5224   return(object->getParentItem(itemId));
5225}
5226
5227DefineEngineMethod( GuiTreeViewCtrl, getNextSibling, S32, (S32 itemId), ,
5228   "Get the next sibling of the given item id in the tree.\n\n"
5229   "@param itemId TreeItemID of item that we want the next sibling of.\n"
5230   "@return Id of next sibling of the given item.")
5231{      
5232   return(object->getNextSiblingItem(itemId));
5233}
5234
5235DefineEngineMethod( GuiTreeViewCtrl, getPrevSibling, S32, (S32 itemId), ,
5236   "Get the previous sibling of the given item id in the tree.\n\n"
5237   "@param itemId TreeItemID of item that we want the previous sibling of.\n"
5238   "@return Id of previous sibling of the given item.")
5239{      
5240   return(object->getPrevSiblingItem(itemId));
5241}
5242
5243DefineEngineMethod( GuiTreeViewCtrl, getItemCount, S32, (), ,
5244   "Get the total number of items in the tree or item count.\n\n"
5245   "@return total number of items in the tree.")
5246{      
5247   return(object->getItemCount());
5248}
5249
5250DefineEngineMethod( GuiTreeViewCtrl, getSelectedItem, S32, (S32 index), (0),
5251   "Return the selected item at the given index.\n\n"
5252   "@param index Given index to look for selected item."
5253   "@return selected item at the given index.")
5254{
5255   return ( object->getSelectedItem( index ) );
5256}
5257
5258DefineEngineMethod( GuiTreeViewCtrl, getSelectedObject, S32, (S32 index), (0),
5259   "Return the currently selected SimObject at the given index in inspector mode or -1.\n\n"
5260   "@param index Given index to look for selected object."
5261   "@return currently selected SimObject at the given index in inspector mode or -1.")
5262{
5263   GuiTreeViewCtrl::Item *item = object->getItem( object->getSelectedItem( index ) );
5264   if( item != NULL && item->isInspectorData() )
5265   {
5266      SimObject *obj = item->getObject();
5267      if( obj != NULL )
5268         return obj->getId();
5269   }
5270
5271   return -1;
5272}
5273
5274const char* GuiTreeViewCtrl::getSelectedObjectList()
5275{
5276   static const U32 bufSize = 1024;
5277   char* buff = Con::getReturnBuffer(bufSize);
5278   dSprintf(buff,bufSize,"");
5279
5280
5281   const Vector< GuiTreeViewCtrl::Item*> selectedItems = this->getSelectedItems();
5282   for(S32 i = 0; i < selectedItems.size(); i++)
5283   {
5284      GuiTreeViewCtrl::Item *item = selectedItems[i];
5285
5286      if ( item->isInspectorData() && item->getObject() )
5287      {      
5288         S32 id  = item->getObject()->getId();
5289         //get the current length of the buffer
5290         U32   len = dStrlen(buff);
5291         //the start of the buffer where we want to write
5292         char* buffPart = buff+len;
5293         //the size of the remaining buffer (-1 cause dStrlen doesn't count the \0)
5294         S32 size =  bufSize-len-1;
5295         //write it:
5296         if(size < 1)
5297         {
5298            Con::errorf("GuiTreeViewCtrl::getSelectedItemList - Not enough room to return our object list");
5299            return buff;
5300         }
5301
5302         dSprintf(buffPart,size,"%d ", id);
5303      }
5304   }
5305
5306   return buff;
5307}
5308
5309DefineEngineMethod( GuiTreeViewCtrl, getSelectedObjectList, const char*, (), ,
5310   "Returns a space separated list of all selected object ids.\n\n"
5311   "@return space separated list of all selected object ids.")
5312{
5313   return object->getSelectedObjectList();
5314}
5315
5316DefineEngineMethod( GuiTreeViewCtrl, moveItemUp, void, (S32 itemId), ,
5317   "Move the specified item up in the tree.\n\n"
5318   "@param itemId TreeItemId of item to move up in the tree.")
5319{
5320   object->moveItemUp( itemId );
5321}
5322
5323DefineEngineMethod( GuiTreeViewCtrl, getSelectedItemsCount, S32, (), ,
5324   "Get the selected number of items.\n\n"
5325   "@return number of selected items.")
5326{
5327   return ( object->getSelectedItemsCount() );
5328}
5329
5330DefineEngineMethod( GuiTreeViewCtrl, moveItemDown, void, (S32 itemId), ,
5331   "Move the specified item down in the tree.\n\n"
5332   "@param itemId TreeItemId of item to move down in the tree.")
5333{
5334   object->moveItemDown( itemId );
5335}
5336
5337//-----------------------------------------------------------------------------
5338
5339DefineEngineMethod( GuiTreeViewCtrl, getTextToRoot, const char*, (S32 itemId, const char* delimiter), (""),
5340   "Gets the text from the current node to the root, concatenating at each branch upward, with a specified delimiter optionally.\n\n"
5341   "@param itemId TreeItemId of node to start at."
5342   "@param delimiter (Optional) delimiter to use between each branch concatenation."
5343   "@return text from the current node to the root.")
5344{
5345   if (!String::compare(delimiter, "" ))
5346   {
5347      Con::warnf("GuiTreeViewCtrl::getTextToRoot - Invalid number of arguments!");
5348      return ("");
5349   }
5350   return object->getTextToRoot( itemId, delimiter );
5351}
5352
5353DefineEngineMethod( GuiTreeViewCtrl, getSelectedItemList, const char*, (), ,
5354   "Returns a space separated list if ids of all selected items.\n\n"
5355   "@return space separated list of selected item ids.")
5356{
5357   const U32 bufSize = 1024;
5358   char* buff = Con::getReturnBuffer(bufSize);
5359   dSprintf(buff, bufSize, "");
5360
5361   const Vector< S32>& selected = object->getSelected();
5362   for(int i = 0; i < selected.size(); i++)
5363   {
5364      S32 id  = selected[i];
5365      //get the current length of the buffer
5366      U32   len = dStrlen(buff);
5367      //the start of the buffer where we want to write
5368      char* buffPart = buff+len;
5369      //the size of the remaining buffer (-1 cause dStrlen doesn't count the \0)
5370      S32 size =  bufSize-len-1;
5371      //write it:
5372      if(size < 1)
5373      {
5374         Con::errorf("GuiTreeViewCtrl::getSelectedItemList - Not enough room to return our object list");
5375         return buff;
5376      }
5377
5378      dSprintf(buffPart,size,"%d ", id);
5379   }
5380//mSelected
5381
5382   return buff;
5383}
5384
5385S32 GuiTreeViewCtrl::findItemByObjectId(S32 iObjId)
5386{  
5387   for (S32 i = 0; i < mItems.size(); i++)
5388   {    
5389      if ( !mItems[i] )
5390         continue;
5391
5392      SimObject* pObj = mItems[i]->getObject();
5393      if( pObj && pObj->getId() == iObjId )
5394         return mItems[i]->mId;
5395   }
5396
5397   return -1;
5398}
5399
5400//------------------------------------------------------------------------------
5401DefineEngineMethod( GuiTreeViewCtrl, findItemByObjectId, S32, (S32 objectId), ,
5402   "Find an item by its object id and returns the Tree Item ID for it.\n\n"
5403   "@param objectId  Object id you want the item id for."
5404   "@return Tree Item Id for the given object ID.")
5405{
5406   return(object->findItemByObjectId(objectId));
5407}
5408
5409//------------------------------------------------------------------------------
5410S32 GuiTreeViewCtrl::getItemObject(S32 itemId)
5411{
5412   GuiTreeViewCtrl::Item* item = getItem(itemId);
5413   if (!item)
5414   {
5415      return 0;
5416   }
5417
5418   SimObject* pObj = item->getObject();
5419   if (pObj)
5420      return pObj->getId();
5421
5422   return 0;
5423}
5424
5425//------------------------------------------------------------------------------
5426DefineEngineMethod(GuiTreeViewCtrl, getItemObject, S32, (S32 itemId), ,
5427   "Gets the object for a particular item.\n\n"
5428   "@param itemId  Item id you want the object id for."
5429   "@return Object Id for the given tree item ID.")
5430{
5431   return(object->getItemObject(itemId));
5432}
5433
5434//------------------------------------------------------------------------------
5435bool GuiTreeViewCtrl::scrollVisibleByObjectId(S32 objID)
5436{
5437   S32 itemID = findItemByObjectId(objID);
5438
5439   if(itemID == -1)
5440   {
5441      // we did not find the item in our current items
5442      // we should try to find and show the parent of the item.
5443      SimObject *obj = Sim::findObject(objID);
5444      if(!obj || !obj->getGroup())
5445         return false;
5446    
5447      // if we can't show the parent, we fail.
5448      if(! scrollVisibleByObjectId(obj->getGroup()->getId()) )
5449         return false;
5450      
5451      // get the parent. expand the parent. rebuild the tree. this ensures that
5452      // we'll be able to find the child item we're targeting.
5453      S32 parentID = findItemByObjectId(obj->getGroup()->getId());
5454      AssertFatal(parentID != -1, "We were able to show the parent, but could not then find the parent. This should not happen.");
5455      Item *parentItem = getItem(parentID);
5456      parentItem->setExpanded(true);
5457      buildVisibleTree();
5458      
5459      // NOW we should be able to find the object. if not... something's wrong.
5460      itemID = findItemByObjectId(objID);
5461      AssertWarn(itemID != -1,"GuiTreeViewCtrl::scrollVisibleByObjectId() found the parent, but can't find it's immediate child. This should not happen.");
5462      if(itemID == -1)
5463         return false;
5464   }
5465   
5466   // ok, item found. scroll to it.
5467   mFlags.set( RebuildVisible );
5468   scrollVisible(itemID);
5469   
5470   return true;
5471}
5472
5473//------------------------------------------------------------------------------
5474DefineEngineMethod( GuiTreeViewCtrl, scrollVisibleByObjectId, S32, (S32 objectId), ,
5475   "Show item by object id.\n\n"
5476   "@param objectId  Object id you want to scroll to."
5477   "@return True if successful, false if not.")
5478{
5479   return(object->scrollVisibleByObjectId(objectId));
5480}
5481
5482//------------------------------------------------------------------------------
5483
5484//FIXME: this clashes with SimSet.sort()
5485DefineEngineMethod( GuiTreeViewCtrl, sort, void, (S32 parentId, bool traverseHierarchy, bool parentsFirst, bool caseSensitive), (0, false, false, true),
5486   "Sorts all items of the given parent (or root).  With 'hierarchy', traverses hierarchy."
5487   "@param parentId  TreeItemID of parent/root to sort all the items under. Use 0 to sort the entire tree."
5488   "@param traverseHierarchy True to traverse the hierarchy, false to not."
5489   "@param parentsFirst True to sort the parents first."
5490   "@param caseSensitive True to pay attention to case, false to ignore it.")
5491{
5492      
5493   if( !parentId )
5494      object->sortTree( caseSensitive, traverseHierarchy, parentsFirst );
5495   else
5496   {
5497      GuiTreeViewCtrl::Item* item = object->getItem( parentId );
5498      if( !item )
5499      {
5500         Con::errorf( "GuiTreeViewCtrl::sort - no item '%i' in tree", parentId );
5501         return;
5502      }
5503      
5504      item->sort( caseSensitive, traverseHierarchy, parentsFirst );
5505   }
5506}
5507
5508void GuiTreeViewCtrl::cancelRename()
5509{
5510   if ( !mRenamingItem || !mRenameCtrl )
5511      return;
5512
5513   mRenamingItem = NULL;  
5514
5515   if ( mRenameCtrl )
5516      mRenameCtrl->clearFirstResponder();
5517}
5518
5519void GuiTreeViewCtrl::onRenameValidate()
5520{
5521   if ( !mRenamingItem || !mRenameCtrl )
5522      return;
5523
5524   char data[ GuiTextCtrl::MAX_STRING_LENGTH+1 ];
5525   mRenameCtrl->getText( data );
5526
5527   SimObject *obj = mRenamingItem->getObject();
5528
5529   mRenamingItem = NULL;  
5530
5531   // Object could have been deleted in the interum.
5532   if ( !obj )
5533      return;
5534   
5535   if( isMethod( "handleRenameObject" ) && handleRenameObject_callback( data, obj ) )
5536      return;
5537
5538   if ( mRenameInternal )
5539      obj->setInternalName( data );   
5540   else
5541#ifdef TORQUE_TOOLS
5542   if ( validateObjectName( data, obj ) )
5543#endif
5544      obj->assignName( data ); 
5545}
5546
5547void GuiTreeViewCtrl::showItemRenameCtrl( Item* item )
5548{
5549   SimObject *renameObj = item->getObject();
5550   
5551   mRenamingItem = item;
5552   
5553   if ( !mRenameCtrl )
5554   {
5555      mRenameCtrl = new GuiTextEditCtrl;
5556      mRenameCtrl->registerObject();
5557      addObject( mRenameCtrl );        
5558      
5559      if ( mRenameInternal )
5560         mRenameCtrl->setText( renameObj->getInternalName() );
5561      else
5562         mRenameCtrl->setText( renameObj->getName() );
5563
5564      mRenameCtrl->setFirstResponder();
5565      mRenameCtrl->setSinkAllKeys(true);
5566      mRenameCtrl->selectAllText();
5567      mRenameCtrl->setCursorPos(0);
5568      
5569      char cmd[256];
5570      dSprintf( cmd, 256, "%i.onRenameValidate();", getId() );
5571      mRenameCtrl->setField( "validate", cmd );
5572
5573      dSprintf( cmd, 256, "%i.cancelRename();", getId() );
5574      mRenameCtrl->setField( "escapeCommand", cmd );
5575   }
5576}
5577
5578DefineEngineMethod( GuiTreeViewCtrl, cancelRename, void, (), , "Cancel renaming an item (For internal use).")
5579{
5580   object->cancelRename();
5581}
5582
5583DefineEngineMethod( GuiTreeViewCtrl, onRenameValidate, void, (), , "Validate the new name for an object (For internal use).")
5584{
5585   object->onRenameValidate();
5586}
5587
5588DefineEngineMethod( GuiTreeViewCtrl, showItemRenameCtrl, void, (S32 itemId), ,
5589   "Show the rename text field for the given item (only one at a time)."
5590   "@param itemId TreeItemId of item to show rename text field for.")
5591{
5592   GuiTreeViewCtrl::Item* item = object->getItem( itemId );
5593   if( !item )
5594   {
5595      Con::errorf( "GuiTreeViewCtrl::showItemRenameCtrl - invalid item id '%i'", itemId );
5596      return;
5597   }
5598   
5599   object->showItemRenameCtrl( item );
5600}
5601
5602DefineEngineMethod( GuiTreeViewCtrl, setDebug, void, (bool value), (true),
5603   "Enable/disable debug output."
5604   "@param value True to enable debug output, false to disable it.")
5605{
5606      
5607   object->setDebug( value );
5608}
5609
5610//-----------------------------------------------------------------------------
5611
5612DefineEngineMethod( GuiTreeViewCtrl, isItemSelected, bool, ( S32 id ),,
5613   "Check whether the given item is currently selected in the tree.\n\n"
5614   "@param id Item/object ID.\n"
5615   "@return True if the given item/object is currently selected in the tree." )
5616{
5617   const Vector< GuiTreeViewCtrl::Item*>& selectedItems = object->getSelectedItems();
5618   for( S32 i = 0; i < selectedItems.size(); ++ i )
5619      if( selectedItems[ i ]->mId == id )
5620         return true;
5621         
5622   return false;
5623}
5624
5625//-----------------------------------------------------------------------------
5626
5627DefineEngineMethod( GuiTreeViewCtrl, getFilterText, const char*, (),,
5628   "Get the current filter expression.  Only tree items whose text matches this expression "
5629   "are displayed.  By default, the expression is empty and all items are shown.\n\n"
5630   "@return The current filter pattern or an empty string if no filter pattern is currently active.\n\n"
5631   "@see setFilterText\n"
5632   "@see clearFilterText" )
5633{
5634   return object->getFilterText();
5635}
5636
5637//-----------------------------------------------------------------------------
5638
5639DefineEngineMethod( GuiTreeViewCtrl, setFilterText, void, ( const char* pattern ),,
5640   "Set the pattern by which to filter items in the tree.  Only items in the tree whose text "
5641   "matches this pattern are displayed.\n\n"
5642   "@param pattern New pattern based on which visible items in the tree should be filtered.  If empty, all items become visible.\n\n"
5643   "@see getFilterText\n"
5644   "@see clearFilterText" )
5645{
5646   object->setFilterText( pattern );
5647}
5648
5649DefineEngineMethod(GuiTreeViewCtrl, setFilterChildren, void, (bool doFilterChildren), (true),
5650   "Set the pattern by which to filter items in the tree.  Only items in the tree whose text "
5651   "matches this pattern are displayed.\n\n"
5652   "@param pattern New pattern based on which visible items in the tree should be filtered.  If empty, all items become visible.\n\n"
5653   "@see getFilterText\n"
5654   "@see clearFilterText")
5655{
5656   object->setFilterChildren(doFilterChildren);
5657}
5658
5659DefineEngineMethod(GuiTreeViewCtrl, setItemFilterException, void, (U32 item, bool isExempt), (0, true),
5660   "Set the pattern by which to filter items in the tree.  Only items in the tree whose text "
5661   "matches this pattern are displayed.\n\n"
5662   "@param pattern New pattern based on which visible items in the tree should be filtered.  If empty, all items become visible.\n\n"
5663   "@see getFilterText\n"
5664   "@see clearFilterText")
5665{
5666   object->setItemFilterException(item, isExempt);
5667}
5668
5669DefineEngineMethod(GuiTreeViewCtrl, setItemHidden, void, (U32 item, bool hidden), (0, true),
5670   "Set the pattern by which to filter items in the tree.  Only items in the tree whose text "
5671   "matches this pattern are displayed.\n\n"
5672   "@param pattern New pattern based on which visible items in the tree should be filtered.  If empty, all items become visible.\n\n"
5673   "@see getFilterText\n"
5674   "@see clearFilterText")
5675{
5676   object->setItemHidden(item, hidden);
5677}
5678
5679DefineEngineMethod(GuiTreeViewCtrl, clearHiddenItems, void, (),,
5680   "Set the pattern by which to filter items in the tree.  Only items in the tree whose text "
5681   "matches this pattern are displayed.\n\n"
5682   "@param pattern New pattern based on which visible items in the tree should be filtered.  If empty, all items become visible.\n\n"
5683   "@see getFilterText\n"
5684   "@see clearFilterText")
5685{
5686   object->clearHiddenItems();
5687}
5688//-----------------------------------------------------------------------------
5689
5690DefineEngineMethod( GuiTreeViewCtrl, clearFilterText, void, (),,
5691   "Clear the current item filtering pattern.\n\n"
5692   "@see setFilterText\n"
5693   "@see getFilterText" )
5694{
5695   object->clearFilterText();
5696}
5697
5698DefineEngineMethod(GuiTreeViewCtrl, getItemAtPosition, S32, (Point2I position), (Point2I::Zero),
5699   "Get the tree item at the passed in position.\n\n"
5700   "@param position The position to check for what item is below it.\n"
5701   "@return The id of the item under the position.")
5702{
5703   return object->getItemAtPosition(position);
5704}
5705
5706DefineEngineMethod(GuiTreeViewCtrl, reparentItem, void, (S32 itemId, S32 parentId), (0, 0),
5707   "Check whether the given item is currently selected in the tree.\n\n"
5708   "@param id Item/object ID.\n"
5709   "@return True if the given item/object is currently selected in the tree.")
5710{
5711   if (itemId == parentId || itemId < 0 || parentId < 0)
5712      return;
5713
5714   const Vector< GuiTreeViewCtrl::Item*> & selectedItems = object->getItems();
5715   Vector<GuiTreeViewCtrl::Item*> items;
5716   GuiTreeViewCtrl::Item * parent = nullptr;
5717
5718   for (S32 i = 0; i < selectedItems.size(); ++i)
5719   {
5720      if (selectedItems[i]->mId == itemId)
5721      {
5722         items.push_back(selectedItems[i]);
5723      }
5724
5725      if (selectedItems[i]->mId == parentId)
5726      {
5727         parent = selectedItems[i];
5728      }
5729   }
5730
5731   if (!items.empty() && parent != nullptr)
5732   {
5733      object->reparentItems(items, parent);
5734   }
5735}
5736
5737DefineEngineMethod(GuiTreeViewCtrl, getTabLevel, S32, (S32 itemId), (0),
5738   "Get the tree item at the passed in position.\n\n"
5739   "@param position The position to check for what item is below it.\n"
5740   "@return The id of the item under the position.")
5741{
5742   return object->getTabLevel(itemId);
5743}
5744