## PPGLayout

Object Hierarchy | Related C++ Class: PPGLayout

### Introduced

v4.0

### Description

The PPGLayout object represents the visual appearance of an object's state when it is inspected. (PPG is a common acronym for Property Page). The layout makes it possible to group objects together, use special controls, hide obsolete parameters, add Buttons and in general create a presentation of an object's state that is pleasing to the eye.
A Layout is modeled in Softimage as a linear list of PPGItem objects. Each PPGItem represents either a parameter in the inspected object, or a special UI item like a Tab or Button. In most cases the layout does not specify hard-coded pixel positions or dimensions for the PPGItems. Instead Softimage automatically draws the controls with a sensible layout. This allows the presentation to change in a pleasing manner when the user resizes the property page. However there is some support for providing hints, for example PPGItem.WidthPercentage, or even explicit sizes via PPGItem.SetAttribute.
Many different controls are available for use on a property page, see siPPGControlType. All controls can be added using PPGLayout.AddItem but convenience methods are provided for some of the most common controls, for example PPGLayout.AddColor.
Practically every built-in Softimage object has its own layout. However, if there is no specific layout, Softimage displays a default layout that lists all the parameters in a simple fashion.
Layouts are remembered in memory while Softimage is running. For internal objects they are reloaded from SPDL files when Softimage restarts. The layout for a CustomProperty object implemented as a PluginItem is defined by implementing the DefineLayout callback.
You cannot directly modify an existing layout structure, apart from adding new items at the end or changing the attributes of items already in the layout. However to modify a layout it is often reasonable to call PPGLayout.Clear and then rebuild the entire layout with the changes included. You can also use the Parameter.Enable method to hide parameters without removing them from the layout.
If the layout is changed from within Logic code (see PPGLayout.Logic) it is necessary to call PPG.Refresh to see the changes take effect.
Normally the layout is associated with an object that remains in the scene. However it is also possible to use this object to define the user interface of a temporary dialog box. For example a script can ask the user to specify some import or export options. This is done in conjunction with a temporary CustomProperty object and the InspectObj command. This approach is demonstrated in the following examples.

### Methods

AddButton | AddColor | AddEnumControl | AddFCurve
AddGroup | AddItem | AddRow | AddSpacer
AddStaticText | AddString | AddTab | Clear
Delete | EndGroup | EndRow | GetAttribute
SetAttribute | SetViewPosition | SetViewSize |

### Properties

Count | Item | Language | Logic
ViewPosition | ViewSize |  |

### Examples

#### 1. JScript Example

    /*
            This example demonstrates a typical use of a custom pset with custom layout as a way of
            collecting some information from the user.
    */
    // Step 1: Create a custom pset and define the data on it
    var oPSet=ActiveSceneRoot.AddProperty("CustomProperty",false,"Demo") ;
    // Color is made up of 4 components
    oPSet.AddParameter3( "MyR", siDouble ) ;
    oPSet.AddParameter3( "MyG", siDouble ) ;
    oPSet.AddParameter3( "MyB", siDouble ) ;
    oPSet.AddParameter3( "MyA", siDouble ) ;
    oPSet.AddParameter3( "EnumCtrl", siInt4, 4 ) ;
    // Step 2: Put the items on the layout with a custom UI
    var oPPGLayout = oPSet.PPGLayout ;
    oPPGLayout.AddGroup( "Pick a Color" ) ;
    var oItem = oPPGLayout.AddColor( "MyR", "",true ) ;
    oItem.SetAttribute("NoLabel", true ) ;
    oPPGLayout.EndGroup() ;
    oPPGLayout.AddEnumControl( "EnumCtrl", new Array( "item 1", 4, "item 2", 6 ), "Choice",  siControlCombo ) ;
    // Step 3: Show the user the dialog.  They can change the
    // parameter values and then click OK or Cancel
    try {
            InspectObj( oPSet, "", "Check out this layout created from scripting", siModal );
            // Step 4: Read the values and do something with them.  Normally this
            //      would be where you call a custom command which does the operation
            Application.LogMessage( "User picked the color (" + oPSet.Parameters("MyR").Value + ","  + oPSet.Parameters("MyG").Value + ","
                    + oPSet.Parameters("MyB").Value + ","  + oPSet.Parameters("MyA").Value + ")" ) ;
            if ( oPSet.Parameters( "EnumCtrl" ).Value == 4 ) {
                    Application.LogMessage( "User selected item 1" ) ;
            } else {
                    Application.LogMessage( "User selected item 2" ) ;
            }
    } catch( e ) {
            // Tip: rather than using try/catch, you can specify false
            // as the 5th argument to InspectObj and it will not throw an exception
            Application.LogMessage( "User Cancelled" );
    }
    //Step 5: Remove the pset now that we are done with it
    DeleteObj( oPSet ) ;

