MEL How-To #101

Back · Previous · Next Maya

How do I find a window and query its child layout and controls?

You can get a list of all MEL windows using the "lsUI" command, and filtering its results to display only windows with its '-type' flag:

string $allWindows[] = `lsUI -type "window"`;
// Result: CommandWindow MayaWindow //

From this list you can query the string used as the title for each window:

window -q -title $allWindows[0];
// Result: Script Editor //

If you want to go the other way - that is, knowing the title you want to find the window's UI name:

proc string findWindowByTitle( string $windowTitle )
{
  // Default empty string to denote that no matching window was found.
  //
  string $windowUI = "";
  string $allWindows[] = `lsUI -type "window"`;

  for ( $w in $allWindows )
  {
    // Compare the specified title with that queried from each window.
    //
    if ( $windowTitle == `window -q -title $w` )
    {
      // Found it!
      //
      $windowUI = $w;
      break;
    }
  }

  return $windowUI;
}

An example run:

string $windowUI = findWindowByTitle( "Script Editor" );
print ( "The window titled \"" + $windowTitle + "\" is: " + $windowUI + "\n" );

// Result: The window titled "Script Editor" is: CommandWindow //

The next logical step is to use the name of the window UI to query its child controls. Here's where you run into a bit of a snag. The "window" command does not have the expected '-childArray' flag, and there's no direct way to query the layout or controls used in the window. Therefore, it is necessary to perform a reverse lookup to find the layout.

global proc string findWindowLayout( string $windowUI )
{
  // Brute force: Get a list of all control layouts, and see which
  // is a child of the specified window.
  //
  string $controls[] = `lsUI -l -controlLayouts`;

  // Create a wildcard pattern used by the "gmatch" command.
  //
  string $pattern = $windowUI + "*";

  // Default empty string to denote that no matching layout was found.
  //
  string $layout = "";

  for ( $ui in $controls )
  {
    // Compare the wildcard pattern against the name of this control.
    //
    if ( `gmatch $ui $pattern` )
    {
      // Found it!
      //
      string $tokens[];
      int $numTokens = `tokenize $ui "|" $tokens`;
      if ( $numTokens > 1 )
      {
        // This returns a path to the control, specifying the window as the parent.
        // It's advisable to always reference UI controls by their full path.
        //
        $layout = $tokens[0] + "|" + $tokens[1];

        break;
      }
    }
  }

  return $layout;
}

An example usage:

string $windowUI = "MayaWindow";
string $layout = findWindowLayout( $windowUI );

if ( "" != $layout )
{
  // Found a layout.
  //
  print ( "Layout for window \"" + $windowUI + "\": " + $layout + "\n" );

  // List the child controls.
  //
  string $ca[] = `layout -q -ca $layout`;
  print ( "Layout controls:\n" );

  for ( $c in $ca )
  {
    // Always expand UI control names to their full path.
    //
    print ( $layout + "|" + $c + "\n" );
  }
}
else
{
  print ( "Layout for \"" + $windowUI + "\" not found.\n" );
}
Layout for window "MayaWindow": MayaWindow|mayaMainWindowForm
Layout controls:
MayaWindow|mayaMainWindowForm|formLayout1
MayaWindow|mayaMainWindowForm|formLayout2
MayaWindow|mayaMainWindowForm|formLayout3
MayaWindow|mayaMainWindowForm|TimeSliderForm
MayaWindow|mayaMainWindowForm|formLayout4
MayaWindow|mayaMainWindowForm|formLayout5
MayaWindow|mayaMainWindowForm|formLayout6
MayaWindow|mayaMainWindowForm|formLayout7

Now that you have each layout you can query each's children. You don't need to know the type of layout referred to by the path; you can use the generic "layout" command to query the child array.

string $ca[] = `layout -q -childArray $layout`;

Howver, if you want to query any properties for a layout that are specific to its type, the generic "layout" command will not suffice. Here you can use the "objectTypeUI" command to query the layout's type, followed by a series of queries (or edits) for the types you will support.

