//-----------------------------------------------------------------------------
// GuiInspectorDynamicGroup - inspectGroup override
//-----------------------------------------------------------------------------
bool GuiInspectorDynamicGroup::inspectGroup()
{
   // clear the first responder if it's set
   mStack->clearFirstResponder();

   // Clearing the fields and recreating them will more than likely be more
   // efficient than looking up existent fields, updating them, and then iterating
   // over existent fields and making sure they still exist, if not, deleting them.
   clearFields();

   // Create a vector of the fields
   Vector< FieldEntry > flist;
   
   const U32 numTargets = mParent->getNumInspectObjects();
   for( U32 i = 0; i < numTargets; ++ i )
   {
      SimObject* target = mParent->getInspectObject( i );
      
      // Then populate with fields
      SimFieldDictionary * fieldDictionary = target->getFieldDictionary();
      for(SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
      {
         if( i == 0 )
         {
            flist.increment();
            flist.last().mEntry = *ditr;
            flist.last().mNumTargets = 1;
         }
         else
         {
            const U32 numFields = flist.size();
            for( U32 n = 0; n < numFields; ++ n )
               if( flist[ n ].mEntry->slotName == ( *ditr )->slotName )
               {
                  flist[ n ].mNumTargets ++;
                  break;
               }
         }
      }
   }

   dQsort( flist.address(), flist.size(), sizeof( FieldEntry ), compareEntries );

   for(U32 i = 0; i < flist.size(); i++)
   {
      if( flist[ i ].mNumTargets != numTargets )
         continue;

      SimFieldDictionary::Entry* entry = flist[i].mEntry;

      // Create a dynamic field inspector.  Can't reuse typed GuiInspectorFields as
      // these rely on AbstractClassRep::Fields.
      GuiInspectorDynamicField *field = new GuiInspectorDynamicField( mParent, this, entry );

      // Register the inspector field and add it to our lists
      if( field->registerObject() )
      {
         mChildren.push_back( field );
         mStack->addObject( field );
      }
      else
         delete field;
   }

   mStack->pushObjectToBack(mAddCtrl);

   setUpdate();

   return true;
}
void GuiInspectorDynamicField::renameField( const char* newFieldName )
{
   newFieldName = StringTable->insert( newFieldName );
   
   if ( mDynField == NULL || mParent == NULL || mEdit == NULL )
   {
      Con::warnf("GuiInspectorDynamicField::renameField - No target object or dynamic field data found!" );
      return;
   }

   if ( !newFieldName )
   {
      Con::warnf("GuiInspectorDynamicField::renameField - Invalid field name specified!" );
      return;
   }

   // Only proceed if the name has changed
   if ( dStricmp( newFieldName, getFieldName() ) == 0 )
      return;
      
   // Grab a pointer to our parent and cast it to GuiInspectorDynamicGroup
   GuiInspectorDynamicGroup *group = dynamic_cast<GuiInspectorDynamicGroup*>(mParent);
   if ( group == NULL )
   {
      Con::warnf("GuiInspectorDynamicField::renameField - Unable to locate GuiInspectorDynamicGroup parent!" );
      return;
   }
   
   const U32 numTargets = mInspector->getNumInspectObjects();
   if( numTargets > 1 )
   { mInspector->onBeginCompoundEdit_callback(); }
      
   const char* oldFieldName = getFieldName();
   SimFieldDictionary::Entry* newEntry = NULL;
   
   for( U32 i = 0; i < numTargets; ++ i )
   {
      SimObject* target = mInspector->getInspectObject( i );
      
      // Make sure the new field is not already defined as a static field
      // on the object.
      
      if( target->isField( newFieldName ) )
      {
         // New field is already defined.  If we can, let the scripts handle
         // the error.  Otherwise, just emit an error on the console and proceed.
         
         if( numTargets == 1 )
         { mInspector->onFieldRenameAlreadyDefined_callback( target->getIdString(), oldFieldName, newFieldName ); }
         else
         { 
             Con::errorf( "GuiInspectorDynamicField::renameField - field '%s' is already defined on %i:%s (%s)", 
               newFieldName, target->getId(), target->getClassName(), target->getName() );
         }
               
         // Reset the text entry.
               
         if( mRenameCtrl )
            mRenameCtrl->setText( oldFieldName );
            
         continue;
      }
      
      char currentValue[1024] = {0};
      // Grab our current dynamic field value (we use a temporary buffer as this gets corrupted upon Con::eval)
      dSprintf( currentValue, sizeof( currentValue ), "%s", target->getDataField( oldFieldName, NULL ) );

      // Unset the old field and set the new field.
      
      target->setDataField( oldFieldName, NULL, "" );
      target->setDataField( newFieldName, NULL, currentValue );

      // Notify script.
      
      mInspector->onFieldRenamed_callback( target->getIdString(), oldFieldName, newFieldName );
      
      // Look up the new SimFieldDictionary entry.
      
      if( !newEntry )
      {
         newEntry = target->getFieldDictionary()->findDynamicField( newFieldName );
         if( !newEntry )
         {
            Con::warnf( "GuiInspectorDynamicField::renameField - could not find new field '%s' on object %i:%s (%s)",
               newFieldName, target->getId(), target->getClassName(), target->getName() );
         }
         
         mDynField = newEntry;
      }
   }

   if( numTargets > 1 )
   { mInspector->onEndCompoundEdit_callback(); }
      
   // Lastly we need to reassign our validate field for our value edit control
   char szBuffer[1024];
   dSprintf( szBuffer, sizeof( szBuffer ), "%d.apply(%d.getText());", getId(), mEdit->getId() );
   mEdit->setField("validate", szBuffer );

   if( mDeleteButton )
   {
      dSprintf(szBuffer, sizeof( szBuffer ), "%d.apply("");%d.inspectGroup();", getId(), newFieldName, group->getId());
      mDeleteButton->setField("Command", szBuffer);
   }
}