#### 2. JScript Example

    /*
            A demonstration of the Number Control on a Custom Property Set. The number control
            normally appears as a [Animation Divot] [Label] [Edit+Slider Control] but this
            example demonstrates how this appearance can be controlled. It also shows how to
            change the range of a parameter. All these changes can be made dynamically.
    */
    NewScene( null, false ) ;
    var oCustomProperty = ActiveSceneRoot.AddProperty( "CustomProperty", false, "NumberControlTester" ) ;
    // Add a parameter of type double.
    // It has the min/max values of -1000 to 1000,
    // default value of -1.0, and ui range -100 to 100
    var oGridParam = oCustomProperty.AddParameter2( "number", siDouble, -1.0, -1000.0, 1000.0, -100.0, 100.0, siClassifUnknown, siPersistable | siAnimatable ) ;
    // Add the Edit boxes and other controls that will
    // be used to get information from the user
    oCustomProperty.AddParameter3( "setLabel", siString, "NewLabel" ) ;
    oCustomProperty.AddParameter3( "setNoLabel", siBool, false,null,null,false) ;
    oCustomProperty.AddParameter3( "setValueOnly", siBool, false,null,null,false) ;
    oCustomProperty.AddParameter3( "setNoSlider", siBool, false,null,null,false) ;
    oCustomProperty.AddParameter3( "setThumbWheel", siBool, false,null,null,false) ;
    oCustomProperty.AddParameter3( "setTreadmill", siBool, false,null,null,false) ;
    oCustomProperty.AddParameter3( "setDecimals", siInt4, 3,0,10,false) ;
    oCustomProperty.AddParameter3( "setLabelMinPixels", siInt4, 10,0,300,false) ;
    oCustomProperty.AddParameter3( "setLabelPercentage", siInt4, 30,0,100,false) ;
    oCustomProperty.AddParameter3( "setCX", siInt4, 0,0,500,false) ;
    oCustomProperty.AddParameter3( "setCY", siInt4, 0,0,100,false) ;
    oCustomProperty.AddParameter3( "setUIMin", siDouble, -100,-10000,10000,false) ;
    oCustomProperty.AddParameter3( "setUIMax", siDouble, 100,-10000,10000,false) ;
    oCustomProperty.AddParameter3( "setMin", siDouble, -1000,-10000,10000,false) ;
    oCustomProperty.AddParameter3( "setMax", siDouble, 1000,-10000,10000,false) ;
    //
    // Build the layout for the test property page
    //
    var oLayout = oCustomProperty.PPGLayout
    oLayout.AddGroup( "Test Number Parameter" ) ;
            //The logic code will set all the detailed attributes
            oLayout.AddItem( "number" ) ;
    oLayout.EndGroup() ;
    oLayout.AddGroup( "Display Attributes" ) ;
            oLayout.AddItem( "setLabel","Label" ) ;
            oLayout.AddItem( "setNoLabel","NoLabel" ) ;
            oLayout.AddItem( "setNoSlider","NoSlider" ) ;
            oLayout.AddItem( "setThumbWheel","ThumbWheel" ) ;
            oLayout.AddItem( "setTreadmill","Treadmill" ) ;
            oLayout.AddItem( "setCX","Fixed Width" ) ;
            oLayout.AddItem( "setCY","Fixed Height" ) ;
            oLayout.AddItem( "setDecimals","Decimals" ) ;
            oLayout.AddItem( "setLabelMinPixels","Label Pixels (Min)" ) ;
            oLayout.AddItem( "setLabelPercentage","Label %" ) ;
            oLayout.AddButton( "Update" ) ;
    oLayout.EndGroup() ;
    // These values actually fundamentally affect the
    // parameter itself.
    // Note1:You could potentially change the script name
    //      but that would break the logic code that depends
    //      on the scripting name
    // Note2:You can't change the type of a parameter.
    //      Instead you could delete and recreate a new parameter
    //      dynamically but that is not part of this example
    oLayout.AddGroup( "Parameter Attributes" ) ;
            oLayout.AddItem( "setMin" ) ;
            oLayout.AddItem( "setMax" ) ;
            oLayout.AddItem( "setUIMin" ) ;
            oLayout.AddItem( "setUIMax" ) ;
            oLayout.AddButton( "PDefUpdate","Update" ) ;
    oLayout.EndGroup() ;
    oLayout.Language = "Jscript" ;
    oLayout.Logic = NumberControlTester_Update_OnClicked.toString() +
                    NumberControlTester_PDefUpdate_OnClicked.toString();
    oLayout.SetAttribute( "LogicPrefix", "NumberControlTester_" ) ;
    InspectObj( oCustomProperty ) ;
    //
    // This is the logic code
    //
    function NumberControlTester_Update_OnClicked()
    {
            var oCustomProperty = PPG.Inspected(0) ;
            var oLayout = oCustomProperty.PPGLayout
            var oPPGItem = oLayout.Item( "number" ) ;
            // Based on the property page items, set the attributes
            // of the control
            oPPGItem.Label = oCustomProperty.setLabel.Value ;
            oPPGItem.SetAttribute( "NoLabel", oCustomProperty.setNoLabel.Value ) ;
            oPPGItem.SetAttribute( "ValueOnly", oCustomProperty.setValueOnly.Value ) ;
            oPPGItem.SetAttribute( "NoSlider", oCustomProperty.setNoSlider.Value ) ;
            oPPGItem.SetAttribute( "Decimals", oCustomProperty.setDecimals.Value ) ;
            oPPGItem.SetAttribute( "ThumbWheel", oCustomProperty.setThumbWheel.Value ) ;
            oPPGItem.SetAttribute( "Treadmill", oCustomProperty.setTreadmill.Value ) ;
            oPPGItem.SetAttribute( "CX", oCustomProperty.setCX.Value ) ;
            oPPGItem.SetAttribute( "CY", oCustomProperty.setCY.Value ) ;
            oPPGItem.LabelMinPixels = oCustomProperty.setLabelMinPixels.Value ;
            oPPGItem.LabelPercentage = oCustomProperty.setLabelPercentage.Value ;
            // (There is also a logithmic attribute
            // but it only works for integer parameters)
            // You need to rebuild the PPG contents to see the changes
            PPG.Refresh() ;
    }
    function NumberControlTester_PDefUpdate_OnClicked()
    {
            var oCustomProperty = PPG.Inspected(0) ;
            var oLayout = oCustomProperty.PPGLayout
            var newUIMin = oCustomProperty.setUIMin.Value ;
            var newUIMax = oCustomProperty.setUIMax.Value ;
            var newMin = oCustomProperty.setMin.Value ;
            var newMax = oCustomProperty.setMax.Value ;
            if ( newUIMin > newUIMax ) {
                    Logmessage( "UIMin must be less than UIMax!" ) ;
                    return ;
            }
            if ( newMax < newUIMax ) {
                    Logmessage( "UIMax can't be bigger than Max!" ) ;
                    return ;
            }
            if ( newMin > newUIMin ) {
                    Logmessage( "UIMin can't be smaller than Min!" ) ;
                    return ;
            }
            // Call the command with the new parameter ranges
            EditParameterDefinition( oCustomProperty.number.FullName, null, null, newMin, newMax, newUIMin, newUIMax ) ;
            // You need to rebuild the PPG contents to see the changes
            PPG.Refresh() ;
    }

### See Also

PPGItem ProjectItem.PPGLayout InspectObj