| Search Locate Previous Next | Contents |
In Causeway, the MDI parent form is treated no differently from any other main form the only thing to remember is that the child forms are made as a special MDI child class. Typically you would localise all your working variables on the child form, and read them from file on its create event, probably passing the file name as an argument to #.CPro.Make. In this example I have a simple notepad field on each child, with the content set to the forms Dyalog Gui-name on creation:
Here the main form makes the toolbar and creates two children:
Disp dbx.mdip[1;1 2 5]ÚÎÎÂÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÌ
ÛFMÛSample MDIÛÚÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÌÛ
Û Û ÛÛBehaviourÛÚÎÎÂÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÂÎÎÌÛÛ
Û Û ÛÛ ÛÛCRÛÛtop Û{}ÛÛÛ
Û Û ÛÛ ÛÃÎÎÏÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÏÎÎÝÛÛ
Û Û ÛÛ ÛÛPCÛÛMake #.Class.MakeBa... Û{}ÛÛÛ
Û Û ÛÛ ÛÃÎÎÏÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÏÎÎÝÛÛ
Û Û ÛÛ ÛÛPCÛÛMake¨2½dbx.ch Û{}ÛÛÛ
Û Û ÛÛ ÛÀÎÎÁÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÁÎÎÙÛÛ
Û Û ÛÃÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝÛ
Û Û ÛÛLocals Û{top} ÛÛ
Û Û ÛÃÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝÛ
Û Û ÛÛTitlebar ÛÚÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÌ ÛÛ
Û Û ÛÛ ÛÛExpressionÛSample MDI ,topÛ ÛÛ
Û Û ÛÛ ÛÃÎÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝ ÛÛ
Û Û ÛÛ ÛÛDependenceÛ{top} Û ÛÛ
Û Û ÛÛ ÛÀÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÙ ÛÛ
Û Û ÛÃÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝÛ
Û Û ÛÛMenu ÛÚÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÌ ÛÛ
Û Û ÛÛ ÛÛExpressionÛmenu_mdiÛ ÛÛ
Û Û ÛÛ ÛÀÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÙ ÛÛ
Û Û ÛÃÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝÛ
Û Û ÛÛTopform ÛÚÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÌ ÛÛ
Û Û ÛÛ ÛÛExpressionÛtop Û ÛÛ
Û Û ÛÛ ÛÃÎÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÝ ÛÛ
Û Û ÛÛ ÛÛDependenceÛ{top}Û ÛÛ
Û Û ÛÛ ÛÀÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÙ ÛÛ
Û Û ÛÀÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÙÛ
ÀÎÎÁÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÙ
... and the children set up their data:
'mdi' Dbx 'dbx.ch1'
Disp dbx.ch[;1 2 5]ÚÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÌ
ÛMDIÛChild WindowÛÚÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÌÛ
Û Û ÛÛBehaviourÛÚÎÎÂÂÎÎÎÎÎÎÎÂÎÎÌ ÛÛ
Û Û ÛÛ ÛÛCRÛÛnotes¸Û{}Û ÛÛ
Û Û ÛÛ ÛÀÎÎÁÁÎÎÎÎÎÎÎÁÎÎÙ ÛÛ
Û Û ÛÃÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝÛ
Û Û ÛÛLocals Û{notes} ÛÛ
Û Û ÛÃÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝÛ
Û Û ÛÛMenu ÛÚÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÎÌÛÛ
Û Û ÛÛ ÛÛExpressionÛwindowÛÛÛ
Û Û ÛÛ ÛÀÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÙÛÛ
Û Û ÛÀÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÙÛ
ÃÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÝ
ÛNP Û ÛÚÎÎÎÎÂÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÌ Û
Û Û ÛÛTextÛÚÎÎÎÎÎÎÎÎÎÎÂÎÎÎÎÎÎÎÌÛ Û
Û Û ÛÛ ÛÛExpressionÛnotes ÛÛ Û
Û Û ÛÛ ÛÃÎÎÎÎÎÎÎÎÎÎÏÎÎÎÎÎÎÎÝÛ Û
Û Û ÛÛ ÛÛDependenceÛ{notes}ÛÛ Û
Û Û ÛÛ ÛÀÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÙÛ Û
Û Û ÛÀÎÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÙ Û
ÀÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÁÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÙ
The other two important things to set up are the window menu for the main form, and the corresponding Menu property for each child.
The main menu now looks like this ...
menu_mdi
[Root]
&File>file
&Window>window
&Help>help
[file]
&New=Ctrl+N;Adds a New child window: Make dbx.ch
&Open=Ctrl+O;Open an existing file : 'Open'
&Save=Ctrl+S;Save your work : 'Save'
Save&As;Save with a new name : 'SaveAs'
-------------
E&xit:Post 'SC'
[window]
Tile &Horizontal: ¸ Do 'Htile'
Tile &Vertical: ¸ Do 'Vtile'
&Cascade: ¸ Do 'Cascade'
[help]
&About:#.Win.Msg 'My Program' 'Keep off'
The setting of the Menu property of the MDI child to window allows Causeway to make the connection between the children and the menu structure on the main form (called [window]), so that as we add more windows they are listed automatically at the end of the window menu and the user can switch between them even when they are maximised.
Starting with a Clear MDI Frame
Because Causeway only fills in the MDI backdrop when you make the first child, a small cheat is required if you want to start the application with no child windows open. Make a dummy MDI child form (just 'MDI' Dbx 'dbx.dummy' and save immediately) and set the post-create action on the parent to:
(Make dbx.dummy) Do 'Close'
... which makes the child form (the parent is still hidden, so nothing shows on the screen) and immediately discards it.
Running Toolbar Actions on the MDI Children
A major complexity added by MDI is that toolbar and menu actions must act on the child form which is currently at the top of the heap. You may have noticed that the parent form localises a variable top and sets this as the data expression for the Topform property. This is also shown in the titlebar of the main form, so that we can see it change as the child forms are brought to the top of the stack. If you try running this example and switch between the child forms you will see how Causeway maintains this property for you.
A simple extension to the toolbar is to make the <Close> button close down the current child:
Select: top Post 'SC'
The next stage is to add some controls to the toolbar which modify the local data on each child. Here is the toolbar with two extra buttons to clear the notes field and flip its contents around:
... and here are the Select actions on the two new buttons:
top Execute 'notes²notes ª Notify ''notes''' top ExecuteNR 'Wipe'
... where the Wipe function just looks like:
Wipe[] [0] Wipe [1] © Clear down the notes [2] notes'Hi' [3] #.CPro.Notify'notes'
The new functions you need to know about are #.CPro.Execute and #.CPro.ExecuteNR, which take any simple character vector and run it as if it were an action on the object which you pass as the left argument. This means that the expression has full access to all the locals on that form, and it can notify changes which will only apply locally it does not matter that there is another form out there with locals of the same name! Note that you should use the NR version if your function does not return a result.
It is probably tidier to make small subfunctions (like Wipe) for all these actions, as otherwise you rapidly get buried under strings of quotes. Also it is often very convenient to stop the code (for example on line-2 of Wipe) where you can inspect the variables, try out expressions, paste bits of code from the session into the definition, and so on.
As a final refinement, you might make the <Close>, <Wipe> and <Flip> buttons inactive unless there is at least one child form available. You could add an expression such as:
0<½top
as the Active property of each of them (with a dependency of top, naturally), or you could put them all into a group and run 'BTNS' Do 'Disable' or 'Enable' as appropriate from a Post-Update handler on the top variable. The former is easier to code, the latter may be faster if you have lots of buttons.