ソースを参照

Updates to the GuiListBoxCtrl

This updates the GuiListBoxCtrl to use advanced profiles. Each item now applies borders and background. This also adds a few callbacks.
Peter Robinson 4 年 前
コミット
a991669a33

+ 1 - 0
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj

@@ -1166,6 +1166,7 @@
     <ClInclude Include="..\..\source\gui\guiDefaultControlRender.h" />
     <ClInclude Include="..\..\source\gui\guiDefaultControlRender.h" />
     <ClInclude Include="..\..\source\gui\guiInputCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiInputCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiListBoxCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiListBoxCtrl.h" />
+    <ClInclude Include="..\..\source\gui\guiListBoxCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\guiMessageVectorCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiMessageVectorCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiMLTextCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiMLTextCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiMLTextEditCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiMLTextEditCtrl.h" />

+ 3 - 0
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters

@@ -3322,6 +3322,9 @@
     <ClInclude Include="..\..\source\gui\containers\guiWindowCtrl_ScriptBinding.h">
     <ClInclude Include="..\..\source\gui\containers\guiWindowCtrl_ScriptBinding.h">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="..\..\source\gui\guiListBoxCtrl_ScriptBinding.h">
+      <Filter>gui</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Torque 2D.rc" />
     <ResourceCompile Include="Torque 2D.rc" />

+ 0 - 5
engine/source/gui/guiControl.cc

