Maya workspaceControl, adjusting height after creation

Hello there!
I have been trying to make a window with a collapsible layout, and that’s working great. However, I am also trying to make this window have the ability to be floating or dock-able depending on the artists needs.

To do this, I have used the workspaceControl and parented the window I am creating, into it.

The issue that is happening is that when I resize the window inside the control, and then try to resize the workspaceControl, the workspaceControl will not adjust height back down to the window.

I know that I could do this with QT if I had the knowledge, but I don’t, and learning a whole new language at the moment would be rough.

Any help would be greatly appreciated!! Thank you!

import maya.cmds as mc
from functools import partial



class MainClassToolBox:
    
    def __init__(self):
        self.tbWinID = 'ToolsWindow_v002'
        self.tbWorkID = 'ToolBox_v002_WorkspaceControl'

        self.toolBoxUI()

    def toolBoxUI(self, *args):

        if mc.window(self.tbWinID, exists=True):
            mc.deleteUI(self.tbWinID, wnd=True)
        if mc.workspaceControl(self.tbWorkID, q=True, exists=True):
            mc.deleteUI(self.tbWorkID)
        
        mc.workspaceControl(self.tbWorkID, retain=False, label='Tool_Box')
        mc.window(self.tbWinID, sizeable=False, toolbox=True)
        mc.tabLayout('toolsTabs')

        tabMenu = mc.columnLayout("Menu", adj=False)

        self.tbFileTab = mc.frameLayout(
            label="File", 
            bgc=(0.3, 0.3, 0.3),
            collapsable=True,
            collapse=True,
            collapseCommand=partial(self.tbResizeWin, tbTabHeightWin=66),
            expandCommand=partial(self.tbResizeWin, tbTabHeightWin=(-66)))

        mc.columnLayout(nch=6, parent=self.tbFileTab, adj=True)
        mc.textField("tbTransformMin", h=30, w=50, placeholderText="min")
        mc.textField("tbTransformMax", h=30, w=50, placeholderText="min")
        self.tbTransformRB = mc.nodeIconButton(label="rotate",
                backgroundColor=(0.2, 0.2, 0.2),
                height=32,
                width=32,
                command=partial(self.button_cmd),
                ann='LMB: random rotate Y // LMBDbl: random rotate XYZ // RMB: Choose input method or a preset')

        mc.setParent('..')

        mc.showWindow(self.tbWinID)
        mc.window(self.tbWinID, edit=True, width=150, h=125)
        mc.control(self.tbWinID, edit=True, parent=self.tbWorkID)

        
    def random_transform_RB(self, options, *args):
        for opt in options:
            if mc.menuItem(opt, q=True, radioButton=True):
                return True

    def button_cmd(self, *args):
        print 'hello world'
    
    def tbResizeWin(self, tbTabHeightWin, _=False):
        tbWindowSize = mc.window(self.tbWinID, query=True, height=True)
        mc.window(self.tbWinID, edit=True, height=(tbWindowSize-tbTabHeightWin))
        mc.workspaceControl(self.tbWorkID, edit=True, resizeHeight=(tbWindowSize-tbTabHeightWin))
        mc.window(self.tbWinID, edit=True, topLeftCorner=[0,0])

def main():
    mainClass = MainClassToolBox()
    mainClass.__init__()


#import tool_box_simple
#reload(tool_box_simple)
#tool_box_simple.main()

pointed to where I am using the workspace control.

So I just want to point out, that you don’t need to manually call __init__ here. When instantiating the class, __init__ is called for you. So in this case you’re actually double initializing the class.

Its been awhile since I’ve used workspaceControl, but you shouldn’t need it and a window. You can parent a layout directly to the workspaceControl and then add items to the layout as usual.
This should help avoid trying to keep the two containers in sync with each other.

1 Like

Thanks Bob!

Yeah, my first time writing a class, so I appreciate the help! :smiley:

I have tried out just using the workspaceControl without the window and that seems to have helped, however on the first execution of lowering the height of the workspaceControl, it doesn’t work. After that, it starts to work properly. I’ve re-posted my code (with just a duplication of the drop down frameLayouts to see how it would function).

I have added a workspaceControlState to remove the window preferences too so that shouldn’t interfere.
I have also added a columnLayout with 4 children, those being the frameLayouts that expand and collapse.

I think maybe some of the ordering of my ui is bad? I’m not the most experienced coder and I’m sure it may be just me missing something small, or doing it in the wrong order, etc.

Thanks so much for the help Bob, if you or anyone has more ideas as to how to solve the workspaceControl height not changing, that would be a huge help!!

P.S I took out the useless “tabLayout” - ‘toolsTabs’ and “columnLayout” - ‘Menu’!

ui_not_working

import maya.cmds as mc
from functools import partial



