Wednesday, March 13, 2013

Executing Commands with GUI Objects


class AR_OptionsWindow(object):
    def showUI(cls): //provides a shortcut for creating and displaying a new window instance.
        win = cls();
        win.create();
        return win;
    def __init__(self):
        self.window = 'ar_optionsWindow';
        self.title = 'Meng\'s Window';
        self.size = (546, 350);
        self.supportsToolAction = False;
        self.actionName = 'Apply and Close'; //set Apply and Close as the name that will display on the window's action button.Apply button and Close button do not need to set because most windows in Maya default to something like Apply and Close.

    def actionBtnCmd(self, *args): //invoke the Apply behavior and then the Close behavior.
        self.applyBtnCmd();
        self.closeBtnCmd();
    def applyBtnCmd(self, *args): pass //subclasses will need to override this method.
    def closeBtnCmd(self, *args): //simply closes the window
        cmds.deleteUI(self.window, window=True);

    def commonMenu(self):

        self.editMenu = cmds.menu(label='Edit');
        self.editMenuSave = cmds.menuItem(
            label='Save Settings',
            command=self.editMenuSaveCmd //pass the pointer to the editMenuSaveCmd() method.                                   
        );
        self.editMenuReset = cmds.menuItem(
            label='Reset Settings',
            command=self.editMenuResetCmd //pass the pointer to the editMenuResetCmd() method.
        );
        self.editMenuDiv = cmds.menuItem(d=True);
        self.editMenuRadio = cmds.radioMenuItemCollection();
        self.editMenuTool = cmds.menuItem(
            label='As Tool',
            radioButton=True,
            enable=self.supportsToolAction,
            command=self.editMenuActionCmd //pass the pointer to the editMenuToolCmd() method.
        );
        self.editMenuAction = cmds.menuItem(
            label='As Action',
            radioButton=True,
            enable=self.supportsToolAction,
            command=self.editMenuActionCmd //pass the pointer to the editMenuActionCmd() method.
        );

        self.helpMenu = cmds.menu(label='Help');
        self.helpMenuItem = cmds.menuItem(
            label='Help on %s'%self.title,
            command=self.helpMenuCmd //pass the pointer to the helpMenuCmd() method.
        );

    def commonButtons(self):
        self.commonBtnSize = ((self.size[0]-18)/3, 26); //specify a size for buttons as a tuple: (width,height)
        self.commonBtnLayout = cmds.rowLayout(
            numberOfColumns=3, //specify the layout should have three columns
            cw3=( 
                self.commonBtnSize[0]+3,
                self.commonBtnSize[0]+3,
                self.commonBtnSize[0]+3
            ), //set properties for column width
            ct3=('both', 'both', 'both'), //set properties for column attachment
            co3=(2,0,2), //set properties for column offset
            cl3=('center', 'center', 'center')
        ); //set properties for column text alignment
//the commonBtnLayout assignment (rowLayout call) do not scale when adjust the size of the window. Sacling in the width of the window simply clips the buttons on the right side. To fix this problem, I use a more advanced layout: formLayout as below:
        self.actionBtn = cmds.button(
            label=self.actionName,
            height=self.commonBtnSize[1],
            command=self.actionBtnCmd
        );
        self.applyBtn = cmds.button(
            label='Apply',
            height=self.commonBtnSize[1],
            command=self.applyBtnCmd
        );
        self.closeBtn = cmds.button(
            label='Close',
            height=self.commonBtnSize[1],
            command=self.closeBtnCmd
        );  

        cmds.formLayout( //the formLayout command in edit mode to configure how the buttons need to be attached in mainForm
            self.mainForm, e=True,
            attachForm=( //specifies edges on controls that pin to the bounds of the form we passed to the command.
                [self.actionBtn, 'left', 5],
                [self.actionBtn, 'bottom', 5],
                [self.applyBtn, 'bottom', 5],
                [self.closeBtn, 'right', 5],
                [self.closeBtn, 'bottom', 5]
            ),
            attachPosition=(
                [self.actionBtn, 'right',1,33],//correspond to points approximately one-third of the form's width(33/100). The middle number(1) represents a pixel offset for the attachment.
                [self.closeBtn, 'left',0,67]
            ),
            attachControl=( //specifies edges on a control that attach to another control, with an optional offset.
                [self.applyBtn, 'left',4,self.actionBtn],
                [self.applyBtn, 'right',4,self.closeBtn]
            ),
            attachNone=( //specifies edges on controls that should not attach to anything, and hence should not scale.
                [self.actionBtn, 'top'],
                [self.applyBtn, 'top'],
                [self.closeBtn, 'top']
            )
        );


    def helpMenuCmd(self, *args): //this method will load the Python Standard Library web site in a browser.
        cmds.launch(web='http://docs.python.org/2/library/');

    def editMenuSaveCmd(self, *args): pass //add four placeholder methods for child classes to override: editMenuSaveCmd(), editMenuResetCmd(), editMenuToolCmd(), editMenuActionCmd().
    def editMenuResetCmd(self, *args): pass
    def editMenuToolCmd(self, *args): pass
    def editMenuActionCmd(self, *args): pass
    def displayOptions(self): pass //This method will be overridden in child classes to actually display the contents in the main part of the options window.

    def create(self):
        if cmds.window(self.window, exists=True):
            cmds.deleteUI(self.window, window=True);
        self.window = cmds.window(
            self.window,
            title=self.title,
            widthHeight=self.size,
            menuBar=True
        );
        self.mainForm = cmds.formLayout(nd=100); //The mainForm attribute will be the parent for the next layout defined in the window (the row layout), which will be positioned at the top left of the form by default. The nd (numberOfDivisions) flag that passed to the formLayout command allows to use relative coordinates when specifying attachment positions of controls.
        self.commonMenu();
        self.commonButtons(); //add a call to commonButtons() in the create() method

        self.optionsBorder = cmds.tabLayout( //add a border for the window
            scrollable=True,
            tabsVisible=False,
            height=1
        );
        cmds.formLayout(
            self.mainForm, e=True,
            attachForm=(
                [self.optionsBorder,'top',0],
                [self.optionsBorder,'left',2],
                [self.optionsBorder,'right',2]
            ),
            attachControl=(
                [self.optionsBorder,'bottom',5,self.applyBtn]
            )
        );
        self.optionsForm = cmds.formLayout(nd=100);
        self.displayOptions();

        cmds.showWindow();
testWindow = AR_OptionsWindow();
testWindow.create();
Result:

No comments:

Post a Comment