@@ -482,7 +482,6 @@ void GuiControl::onRender(Point2I offset, const RectI &updateRect)
 
 
 RectI GuiControl::applyMargins(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 RectI GuiControl::applyMargins(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 {
 {
-
 	//Get the border profiles
 	//Get the border profiles
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
@@ -499,7 +498,6 @@ RectI GuiControl::applyMargins(Point2I offset, Point2I extent, GuiControlState c
 
 
 RectI GuiControl::applyBorders(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 RectI GuiControl::applyBorders(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 {
 {
-
 	//Get the border profiles
 	//Get the border profiles
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
@@ -516,7 +514,6 @@ RectI GuiControl::applyBorders(Point2I offset, Point2I extent, GuiControlState c
 
 
 RectI GuiControl::applyPadding(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 RectI GuiControl::applyPadding(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 {
 {
-
 	//Get the border profiles
 	//Get the border profiles
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
@@ -533,7 +530,6 @@ RectI GuiControl::applyPadding(Point2I offset, Point2I extent, GuiControlState c
 
 
 RectI GuiControl::getInnerRect(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 RectI GuiControl::getInnerRect(Point2I offset, Point2I extent, GuiControlState currentState, GuiControlProfile *profile)
 {
 {
-
 	//Get the border profiles
 	//Get the border profiles
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
@@ -550,7 +546,6 @@ RectI GuiControl::getInnerRect(Point2I offset, Point2I extent, GuiControlState c
 
 
 Point2I GuiControl::getOuterExtent(Point2I innerExtent, GuiControlState currentState, GuiControlProfile *profile)
 Point2I GuiControl::getOuterExtent(Point2I innerExtent, GuiControlState currentState, GuiControlProfile *profile)
 {
 {
-
 	//Get the border profiles
 	//Get the border profiles
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *leftProfile = profile->getLeftBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();
 	GuiBorderProfile *rightProfile = profile->getRightBorder();

+ 1 - 1
engine/source/gui/guiControl.h

@@ -348,7 +348,7 @@ public:
 
 
     /// Adds an object as a child of this object.
     /// Adds an object as a child of this object.
     /// @param   obj   New child object of this control
     /// @param   obj   New child object of this control
-    void addObject(SimObject *obj);
+    virtual void addObject(SimObject *obj);
 
 
     /// Removes a child object from this control.
     /// Removes a child object from this control.
     /// @param   obj Object to remove from this control
     /// @param   obj Object to remove from this control

+ 145 - 472
engine/source/gui/guiListBoxCtrl.cc

@@ -20,6 +20,9 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 #include "gui/guiListBoxCtrl.h"
 #include "gui/guiListBoxCtrl.h"
+#include "gui/guiCanvas.h"
+
+#include "guiListBoxCtrl_ScriptBinding.h"
 
 
 IMPLEMENT_CONOBJECT(GuiListBoxCtrl);
 IMPLEMENT_CONOBJECT(GuiListBoxCtrl);
 
 
@@ -31,6 +34,10 @@ GuiListBoxCtrl::GuiListBoxCtrl()
    mFitParentWidth = true;
    mFitParentWidth = true;
    mItemSize = Point2I(10,20);
    mItemSize = Point2I(10,20);
    mLastClickItem = NULL;
    mLastClickItem = NULL;
+   mIsContainer = false;
+   mActive = true;
+
+   setField("profile", "GuiListBoxProfile");
 }
 }
 
 
 GuiListBoxCtrl::~GuiListBoxCtrl()
 GuiListBoxCtrl::~GuiListBoxCtrl()
@@ -56,23 +63,12 @@ bool GuiListBoxCtrl::onWake()
    return true;
    return true;
 }
 }
 
 
-//////////////////////////////////////////////////////////////////////////
-// Item Accessors
-//////////////////////////////////////////////////////////////////////////
-ConsoleMethod( GuiListBoxCtrl, setMultipleSelection, void, 3, 3, "(bool setMS) Set the MultipleSelection field.\n"
-              "@return No return value.\n"
-              "@note %listBox.setMultipleSelection([true/false])")
-{
-   object->setMultipleSelection( dAtob( argv[2] ) );
-}
-
-
-ConsoleMethod( GuiListBoxCtrl, clearItems, void, 2, 2, "() Clears all the items in the listbox\n" 
-              "@return No return value.")
+void GuiListBoxCtrl::addObject(SimObject *obj)
 {
 {
-   object->clearItems();
+	AssertWarn(0, "GuiListBoxCtrl::addObject: cannot add children to the GuiListBoxCtrl. It is not a container. Child was not added.");
 }
 }
 
 
+#pragma region ItemAccessors
 void GuiListBoxCtrl::clearItems()
 void GuiListBoxCtrl::clearItems()
 {
 {
    // Free item list allocated memory
    // Free item list allocated memory
@@ -84,12 +80,6 @@ void GuiListBoxCtrl::clearItems()
    mSelectedItems.clear();
    mSelectedItems.clear();
 }
 }
 
 
-
-ConsoleMethod( GuiListBoxCtrl, clearSelection, void, 2, 2, "() Sets all currently selected items to unselected\n"
-              "@return No return value.")
-{
-   object->clearSelection();
-}
 void GuiListBoxCtrl::clearSelection()
 void GuiListBoxCtrl::clearSelection()
 {
 {
    if( !mSelectedItems.size() )
    if( !mSelectedItems.size() )
@@ -102,22 +92,6 @@ void GuiListBoxCtrl::clearSelection()
    mSelectedItems.clear();
    mSelectedItems.clear();
 }
 }
 
 
-
-ConsoleMethod( GuiListBoxCtrl, setSelected, void, 3, 4, "(S32 index, bool setting) Sets the item at the index specified to selected or not"
-              "@param index The index of the item you wish to modify.\n"
-              "@param setting A boolean value. True sets it as selected; false, not selected.\n"
-              "@return No return value.")
-{
-   bool value = true;
-   if( argc == 4 )
-      value = dAtob( argv[3] );
-
-   if( value == true )
-      object->addSelection( dAtoi( argv[2] ) );
-   else
-      object->removeSelection( dAtoi( argv[2] ) );
-}
-
 void GuiListBoxCtrl::removeSelection( S32 index )
 void GuiListBoxCtrl::removeSelection( S32 index )
 {
 {
    // Range Check
    // Range Check
@@ -189,7 +163,8 @@ void GuiListBoxCtrl::addSelection( LBItem *item, S32 index )
    item->isSelected = true;
    item->isSelected = true;
    mSelectedItems.push_front( item );
    mSelectedItems.push_front( item );
 
 
-   Con::executef(this, 3, "onSelect", Con::getIntArg( index ), item->itemText);
+   if(isMethod("onSelect"))
+		Con::executef(this, 3, "onSelect", Con::getIntArg( index ), item->itemText);
 
 
 }
 }
 
 
@@ -206,30 +181,16 @@ S32 GuiListBoxCtrl::getItemIndex( LBItem *item )
    return -1;
    return -1;
 }
 }
 
 
-ConsoleMethod( GuiListBoxCtrl, getItemCount, S32, 2, 2, "()\n @return Returns the number of items in the list")
-{
-   return object->getItemCount();
-}
-
 S32 GuiListBoxCtrl::getItemCount()
 S32 GuiListBoxCtrl::getItemCount()
 {
 {
    return mItems.size();
    return mItems.size();
 }
 }
 
 
-ConsoleMethod( GuiListBoxCtrl, getSelCount, S32, 2, 2, "()\n @return Returns the number of items currently selected")
-{
-   return object->getSelCount();
-}
 S32 GuiListBoxCtrl::getSelCount()
 S32 GuiListBoxCtrl::getSelCount()
 {
 {
    return mSelectedItems.size();
    return mSelectedItems.size();
 }
 }
 
 
-ConsoleMethod( GuiListBoxCtrl, getSelectedItem, S32, 2, 2, "()\n @return Returns the selected items index or -1 if none. "
-              "If multiple selections exist it returns the first selected item" )
-{
-   return object->getSelectedItem();
-}
 S32 GuiListBoxCtrl::getSelectedItem()
 S32 GuiListBoxCtrl::getSelectedItem()
 {
 {
    if( mSelectedItems.empty() || mItems.empty() )
    if( mSelectedItems.empty() || mItems.empty() )
@@ -242,33 +203,6 @@ S32 GuiListBoxCtrl::getSelectedItem()
    return -1;
    return -1;
 }
 }
 
 
-ConsoleMethod( GuiListBoxCtrl, getSelectedItems, const char*, 2, 2, "()\n @return Returns a space delimited list "
-              "of the selected items indexes in the list")
-{
-   S32 selCount = object->getSelCount();
-   if( selCount == -1 || selCount == 0 )
-      return StringTable->lookup("-1");
-   else if( selCount == 1 )
-      return Con::getIntArg(object->getSelectedItem());
-
-   Vector<S32> selItems;
-   object->getSelectedItems( selItems );
-
-   if( selItems.empty() )
-      return StringTable->lookup("-1");
-
-   UTF8 *retBuffer = Con::getReturnBuffer( selItems.size() * 4 );
-   dMemset( retBuffer, 0, selItems.size() * 4 );
-   Vector<S32>::iterator i = selItems.begin();
-   for( ; i != selItems.end(); i++ )
-   {
-      UTF8 retFormat[12];
-      dSprintf( retFormat, 12, "%d ", (*i) );
-      dStrcat( retBuffer, retFormat );
-   }
-
-   return retBuffer;
-}
 void GuiListBoxCtrl::getSelectedItems( Vector<S32> &Items )
 void GuiListBoxCtrl::getSelectedItems( Vector<S32> &Items )
 {
 {
    // Clear our return vector
    // Clear our return vector
@@ -283,20 +217,6 @@ void GuiListBoxCtrl::getSelectedItems( Vector<S32> &Items )
          Items.push_back( i );
          Items.push_back( i );
 }
 }
 
 
-ConsoleMethod(GuiListBoxCtrl, findItemText, S32, 3, 4, " (string itemText, bool caseSensitive) Find the item with the given text.\n"
-              "@param itemText The text to search for.\n"
-              "@param caseSensitive Sets whether or not to ignore text in the search.\n"
-              "@return Returns index of item with matching text or -1 if none"
-              "@note %listBox.findItemText( myItemText, [?caseSensitive - false] )")
-{
-   bool bCaseSensitive = false;
-
-   if( argc == 4 )
-      bCaseSensitive = dAtob( argv[3] );
-
-   return object->findItemText( argv[2], bCaseSensitive );
-}
-
 S32 GuiListBoxCtrl::findItemText( StringTableEntry text, bool caseSensitive )
 S32 GuiListBoxCtrl::findItemText( StringTableEntry text, bool caseSensitive )
 {
 {
    // Check Proper Arguments
    // Check Proper Arguments
@@ -324,11 +244,6 @@ S32 GuiListBoxCtrl::findItemText( StringTableEntry text, bool caseSensitive )
    return -1;
    return -1;
 }
 }
 
 
-ConsoleMethod(GuiListBoxCtrl, setCurSel, void, 3, 3, "(index) Sets the currently selected item at the specified index\n"
-              "@return No return value.")
-{
-   object->setCurSel( dAtoi( argv[2] ) );
-}
 void GuiListBoxCtrl::setCurSel( S32 index )
 void GuiListBoxCtrl::setCurSel( S32 index )
 {
 {
    // Range Check
    // Range Check
@@ -350,17 +265,6 @@ void GuiListBoxCtrl::setCurSel( S32 index )
 
 
 }
 }
 
 
-ConsoleMethod( GuiListBoxCtrl, setCurSelRange, void, 3, 4, "(start,[stop]) Sets the current selection range from"
-              "index start to stop.\n"
-              "@param start The start of the selection range.\n"
-              "@param stop The stopping point of the selection range. If no stop is specified it sets from start index to the end of the list\n"
-              "@return No return value.")
-{
-   if( argc == 4 )
-      object->setCurSelRange( dAtoi(argv[2]) , dAtoi( argv[3] ) );
-   else
-      object->setCurSelRange( dAtoi(argv[2]), 999999 );
-}
 void GuiListBoxCtrl::setCurSelRange( S32 start, S32 stop )
 void GuiListBoxCtrl::setCurSelRange( S32 start, S32 stop )
 {
 {
    // Verify Selection Range
    // Verify Selection Range
@@ -381,39 +285,6 @@ void GuiListBoxCtrl::setCurSelRange( S32 start, S32 stop )
       addSelection( mItems[iterStart], iterStart );
       addSelection( mItems[iterStart], iterStart );
 }
 }
 
 
-
-ConsoleMethod( GuiListBoxCtrl, addItem, void, 3, 4, "(text, [color]) Adds an item to the end of the list with an optional color\n" 
-              "@param text The object text.\n"
-              "@param color Optional color setting.\n"
-              "@return No return value.")
-{
-   if(argc == 3)
-   {
-      object->addItem( argv[2] );
-   } else if(argc == 4)
-   {
-      U32 elementCount = GuiListBoxCtrl::getStringElementCount(argv[3]);
-
-      if(elementCount == 3)
-      {
-         F32 red, green, blue;
-
-         red = dAtof(GuiListBoxCtrl::getStringElement( argv[3], 0 ));
-         green = dAtof(GuiListBoxCtrl::getStringElement( argv[3], 1 ));
-         blue = dAtof(GuiListBoxCtrl::getStringElement( argv[3], 2 ));
-
-         object->addItemWithColor( argv[2], ColorF(red, green, blue) );
-      } 
-     else
-      {
-         Con::warnf("GuiListBoxCtrl::addItem() - Invalid number of parameters for the color!");
-      }
-
-   } else
-   {
-      Con::warnf("GuiListBoxCtrl::addItem() - Invalid number of parameters!");
-   }  
-}
 S32 GuiListBoxCtrl::addItem( StringTableEntry text, void *itemData )
 S32 GuiListBoxCtrl::addItem( StringTableEntry text, void *itemData )
 {
 {
    // This just calls insert item at the end of the list
    // This just calls insert item at the end of the list
@@ -426,25 +297,6 @@ S32 GuiListBoxCtrl::addItemWithColor( StringTableEntry text, ColorF color, void
    return insertItemWithColor( mItems.size(), text, color, itemData );
    return insertItemWithColor( mItems.size(), text, color, itemData );
 }
 }
 
 
-ConsoleMethod(GuiListBoxCtrl, setItemColor, void, 4, 4, "(index, color) Sets the color of the item at given index.\n"
-              "@param index The index of the item you wish to modify.\n"
-              "@param color The color you wish to set the object to.\n"
-              "@return No return value.")
-{
-   U32 elementCount = GuiListBoxCtrl::getStringElementCount(argv[3]);
-
-   if(elementCount == 3)
-   {
-      F32 red = dAtof(GuiListBoxCtrl::getStringElement( argv[3], 0 ));
-      F32 green = dAtof(GuiListBoxCtrl::getStringElement( argv[3], 1 ));
-      F32 blue = dAtof(GuiListBoxCtrl::getStringElement( argv[3], 2 ));
-
-      object->setItemColor( dAtoi(argv[2]), ColorF(red, green, blue) );
-   }
-   else
-      Con::warnf("GuiListBoxCtrl::addItem() - Invalid number of parameters for the color!");
-}
-
 void GuiListBoxCtrl::setItemColor( S32 index, ColorF color )
 void GuiListBoxCtrl::setItemColor( S32 index, ColorF color )
 {
 {
    if ((index >= mItems.size()) || index < 0)
    if ((index >= mItems.size()) || index < 0)
@@ -458,31 +310,26 @@ void GuiListBoxCtrl::setItemColor( S32 index, ColorF color )
    item->color = color;
    item->color = color;
 }
 }
 
 
-ConsoleMethod(GuiListBoxCtrl, clearItemColor, void, 3, 3, "(index) Clears the color of the item at index.\n"
-              "@param index The index of the item to modify.\n"
-              "@return No return value.")
+void GuiListBoxCtrl::clearItemColor(S32 index)
 {
 {
-   object->clearItemColor(dAtoi(argv[2]));
-}
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemColor - invalid index");
+		return;
+	}
 
 
-void GuiListBoxCtrl::clearItemColor( S32 index )
-{
-   if ((index >= mItems.size()) || index < 0)
-   {
-      Con::warnf("GuiListBoxCtrl::setItemColor - invalid index");
-      return;
-   }
-
-   LBItem* item = mItems[index];
-   item->hasColor = false;
+	LBItem* item = mItems[index];
+	item->hasColor = false;
 }
 }
 
 
-ConsoleMethod( GuiListBoxCtrl, insertItem, void, 4, 4, "( text, index ) Inserts an item into the list at the specified index.\n"
-              "@param text The desired object text.\n"
-              "@param index The index to set the object at.\n"
-              "@return Returns the index assigned or -1 on error")
+void GuiListBoxCtrl::clearAllColors()
 {
 {
-   object->insertItem( dAtoi( argv[3] ), argv[2] );
+	if (!mSelectedItems.size())
+		return;
+
+	VectorPtr<LBItem*>::iterator i = mSelectedItems.begin();
+	for (; i != mSelectedItems.end(); i++)
+		(*i)->hasColor = false;
 }
 }
 
 
 S32 GuiListBoxCtrl::insertItem( S32 index, StringTableEntry text, void *itemData )
 S32 GuiListBoxCtrl::insertItem( S32 index, StringTableEntry text, void *itemData )
@@ -568,13 +415,6 @@ S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, Color
 
 
 }
 }
 
 
-ConsoleMethod ( GuiListBoxCtrl, deleteItem, void, 3, 3, "(index) Deletes the item at the given index.\n"
-               "@param index The index of the item to delete.\n"
-               "@return No return value.")
-{
-   object->deleteItem( dAtoi( argv[2] ) );
-}
-
 void  GuiListBoxCtrl::deleteItem( S32 index )
 void  GuiListBoxCtrl::deleteItem( S32 index )
 {
 {
    // Range Check
    // Range Check
@@ -612,12 +452,6 @@ void  GuiListBoxCtrl::deleteItem( S32 index )
    delete item;
    delete item;
 }
 }
 
 
-
-ConsoleMethod( GuiListBoxCtrl, getItemText, const char*, 3, 3, "(index) \n @return Returns the text of the item at the specified index")
-{
-   return object->getItemText( dAtoi( argv[2] ) );
-}
-
 StringTableEntry GuiListBoxCtrl::getItemText( S32 index )
 StringTableEntry GuiListBoxCtrl::getItemText( S32 index )
 {
 {
    // Range Checking
    // Range Checking
@@ -630,14 +464,6 @@ StringTableEntry GuiListBoxCtrl::getItemText( S32 index )
    return mItems[ index ]->itemText;   
    return mItems[ index ]->itemText;   
 }
 }
 
 
-
-ConsoleMethod( GuiListBoxCtrl, setItemText, void, 4, 4, "(index, newtext) Sets the item's text at the specified index\n"
-              "@param index The index of the item to modify.\n"
-              "@param newtext The new text to set to the object.\n"
-              "@return No return value.")
-{
-   object->setItemText( dAtoi( argv[2] ), argv[3] );
-}
 void GuiListBoxCtrl::setItemText( S32 index, StringTableEntry text )
 void GuiListBoxCtrl::setItemText( S32 index, StringTableEntry text )
 {
 {
    // Sanity Checking
    // Sanity Checking
@@ -655,20 +481,18 @@ void GuiListBoxCtrl::setItemText( S32 index, StringTableEntry text )
 
 
    mItems[ index ]->itemText = StringTable->insert( text );
    mItems[ index ]->itemText = StringTable->insert( text );
 }
 }
-//////////////////////////////////////////////////////////////////////////
-// Sizing Functions
-//////////////////////////////////////////////////////////////////////////
+#pragma endregion
+
+#pragma region Sizing
 void GuiListBoxCtrl::updateSize()
 void GuiListBoxCtrl::updateSize()
 {
 {
    if( !mProfile )
    if( !mProfile )
       return;
       return;
 
 
    GFont *font = mProfile->mFont;
    GFont *font = mProfile->mFont;
-   GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl *>(getParent());
+   Point2I contentSize = Point2I(10, font->getHeight() + 2);
 
 
-   if ( mFitParentWidth && parent )
-      mItemSize.x = 100;//parent->getContentExtent().x;
-   else
+   if (!mFitParentWidth)
    {
    {
       // Find the maximum width cell:
       // Find the maximum width cell:
       S32 maxWidth = 1;
       S32 maxWidth = 1;
@@ -678,14 +502,19 @@ void GuiListBoxCtrl::updateSize()
          if( width > maxWidth )
          if( width > maxWidth )
             maxWidth = width;
             maxWidth = width;
       }
       }
-      mItemSize.x = maxWidth + 6;
+      contentSize.x = maxWidth + 6;
    }
    }
 
 
-   mItemSize.y = font->getHeight() + 2;
+   mItemSize = this->getOuterExtent(contentSize, NormalState, mProfile);
+   Point2I newExtent = Point2I(mItemSize.x, mItemSize.y * mItems.size());
 
 
-   Point2I newExtent( mItemSize.x, mItemSize.y * mItems.size() );
-   resize( mBounds.point, newExtent );
+   //Don't update the extent.x if we are matching our parent's size. We will handle it during rendering.
+   if (mFitParentWidth)
+   {
+	   newExtent.x = mBounds.extent.x;
+   }
 
 
+   resize( mBounds.point, newExtent );
 }
 }
 
 
 void GuiListBoxCtrl::parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent)
 void GuiListBoxCtrl::parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent)
@@ -694,79 +523,116 @@ void GuiListBoxCtrl::parentResized(const Point2I &oldParentExtent, const Point2I
 
 
    updateSize();
    updateSize();
 }
 }
+#pragma endregion
 
 
-//////////////////////////////////////////////////////////////////////////
-// Overrides
-//////////////////////////////////////////////////////////////////////////
+#pragma region Rendering
 void GuiListBoxCtrl::onRender( Point2I offset, const RectI &updateRect )
 void GuiListBoxCtrl::onRender( Point2I offset, const RectI &updateRect )
 {
 {
-   if( !mProfile )
-      return;
+	RectI clip = dglGetClipRect();
+	if (mFitParentWidth && ( mBounds.extent.x != clip.extent.x || mItemSize.x != clip.extent.x))
+	{
+		mBounds.extent.x = clip.extent.x;
+		mItemSize.x = clip.extent.x;
+	}
 
 
-   for ( S32 i = 0; i < mItems.size(); i++)
-   {
-      S32 colorBoxSize = 0;
-      ColorI boxColor = ColorI(0, 0, 0);
-      // Only render visible items
-      if ((i + 1) * mItemSize.y + offset.y < updateRect.point.y)
-         continue;
-
-      // Break our once we're no longer in visible item range
-      if( i * mItemSize.y + offset.y >= updateRect.point.y + updateRect.extent.y)
-         break;
-
-      // Render color box if needed
-      if(mItems[i]->hasColor)
-      {
-         // Set the size of the color box to be drawn next to the item text
-         colorBoxSize = 3;
-         boxColor = ColorI(mItems[i]->color);
-         // Draw the box first
-         ColorI black = ColorI(0, 0, 0);
-         drawBox(  Point2I(offset.x + mProfile->mTextOffset.x + colorBoxSize, offset.y + ( i * mItemSize.y ) + 8), colorBoxSize, black, boxColor );
-      }
 
 
-      RectI itemRect = RectI( offset.x + mProfile->mTextOffset.x + (colorBoxSize * 2), offset.y + ( i * mItemSize.y ), mItemSize.x, mItemSize.y );
+	for ( S32 i = 0; i < mItems.size(); i++)
+	{
+		S32 colorBoxSize = 0;
+		ColorI boxColor = ColorI(0, 0, 0);
+		// Only render visible items
+		if ((i + 1) * mItemSize.y + offset.y < updateRect.point.y)
+		continue;
 
 
-      // Render our item
-      onRenderItem( itemRect, mItems[i] );
-   }
+		// Break out once we're no longer in visible item range
+		if( i * mItemSize.y + offset.y >= updateRect.point.y + updateRect.extent.y)
+		break;
+
+		RectI itemRect = RectI( offset.x, offset.y + ( i * mItemSize.y ), mItemSize.x, mItemSize.y );
+
+		// Render our item
+		onRenderItem( itemRect, mItems[i] );
+	}
 }
 }
 
 
-void GuiListBoxCtrl::onRenderItem( RectI itemRect, LBItem *item )
+void GuiListBoxCtrl::onRenderItem( RectI &itemRect, LBItem *item )
 {
 {
-   if( item->isSelected )
-      dglDrawRectFill( itemRect, mProfile->mFillColor );
+   Point2I cursorPt = Point2I(0,0);
+   GuiCanvas *root = getRoot();
+   if (root)
+   {
+	   cursorPt = root->getCursorPos();
+   }
+   GuiControlState currentState = GuiControlState::NormalState;
+   if (!mActive)
+	   currentState = GuiControlState::DisabledState;
+   else if (item->isSelected)
+	   currentState = GuiControlState::SelectedState;
+   else if (itemRect.pointInRect(cursorPt))
+	   currentState = GuiControlState::HighlightState;
+   RectI ctrlRect = applyMargins(itemRect.point, itemRect.extent, currentState, mProfile);
+
+   if (!ctrlRect.isValidRect())
+   {
+	   return;
+   }
+
+   renderUniversalRect(ctrlRect, mProfile, currentState);
+
+   //Render Text
+   dglSetBitmapModulation(mProfile->getFontColor(currentState));
+   RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
+   RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
+
+   // Render color box if needed
+   if (item->hasColor)
+   {
+	   RectI drawArea = RectI(contentRect.point.x + 1, contentRect.point.y + 1, contentRect.extent.y - 2, contentRect.extent.y - 2);
+	   drawBox(drawArea, ColorI(item->color));
+
+	   contentRect.point.x += contentRect.extent.y;
+	   contentRect.extent.x -= contentRect.extent.y;
+   }
 
 
-   dglSetBitmapModulation(mProfile->mFontColor);
-   renderText(itemRect.point + Point2I( 2, 0 ), itemRect.extent, item->itemText, mProfile);
+   renderText(contentRect.point, contentRect.extent, item->itemText, mProfile);
 }
 }
 
 
-void GuiListBoxCtrl::drawBox(const Point2I &box, S32 size, ColorI &outlineColor, ColorI &boxColor)
+void GuiListBoxCtrl::drawBox(RectI &box, ColorI &boxColor)
 {
 {
-   RectI r(box.x - size, box.y - size, 2 * size + 1, 2 * size + 1);
-   r.inset(1, 1);
-   dglDrawRectFill(r, boxColor);
-   r.inset(-1, -1);
-   dglDrawRect(r, outlineColor);
+	const S32 max = 5;
+	if (box.extent.x > max)
+	{
+		S32 delta = mCeil((box.extent.x - max) / 2);
+		box.inset(delta, delta);
+	}
+	dglDrawRectFill(box, ColorI(0,0,0, 100));
+	box.inset(1, 1);
+	dglDrawRectFill(box, boxColor);
 }
 }
+#pragma endregion
 
 
-//////////////////////////////////////////////////////////////////////////
-// Mouse Events
-//////////////////////////////////////////////////////////////////////////
-
+#pragma region InputEvents
 void GuiListBoxCtrl::onTouchDragged(const GuiEvent &event)
 void GuiListBoxCtrl::onTouchDragged(const GuiEvent &event)
 {
 {
    Parent::onTouchDragged(event);
    Parent::onTouchDragged(event);
 
 
+   Point2I localPoint = globalToLocalCoord(event.mousePoint);
+   S32 itemHit = (localPoint.y < 0) ? -1 : (S32)mFloor((F32)localPoint.y / (F32)mItemSize.y);
+
+   if (itemHit >= mItems.size() || itemHit == -1)
+	   return;
+
+   LBItem *hitItem = mItems[itemHit];
+   if (hitItem == NULL)
+	   return;
+
    if(isMethod("onTouchDragged"))
    if(isMethod("onTouchDragged"))
-      Con::executef(this, 1, "onTouchDragged");
+      Con::executef(this, 3, "onTouchDragged", Con::getIntArg(itemHit), hitItem->itemText);
 }
 }
 
 
 void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
 void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
 {
 {
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
    Point2I localPoint = globalToLocalCoord(event.mousePoint);
-   
    S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
    S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
 
 
    if ( itemHit >= mItems.size() || itemHit == -1 )
    if ( itemHit >= mItems.size() || itemHit == -1 )
@@ -788,16 +654,19 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
       // Set the current selection
       // Set the current selection
       setCurSel( itemHit );
       setCurSel( itemHit );
 
 
-      if( itemHit == selItem && event.mouseClickCount == 2 && isMethod("onDoubleClick") )
-         Con::executef( this, 2, "onDoubleClick" );
+		if( itemHit == selItem && event.mouseClickCount == 2)
+		{
+			if(isMethod("onDoubleClick") )
+				Con::executef( this, 3, "onDoubleClick", Con::getIntArg(itemHit), hitItem->itemText);
+		}
+		else if (isMethod("onClick"))
+		{
+			Con::executef(this, 3, "onClick", Con::getIntArg(itemHit), hitItem->itemText);
+		}
 
 
       // Store the clicked item
       // Store the clicked item
       mLastClickItem = hitItem;
       mLastClickItem = hitItem;
 
 
-      // Evaluate the console command if we clicked the same item twice
-      if( selItem == itemHit && event.mouseClickCount > 1 && mAltConsoleCommand[0] )
-         Con::evaluate( mAltConsoleCommand, false );
-
       return;
       return;
 
 
    }
    }
@@ -834,214 +703,18 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
       addSelection( hitItem, itemHit );
       addSelection( hitItem, itemHit );
    }
    }
 
 
-   if( hitItem == mLastClickItem && event.mouseClickCount == 2 && isMethod("onDoubleClick") )
-      Con::executef( this, 2, "onDoubleClick" );
+   if( hitItem == mLastClickItem && event.mouseClickCount == 2)
+   {
+		if(isMethod("onDoubleClick") )
+			Con::executef( this, 3, "onDoubleClick", Con::getIntArg(itemHit), hitItem->itemText);
+	}
+   else if (isMethod("onClick"))
+   {
+	   Con::executef(this, 3, "onClick", Con::getIntArg(itemHit), hitItem->itemText);
+   }
 
 
    mLastClickItem = hitItem;
    mLastClickItem = hitItem;
 
 
 
 
 }
 }
-
-U32 GuiListBoxCtrl::getStringElementCount( const char* inString )
-{
-    // Non-whitespace chars.
-    static const char* set = " \t\n";
-
-    // End of string.
-    if ( *inString == 0 )
-        return 0;
-
-    U32 wordCount = 0;
-    U8 search = 0;
-
-    // Search String.
-    while( *inString )
-    {
-        // Get string element.
-        search = *inString;
-
-        // End of string?
-        if ( search == 0 )
-            break;
-
-        // Move to next element.
-        inString++;
-
-        // Search for seperators.
-        for( U32 i = 0; set[i]; i++ )
-        {
-            // Found one?
-            if( search == set[i] )
-            {
-                // Yes...
-                search = 0;
-                break;
-            }   
-        }
-
-        // Found a seperator?
-        if ( search == 0 )
-            continue;
-
-        // We've found a non-seperator.
-        wordCount++;
-
-        // Search for end of non-seperator.
-        while( 1 )
-        {
-            // Get string element.
-            search = *inString;
-
-            // End of string?
-            if ( search == 0 )
-                break;
-
-            // Move to next element.
-            inString++;
-
-            // Search for seperators.
-            for( U32 i = 0; set[i]; i++ )
-            {
-                // Found one?
-                if( search == set[i] )
-                {
-                    // Yes...
-                    search = 0;
-                    break;
-                }   
-            }
-
-            // Found Seperator?
-            if ( search == 0 )
-                break;
-        }
-
-        // End of string?
-        if ( *inString == 0 )
-        {
-            // Bah!
-            break;
-        }
-    }
-
-    // We've finished.
-    return wordCount;
-}
-
-//------------------------------------------------------------------------------
-// Get String Element.
-//------------------------------------------------------------------------------
-const char* GuiListBoxCtrl::getStringElement( const char* inString, const U32 index )
-{
-    // Non-whitespace chars.
-    static const char* set = " \t\n";
-
-    U32 wordCount = 0;
-    U8 search = 0;
-    const char* pWordStart = NULL;
-
-    // End of string?
-    if ( *inString != 0 )
-    {
-        // No, so search string.
-        while( *inString )
-        {
-            // Get string element.
-            search = *inString;
-
-            // End of string?
-            if ( search == 0 )
-                break;
-
-            // Move to next element.
-            inString++;
-
-            // Search for seperators.
-            for( U32 i = 0; set[i]; i++ )
-            {
-                // Found one?
-                if( search == set[i] )
-                {
-                    // Yes...
-                    search = 0;
-                    break;
-                }   
-            }
-
-            // Found a seperator?
-            if ( search == 0 )
-                continue;
-
-            // Found are word?
-            if ( wordCount == index )
-            {
-                // Yes, so mark it.
-                pWordStart = inString-1;
-            }
-
-            // We've found a non-seperator.
-            wordCount++;
-
-            // Search for end of non-seperator.
-            while( 1 )
-            {
-                // Get string element.
-                search = *inString;
-
-                // End of string?
-                if ( search == 0 )
-                    break;
-
-                // Move to next element.
-                inString++;
-
-                // Search for seperators.
-                for( U32 i = 0; set[i]; i++ )
-                {
-                    // Found one?
-                    if( search == set[i] )
-                    {
-                        // Yes...
-                        search = 0;
-                        break;
-                    }   
-                }
-
-                // Found Seperator?
-                if ( search == 0 )
-                    break;
-            }
-
-            // Have we found our word?
-            if ( pWordStart )
-            {
-                // Yes, so we've got our word...
-
-                // Result Buffer.
-                static char buffer[4096];
-
-                // Calculate word length.
-                const U32 length = (const U32)(inString - pWordStart - ((*inString)?1:0));
-
-                // Copy Word.
-                dStrncpy( buffer, pWordStart, length);
-                buffer[length] = '\0';
-
-                // Return Word.
-                return buffer;
-            }
-
-            // End of string?
-            if ( *inString == 0 )
-            {
-                // Bah!
-                break;
-            }
-        }
-    }
-
-    // Sanity!
-    AssertFatal( false, "SceneObject::getStringElement() - Couldn't find specified string element!" );
-    // Didn't find it
-    return " ";
-}
+#pragma endregion

+ 6 - 9
engine/source/gui/guiListBoxCtrl.h

@@ -92,6 +92,7 @@ public:
 
 
    void              setItemColor(S32 index, ColorF color);
    void              setItemColor(S32 index, ColorF color);
    void              clearItemColor(S32 index);
    void              clearItemColor(S32 index);
+   void				 clearAllColors();
 
 
    void              deleteItem( S32 index );
    void              deleteItem( S32 index );
    void              clearItems();
    void              clearItems();
@@ -100,27 +101,23 @@ public:
    void              removeSelection( S32 index );
    void              removeSelection( S32 index );
    void              addSelection( LBItem *item, S32 index );
    void              addSelection( LBItem *item, S32 index );
    void              addSelection( S32 index );
    void              addSelection( S32 index );
-   inline void       setMultipleSelection( bool allowMultipleSelect = true ) { mMultipleSelections = allowMultipleSelect; };
+   inline void       setMultipleSelection(bool allowMultipleSelect = true) { mMultipleSelections = allowMultipleSelect; };
+   inline bool       getMultipleSelection() { return mMultipleSelections; };
 
 
    // Sizing
    // Sizing
    void              updateSize();
    void              updateSize();
    virtual void      parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
    virtual void      parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
    virtual bool      onWake();
    virtual bool      onWake();
+   virtual void		 addObject(SimObject *obj);
 
 
    // Rendering
    // Rendering
    virtual void      onRender( Point2I offset, const RectI &updateRect );
    virtual void      onRender( Point2I offset, const RectI &updateRect );
-   virtual void      onRenderItem( RectI itemRect, LBItem *item );
-   void              drawBox( const Point2I &box, S32 size, ColorI &outlineColor, ColorI &boxColor );
+   virtual void      onRenderItem( RectI &itemRect, LBItem *item );
+   void              drawBox( RectI &box, ColorI &boxColor );
 
 
    // Mouse Events
    // Mouse Events
    virtual void      onTouchDown( const GuiEvent &event );
    virtual void      onTouchDown( const GuiEvent &event );
    virtual void      onTouchDragged(const GuiEvent &event);
    virtual void      onTouchDragged(const GuiEvent &event);
-
-   // String Utility
-   static U32        getStringElementCount( const char *string );
-   static const char* getStringElement( const char* inString, const U32 index );
-   
-
 };
 };
 
 
 #endif
 #endif

+ 303 - 0
engine/source/gui/guiListBoxCtrl_ScriptBinding.h

@@ -0,0 +1,303 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(GuiListBoxCtrl, GuiControl)
+
+/*! If true, allows the user to select multiple items.
+	@param allowMultiSelection True to allow multi-selection. False to allow single selection.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setMultiSelection, ConsoleVoid, 3, 3, "(bool allowMultiSelection)")
+{
+	object->setMultipleSelection(dAtob(argv[2]));
+}
+
+/*! Reports if multi-selection is enabled.
+	@return Returns true if multi-selection is enabled. False otherwise.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getMultiSelection, ConsoleVoid, 2, 2, "()")
+{
+	object->getMultipleSelection();
+}
+
+/*! Removes all items from the listbox.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, clearItems, ConsoleVoid, 2, 2, "()")
+{
+	object->clearItems();
+}
+
+/*! Unselects any items that have been selected.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, clearSelection, ConsoleVoid, 2, 2, "()")
+{
+	object->clearSelection();
+}
+
+/*! Sets an item to selected or unselected using an index.
+	@param index The zero-based index of the item that should be selected.
+	@param setting If true, the item is selected. If false, it is unselected.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setSelected, ConsoleVoid, 3, 4, "(S32 index, bool setting)")
+{
+	bool value = true;
+	if (argc == 4)
+		value = dAtob(argv[3]);
+
+	if (value == true)
+		object->addSelection(dAtoi(argv[2]));
+	else
+		object->removeSelection(dAtoi(argv[2]));
+}
+
+/*! Returns the number of items in the list.
+	@return The number of items.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getItemCount, ConsoleInt, 2, 2, "()")
+{
+	return object->getItemCount();
+}
+
+/*! Returns the number of selected items in the list.
+	@return The number of items currently selected.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getSelCount, ConsoleInt, 2, 2, "()")
+{
+	return object->getSelCount();
+}
+
+/*! Returns the index of the first selected item.
+	@return The index of the first selected item or -1 if the item does not belong to the listbox.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getSelectedItem, ConsoleInt, 2, 2, "()")
+{
+	return object->getSelectedItem();
+}
+
+/*! Returns a list of selected item indexes.
+	@return A spaced-delimited list of selected item indexes or -1 if no items are selected.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getSelectedItems, ConsoleString, 2, 2, "()")
+{
+	S32 selCount = object->getSelCount();
+	if (selCount == -1 || selCount == 0)
+		return StringTable->lookup("-1");
+	else if (selCount == 1)
+		return Con::getIntArg(object->getSelectedItem());
+
+	Vector<S32> selItems;
+	object->getSelectedItems(selItems);
+
+	if (selItems.empty())
+		return StringTable->lookup("-1");
+
+	UTF8 *retBuffer = Con::getReturnBuffer(selItems.size() * 4);
+	dMemset(retBuffer, 0, selItems.size() * 4);
+	Vector<S32>::iterator i = selItems.begin();
+	for (; i != selItems.end(); i++)
+	{
+		UTF8 retFormat[12];
+		dSprintf(retFormat, 12, "%d ", (*i));
+		dStrcat(retBuffer, retFormat);
+	}
+
+	return retBuffer;
+}
+
+/*! Finds an item with the given text.
+	@param itemText The text to search for.
+	@param caseSensitive If true, a cases sensitive search will be performed.
+	@return A spaced-delimited list of matching item indexes or -1 if no items are found.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, findItemText, ConsoleInt, 3, 4, "(string itemText, bool caseSensitive)")
+{
+	bool bCaseSensitive = false;
+
+	if (argc == 4)
+		bCaseSensitive = dAtob(argv[3]);
+
+	return object->findItemText(argv[2], bCaseSensitive);
+}
+
+/*! Selects the item at the given index.
+	@param index The zero-based index of the item that should be selected. Passing a -1 clears the selection.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setCurSel, ConsoleVoid, 3, 3, "(S32 index)")
+{
+	object->setCurSel(dAtoi(argv[2]));
+}
+
+/*! Selects a range of items from a start index to the end or an ending index.
+	@param start The zero-based index of the start of the selected range.
+	@param stop The optional, zero-based index of the end of the selected range. If no stop is given, the selection will go to the end of the list.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setCurSelRange, ConsoleVoid, 3, 4, "(S32 start, [S32 stop])")
+{
+	if (argc == 4)
+		object->setCurSelRange(dAtoi(argv[2]), dAtoi(argv[3]));
+	else
+		object->setCurSelRange(dAtoi(argv[2]), 999999);
+}
+
+/*! Adds an item to the end of the list with an optional color box.
+	@param text The text of the new item.
+	@param color The optional color of a color box that will appear to the left of the text. Values range between 0 and 255.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, addItem, ConsoleVoid, 3, 4, "(string text, [color red / green / blue / [alpha]])")
+{
+	if (argc == 3)
+	{
+		object->addItem(argv[2]);
+	}
+	else if (argc == 4)
+	{
+		const U32 colorCount = Utility::mGetStringElementCount(argv[3]);
+		if (colorCount != 4 && colorCount != 3)
+		{
+			Con::warnf("GuiListBoxCtrl::addItem() - Invalid color! Colors require three or four values (red / green / blue / [alpha])!");
+			return;
+		}
+
+		F32 red, green, blue, alpha;
+
+		red = dAtof(Utility::mGetStringElement(argv[3], 0));
+		green = dAtof(Utility::mGetStringElement(argv[3], 1));
+		blue = dAtof(Utility::mGetStringElement(argv[3], 2));
+
+		if (colorCount == 3)
+		{
+			alpha = 255;
+		}
+		else 
+		{
+			alpha = dAtof(Utility::mGetStringElement(argv[3], 3));
+		}
+
+		object->addItemWithColor(argv[2], ColorI(red, green, blue, alpha));
+	}
+	else
+	{
+		Con::warnf("GuiListBoxCtrl::addItem() - Invalid number of parameters!");
+	}
+}
+
+/*! Sets the color of the color box at the given index.
+	@param index The zero-based index of the item that should have a color box.
+	@param color The color of a color box that will appear to the left of the text. Values range between 0 and 255.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setItemColor, ConsoleVoid, 4, 4, "(S32 index, color red / green / blue / [alpha])")
+{
+	if (argc == 4)
+	{
+		const U32 colorCount = Utility::mGetStringElementCount(argv[3]);
+		if (colorCount != 4 && colorCount != 3)
+		{
+			Con::warnf("GuiListBoxCtrl::setItemColor() - Invalid color! Colors require three or four values (red / green / blue / [alpha])!");
+			return;
+		}
+
+		F32 red, green, blue, alpha;
+
+		red = dAtof(Utility::mGetStringElement(argv[3], 0));
+		green = dAtof(Utility::mGetStringElement(argv[3], 1));
+		blue = dAtof(Utility::mGetStringElement(argv[3], 2));
+
+		if (colorCount == 3)
+		{
+			alpha = 255;
+		}
+		else
+		{
+			alpha = dAtof(Utility::mGetStringElement(argv[3], 3));
+		}
+
+		object->setItemColor(dAtoi(argv[2]), ColorI(red, green, blue, alpha));
+	}
+	else
+	{
+		Con::warnf("GuiListBoxCtrl::setItemColor() - Invalid number of parameters!");
+	}
+}
+
+/*! Clears the color of the color box at the given index.
+	@param index The zero-based index of the item's color box.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, clearItemColor, ConsoleVoid, 3, 3, "(S32 index)")
+{
+	object->clearItemColor(dAtoi(argv[2]));
+}
+
+/*! Clears the color boxes on all items.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, clearAllColors, ConsoleVoid, 2, 2, "()")
+{
+	object->clearAllColors();
+}
+
+/*! Inserts an item into the list at the specified index.
+	@param index The zero-based index of the new location of the item.
+	@param text The text of the new item.
+	@return Returns the index assigned or -1 on error.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, insertItem, ConsoleVoid, 4, 4, "(S32 index, string text)")
+{
+	object->insertItem(dAtoi(argv[2]), argv[3]);
+}
+
+/*! Removes the item at the given index.
+	@param index The zero-based index of the item to delete.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, deleteItem, ConsoleVoid, 3, 3, "(S32 index)")
+{
+	object->deleteItem(dAtoi(argv[2]));
+}
+
+/*! Returns the text of the given item index.
+	@param index The zero-based index of the item to inspect.
+	@return The text of the inspected item.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getItemText, ConsoleString, 3, 3, "(S32 index)")
+{
+	return object->getItemText(dAtoi(argv[2]));
+}
+
+/*! Sets the text of the item at the given item index.
+	@param index The zero-based index of the item that will be updated.
+	@param text The text value to update with.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setItemText, ConsoleVoid, 4, 4, "(S32 index, string text)")
+{
+	object->setItemText(dAtoi(argv[2]), argv[3]);
+}
+
+ConsoleMethodGroupEndWithDocs(GuiListBoxCtrl)

+ 1 - 1
toybox/GuiEditorToy/1/assets/gui/guiToolbox.gui

@@ -69,7 +69,7 @@
 				Profile = "GuiListBoxProfile";
 				Profile = "GuiListBoxProfile";
 				HorizSizing = "width";
 				HorizSizing = "width";
 				VertSizing = "height";
 				VertSizing = "height";
-				position = "2 2";
+				position = "0 0";
 				Extent = "218 1260";
 				Extent = "218 1260";
 				MinExtent = "8 2";
 				MinExtent = "8 2";
 				canSave = "1";
 				canSave = "1";

+ 43 - 48
toybox/GuiEditorToy/1/main.cs

@@ -29,28 +29,28 @@ function GuiEditorToy::create( %this )
     // Set the sandbox drag mode availability.
     // Set the sandbox drag mode availability.
     Sandbox.allowManipulation( pan );
     Sandbox.allowManipulation( pan );
     Sandbox.allowManipulation( pull );
     Sandbox.allowManipulation( pull );
-    
+
     // Set the manipulation mode.
     // Set the manipulation mode.
     Sandbox.useManipulation( pull );
     Sandbox.useManipulation( pull );
 	SandboxScene.clear();
 	SandboxScene.clear();
     //SandboxWindow.delete();
     //SandboxWindow.delete();
 	GuiEditor.blankGui = new GuiControl();
 	GuiEditor.blankGui = new GuiControl();
-	
+
 	// Init menu
 	// Init menu
 	GuiEditorToy.initMenus();
 	GuiEditorToy.initMenus();
-	
+
     // Reset the toy initially.
     // Reset the toy initially.
     GuiEditorToy.reset();
     GuiEditorToy.reset();
-	
+
 }
 }
 
 
 function GuiEditorToy::initMenus( %this )
 function GuiEditorToy::initMenus( %this )
 {
 {
    if( isObject( %this.menuGroup ) )
    if( isObject( %this.menuGroup ) )
       %this.menuGroup.delete();
       %this.menuGroup.delete();
-      
+
    %this.menuGroup = new SimGroup();
    %this.menuGroup = new SimGroup();
-   
+
    //set up %cmdctrl variable so that it matches OS standards
    //set up %cmdctrl variable so that it matches OS standards
    %cmdCtrl = $platform $= "macos" ? "Cmd" : "Ctrl";
    %cmdCtrl = $platform $= "macos" ? "Cmd" : "Ctrl";
 
 
@@ -59,7 +59,7 @@ function GuiEditorToy::initMenus( %this )
       superClass = "MenuBuilder";
       superClass = "MenuBuilder";
       barPosition = 0;
       barPosition = 0;
       barName = "File";
       barName = "File";
-      
+
       item[0] = "New Gui..." TAB %cmdCtrl SPC "N" TAB "GuiEditorStartCreate();";
       item[0] = "New Gui..." TAB %cmdCtrl SPC "N" TAB "GuiEditorStartCreate();";
       item[1] = "Open Gui..." TAB %cmdCtrl SPC "O" TAB "GuiEditorOpenGui();";
       item[1] = "Open Gui..." TAB %cmdCtrl SPC "O" TAB "GuiEditorOpenGui();";
       item[2] = "-";
       item[2] = "-";
@@ -71,7 +71,7 @@ function GuiEditorToy::initMenus( %this )
       superClass = "MenuBuilder";
       superClass = "MenuBuilder";
       barPosition = 1;
       barPosition = 1;
       barName = "Layout";
       barName = "Layout";
-      
+
       item[0] = "Align Left" TAB %cmdCtrl SPC "L" TAB "GuiEditor.Justify(0);";
       item[0] = "Align Left" TAB %cmdCtrl SPC "L" TAB "GuiEditor.Justify(0);";
       item[1] = "Align Right" TAB %cmdCtrl SPC "R" TAB "GuiEditor.Justify(2);";
       item[1] = "Align Right" TAB %cmdCtrl SPC "R" TAB "GuiEditor.Justify(2);";
       item[2] = "Align Top" TAB %cmdCtrl SPC "T" TAB "GuiEditor.Justify(3);";
       item[2] = "Align Top" TAB %cmdCtrl SPC "T" TAB "GuiEditor.Justify(3);";
@@ -86,33 +86,33 @@ function GuiEditorToy::initMenus( %this )
       item[11] = "Lock Selection" TAB "" TAB "GuiEditorTreeView.lockSelection(true);";
       item[11] = "Lock Selection" TAB "" TAB "GuiEditorTreeView.lockSelection(true);";
       item[12] = "Unlock Selection" TAB "" TAB "GuiEditorTreeView.lockSelection(false);";
       item[12] = "Unlock Selection" TAB "" TAB "GuiEditorTreeView.lockSelection(false);";
    };
    };
-   
+
    %movemenu = new PopupMenu()
    %movemenu = new PopupMenu()
    {
    {
       superClass = "MenuBuilder";
       superClass = "MenuBuilder";
       barPosition = 2;
       barPosition = 2;
       barName = "Move";
       barName = "Move";
-      
+
       item[0] = "Nudge Up" TAB "Up" TAB "GuiEditor.moveSelection(0,-1);";
       item[0] = "Nudge Up" TAB "Up" TAB "GuiEditor.moveSelection(0,-1);";
       item[1] = "Nudge Down" TAB "Down" TAB "GuiEditor.moveSelection(0,1);";
       item[1] = "Nudge Down" TAB "Down" TAB "GuiEditor.moveSelection(0,1);";
 	  item[2] = "Nudge Right" TAB "Right" TAB "GuiEditor.moveSelection(1,0);";
 	  item[2] = "Nudge Right" TAB "Right" TAB "GuiEditor.moveSelection(1,0);";
 	  item[3] = "Nudge Left" TAB "Left" TAB "GuiEditor.moveSelection(-1,0);";
 	  item[3] = "Nudge Left" TAB "Left" TAB "GuiEditor.moveSelection(-1,0);";
    };
    };
-   
+
    // add menus to a group
    // add menus to a group
    %this.menuGroup.add(%fileMenu);
    %this.menuGroup.add(%fileMenu);
    %this.menuGroup.add(%layoutmenu);
    %this.menuGroup.add(%layoutmenu);
    %this.menuGroup.add(%movemenu);
    %this.menuGroup.add(%movemenu);
-   
+
    for( %i = 0; %i < %this.menuGroup.getCount(); %i++ )
    for( %i = 0; %i < %this.menuGroup.getCount(); %i++ )
      %this.menuGroup.getObject( %i ).attachToMenuBar();
      %this.menuGroup.getObject( %i ).attachToMenuBar();
-   
+
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 function GuiEditorToy::destroy( %this )
 function GuiEditorToy::destroy( %this )
-{   
+{
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -120,27 +120,27 @@ function GuiEditorToy::destroy( %this )
 function GuiEditorToy::reset(%this)
 function GuiEditorToy::reset(%this)
 {
 {
     // Clear the scene.
     // Clear the scene.
-    
+
 	Canvas.setContent(GuiEditorCtrl);
 	Canvas.setContent(GuiEditorCtrl);
-	
+
 	GuiEditorContent.add(GuiEditor.blankGui);
 	GuiEditorContent.add(GuiEditor.blankGui);
 	GuiEditorCtrl.add(GuiTreeViewWindow);
 	GuiEditorCtrl.add(GuiTreeViewWindow);
-	
+
 	$GuiRootElement = GuiBlank;
 	$GuiRootElement = GuiBlank;
 	%rootSize = $GuiRootElement.extent;
 	%rootSize = $GuiRootElement.extent;
-	
+
 	GuiEditor.setRoot(GuiBlank);
 	GuiEditor.setRoot(GuiBlank);
 	GuiEditorTreeView.open(GuiBlank);
 	GuiEditorTreeView.open(GuiBlank);
-	
+
 	GuiEditor.setFirstResponder();
 	GuiEditor.setFirstResponder();
-	
+
 	GuiEditor.setSnapToGrid("8");
 	GuiEditor.setSnapToGrid("8");
-	
+
     GuiEditorCtrl.add(GuiToolbox);
     GuiEditorCtrl.add(GuiToolbox);
     GuiEditorCtrl.add(GuiInspectorWindow);
     GuiEditorCtrl.add(GuiInspectorWindow);
-    
+
     //GuiEditorCtrl.add(CBBWindow);
     //GuiEditorCtrl.add(CBBWindow);
-	
+
 }
 }
 
 
 function GuiEditorToy::save(%this)
 function GuiEditorToy::save(%this)
@@ -150,7 +150,7 @@ function GuiEditorToy::save(%this)
 	{
 	{
 		return;
 		return;
 	}
 	}
-	
+
 	if(%guiObj.getName() !$= "")
 	if(%guiObj.getName() !$= "")
 	{
 	{
 		%name = %guiObj.getName() @ ".gui";
 		%name = %guiObj.getName() @ ".gui";
@@ -159,7 +159,7 @@ function GuiEditorToy::save(%this)
 	{
 	{
 		%name = "untitled.gui";
 		%name = "untitled.gui";
 	}
 	}
-	
+
 	%fo = new FileObject();
 	%fo = new FileObject();
 	%fo.openForWrite(%name);
 	%fo.openForWrite(%name);
 	%fo.writeLine("//--- Created With GUIEDITORTOY ---//");
 	%fo.writeLine("//--- Created With GUIEDITORTOY ---//");
@@ -167,7 +167,7 @@ function GuiEditorToy::save(%this)
 	%fo.writeLine("//--- GUIEDITORTOY END ---//");
 	%fo.writeLine("//--- GUIEDITORTOY END ---//");
 	%fo.close();
 	%fo.close();
 	%fo.delete();
 	%fo.delete();
-	
+
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -185,23 +185,23 @@ function GuiToolbox::onWake(%this)
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-function GuiEditorToolboxDrag::onTouchDragged(%this)
+function GuiEditorToolboxDrag::onTouchDragged(%this, %index, %text)
 {
 {
 	%position = %this.getGlobalPosition();
 	%position = %this.getGlobalPosition();
 	%cursorpos = Canvas.getCursorPos();
 	%cursorpos = Canvas.getCursorPos();
-   
+
 	%class = %this.getItemText(%this.getSelectedItem());
 	%class = %this.getItemText(%this.getSelectedItem());
 	%payload = eval("return new " @ %class @ "();");
 	%payload = eval("return new " @ %class @ "();");
 	if(!isObject(%payload))
 	if(!isObject(%payload))
 		return;
 		return;
-      
+
 	%xOffset = getWord(%payload.extent, 0) / 2;
 	%xOffset = getWord(%payload.extent, 0) / 2;
-	%yOffset = getWord(%payload.extent, 1) / 2; 
-	
+	%yOffset = getWord(%payload.extent, 1) / 2;
+
 	// position where the drag will start, to prevent visible jumping.
 	// position where the drag will start, to prevent visible jumping.
 	%xPos = getWord(%cursorpos, 0) - %xOffset;
 	%xPos = getWord(%cursorpos, 0) - %xOffset;
 	%yPos = getWord(%cursorpos, 1) - %yOffset;
 	%yPos = getWord(%cursorpos, 1) - %yOffset;
-	   
+
 	%dragCtrl = new GuiDragAndDropControl() {
 	%dragCtrl = new GuiDragAndDropControl() {
 		canSaveDynamicFields = "0";
 		canSaveDynamicFields = "0";
 		Profile = "GuiDefaultProfile";
 		Profile = "GuiDefaultProfile";
@@ -218,7 +218,7 @@ function GuiEditorToolboxDrag::onTouchDragged(%this)
 
 
 	%dragCtrl.add(%payload);
 	%dragCtrl.add(%payload);
 	Canvas.getContent().add(%dragCtrl);
 	Canvas.getContent().add(%dragCtrl);
-	   
+
 	%dragCtrl.startDragging(%xOffset, %yOffset);
 	%dragCtrl.startDragging(%xOffset, %yOffset);
 }
 }
 
 
@@ -230,12 +230,12 @@ function GuiEditor::onControlDragged(%this, %payload, %position)
 	%x = getWord(%pos, 0);
 	%x = getWord(%pos, 0);
 	%y = getWord(%pos, 1);
 	%y = getWord(%pos, 1);
 	%target = GuiEditorContent.findHitControl(%x, %y);
 	%target = GuiEditorContent.findHitControl(%x, %y);
-	
+
 	while(! %target.isContainer )
 	while(! %target.isContainer )
 	{
 	{
 		%target = %target.getParent();
 		%target = %target.getParent();
 	}
 	}
-	
+
 	if(%target != %this.getCurrentAddset())
 	if(%target != %this.getCurrentAddset())
 	{
 	{
 		%this.setCurrentAddSet(%target);
 		%this.setCurrentAddSet(%target);
@@ -246,19 +246,19 @@ function GuiEditor::onControlDragged(%this, %payload, %position)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 function GuiEditor::onControlDropped(%this, %payload, %position)
 function GuiEditor::onControlDropped(%this, %payload, %position)
-{  
+{
    %pos = %payload.getGlobalPosition();
    %pos = %payload.getGlobalPosition();
    %x = getWord(%pos, 0);
    %x = getWord(%pos, 0);
    %y = getWord(%pos, 1);
    %y = getWord(%pos, 1);
-   
+
    if(%x > $GuiRootElement.extent.x || %y > $GuiRootElement.extent.y)
    if(%x > $GuiRootElement.extent.x || %y > $GuiRootElement.extent.y)
    {
    {
       messageBox("Error", "Cannot add a control outside the root gui element!");
       messageBox("Error", "Cannot add a control outside the root gui element!");
       return;
       return;
    }
    }
-   
+
    %this.addNewCtrl(%payload);
    %this.addNewCtrl(%payload);
-   
+
    %payload.setPositionGlobal(%x, %y);
    %payload.setPositionGlobal(%x, %y);
    %this.setFirstResponder();
    %this.setFirstResponder();
 }
 }
@@ -279,7 +279,7 @@ function GuiEditor::onSelectionMoved(%this, %ctrl)
 }
 }
 
 
 function GuiEditor::onClearSelected(%this)
 function GuiEditor::onClearSelected(%this)
-{ 
+{
    GuiEditorTreeView.clearSelection();
    GuiEditorTreeView.clearSelection();
 }
 }
 
 
@@ -302,7 +302,7 @@ function GuiEditor::onAddSelected(%this,%ctrl)
 
 
 function GuiEditor::onRemoveSelected(%this,%ctrl)
 function GuiEditor::onRemoveSelected(%this,%ctrl)
 {
 {
-   GuiEditorTreeView.removeSelection(%ctrl); 
+   GuiEditorTreeView.removeSelection(%ctrl);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -310,7 +310,7 @@ function GuiEditor::onRemoveSelected(%this,%ctrl)
 function GuiEditorTreeView::update(%this)
 function GuiEditorTreeView::update(%this)
 {
 {
 	%obj = GuiEditorContent.getObject(0);
 	%obj = GuiEditorContent.getObject(0);
-	
+
 	if(!isObject(%obj))
 	if(!isObject(%obj))
 	{
 	{
 		GuiEditorTreeView.clear();
 		GuiEditorTreeView.clear();
@@ -340,7 +340,7 @@ function GuiEditorTreeView::onRemoveSelection(%this, %ctrl)
 }
 }
 
 
 function GuiEditorTreeView::onDeleteSelection(%this)
 function GuiEditorTreeView::onDeleteSelection(%this)
-{ 
+{
    GuiEditor.clearSelection();
    GuiEditor.clearSelection();
 }
 }
 
 
@@ -353,8 +353,3 @@ function GuiEditorTreeView::onSelect(%this, %obj)
       GuiEditor.select(%obj);
       GuiEditor.select(%obj);
    }
    }
 }
 }
-
-
-
-
-

+ 24 - 3
toybox/Sandbox/1/gui/guiProfiles.cs

@@ -191,17 +191,38 @@ if(!isObject(GuiPanelProfile)) new GuiControlProfile (GuiPanelProfile : GuiDefau
 	category = "defaultPanel";
 	category = "defaultPanel";
 };
 };
 
 
+if (!isObject(GuiListBoxBorderProfile)) new GuiBorderProfile (GuiListBoxBorderProfile : GuiDefaultBorderProfile)
+{
+	margin = 1;
+	marginHL = 1;
+	marginSL = 1;
+	MarginNA = 1;
+
+	padding = 4;
+	paddingHL = 4;
+	paddingSL = 4;
+	paddingNA = 4;
+};
+
 if(!isObject(GuiListBoxProfile)) new GuiControlProfile (GuiListBoxProfile : GuiDefaultProfile)
 if(!isObject(GuiListBoxProfile)) new GuiControlProfile (GuiListBoxProfile : GuiDefaultProfile)
 {
 {
     // fill color
     // fill color
     fillColor = $color1;
     fillColor = $color1;
     fillColorHL = AdjustColorValue($color1, 10);
     fillColorHL = AdjustColorValue($color1, 10);
-    fillColorSL = AdjustColorValue($color1, 15);
+    fillColorSL = $color4;
     fillColorNA = SetColorAlpha($color1, 100);
     fillColorNA = SetColorAlpha($color1, 100);
 	align = left;
 	align = left;
-	tab = true;
-	canKeyFocus = true;
+
+	tab = false;
+	canKeyFocus = false;
 	category = "defaultListBox";
 	category = "defaultListBox";
+
+	fontColor = $color3;
+	fontColorHL = AdjustColorValue($color3, 20);
+	fontColorSL = AdjustColorValue($color3, 20);
+	fontColorNA = SetColorAlpha($color1, 100);
+
+	borderDefault = GuiListBoxBorderProfile;
 };
 };
 
 
 if(!isObject(GuiWindowBorderProfile)) new GuiBorderProfile (GuiWindowBorderProfile : GuiDefaultBorderProfile)
 if(!isObject(GuiWindowBorderProfile)) new GuiBorderProfile (GuiWindowBorderProfile : GuiDefaultBorderProfile)