class MainClassToolBox:
    
    def __init__(self):
        self.tbWinID = 'ToolsWindow_v002'
        self.tbWorkID = 'ToolBox_v002_WorkspaceControl'

        self.toolBoxUI()

    def toolBoxUI(self, *args):

        if mc.workspaceControl(self.tbWorkID, q=True, exists=True):
            mc.deleteUI(self.tbWorkID)
        if mc.workspaceControlState(self.tbWorkID, q=True, exists=True):
            mc.workspaceControlState(self.tbWorkID, remove=True)

        mc.workspaceControl(self.tbWorkID, initialHeight=500, retain=False, label='Tool_Box')
        mc.columnLayout('tbTabs', nch=4, parent=self.tbWorkID)
        self.tbFileTab = mc.frameLayout(parent='tbTabs',
            label="File",
            backgroundColor=(0.3, 0.3, 0.3),
            collapsable=True,
            collapse=True,
            collapseCommand=partial(self.tbResizeWin, tbTabHeightWin=64),
            expandCommand=partial(self.tbResizeWin, tbTabHeightWin=(-64)))

        mc.columnLayout(nch=6, parent=self.tbFileTab, adj=False)
        mc.textField("tbTransformMin", h=30, w=50, placeholderText="min")
        mc.textField("tbTransformMax", h=30, w=50, placeholderText="min")
        self.tbTransformRB = mc.nodeIconButton(label="rotate",
                backgroundColor=(0.2, 0.2, 0.2),
                height=32,
                width=32,
                command=partial(self.button_cmd),
                ann='LMB: random rotate Y // LMBDbl: random rotate XYZ // RMB: Choose input method or a preset')

        mc.setParent(self.tbWorkID)

        self.tbModTab = mc.frameLayout(parent='tbTabs',
            label="Mod", 
            backgroundColor=(0.3, 0.3, 0.3),
            collapsable=True,
            collapse=True,
            collapseCommand=partial(self.tbResizeWin, tbTabHeightWin=64),
            expandCommand=partial(self.tbResizeWin, tbTabHeightWin=(-64)))

        mc.columnLayout(nch=6, parent=self.tbModTab, adj=False)
        mc.textField("tbTransformMin", h=30, w=50, placeholderText="min")
        mc.textField("tbTransformMax", h=30, w=50, placeholderText="min")
        self.tbTransformRB = mc.nodeIconButton(label="rotate",
                backgroundColor=(0.2, 0.2, 0.2),
                height=32,
                width=32,
                command=partial(self.button_cmd),
                ann='LMB: random rotate Y // LMBDbl: random rotate XYZ // RMB: Choose input method or a preset')

        mc.setParent(self.tbWorkID)

        self.tbDeformTab = mc.frameLayout(parent='tbTabs',
            label="Deform", 
            backgroundColor=(0.3, 0.3, 0.3),
            collapsable=True,
            collapse=True,
            collapseCommand=partial(self.tbResizeWin, tbTabHeightWin=64),
            expandCommand=partial(self.tbResizeWin, tbTabHeightWin=(-64)))

        mc.columnLayout(nch=6, parent=self.tbDeformTab, adj=False)
        mc.textField("tbTransformMin", h=30, w=50, placeholderText="min")
        mc.textField("tbTransformMax", h=30, w=50, placeholderText="min")
        self.tbTransformRB = mc.nodeIconButton(label="rotate",
                backgroundColor=(0.2, 0.2, 0.2),
                height=32,
                width=32,
                command=partial(self.button_cmd),
                ann='LMB: random rotate Y // LMBDbl: random rotate XYZ // RMB: Choose input method or a preset')

        mc.setParent(self.tbWorkID)
        
        self.tbTextureTab = mc.frameLayout(parent='tbTabs',
            label="Texture", 
            backgroundColor=(0.3, 0.3, 0.3),
            collapsable=True,
            collapse=True,
            collapseCommand=partial(self.tbResizeWin, tbTabHeightWin=64),
            expandCommand=partial(self.tbResizeWin, tbTabHeightWin=(-64)))

        mc.columnLayout(nch=6, parent=self.tbTextureTab, adj=False)
        mc.textField("tbTransformMin", h=30, w=50, placeholderText="min")
        mc.textField("tbTransformMax", h=30, w=50, placeholderText="min")
        self.tbTransformRB = mc.nodeIconButton(label="rotate",
                backgroundColor=(0.2, 0.2, 0.2),
                height=32,
                width=32,
                command=partial(self.button_cmd),
                ann='LMB: random rotate Y // LMBDbl: random rotate XYZ // RMB: Choose input method or a preset')

        mc.setParent(self.tbWorkID)

        
    def random_transform_RB(self, options, *args):
        for opt in options:
            if mc.menuItem(opt, q=True, radioButton=True):
                return True

    def button_cmd(self, *args):
        print 'hello world'
    
    def tbResizeWin(self, tbTabHeightWin, _=False):
        tbWindowSize = mc.workspaceControl(self.tbWorkID, query=True, height=True)
        mc.workspaceControl(self.tbWorkID, edit=True, resizeHeight=(tbWindowSize-tbTabHeightWin))

