field.cpp
Engine/source/gui/editor/inspector/field.cpp
Public Functions
ConsoleDocClass(GuiInspectorField , "@brief The <a href="/coding/class/classguiinspectorfield/">GuiInspectorField</a> <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> representation of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single abstract " "field <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/class/classconsoleobject/">ConsoleObject</a> derived <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
DefineEngineMethod(GuiInspectorField , apply , void , (const char *newValue, bool callbacks) , (true) )
DefineEngineMethod(GuiInspectorField , applyWithoutUndo , void , (const char *data) , "() - Set field <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> without recording undo (same as 'apply( <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>, false )')." )
DefineEngineMethod(GuiInspectorField , getData , const char * , () , "() - Return the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> currently displayed on the field." )
DefineEngineMethod(GuiInspectorField , getInspectedFieldName , const char * , () , "() - Return the name of the field edited by this inspector field." )
DefineEngineMethod(GuiInspectorField , getInspectedFieldType , const char * , () , "() - Return the type of the field edited by this inspector field." )
DefineEngineMethod(GuiInspectorField , getInspector , S32 , () , "() - Return the <a href="/coding/class/classguiinspector/">GuiInspector</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> which this field belongs." )
DefineEngineMethod(GuiInspectorField , reset , void , () , "() - Reset <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> default value." )
DefineEngineMethod(GuiInspectorField , setCaption , void , (String newCaption) , "() - Reset <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> default value." )
DefineEngineMethod(GuiInspectorField , setEditControl , void , (GuiControl *editCtrl) , (nullAsType< GuiControl * >()) , "() - Reset <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> default value." )
DefineEngineMethod(GuiInspectorField , setHeightOverride , void , (bool useOverride, U32 heightOverride) , "" )
Detailed Description
Public Functions
ConsoleDocClass(GuiInspectorField , "@brief The <a href="/coding/class/classguiinspectorfield/">GuiInspectorField</a> <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> representation of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single abstract " "field <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/class/classconsoleobject/">ConsoleObject</a> derived <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
DefineEngineMethod(GuiInspectorField , apply , void , (const char *newValue, bool callbacks) , (true) )
DefineEngineMethod(GuiInspectorField , applyWithoutUndo , void , (const char *data) , "() - Set field <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> without recording undo (same as 'apply( <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>, false )')." )
DefineEngineMethod(GuiInspectorField , getData , const char * , () , "() - Return the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> currently displayed on the field." )
DefineEngineMethod(GuiInspectorField , getInspectedFieldName , const char * , () , "() - Return the name of the field edited by this inspector field." )
DefineEngineMethod(GuiInspectorField , getInspectedFieldType , const char * , () , "() - Return the type of the field edited by this inspector field." )
DefineEngineMethod(GuiInspectorField , getInspector , S32 , () , "() - Return the <a href="/coding/class/classguiinspector/">GuiInspector</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> which this field belongs." )
DefineEngineMethod(GuiInspectorField , reset , void , () , "() - Reset <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> default value." )
DefineEngineMethod(GuiInspectorField , setCaption , void , (String newCaption) , "() - Reset <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> default value." )
DefineEngineMethod(GuiInspectorField , setEditControl , void , (GuiControl *editCtrl) , (nullAsType< GuiControl * >()) , "() - Reset <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> default value." )
DefineEngineMethod(GuiInspectorField , setHeightOverride , void , (bool useOverride, U32 heightOverride) , "" )
IMPLEMENT_CONOBJECT(GuiInspectorField )
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 "console/engineAPI.h" 25#include "platform/platform.h" 26#include "gui/editor/inspector/field.h" 27#include "gui/buttons/guiIconButtonCtrl.h" 28#include "gui/editor/guiInspector.h" 29#include "core/util/safeDelete.h" 30#include "gfx/gfxDrawUtil.h" 31#include "math/mathTypes.h" 32#include "core/strings/stringUnit.h" 33 34 35IMPLEMENT_CONOBJECT(GuiInspectorField); 36 37ConsoleDocClass( GuiInspectorField, 38 "@brief The GuiInspectorField control is a representation of a single abstract " 39 "field for a given ConsoleObject derived object.\n\n" 40 "Editor use only.\n\n" 41 "@internal" 42); 43 44//----------------------------------------------------------------------------- 45 46GuiInspectorField::GuiInspectorField( GuiInspector* inspector, 47 GuiInspectorGroup* parent, 48 AbstractClassRep::Field* field ) 49 : mParent( parent ), 50 mInspector( inspector ), 51 mField( field ), 52 mFieldArrayIndex( NULL ), 53 mEdit( NULL ), 54 mTargetObject(NULL), 55 mUseHeightOverride(false), 56 mHighlighted(false), 57 mHeightOverride(18), 58 mSpecialEditField(false), 59 mVariableName(StringTable->EmptyString()), 60 mCallbackName(StringTable->EmptyString()) 61{ 62 if( field != NULL ) 63 mCaption = field->pFieldname; 64 else 65 mCaption = StringTable->EmptyString(); 66 67 setCanSave( false ); 68 setBounds(0,0,100,18); 69 70 if( field != NULL ) 71 _setFieldDocs( field->pFieldDocs ); 72} 73 74//----------------------------------------------------------------------------- 75 76GuiInspectorField::GuiInspectorField() 77 : mParent( NULL ), 78 mInspector( NULL ), 79 mField( NULL ), 80 mEdit( NULL ), 81 mCaption( StringTable->EmptyString() ), 82 mFieldArrayIndex( NULL ), 83 mHighlighted( false ), 84 mTargetObject(NULL), 85 mVariableName(StringTable->EmptyString()), 86 mCallbackName(StringTable->EmptyString()), 87 mSpecialEditField(false), 88 mUseHeightOverride(false), 89 mHeightOverride(18) 90{ 91 setCanSave( false ); 92} 93 94//----------------------------------------------------------------------------- 95 96GuiInspectorField::~GuiInspectorField() 97{ 98} 99 100//----------------------------------------------------------------------------- 101 102void GuiInspectorField::init( GuiInspector *inspector, GuiInspectorGroup *group ) 103{ 104 mInspector = inspector; 105 mParent = group; 106} 107 108//----------------------------------------------------------------------------- 109 110bool GuiInspectorField::onAdd() 111{ 112 setInspectorProfile(); 113 114 if ( !Parent::onAdd() ) 115 return false; 116 117 if ( !mInspector ) 118 return false; 119 120 mEdit = constructEditControl(); 121 if ( mEdit == NULL ) 122 return false; 123 124 S32 fieldHeight = 18; 125 126 if (mUseHeightOverride) 127 fieldHeight = mHeightOverride; 128 129 setBounds(0,0,100, fieldHeight); 130 131 // Add our edit as a child 132 addObject( mEdit ); 133 134 // Calculate Caption and EditCtrl Rects 135 updateRects(); 136 137 // Force our editField to set it's value 138 updateValue(); 139 140 Con::evaluatef("%d.edit = %d;", this->getId(), mEdit->getId()); 141 return true; 142} 143 144//----------------------------------------------------------------------------- 145 146bool GuiInspectorField::resize( const Point2I &newPosition, const Point2I &newExtent ) 147{ 148 if ( !Parent::resize( newPosition, newExtent ) ) 149 return false; 150 151 return updateRects(); 152} 153 154//----------------------------------------------------------------------------- 155 156void GuiInspectorField::onRender( Point2I offset, const RectI &updateRect ) 157{ 158 RectI ctrlRect(offset, getExtent()); 159 160 // Render fillcolor... 161 if ( mProfile->mOpaque ) 162 GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColor); 163 164 // Render caption... 165 if ( mCaption && mCaption[0] ) 166 { 167 // Backup current ClipRect 168 RectI clipBackup = GFX->getClipRect(); 169 170 RectI clipRect = updateRect; 171 172 // The rect within this control in which our caption must fit. 173 RectI rect( offset + mCaptionRect.point + mProfile->mTextOffset, mCaptionRect.extent + Point2I(1,1) - Point2I(5,0) ); 174 175 // Now clipRect is the amount of our caption rect that is actually visible. 176 bool hit = clipRect.intersect( rect ); 177 178 if ( hit ) 179 { 180 GFX->setClipRect( clipRect ); 181 GFXDrawUtil *drawer = GFX->getDrawUtil(); 182 183 // Backup modulation color 184 ColorI currColor; 185 drawer->getBitmapModulation( &currColor ); 186 187 // Draw caption background... 188 if( !isActive() ) 189 GFX->getDrawUtil()->drawRectFill( clipRect, mProfile->mFillColorNA ); 190 else if ( mHighlighted ) 191 GFX->getDrawUtil()->drawRectFill( clipRect, mProfile->mFillColorHL ); 192 193 // Draw caption text... 194 195 drawer->setBitmapModulation( !isActive() ? mProfile->mFontColorNA : mHighlighted ? mProfile->mFontColorHL : mProfile->mFontColor ); 196 197 // Clip text with '...' if too long to fit 198 String clippedText( mCaption ); 199 clipText( clippedText, clipRect.extent.x ); 200 201 renderJustifiedText( offset + mProfile->mTextOffset, getExtent(), clippedText ); 202 203 // Restore modulation color 204 drawer->setBitmapModulation( currColor ); 205 206 // Restore previous ClipRect 207 GFX->setClipRect( clipBackup ); 208 } 209 } 210 211 // Render Children... 212 renderChildControls(offset, updateRect); 213 214 // Render border... 215 if ( mProfile->mBorder ) 216 renderBorder(ctrlRect, mProfile); 217 218 // Render divider... 219 Point2I worldPnt = mEditCtrlRect.point + offset; 220 GFX->getDrawUtil()->drawLine( worldPnt.x - 5, 221 worldPnt.y, 222 worldPnt.x - 5, 223 worldPnt.y + getHeight(), 224 !isActive() ? mProfile->mBorderColorNA : mHighlighted ? mProfile->mBorderColorHL : mProfile->mBorderColor ); 225} 226 227//----------------------------------------------------------------------------- 228 229void GuiInspectorField::setFirstResponder( GuiControl *firstResponder ) 230{ 231 Parent::setFirstResponder( firstResponder ); 232 233 if ( firstResponder == this || firstResponder == mEdit ) 234 { 235 mInspector->setHighlightField( this ); 236 } 237} 238 239//----------------------------------------------------------------------------- 240 241void GuiInspectorField::onMouseDown( const GuiEvent &event ) 242{ 243 if ( mCaptionRect.pointInRect( globalToLocalCoord( event.mousePoint ) ) ) 244 { 245 if ( mEdit ) 246 //mEdit->onMouseDown( event ); 247 mInspector->setHighlightField( this ); 248 } 249 else 250 Parent::onMouseDown( event ); 251} 252 253//----------------------------------------------------------------------------- 254 255void GuiInspectorField::onRightMouseUp( const GuiEvent &event ) 256{ 257 if ( mCaptionRect.pointInRect( globalToLocalCoord( event.mousePoint ) ) ) 258 Con::executef( mInspector, "onFieldRightClick", getIdString() ); 259 else 260 Parent::onMouseDown( event ); 261} 262 263//----------------------------------------------------------------------------- 264 265void GuiInspectorField::setData( const char* data, bool callbacks ) 266{ 267 if (mSpecialEditField) 268 { 269 if (mTargetObject != nullptr && mVariableName != StringTable->EmptyString()) 270 { 271 mTargetObject->setDataField(mVariableName, NULL, data); 272 273 if (mCallbackName != StringTable->EmptyString()) 274 Con::executef(mInspector, mCallbackName, mVariableName, data, mTargetObject); 275 } 276 else if (mVariableName != StringTable->EmptyString()) 277 { 278 Con::setVariable(mVariableName, data); 279 280 if (mCallbackName != StringTable->EmptyString()) 281 Con::executef(mInspector, mCallbackName, mVariableName, data); 282 } 283 } 284 285 if( mField == NULL ) 286 return; 287 288 if( verifyData( data ) ) 289 { 290 String strData = data; 291 const U32 numTargets = mInspector->getNumInspectObjects(); 292 293 if( callbacks && numTargets > 1 ) 294 Con::executef( mInspector, "onBeginCompoundEdit" ); 295 296 for( U32 i = 0; i < numTargets; ++ i ) 297 { 298 //For now, for simplicity's sake, you can only edit the components in a simple edit 299 SimObject* target = NULL; 300 if (numTargets == 1) 301 { 302 target = mTargetObject; 303 304 if (!target) 305 target = mInspector->getInspectObject(i); 306 } 307 else 308 { 309 target = mInspector->getInspectObject(i); 310 } 311 312 String oldValue = target->getDataField( mField->pFieldname, mFieldArrayIndex); 313 314 // For numeric fields, allow input expressions. 315 316 String newValue = strData; 317 S32 type= mField->type; 318 if( type == TypeS8 || type == TypeS32 || type == TypeF32 ) 319 { 320 char buffer[ 2048 ]; 321 expandEscape( buffer, newValue ); 322 newValue = (const char*)Con::evaluatef( "%%f = \"%s\"; return ( %s );", oldValue.c_str(), buffer ); 323 } 324 else if( type == TypeS32Vector 325 || type == TypeF32Vector 326 || type == TypeColorI 327 || type == TypeColorF 328 || type == TypePoint2I 329 || type == TypePoint2F 330 || type == TypePoint3F 331 || type == TypePoint4F 332 || type == TypeRectI 333 || type == TypeRectF 334 || type == TypeMatrixPosition 335 || type == TypeMatrixRotation 336 || type == TypeBox3F 337 || type == TypeRectUV 338 || type == TypeRotationF) 339 { 340 //TODO: we should actually take strings into account and not chop things up between quotes 341 342 U32 numNewUnits = StringUnit::getUnitCount( newValue, " \t\n\r" ); 343 344 StringBuilder strNew; 345 bool isFirst = true; 346 for( U32 n = 0; n < numNewUnits; ++ n ) 347 { 348 char oldComponentVal[ 1024 ]; 349 StringUnit::getUnit( oldValue, n, " \t\n\r", oldComponentVal, sizeof( oldComponentVal ) ); 350 351 char newComponentExpr[ 1024 ]; 352 StringUnit::getUnit( newValue, n, " \t\n\r", newComponentExpr, sizeof( newComponentExpr ) ); 353 354 char buffer[ 2048 ]; 355 expandEscape( buffer, newComponentExpr ); 356 357 const char* newComponentVal = Con::evaluatef( "%%f = \"%s\"; %%v = \"%s\"; return ( %s );", 358 oldComponentVal, oldValue.c_str(), buffer ); 359 360 if( !isFirst ) 361 strNew.append( ' ' ); 362 strNew.append( newComponentVal ); 363 364 isFirst = false; 365 } 366 367 newValue = strNew.end(); 368 } 369 370 target->inspectPreApply(); 371 372 // Fire callback single-object undo. 373 374 if( callbacks ) 375 Con::executef( mInspector, "onInspectorFieldModified", 376 target->getIdString(), 377 mField->pFieldname, 378 mFieldArrayIndex ? mFieldArrayIndex : "(null)", 379 oldValue.c_str(), 380 newValue.c_str() ); 381 382 target->setDataField( mField->pFieldname, mFieldArrayIndex, newValue ); 383 384 // Give the target a chance to validate. 385 target->inspectPostApply(); 386 } 387 388 if( callbacks && numTargets > 1 ) 389 Con::executef( mInspector, "onEndCompoundEdit" ); 390 } 391 392 // Force our edit to update 393 updateValue(); 394} 395 396//----------------------------------------------------------------------------- 397 398const char* GuiInspectorField::getData( U32 inspectObjectIndex ) 399{ 400 if (!mSpecialEditField) 401 { 402 if (mField == NULL) 403 return ""; 404 405 if (mTargetObject) 406 return mTargetObject->getDataField(mField->pFieldname, mFieldArrayIndex); 407 408 return mInspector->getInspectObject(inspectObjectIndex)->getDataField(mField->pFieldname, mFieldArrayIndex); 409 } 410 else 411 { 412 if (mTargetObject != nullptr && mVariableName != StringTable->EmptyString()) 413 { 414 return mTargetObject->getDataField(mVariableName, NULL); 415 } 416 else if (mVariableName != StringTable->EmptyString()) 417 { 418 return Con::getVariable(mVariableName); 419 } 420 else 421 { 422 return ""; 423 } 424 } 425} 426 427//----------------------------------------------------------------------------- 428 429void GuiInspectorField::resetData() 430{ 431 if( !mField ) 432 return; 433 434 SimObject* inspectObject = getInspector()->getInspectObject(); 435 436 SimObject* tempObject = static_cast< SimObject* >( inspectObject->getClassRep()->create() ); 437 setData( tempObject->getDataField( mField->pFieldname, mFieldArrayIndex ) ); 438 delete tempObject; 439} 440 441//----------------------------------------------------------------------------- 442 443void GuiInspectorField::setInspectorField( AbstractClassRep::Field *field, StringTableEntry caption, const char*arrayIndex ) 444{ 445 mField = field; 446 447 if ( arrayIndex != NULL ) 448 mFieldArrayIndex = StringTable->insert( arrayIndex ); 449 450 if ( !caption || !caption[0] ) 451 mCaption = getFieldName(); 452 else 453 mCaption = caption; 454 455 if ( mField != NULL ) 456 _setFieldDocs( mField->pFieldDocs ); 457} 458 459//----------------------------------------------------------------------------- 460 461StringTableEntry GuiInspectorField::getRawFieldName() 462{ 463 if( !mField ) 464 return StringTable->EmptyString(); 465 466 return mField->pFieldname; 467} 468 469//----------------------------------------------------------------------------- 470 471StringTableEntry GuiInspectorField::getFieldName() 472{ 473 // Sanity 474 if ( mField == NULL ) 475 return StringTable->EmptyString(); 476 477 // Array element? 478 if( mFieldArrayIndex != NULL ) 479 { 480 S32 frameTempSize = dStrlen( mField->pFieldname ) + 32; 481 FrameTemp<char> valCopy( frameTempSize ); 482 dSprintf( (char *)valCopy, frameTempSize, "%s[%s]", mField->pFieldname, mFieldArrayIndex ); 483 484 // Return formatted element 485 return StringTable->insert( valCopy ); 486 } 487 488 // Plain field name. 489 return mField->pFieldname; 490} 491 492//----------------------------------------------------------------------------- 493 494StringTableEntry GuiInspectorField::getFieldType() 495{ 496 if( !mField ) 497 return StringTable->EmptyString(); 498 499 return ConsoleBaseType::getType( mField->type )->getTypeName(); 500} 501 502//----------------------------------------------------------------------------- 503 504GuiControl* GuiInspectorField::constructEditControl() 505{ 506 GuiControl* retCtrl = new GuiTextEditCtrl(); 507 508 static StringTableEntry sProfile = StringTable->insert( "profile" ); 509 retCtrl->setDataField( sProfile, NULL, "GuiInspectorTextEditProfile" ); 510 511 _registerEditControl( retCtrl ); 512 513 char szBuffer[512]; 514 dSprintf( szBuffer, 512, "%d.apply(%d.getText());",getId(), retCtrl->getId() ); 515 516 // Suffices to hook on to "validate" as regardless of whether we lose 517 // focus through the user pressing enter or clicking away on another 518 // keyboard control, we will see a validate call. 519 520 retCtrl->setField("validate", szBuffer ); 521 522 return retCtrl; 523} 524 525//----------------------------------------------------------------------------- 526 527void GuiInspectorField::setInspectorProfile() 528{ 529 GuiControlProfile *profile = NULL; 530 531 if( mInspector && (mInspector->getNumInspectObjects() > 1) ) 532 { 533 if( !hasSameValueInAllObjects() ) 534 Sim::findObject( "GuiInspectorMultiFieldDifferentProfile", profile ); 535 else 536 Sim::findObject( "GuiInspectorMultiFieldProfile", profile ); 537 } 538 539 if( !profile ) 540 Sim::findObject( "GuiInspectorFieldProfile", profile ); 541 542 if( profile ) 543 setControlProfile( profile ); 544} 545 546//----------------------------------------------------------------------------- 547 548void GuiInspectorField::setValue( StringTableEntry newValue ) 549{ 550 GuiTextEditCtrl *ctrl = dynamic_cast<GuiTextEditCtrl*>( mEdit ); 551 if( ctrl != NULL ) 552 ctrl->setText( newValue ); 553} 554 555//----------------------------------------------------------------------------- 556 557void GuiInspectorField::setEditControl(GuiControl* editCtrl) 558{ 559 if (mEdit) 560 mEdit->deleteObject(); 561 562 mEdit = editCtrl; 563 addObject(mEdit); 564} 565 566//----------------------------------------------------------------------------- 567 568bool GuiInspectorField::updateRects() 569{ 570 S32 dividerPos, dividerMargin; 571 mInspector->getDivider( dividerPos, dividerMargin ); 572 573 Point2I fieldExtent = getExtent(); 574 Point2I fieldPos = getPosition(); 575 576 S32 editWidth = dividerPos - dividerMargin; 577 578 mEditCtrlRect.set( fieldExtent.x - dividerPos + dividerMargin, 1, editWidth, fieldExtent.y - 1 ); 579 mCaptionRect.set( 0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y ); 580 581 if ( !mEdit ) 582 return false; 583 584 return mEdit->resize( mEditCtrlRect.point, mEditCtrlRect.extent ); 585} 586 587//----------------------------------------------------------------------------- 588 589void GuiInspectorField::updateValue() 590{ 591 if( mInspector->getNumInspectObjects() > 1 ) 592 { 593 setInspectorProfile(); 594 595 if( !hasSameValueInAllObjects() ) 596 setValue( StringTable->EmptyString() ); 597 else 598 setValue( getData() ); 599 } 600 else 601 setValue( getData() ); 602} 603 604//----------------------------------------------------------------------------- 605 606void GuiInspectorField::setHLEnabled( bool enabled ) 607{ 608 mHighlighted = enabled; 609 if ( mHighlighted ) 610 { 611 if ( mEdit && !mEdit->isFirstResponder() ) 612 { 613 mEdit->setFirstResponder(); 614 GuiTextEditCtrl *edit = dynamic_cast<GuiTextEditCtrl*>( mEdit ); 615 if ( edit ) 616 { 617 mouseUnlock(); 618 edit->mouseLock(); 619 edit->setCursorPos(0); 620 } 621 } 622 _executeSelectedCallback(); 623 } 624} 625 626//----------------------------------------------------------------------------- 627 628bool GuiInspectorField::hasSameValueInAllObjects() 629{ 630 char value1[ 2048 ]; 631 632 // Get field value from first object. 633 634 const char* data1 = getData( 0 ); 635 if( data1 ) 636 { 637 dStrncpy( value1, data1, sizeof( value1 ) ); 638 value1[ sizeof( value1 ) - 1 ] = 0; 639 } 640 else 641 value1[ 0 ] = 0; 642 643 // Check if all other objects have the same value. 644 645 const U32 numObjects = mInspector->getNumInspectObjects(); 646 for( U32 i = 1; i < numObjects; ++ i ) 647 { 648 const char* value2 = getData( i ); 649 if( !value2 ) 650 value2 = ""; 651 652 if( String::compare( value1, value2 ) != 0 ) 653 return false; 654 } 655 656 return true; 657} 658 659//----------------------------------------------------------------------------- 660 661void GuiInspectorField::_executeSelectedCallback() 662{ 663 if( mField ) 664 Con::executef( mInspector, "onFieldSelected", mField->pFieldname, ConsoleBaseType::getType(mField->type)->getTypeName(), mFieldDocs.c_str() ); 665} 666 667//----------------------------------------------------------------------------- 668 669void GuiInspectorField::_registerEditControl( GuiControl *ctrl ) 670{ 671 char szName[512]; 672 if(mInspector->getInspectObject() != nullptr) 673 dSprintf( szName, 512, "IE_%s_%d_%s_Field", ctrl->getClassName(), mInspector->getInspectObject()->getId(), mCaption); 674 else 675 dSprintf(szName, 512, "IE_%s_%s_Field", ctrl->getClassName(), mCaption); 676 677 // Register the object 678 ctrl->registerObject( szName ); 679} 680 681//----------------------------------------------------------------------------- 682 683void GuiInspectorField::_setFieldDocs( StringTableEntry docs ) 684{ 685 mFieldDocs = String(); 686 if( docs && docs[ 0 ] ) 687 { 688 // Only accept first line of docs for brevity. 689 690 const char* newline = dStrchr( docs, '\n' ); 691 if( newline ) 692 mFieldDocs = String( docs, newline - docs ); 693 else 694 mFieldDocs = docs; 695 } 696} 697 698void GuiInspectorField::setHeightOverride(bool useOverride, U32 heightOverride) 699{ 700 mUseHeightOverride = useOverride; 701 702 if (useOverride) 703 mHeightOverride = heightOverride; 704 705 S32 fieldHeight = 18; 706 707 if (mUseHeightOverride) 708 fieldHeight = mHeightOverride; 709 710 RectI bnds = getBounds(); 711 setBounds(bnds.point.x, bnds.point.y, bnds.extent.x, fieldHeight); 712 713 // Calculate Caption and EditCtrl Rects 714 updateRects(); 715 716 // Force our editField to set it's value 717 updateValue(); 718} 719 720//============================================================================= 721// Console Methods. 722//============================================================================= 723// MARK: ---- Console Methods ---- 724 725//----------------------------------------------------------------------------- 726 727DefineEngineMethod( GuiInspectorField, getInspector, S32, (), , "() - Return the GuiInspector to which this field belongs." ) 728{ 729 return object->getInspector()->getId(); 730} 731 732//----------------------------------------------------------------------------- 733 734DefineEngineMethod( GuiInspectorField, getInspectedFieldName, const char*, (), , "() - Return the name of the field edited by this inspector field." ) 735{ 736 return object->getFieldName(); 737} 738 739//----------------------------------------------------------------------------- 740 741DefineEngineMethod( GuiInspectorField, getInspectedFieldType, const char*, (), , "() - Return the type of the field edited by this inspector field." ) 742{ 743 return object->getFieldType(); 744} 745 746//----------------------------------------------------------------------------- 747 748DefineEngineMethod( GuiInspectorField, apply, void, ( const char * newValue, bool callbacks ), (true), "( string newValue, bool callbacks=true ) - Set the field's value. Suppress callbacks for undo if callbacks=false." ) 749{ 750 object->setData( newValue, callbacks ); 751} 752 753//----------------------------------------------------------------------------- 754 755DefineEngineMethod( GuiInspectorField, applyWithoutUndo, void, (const char * data), , "() - Set field value without recording undo (same as 'apply( value, false )')." ) 756{ 757 object->setData( data, false ); 758} 759 760//----------------------------------------------------------------------------- 761 762DefineEngineMethod( GuiInspectorField, getData, const char*, (), , "() - Return the value currently displayed on the field." ) 763{ 764 return object->getData(); 765} 766 767//----------------------------------------------------------------------------- 768 769DefineEngineMethod( GuiInspectorField, reset, void, (), , "() - Reset to default value." ) 770{ 771 object->resetData(); 772} 773 774DefineEngineMethod(GuiInspectorField, setCaption, void, (String newCaption),, "() - Reset to default value.") 775{ 776 object->setCaption(StringTable->insert(newCaption.c_str())); 777} 778 779DefineEngineMethod(GuiInspectorField, setHeightOverride, void, (bool useOverride, U32 heightOverride), , "") 780{ 781 object->setHeightOverride(useOverride, heightOverride); 782} 783 784DefineEngineMethod(GuiInspectorField, setEditControl, void, (GuiControl* editCtrl), (nullAsType<GuiControl*>()), "() - Reset to default value.") 785{ 786 object->setEditControl(editCtrl); 787} 788