8.6 User interaction#
8.6.1 Busy Window#
A default handling of Busy Window is proposed and should be used for the sake of simplicity if no specific behavior is required, using sdtm.busyWindow.
RO % Function option structure % If no RO.Wa, the default busyWindow is opened with options _blocking, _busyanim and the window named "Busy Window' % If RO.Wa is found, the message is added to the existing list RO.Wa=sdtm.busyWindow('Displaying FRF...',RO); % Add message to the list if RO.Wa exists, else open default empty BusyWindow
If customization is required, the syntax to display a busy window with messages during computation is the following
Wa=sdtm.busy('uomodal'); % Open modal busy window Wa.urn('Msg{_RESET,_blocking,_busyanim,_name,Busy Window,Message to display}'); % Reset previous messages + rename window + message with sdt_icon gif animation try % Things to do and eventualy other messages % The two lines below are here as example to show the animation during 2s and simulate an error that goes to catch pause(2); error; % If success, add "done" message + open info window during 5s Wa.urn('Msg{... Done !}:Dlg{info,"Done message !","_tSuccess !",T5}'); catch % If error, add "failed" message, stop gif animation + open error window during 10s Wa.urn('Msg{Failed message,_busystop}:Dlg{error,"Error message !","_tError",T10}'); end
Some Busy Window properties can be modified on the fly with commands of type Wa.urn('Msg{_command}'). Commands are :
- _RESET : should be placed as first command to remove previous messages
- _blocking : set modal window style
- _normal : set normal window style
- _busyanim : start busy window gif animation
- _busystop : stop busy window gif animation
- _name : Wa.urn('Msg{_name,FigureTitle}'), Modify busy window title
- _hide : hide busy window (also remove modal and stop gif animation)
A dialog window can be opened after the message adding :Dlg{WindowType,"Message to display","_tWindowName",T10} at the end of the Wa.urn command. Arguments are :
- WindowType (mandatory) : accepted values are info, warning or error
- "Message to display" (mandatory) : any message shown at the middle of the window
- _tWindowName (optional) : Window name displayed at the top
- T10 (optional) : A countdown (here 10s but can be any value) that automatically closes the window
8.6.2 Handling tabs#
To initialize tabs, it is recommended to use a call of type my_ui('InitTab')
, that handles the tab generation using the standard button definitions.
To get information on the existing tabs, one can access to uf, with clean_get_uf.
It is possible to switch the display to an existing tab using cinguicurtabTab command, with Tab the tab name to switch to.
To close a tab, one should use a call to subfunction tabChage of cinguj. Handle to the subfunction can be accessed with cinguj('@tabChange')
. One must then provide the close command, the GUI figure tag, and the tab name to close.
- One can use _cur instead of a tab name to close the current tab.
- One can use command closeAll instead of close to close all tabs at once.
% close current tab: feval(cinguj('@tabChange'),'close','my_ui','_cur') % close tab 'tab' feval(cinguj('@tabChange'),'close','my_ui',tab) % close all tabs feval(cinguj('@tabChange'),'closeAll','my_ui')
8.6.3 Handling dependencies#
Dependencies define the set of actions performed consequently to the edition of a given parameter. They should be handled by a call of type my_ui('set')
. Classically dependencies are handled through the SetFcn definition relative to each parameter. In the .csv definition, most SetFcn fields should be set to my_ui('set')
.
For the exclusive case of push buttons, dependencies or actions have to be passed to the callback field.
The set function call must be able to be called from script in the same manner than from CinCell callbacks. Calls of the form my_ui('set',struct('Tab.Par',val,...));
should then edit the parameters and execute dependencies.
A typical entry to the set command can then be
if carg<=nargin; % from script mode r1=varargin{carg}; carg=carg+1; r2=fieldnames(r1); if length(r2)>1 % allow multiple fields input at once for j1=1:length(r2); % loop to assign each field my_ui('Set',struct(r2{j1},r1.(r2{j1}))); end return % get out after having assigned each parameter else % one parameter provided, carry on obj=r1j.(CAM).(r2{1}); val=r1.(r2{1}); gf=GuiGF; uo=struct('FromScript',1); % build the data endelse % callback from CinCell [RO,uo,CAM,Cam]=clean_get_uf('getuo',['SetStruct' CAM]); obj=uo.ob; val=fieldnames(RO); gf=GuiGF; val=RO.(val{1});
end % robustness check regarding object existence if isempty(obj) r1=fieldnames(r1); r1=r1{1}; sdtw('_nb','Property %s does not exist in %s, skipped',r1,CAM); return else; CAM=sdcedit(obj,'_get','name'); Cam=lower(CAM); end
A robust recuperation of the active CinCell is performed through a clean_get_ufgetuo call. Recuperation of the parameter name can be performed with a sdcedit call. Note that obj should be an EditT java object or a CinCell.
To edit or get parameter values it is recommended to use sdcedit that implements robust parameter assignations.
To get values, if the object is an EditT, one should use 4 argument calls of the type r1 = sdcedit(obj,'field','_get','prop')
, with field the parameter name, and prop the property to get, which is one of the fields defined in the button. A shortcut command to get the property value can be used used r1=sdcedit(obj,'_get','field')
.
If the object is a CinCell, one can use direct get commands with r1=obj.get('prop');
.
In the case of pop buttons, the current value can be expressed either as the index in the choices list (or ChoicesTag if defined) or the value in the choices list directly. To ensure the type of data accessed, one can use
st1 = sdcedit(r1j,'field','_popvalue',[])
to get the value in the choice list, or i1=sdcedit(r1j,'field','_popindex',[])
to get the index in the choice list.
To assign properties, if the object is an EditT, one can use 4 argument calls of the type r1 = sdcedit(obj,'field',''prop',value)
, with field the parameter name, and prop the property to set to value. A shortcut command to set the property value to val for both EditT and CinCell objects can be used obj=sdcedit(obj,'field',val)
.
If the object is a CinCell, one can use direct set commands with r1=obj.set('prop',val);
.
8.6.4 Dialogs#
Interaction through dialog windows is possible, and standard sdt_dialogs calls are accessible. Specific dialogs using java objects with interactivity is also possible, but the dialog figure should always be the same and be closed after the dialog to control the number of opened figures.
File input dialog#
The most classical dialog is to ask for a file or directory input. If the input file is a parameter in a push button, the user input is handled using a callback with sdt_dialogsEEdit, and the field SetFcn to handle the dependencies.
One can thus define such interactivity with a csv definition like
h;type=push;name;callback;value;ToolTip;SetFcn=my_ui('Set') n;Familiy.FileInput;sdt_dialogs('EEdit_File');"Click to input file";"Specify a file"
Call EEdit of sdt_dialogs has several variants,
- EEdit_File to ask for an existing file.
- EEdit_Dir to ask for a directory.
- EEdit_FPut to ask for a file that can possibly be created.
- EEdit_prompt to ask for an input defined through a set of parameters defined in a PropertyUnitTypeCell format.
sdt_dialogs('EEdit_prompt m_elastic 2'); sdt_dialogs('EEdit_prompt -eval"my_fun(''proptypecell'');"',indRequired,val);
Selection in a tree dialog#
When performing design of experiment analyses with saved results, one can use a tree representation of the parameter grid using fe_defRangeTree with a standard SDT parameter structure.
It is possible to implement callbacks in the tree to trigger actions for a specific point, such as loading the selected data set or displaying the selected results.
Using a standard SDT RangeGrid structure here named par, one can display in a dialog figure named my_uidlg the RangeTree that will call a specific loading function with
gf=cinguj('ObjFigInit',struct('Tag','my_uidlg,'name',my_uidlg','noMenu',1)); ua=fe_def(['rangetree-outgf-minName-root"DOE"-push-getUA"my_uidlg"'... '-callback"sprintf(''my_ui(''''load'''',%%i);'',RO.valLink(j1));"'],par); cinguj('tabbedpaneAddTree',ua.ParentPanel,ua,'my_uidlg');
In the fe_defRangeTree call,
- -outgf Activated the display mode of RangeTree that will generate the java tree object.
- -minName Asks to generate node names to display only with the sub name corresponding to the node level.
- -root"st" Allows specifying a tab root name in the my_uidlg figure.
- -push Activates the generation of push buttons with callbacks for the tree nodes. By default the callback displays in the command window the index in the Range.val list corresponding to the clicked point.
- -getUA"tag" Asks to output the tree object for customized external display. tag allows specifying to which parent figure the tree will be displayed.
- -callback"fcn" Allows defining a customized callback. The fcn input must in fact be a string that will be evaluated to generate the callback call itself, so that the user can exploit the index in the Range.val list corresponding to the clicked node. Since the displayed nodes are not in the same order than the initial list, fe_defRangeTree uses the internal variable RO.valLink to make the conversion between the displayed node order and the initial val list. The callbacks are generated in a loop in the node order, indexed by j1. In the example, the callback to be generated is
my_ui('load',i1)
with input i1 being the index of the clicked node in the initial val list.
For such behavior to be relevant, one expects the Range variable par to be accessible at any time by the function my_ui. Saving par in the GUI file tree or making it a persistent variable of my_ui are to easy solutions to this issue.
This mechanism can be used to handle a project results file tree. In this case the DefBut variable should contain the Range structure that will have to be incremented on the fly when saving a file.
Check list dialog#
sdt_dialogs provides a check list functionality handling based on keywords. The associated button is valued as the list of keywords separated with commas. Its edition is then based on a list to check.
The following code demonstrates the use of such button, through a complete definition
% Use of buttons associated to a check list % Define a tab with simple DefBut r1=['Post(","#push#"define post list")']; % DefBut % interpet DefBut R1=cingui('paramedit',r1); % Specifc check list definition R1.Post.callback={'sdt_dialogs','EEdit_CheckList'}; % callback % associate a keyword list R1.Post.list=['FcA(#3#"Fc stats unfiltered")'... 'Fc20(#3#"Fc stats filtered 20Hz")' ... 'UpA(#3#"Uplifts unfiltered")' ... 'SubPto(#3#pantograph displacements")']; R1.Post.SetFcn=''; % Now display tab with functional button gf=cinguj('tabbedpanefig','demo_checkList'); R1=cinguj('ObjEditJ',R1,gf); ua=struct('name','demo_checkList','ParentPanel',gf,'table',... {sdt_dialogs('uatable-end0','info','Post',R1)}); cinguj('tabbedpaneadd',gf,ua,ua.name,[]);