def main():
    mainClass = MainClassToolBox()


#import tool_box_simple
#reload(tool_box_simple)
#tool_box_simple.main()

So here is what I think is happening.

When you are in this state:
image

I think its just an order of operations oddity, where it is doing:

  1. shrink workspace control
  2. collapse layout

Where what you were hoping for is:

  1. collapse layout
  2. shrink workspace control

Sadly I have no idea on the best way to solve this one. Usually I don’t mess with the size of windows programatically, I just let users size them however they want and rely on the layouts to manage proper interior layout.

Yeah I figured that might be the case :frowning:
I know doing it through would QT or something would be best, but that’s a whole other ballgame for me to jump into. Maybe now’s the best time though. haha.

Thanks for the help Bob!

If anyone else may have some knowledge of workspaceControl’s please feel free to chime in.

So in order to kind of combat that, I have decided to run the resizing of the workspaceControl inside a button, instead of inside the collapseCommand flag of the control layout.

But after writing this, I am getting an error:
image

here is my script:

import maya.cmds as mc
from functools import partial



class MainClassToolBox:
    
    def __init__(self):
        self.tbWinID = 'ToolsWindow_v002'
        self.tbWorkID = 'ToolBox_v002_WorkspaceControl'

        self.toolBoxUI()

    def toolBoxUI(self, *args):

        if mc.workspaceControl(self.tbWorkID, q=True, exists=True):
            mc.deleteUI(self.tbWorkID)
        if mc.workspaceControlState(self.tbWorkID, q=True, exists=True):
            mc.workspaceControlState(self.tbWorkID, remove=True)

        mc.workspaceControl(self.tbWorkID, retain=False, label='Tool_Box')
        mc.rowLayout(nc=2, parent=self.tbWorkID)

        mc.checkBox('collapseFile', 
            height=30, 
            width=30, 
            offCommand=partial(self.collapseFile, collapseTab=True, tbTabHeight=96),
            onCommand=partial(self.collapseFile, collapseTab=False, tbTabHeight=(-96)))

        mc.columnLayout('tbTabs', nch=4, parent=self.tbWorkID)

        self.tbFileTab = mc.frameLayout(parent='tbTabs',
            label="File",
            backgroundColor=(0.3, 0.3, 0.3),
            collapsable=True,
            collapse=True)

        mc.columnLayout(nch=6, parent=self.tbFileTab, adj=False)
        mc.textField("tbTransformMin", h=30, w=50, placeholderText="min")
        mc.textField("tbTransformMax", h=30, w=50, placeholderText="min")
        self.tbTransformRB = mc.nodeIconButton(label="rotate",
                backgroundColor=(0.2, 0.2, 0.2),
                height=32,
                width=32,
                command=partial(self.button_cmd),
                ann='LMB: random rotate Y // LMBDbl: random rotate XYZ // RMB: Choose input method or a preset')

        mc.setParent(self.tbWorkID)

    def random_transform_RB(self, options, *args):
        for opt in options:
            if mc.menuItem(opt, q=True, radioButton=True):
                return True

    def button_cmd(self, *args):
        print 'hello world'
    
    def collapseFile(self, collapseTab, tbTabHeight, *args):
        mc.frameLayout('File', edit=True, collapse=collapseTab)
        tbWorkHeight = mc.workspaceControl(self.tbWorkID, query=True, height=True)
        mc.workspaceControl(self.tbWorkID, edit=True, resizeHeight=(tbWorkHeight-tbTabHeight))

    # def tbResizeWin(self, tbTabHeight, *args):
    #     tbWorkSize = mc.workspaceControl(self.tbWorkID, query=True, height=True)
    #     mc.workspaceControl(self.tbWorkID, edit=True, resizeHeight=(tbWorkSize-tbTabHeight))

def main():
    mainClass = MainClassToolBox()


#import tool_box_simple
#reload(tool_box_simple)
#tool_box_simple.main()

@bob.w do you have any clue as to why I would be getting a "multiple values for keyword argument ‘collapseTab’, here? Sorry to call on you directly O.O

The collapseTab is located inside the collapseFile function.
the collapseFile function is trying to collapse the frameLayout, and then after that, resize the workspace.
The function is being used inside my new checkbox button.

Possibly try using lambda instead of partial?
If not that, pass the values in by position and not by keyword?

offCommand=lambda *x: self.collapseFile(collapseTab=True, tbTabHeight=96)
onCommand=lambda *x:self.collapseFile(collapseTab=False, tbTabHeight=-96)

If I had to guess, its something to do with how partial is passing the values into the function, along with you already defining the value as a positional-with-default-value.

Thanks for the help @bob.w
I have tried your solution and it definitely fixed the error I was having!
Unfortunately, I was still unable to change the workspace size. For now I have given up on this, but I really appreciate the help here!