if ( `layout -q -exists $layout` )
{
  string $layoutType = `objectTypeUI $layout`;
  
  switch ( $layoutType )
  {
    case "formLayout":
    {
      // Process with "formLayout" command.
      //
      break;
    }
    case "frameLayout":
    {
      // Process with "frameLayout" command.
      //
      break;
    }
    case "shelfLayout":
    {
      // Process with "shelfLayout" command.
      //
      break;
    }
    default:
    {
      // Not supported...
    }
}

Here's an example of using findWindowLayout() to print a hierarchical representation of the family of layouts that comprise Maya's main window:

proc printLayoutHierarchy( string $layout, string $parent, int $tab )
{
  string $bars = "| | | | | | | | | | | | | | | | | | | | | | | | | | | ";

  // Note: You _must_ specify the full path for a control in order to
  //       avoid ambiguous queries (and in this case, an infinite loop).
  //
  string $path = ( $parent + "|" + $layout );

  if ( `layout -q -exists $path` )
  {
    // Print a pseudo-tree representation.
    //
    if ( $tab > 1 ) print ( `substring $bars 1 (($tab-1)*2)` );
    if ( $tab > 0 ) print ( "+ " );
    print ( $layout + "\n" );

    // Query the children of this layout.
    //
    string $ca[] = `layout -q -ca $path`;

    // And recurse...
    //
    for ( $c in $ca )
    {
      printLayoutHierarchy( $c, $path, $tab+1 );
    }
  }
}

// Find the path of the layout control for Maya's main window.
//
string $windowUI = "MayaWindow";
string $path = findWindowLayout( $windowUI );

// Split this into its path and layout name (short form).
//
string $layout = `match "[^|]*$" $path`;
string $parent = `substitute "|[^|]*$" $path ""`;

// Build a hierarchical tree for this layout.
//
printLayoutHierarchy( $layout, $parent, 0 );
Here's an example of its output:
mayaMainWindowForm
+ formLayout1
| + formLayout12
| | + formLayout13
| | | + formLayout40
| | | | + formLayout41
| | | | | + presetForm
| | | | | + masksForm
| | | | | + selectMaskForm
| | | | | | + hierarchyIcons
| | | | | | | + hierPickMenuLayout
| | | | | | + objectMaskIcons
| | | | | | | + objPickMenuLayout
| | | | | | + componentMaskIcons
| | | | | | | + compPickMenuLayout
| | | | | + snapIcons
| | | | | + historyLayout
| | | | | | + formLayout42
| | | | | | + formLayout43
| | | | + formLayout44
+ formLayout2
| + formLayout14
| | + formLayout15
| | | + formLayout49
| | | | + frameLayout4
| | | | | + formLayout50
| | | | + ShelfLayout
| | | | | + Admin
| | | | | + Animation
| | | | | + Colouring
| | | | | + Develop
| | | | | + LevelTools
| | | | | + Polygon
| | | | | + Primitives
| | | | | + Render
| | | | | + Tools
| | | | | + UI
+ formLayout3
| + viewPanes
| | + modelPanel1
| | + modelPanel2
| | + modelPanel3
| | + modelPanel4
| + formLayout8
| | + formLayout26
| | | + formLayout27
| | | | + frameLayout6
| | | | | + gridLayout2
| | | | + frameLayout7
| | | | | + ToolboxConfigurationGrid
| | | | | | + ToolboxConfigurationForm
| | | | | | | + ToolboxContentFrame0
| | | | | | | + ToolboxContentFrame1
| | | | | | | + ToolboxContentFrame2
| | | | | | | + ToolboxContentFrame3
| + formLayout9
| | + formLayout28
| | | + formLayout29
| | | | + formLayout34
| | | | | + AEmenuBarLayout
| | | | | | + AErootLayout
| | | | | | | + AENothingSelectedLayout
| | | | | | | + AEbaseFormLayout
| | | | | | | | + AEheaderLayout
| | | | | | | | | + AEtabLayout
| | | | | | | | + AEnodeNameHeaderLayout
| | | | | | | | + AEcontrolFormLayout
| | | | | | | + AEselectAndCloseButtonLayout
| + formLayout10
| | + formLayout30
| | | + formLayout31
| | | | + tabLayout1
| | | | | + columnLayout1
| + formLayout11
| | + formLayout32
| | | + formLayout33
| | | | + formLayout35
| | | | + ChannelsLayersPaneLayout
| | | | | + formLayout36
| | | | | | + menuBarLayout1
| | | | | | | + frameLayout1
| | | | | + formLayout37
| | | | | | + menuBarLayout2
| | | | | | | + formLayout38
| | | | | | | | + DisplayLayerUITabLayout
| | | | | | | | | + DisplayLayerTab
| | | | | | | | | | + LayerEditorDisplayLayerLayout
| | | | | | | | | + RenderLayerTab
| | | | | | | | | | + LayerEditorRenderLayerLayout
| | | | + formLayout39
+ TimeSliderForm
| + formLayout16
| | + formLayout17
| | | + formLayout45
| | | | + frameLayout2
| | | | + gridLayout1
+ formLayout4
| + formLayout18
| | + formLayout19
| | | + formLayout46
| | | | + frameLayout3
| | | | + formLayout47
+ formLayout5
| + formLayout20
| | + formLayout21
| | | + formLayout48
| | | | + commandLine1
+ formLayout6
| + formLayout22
| | + formLayout23
| | | + frameLayout5
| | | | + formLayout51
+ formLayout7
| + formLayout24
| | + formLayout25

Related How-To's

19 Feb 2005