8.3 Handling data in the GUI format#
8.3.4 Data storage and access#
Initializing the GUI figure#
After generating the Java objects containing the parameters, one can store them in the GUI figure for further access. The data are stored in the GUI figure that is initialized by cinguj ObjFigInit.
GuiGF=cinguj('objFigInit',... struct('tag','my_ui','noMenu',1,'name','my_ui'));
The handle should be stored UI.gf field of persistent variable UI in my_ui. One can also recover this pointer at any time by using GuiGF=findall(0,'tag','my_ui'). It is thus critical to ensure the unicity of the GUI figure tag.
Efficient data storage in a figure is handled in SDT through the use of v_handle uo object. Access to this pointer is possible at any time using
uo = v_handle('uo',GuiGF);
It is recommended to package the access to the java data pointer in a command uo=my_ui('vh')
.
Handling the data java pointer#
Automatic storage of the data pointer is performed at display. The pointer is handled as a MATLAB struct with fields corresponding to the parameter families. The objects stored are then either the EditT containing the full parameter family or a struct of CinCell, respectively corresponding to the first and second outputs of the ObjEditJ command.
A very low level way of storing invisible data is to edit the uo object directly by doing
r1=get(GuiGF,'UserData'); r1.(family)=r1j; set(GuiGF,'UserData',[],'UserData',r1);
where family is the parameter family, r1j the EditT object generated by ObjEditJ and GuiGF the handle to the GUI figure. It is however recommended to let it be stored automatically at display.
Recovering data from java objects#
To recover data in a RunOpt MATLAB struct format from EditT or CinCell objects, command fe_defCleanEntry must be used.
- For an EditT object the output of CleanEntry will be a structure with as many fields as parameters stored in the EditT assigned with their value converted to the proper format provided. When an EditT is displayed in a tab, obj.Peer should be the numeric handle to the Matlab figure so that clean_get_uf can retrieve tab data.
- For a CinCell object, the output of CleanEntry will be the underlying structure of the button, as documented. Each CinCell object can/should have a EditT parent obtained with obj.get('parent').
- For pop objects CinCell or struct, the value is taken to be the choicesTag string if it exists or the choices string otherwise.
fe_defCleanEntry no longer returns the full structure for a button, so that the command r1=cinguj('ObjToStruct',ob); should be used.
To get the current data (.data{.val} of pop button, one uses r1=feval(sdtroot('@obGet'),ob,'data');.
It is recommended to build a call my_ui('GetTab')
that will rethrow the RunOpt structure corresponding to a Tab from the GUI figure.
% get Java pointer and desired tab field out=my_ui('vh'); tab=varargin{carg}; carg=carg+1; % convert to a RunOpt structure out=fe_def('cleanentry',out.(tab));
Direct access to a parameter can also be usefully packaged in my_ui('GetTab.Param')
, with
% get Java pointer and desired tab field out=my_ui('vh'); tab=varargin{carg}; carg=carg+1; % parse tab to see if subfields are desired tab=textscan(tab,'%s','Delimiter','.'); tab=tab{1}; % convert to a RunOpt structure out=fe_def('cleanentry',out.(tab{1})); % output only the desired subfield if it was specified if length(tab)>1; tab(1)=[]; while ~isempty(tab)&&~isempty(out); out=out.(tab{1}); st(1)=[]; end end
Displaying data in the GUI figure#
To display the parameters in the GUI figure, one has to generate a structure that will be interpreted as a JTable that will be included to the JTabbedPane object, that is to say the tabbed area of the GUI figure. This structure contains the fields
- name The name of the object that will be display. It is recommended to use the family name of the parameter family displayed.
- table A cell array containing the buttons in the CinCell. The JTable will have the same size as the table provided.
- ToolTip A string allowing to display some explanations on the tab.
- ParentPanel The handle to the GUI figure.
Generation of the table field can be done automatically with a call to sdt_dialogs uatable
ua.table=sdt_dialogs('uatable-end0','info',name,r1j);
with name the field relative to ua.name and r1j the EditT object (with .Peer defined). This will yield a tab with three columns, the first one being the parameter names, the second one the editable buttons as CinCell objects and the third one being the parameter ToolTip.
More complex layouts can be obtained by generating the table manually, exploiting the second output of the ObjEditJ command to fill in table positions. This allows generating the table by directly positioning the CinCell objects called by their names.
By adding a field level to ua, and calling cingujTabbedPaneAddTree a tree will be displayed instead of a table in the GUI figure. Field level has two columns and as many lines as the table. The first column provides the level of the table line in the tree as an integer. The second column indicates whether the line has to be expanded is set to 1, or not if set to 0.
Once ua is filled display is performed using cinguj TabbedPaneAdd
[ua,ga]=cinguj('TabbedPaneAdd','my_ui',ua);
Command TabbedPaneAdd outputs ua that contains the displayed objects and their information. This can be accessed any time using field tStack of the GUI figure userdata, uf=clean_get_uf(GuiGF)
, and ga that is the handle to the figure axis containing the tab.
8.3.5 Tweaking display#
Display can be tuned to the user will by editing the displayed objects. All display information is accessed through a call to clean_get_uf, using GuiGF the GUI figure handle as input argument.
uf = clean_get_uf(GuiGF);
uf is a user data structure with fields
- ParentFigure The GUI figure handle. This should be equal to GuiGF.
- p The handle to the uipannel displaying the data.
- tStack A cell array of 7 columns and as many lines as tabs generated. Column 1 contains the tab names and column 7 contains the tab userdata object.
- tab the index in tStack corresponding to the tab currently displayed.
- java set to 1. Ensures that the userdata handles java objects for cingui.
- JPeer A pointer to the Java object containing the display, either a JTabbedPane if only tabs are displayed, or a JScrollPane if only a tree is displayed, or a JSplitPane if the display contains several Panes.
- pcontainer The handle to the hgjavacomponent that contains the display.
- toolbarRefresh (Optional) A function handle that can be called at refresh to perform toolbar dependencies (e.g. uicontrol enabling as function of the GUI state.
- tag The GUI figure tag.
- Explo If an exploration tree is present, the JScrollPane java object containing the tree.
- EJPeer If an exploration tree is present, JSplitPane java object containing the global display.
The seventh column of uf.tStack contains information relative to each of the tab objects of the JTabbedPane. It is commonly named ub and contains the following fields
- name The tab name, that should be corresponding to the parameter family.
- table A cell array containing the objects of each cell of the JTable
- ToolTip A string providing a tool tip if the mouse cursor if over the tab tip.
- ParentPannel The handle to the GUI figure.
- type A string providing the table objects type, commonly CinCell.
- JTable The JTable java object.
- JPeer pointer to the JScrollPane typically used for display.
- NeedClose value set to force use of a close button on the tab.
Each tabbed pane can be tweaked regarding the displayed column dimensions.
In the case of a GUI displaying user input objects the table itself does not need to be interactive. (This is different from a results table that will be analyzed by the user). It is thus recommended to deactivate the table selection interactivity using
ub.JTable.setRowSelectionAllowed(false); ub.JTable.setColumnSelectionAllowed(false); ub.JTable.setCellSelectionEnabled(false);
Columns width can be set using a line array with as many columns as columns in the table and providing in pixels the minimal width a column should have to cingujtableColWidth. The value can be set to -1 if the user wishes to let free the width of a column.
% for 3 columns table, last one left free ColWidth=[150 300 -1]; cinguj('tableColWidth',ub.JTable,ColWidth);
For a finer control of the column width, it is possible to provide a three-rows array :
- First row = Preferred width proportion : these columns are allowed to expand and extra space is distributed using these coefficients
- Second row = Minimum width
- Third row = Maximum width (use minimum width = maximum width to fix a column)
% For 3 columns table % Middle column fixed to 20px % First and last column with minimum width to 150px % Extra width is distributed 3 times more on the last coumn than on the first one ColWidth=[1 0 3 ; % Preferred width proportion (0=need mini and maxi width) 150 20 150 ; % Minimum width Inf 20 Inf]; % Maximum width (0 or Inf = nolimit) cinguj('tableColWidth',ub.JTable,ColWidth);
Row height can be set (same for all lines) by calling the setRowHeight method of JTable. The value is in pixel.
% getting the intial row height r1 = ub.JTable.getRowHeight % setting a new row height to 22px ub.JTable.setRowHeight(22)
8.3.6 Defining an exploration tree#
To ease up navigation between tabs, one can use an exploration tree in the GUI figure. Tabs can then be opened by clicking in the tree that should list all available tabs (or parameter families).
The exploration tree is commonly named PTree, and has to be defined in the .csv file. It should contain push type buttons with callbacks triggering the opening of the desired tab.
c; sample PTree definition
h;type=push;name;callback;value;ToolTip;
n;PTree.Family;my_ui('InitFamily');"Family";"Open corresponding family tab"
To properly handle an exploration tree, one has to initialize it when the GuiGF figure is opened, that is to say after the cinguj ObjFigInit call. The initialization should be handled by a call of the type mu_ui('InitPTree')
.
Low level access to the exploration tree is handled by a subfunction of cinguj named treeF. The subfunction handle can be accessed using treeF=cinguj('@treeF');
. It is recommended to store the variable treeF containing the subfunction handle in a persistent variable of the GUI function my_ui.
% option initialization RunOpt=struct('NoInit',0,'lastname',''); % for all fields of DefBut.PTree, sort the buttons r1=fieldnames(DefBut.PTree); table=cell(length(r1),2); for j1=1:length(r1);table(j1,:)={DefBut.PTree.(r1{j1}) [1 1]}; end % generate clean table and corresponding levels level=vertcat(table{:,2}); table=table(:,1); % generate the tree ua ua=struct('table',{table},'level',level,'name','my_ui',... 'ParentPanel',GuiGF,'ToolTip','The GUI exploration tree','NeedClose',2); % display the tree in the GUI figure [tree,gf]=cinguj('tabbedpaneAddTree','my_ui',ua); % tweak the tree to enable selected tab field highlighting tree.getSelectionModel.setSelectionMode( ... javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION) % refresh cingui('resize',GuiGF);
The exploration tree thus defined highlights its node corresponding to the currently displayed tab. This tasks is performed automatically by cinguj when clicking on a button of a tree.
To access the tree object and its highlighted field, one can do
[RunOpt.lastname,tree]=treeF('explolastname',GuiGF);
To switch the highlighted field to a new name newname and get the tree node object, one can do
node=treeF('scrollToNameSelect',tree,newname);