Skip to content

Commit d9168bd

Browse files
committed
BREAKING: refactored getWidgetInfo into getWidgetInfo+getWidgetList
- `getWidgetInfo` now operates on a single widget, whereas `getWidgetList` has the old functionality of `getWidgetInfo` (i.e. it accepts a `uifigure` and returns a list of widgets). The heavy lifting is done by the new `private` `decodeDijitRegistryResult` method. - README updated. - Fixed an off-by-1 bug in the widget decoding logic.
1 parent 60d71b4 commit d9168bd

File tree

2 files changed

+105
-44
lines changed

2 files changed

+105
-44
lines changed

README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ published Wednesday, September 7th, 2016.
1616
[`matlab-app-designer` tag on Stack Overflow](https://stackoverflow.com/questions/tagged/matlab-app-designer).
1717

1818
## Methods
19-
[`aboutDojo`](#aboutDojo) - Return the Dojo toolkit version.
19+
[`aboutDojo`](#aboutDojo) - Return the dojo toolkit version.
2020
[`fontColor`](#fontColor) - Modify font color.
2121
[`fontWeight`](#fontWeight) - Modify font weight.
2222
[`getHTML`](#getHTML) - Return the full HTML code of a `uifigure`.
23-
[`getWebElements`](#getWebElements) - Get a webwindow handle and a widget ID from a `uifigure` control handle.
23+
[`getWebElements`](#getWebElements) - Extract a `webwindow` handle and a widget ID from a `uifigure` control handle.
2424
[`getWebWindow`](#getWebWindow) - Extract a `webwindow` handle from a `uifigure` handle.
25-
[`getWidgetInfo`](#getWidgetInfo) - Get a list of widgets from the dijit registry.
25+
[`getWidgetInfo`](#getWidgetInfo) - Gather information about a specific dijit widget.
26+
[`getWidgetList`](#getWidgetList) - Gather information about all dijit widget in a specified `uifigure`.
2627
[`setStyle`](#setStyle) - Modify a specified style property.
2728
[`setTimeout`](#setTimeout) - Override the default timeout for dojo commands, for a specific `uifigure`.
2829
[`textAlign`](#textAlign) - Modify text alignment.
@@ -144,12 +145,27 @@ A method for getting the webwindow handle associated with the provided `uifigure
144145
Using the demo GUI generated by `./Demo/DOMdemoGUI.m`
145146
```MATLAB
146147
myGUI = DOMdemoGUI;
147-
mlapptools.getWebWindow(myGUI.UIFigure);
148+
win = mlapptools.getWebWindow(myGUI.UIFigure);
148149
```
149150

150151

151152
<a name="getWidgetInfo"></a>
152-
#### *mlapptools*.**getWidgetInfo**(*hUIFigure*, *verbosityFlag*)
153+
#### *mlapptools*.**getWidgetInfo**(*hWebwindow*, *widgetID*, *verbosityFlag*)
154+
##### Description
155+
Query the [dijit registry](https://dojotoolkit.org/reference-guide/dijit/registry.html#dijit-registry) for a widgets
156+
having a specific ID, and return its details in a scalar `cell` containing a `struct`.
157+
158+
##### Examples
159+
Using the demo GUI generated by `./Demo/DOMdemoGUI.m`
160+
```MATLAB
161+
myGUI = DOMdemoGUI;
162+
[win, widgetID] = mlapptools.getWebElements(myGUI.TextArea);
163+
nfo = mlapptools.getWidgetInfo(win, widgetID);
164+
```
165+
166+
167+
<a name="getWidgetList"></a>
168+
#### *mlapptools*.**getWidgetList**(*hUIFigure*, *verbosityFlag*)
153169
##### Description
154170
Query the [dijit registry](https://dojotoolkit.org/reference-guide/dijit/registry.html#dijit-registry) for all widgets
155171
within the current page, and return them in a cell array of structs.
@@ -158,7 +174,7 @@ within the current page, and return them in a cell array of structs.
158174
Using the demo GUI generated by `./Demo/DOMdemoGUI.m`
159175
```MATLAB
160176
myGUI = DOMdemoGUI;
161-
wList = mlapptools.getWidgetInfo(myGUI.UIFigure);
177+
nfoList = mlapptools.getWidgetList(myGUI.UIFigure);
162178
```
163179

164180

@@ -191,7 +207,7 @@ Modify the amount of time allotted to dojo queries before they are considered "f
191207
##### Examples
192208
```MATLAB
193209
myGUI = DOMdemoGUI;
194-
mlapptools.setTimeout(myGUI, 3); % This will wait less for dojo queries to finish.
210+
mlapptools.setTimeout(myGUI.UIFigure, 3); % This will wait less for dojo queries to finish.
195211
```
196212

197213

mlapptools.m

Lines changed: 82 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -130,46 +130,56 @@ function fontWeight(uiElement, weight)
130130

131131
end % getWebWindow
132132

133-
function varargout = getWidgetInfo(hUIFig, verboseFlag)
134-
% A method for gathering information about dijit widgets.
135-
136-
%% Handle missing inputs:
137-
if nargin < 1 || isempty(hUIFig)
138-
throw(MException('getWidgetInfo:noHandleProvided',...
133+
function [nfo] = getWidgetInfo(win, widgetID, verboseFlag)
134+
% A method for gathering information about a specific dijit widget.
135+
%% Handling required positional inputs:
136+
assert(nargin >= 2,'mlapptools:getWidgetInfo:insufficientInputs',...
137+
'getWidgetInfo must be called with at least 2 inputs.');
138+
%% Handling optional inputs:
139+
if nargin < 3 || isempty(verboseFlag)
140+
verboseFlag = false;
141+
end
142+
%% Querying dijit
143+
win.executeJS(['var W; require(["dijit/registry"], '...
144+
'function(registry){W = registry.byId("' widgetID '");}); W = [W];']);
145+
% Decoding
146+
try
147+
nfo = mlapptools.decodeDijitRegistryResult(win,verboseFlag);
148+
catch ME
149+
switch ME.identifier
150+
case 'mlapptools:decodeDijitRegistryResult:noSuchWidget'
151+
warning(ME.identifier, '%s', ME.message);
152+
otherwise
153+
warning('mlapptools:getWidgetInfo:unknownDecodingError',...
154+
'Decoding failed for an unexpected reason: %s', ME.message);
155+
end
156+
nfo = [];
157+
end
158+
% "Clear" the temporary JS variable
159+
win.executeJS('W = undefined');
160+
end % getWidgetInfo
161+
162+
function varargout = getWidgetList(hUIFig, verboseFlag)
163+
% A method for listing all dijit widgets in a uifigure.
164+
warnState = mlapptools.toggleWarnings('off');
165+
%% Handle missing inputs:
166+
if nargin < 1 || isempty(hUIFig) || ~mlapptools.isUIFigure(hUIFig)
167+
throw(MException('mlapptools:getWidgetList:noHandleProvided',...
139168
'Please provide a valid UIFigure handle as a first input.'));
140169
end
170+
warning(warnState); % Restore warning state
141171
if nargin < 2 || isempty(verboseFlag)
142172
verboseFlag = false;
143173
end
144-
%%
174+
%% Process uifigure:
145175
win = mlapptools.getWebWindow(hUIFig);
146-
%% Extract widgets from dijit registry:
147-
n = str2double(win.executeJS(['var W; require(["dijit/registry"], '...
148-
' function(registry){W = registry.toArray();}); W.length;']));
149-
widgets = cell(n,1);
150-
for ind1 = 1:n
151-
try
152-
widgets{ind1} = jsondecode(win.executeJS(sprintf('W[%d]', ind1)));
153-
catch % handle circular references:
154-
if verboseFlag
155-
disp(['Node #' num2str(ind1-1) ' with id ' win.executeJS(sprintf('W[%d].id', ind1-1))...
156-
' could not be fully converted. Attempting fallback...']);
157-
end
158-
props = jsondecode(win.executeJS(sprintf('Object.keys(W[%d])', ind1-1)));
159-
tmp = mlapptools.emptyStructWithFields(props);
160-
validProps = fieldnames(tmp);
161-
for indP = 1:numel(tmp)
162-
try
163-
tmp.(validProps(indP)) = jsondecode(win.executeJS(sprintf(['W[%d].' props{ind1}], ind1-1)));
164-
catch
165-
% Fallback could be executed recursively for all problematic field
166-
% (to keep the most data), but for now do nothing.
167-
end
168-
end
169-
widgets{ind1} = tmp;
170-
clear props validProps tmp
171-
end
172-
end
176+
% Extract widgets from dijit registry:
177+
win.executeJS(['var W; require(["dijit/registry"], '...
178+
' function(registry){W = registry.toArray();});']);
179+
widgets = mlapptools.decodeDijitRegistryResult(win, verboseFlag);
180+
% "Clear" the temporary JS variable
181+
win.executeJS('W = undefined');
182+
%% Assign outputs:
173183
varargout{1} = widgets;
174184
if nargout == 2
175185
% Convert to a single table:
@@ -258,6 +268,41 @@ function textAlign(uiElement, alignment)
258268
end
259269
end % checkJavascriptSyntaxError
260270

271+
function widgets = decodeDijitRegistryResult(win, verboseFlag)
272+
assert(jsondecode(win.executeJS(...
273+
'this.hasOwnProperty("W") && W !== undefined && W instanceof Array && W.length > 0')),...
274+
'mlapptools:decodeDijitRegistryResult:noSuchWidget',...
275+
'The dijit registry doesn''t contain the specified widgetID.');
276+
277+
% Now that we know that W exists, let's try to decode it.
278+
n = str2double(win.executeJS('W.length;'));
279+
widgets = cell(n,1);
280+
% Get the JSON representing the widget, then try to decode, while catching circular references
281+
for ind1 = 1:n
282+
try
283+
widgets{ind1} = jsondecode(win.executeJS(sprintf('W[%d]', ind1-1)));
284+
catch % handle circular references:
285+
if verboseFlag
286+
disp(['Node #' num2str(ind1-1) ' with id ' win.executeJS(sprintf('W[%d].id', ind1-1))...
287+
' could not be fully converted. Attempting fallback...']);
288+
end
289+
props = jsondecode(win.executeJS(sprintf('Object.keys(W[%d])', ind1-1)));
290+
tmp = mlapptools.emptyStructWithFields(props);
291+
validProps = fieldnames(tmp);
292+
for indP = 1:numel(tmp)
293+
try
294+
tmp.(validProps(indP)) = jsondecode(win.executeJS(sprintf(['W[%d].' props{ind1}], ind1-1)));
295+
catch
296+
% Fallback could be executed recursively for all problematic field
297+
% (to keep the most data), but for now do nothing.
298+
end
299+
end
300+
widgets{ind1} = tmp;
301+
clear props validProps tmp
302+
end
303+
end
304+
end % decodeDijitRegistryResult
305+
261306
function eStruct = emptyStructWithFields(fields)
262307
% A convenience method for creating an empty scalar struct with specific field
263308
% names.
@@ -306,12 +351,12 @@ function textAlign(uiElement, alignment)
306351
function to = getTimeout(hFig)
307352
to = getappdata(hFig,'QUERY_TIMEOUT');
308353
if isempty(to), to = mlapptools.QUERY_TIMEOUT; end
309-
end
354+
end % getTimeout
310355

311356
function tf = isUIFigure(hList)
312357
tf = arrayfun(@(x)isa(x,'matlab.ui.Figure') && ...
313358
isstruct(struct(x).ControllerInfo), hList);
314-
end
359+
end % isUIFigure
315360

316361
function oldState = toggleWarnings(togglestr)
317362
OJF = 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame';
@@ -396,7 +441,7 @@ function validateAlignmentStr(alignment)
396441
ww = arrayfun(@mlapptools.getWebWindow, hUIFigs);
397442
warning(warnState); % Restore warning state
398443
hFig = hFigs(hWebwindow == ww);
399-
end
444+
end % figFromWebwindow
400445

401446
end % Private Static Methods
402447

0 commit comments

Comments
 (0)