Placement of exterior subwindows

Dear Igorians,

I'm using exterior subwindows quite a lot for adding GUI controls to graphs.
Now I'm facing the problem that I'm starting to run out of vertical space as I don't seem to be able to place them space efficiently.

The following code

Window Panel0() : Panel
    PauseUpdate; Silent 1       // building window...
    ModifyPanel fixedSize=0
    RenameWindow #,P0
    SetActiveSubwindow ##
    ModifyPanel fixedSize=0
    RenameWindow #,P1
    SetActiveSubwindow ##

gives a graph and two exterior subwindows P1 and P0 on the left of the graph. Is it possible to move P1 below P0?

I find it helps to dynamically extend that side subwindow, and either allow users to collapse capabilities that aren't wanted, or actually hide from users capabilities that are not allowed. See the images attached. In the "mafBrowse" one, the user clicks the little expander buttons to show different things to modify about the wave being displayed. In the "mafScope" one, the user gets to choose which A/D channels to display in the window, and then the side window allows them to only modify properties of those channels. It is a little grueling coding such things, I have to admit, because any time you add a new feature, you have to recalculate where all the controls go. I do also find those subwindows can get quite long, so I like to allow the ability to hide them altogether, with the expander button on the main graph (e.g. on the "mafBrowse" example). Perhaps this doesn't suit your needs.
Thanks for the nice example Matthew.

It looks interesting! I'm a bit concerned about the "grueling coding" as I'm the one how has to code it and also needs to adapt it quite often.

How have you implemented the triangle for opening/closing the sub groups?
I thought that I had posted a code snipped for this. It involves the use of userData to store the open/close state. An additional note is to set constants for the panel in open and closed states.

// Panel Size Parameters

Constant ndepth = 120
Constant nwidth = 255
Constant cdepth = 20
Constant cwidth = 255

// the control in the panel creation procedure

    Button XtendD,pos={4,5},size={15,20},proc=XtendDown,title="v", userData="opened"

// the function to open/close the panel below the arrow

Function XtendDown(ba) : ButtonControl
    STRUCT WMButtonAction &ba

    SVAR/SDFR=$thePackageFolder cw = currWin
    DFREF cwDFR = $(thePackageFolder + ":" + cw)
    SVAR pn = cwDFR:panelName
    switch( ba.eventCode )
        case 2: // mouse up
                case "closed":
                    Button XtendD win=$(cw + "#" + pn), title="v", userData="opened"
                    MoveSubWindow/W=$(cw + "#" + pn) fnum=(0,0,nwidth,ndepth)
                case "opened":
                    Button XtendD win=$(cw + "#" + pn), title=">", userData="closed"
                    MoveSubWindow/W=$(cw + "#" + pn) fnum=(0,0,cwidth,cdepth)
    return 0

Controls below the collapsed panel "disappear" when the panel is collapsed.

Check out the ScrollTraces package for details.

J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAH
You can see an example of this in the Multipeak Fit 2 control panel. I like to use window guides and put all the controls into a panel subwindow. Then it is a simple matter of showing/hiding the subwindow to show/hide all the controls.

John Weeks
WaveMetrics, Inc.
The triangle is one "mode" for checkbox/radio button controls. It seems to be called a "disclosure triangle". I gather from the other comments that lots of other people have solutions for this. I may have found a lousy way to do it, which may have led to my "grueling" comment. Sorry. I should lighten up.
The basic strategy I use is to test each one of those triangles for if it is active, and update the disable state for each of "its" controls (hiding or showing as appropriate). If to be shown, I update each control's position (this is the grueling part), based on its local position plus an overall offset. That overall offset gets incremented with each grouping.
Maybe a simplified snippet will explain better:

Function MyControlCheckProc(cba) : CheckBoxControl  //each disclosure triangle calls this
    STRUCT WMCheckboxAction &cba
    variable thispos = 0, tempcheck

    // update what controls are showing, and where they are
    // Group 1
    tempcheck = checkval ("Group1Check", // checkval returns the true-false state of a checkbox
    ModifyControlList "Group1Group;Group1SetVar1;Group1SetVar2", disable=(1-tempcheck), win=$( // hides or shows all controls in the group
    CheckBox Group1Check, pos={2,3 + thispos}, win=$( // update y-position of disclosure triangle
    if (tempcheck) // showing, so update y-positions of everyone in the group
        SetVariable Group1SetVar1, pos={8, 17 + thispos}, win=$(
        SetVariable Group1SetVar2, pos={24, 36 + thispos}, win=$(
        GroupBox Group1Group, pos={1,1 + thispos}, win=$(  // it is nice to frame these groups of controls
        thispos += 79 // next group starts way down, well clear of these controls
    else // not showing, so just just update start position of next group
        thispos += 18 // next group starts just clear of the disclosure triangle
    // Group2
    tempcheck = checkval ("Group2Check",
    ModifyControlList "Group2Group;Group2SetVar1;Group2SetVar2"  disable=(1-tempcheck), win=$( // update show/hide of next group
    CheckBox Group2Check, pos={2,3 + thispos}, win=$( // update position of disclosure triangle
    if (tempcheck)
    ... // move next groups as appropriate

It is a little fiddly getting all the spacings just right.


p.s. Thanks for pointing out "Extract" somewhere. How did I miss that one? Very useful.