Skip to content

Commit 940d288

Browse files
committed
Added a method for gathering information from the dijit widget registry.
- See `getWidgetInfo`. - Added a utility function for preallocating a `struct` based on a JSON object. - Added a utility function for unifying structs with different fieldnames.
1 parent 053d685 commit 940d288

File tree

1 file changed

+81
-3
lines changed

1 file changed

+81
-3
lines changed

mlapptools.m

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,54 @@ function fontColor(uielement, newcolor)
144144
%}
145145
end % getHTML
146146

147+
function varargout = getWidgetInfo(hUIFig,verbose)
148+
% A method for gathering information about dijit widgets.
149+
150+
%% Handle missing inputs:
151+
if nargin < 1 || isempty(hUIFig)
152+
throw(MException('getWidgetInfo:noHandleProvided',...
153+
'Please provide a valid UIFigure handle as a first input.'));
154+
end
155+
if nargin < 2 || isempty(verbose)
156+
verbose = false;
157+
end
158+
%%
159+
win = mlapptools.getWebWindow(hUIFig);
160+
%% Extract widgets from dijit registry:
161+
n = str2double(win.executeJS(['var W; require(["dijit/registry"], '...
162+
' function(registry){W = registry.toArray();}); W.length;']));
163+
widgets = cell(n,1);
164+
for ind1 = 1:n
165+
try
166+
widgets{ind1} = jsondecode(win.executeJS(sprintf('W[%d]', ind1)));
167+
catch % handle circular references:
168+
if verbose
169+
disp(['Node #' num2str(ind1-1) ' with id ' win.executeJS(sprintf('W[%d].id', ind1-1))...
170+
' could not be fully converted. Attempting fallback...']);
171+
end
172+
props = jsondecode(win.executeJS(sprintf('Object.keys(W[%d])', ind1-1)));
173+
tmp = mlapptools.emptyStructWithFields(props);
174+
validProps = fieldnames(tmp);
175+
for indP = 1:numel(tmp)
176+
try
177+
tmp.(validProps(indP)) = jsondecode(win.executeJS(sprintf(['W[%d].' props{ind1}], ind1-1)));
178+
catch
179+
% Fallback could be executed recursively for all problematic field
180+
% (to keep the most data), but for now do nothing.
181+
end
182+
end
183+
widgets{ind1} = tmp;
184+
clear props validProps tmp
185+
end
186+
end
187+
varargout{1} = widgets;
188+
if nargout == 2
189+
% Convert to a single table:
190+
varargout{2} = struct2table(mlapptools.unifyStructs(widgets));
191+
end % getWidgetInfo
192+
193+
end
194+
147195
end % Public Static Methods
148196

149197
methods (Static = true, Access = private)
@@ -306,6 +354,36 @@ function validateAlignmentStr(alignment)
306354
ME = addCause(ME,causeException);
307355
end
308356
end
309-
end
310-
end
311-
end
357+
end % checkJavascriptSyntaxError
358+
359+
360+
function eStruct = emptyStructWithFields(fields)
361+
% A convenience method for creating an empty scalar struct with specific field
362+
% names.
363+
% INPUTS:
364+
% fields - cell array of strings representing the required fieldnames.
365+
366+
tmp = [ matlab.lang.makeValidName(fields(:)), cell(numel(fields),1)].';
367+
eStruct = struct(tmp{:});
368+
369+
end % emptyStructWithFields
370+
371+
372+
function uStruct = unifyStructs(cellOfStructs)
373+
% A method for merging structs having *some* overlapping field names.
374+
375+
fields = cellfun(@fieldnames, cellOfStructs, 'UniformOutput', false);
376+
uFields = unique(vertcat(fields{:}));
377+
sz = numel(cellOfStructs);
378+
uStruct = repmat(mlapptools.emptyStructWithFields(uFields),sz,1);
379+
for ind1 = 1:sz
380+
fields = fieldnames(cellOfStructs{ind1});
381+
for ind2 = 1:numel(fields)
382+
uStruct(ind1).(fields{ind2}) = cellOfStructs{ind1}.(fields{ind2});
383+
end
384+
end
385+
end % unifyStructs
386+
387+
end % Private Static Methods
388+
389+
end % classdef

0 commit comments

Comments
 (0)