|
16 | 16 | % setStyle - Modify a specified style property. |
17 | 17 | % setTimeout - Override the default timeout for dojo commands, for a specific uifigure. |
18 | 18 | % textAlign - Modify text alignment. |
| 19 | + % waitForFigureReady - A blocking method that only returns after the uifigure is fully loaded. |
19 | 20 | % |
20 | 21 | % See README.md for detailed documentation and examples. |
21 | 22 |
|
@@ -107,41 +108,20 @@ function fontWeight(uiElement, weight) |
107 | 108 |
|
108 | 109 | function [win] = getWebWindow(hUIFig) |
109 | 110 | warnState = mlapptools.toggleWarnings('off'); |
110 | | - % Make sure we got a valid handle |
111 | | - assert(mlapptools.isUIFigure(hUIFig),... |
112 | | - 'mlapptools:getWebWindow:NotUIFigure',... |
113 | | - 'The provided window handle is not of a UIFigure.'); |
114 | 111 |
|
115 | | - to = mlapptools.getTimeout(hUIFig); |
116 | | - tic |
117 | | - while true && (toc < to) |
118 | | - try |
119 | | - hController = struct(struct(hUIFig).Controller); |
120 | | - % Check for Controller version: |
121 | | - switch subsref(ver('matlab'), substruct('.','Version')) |
122 | | - case {'9.0','9.1'} % R2016a or R2016b |
123 | | - win = hController.Container.CEF; |
124 | | - otherwise % R2017a onward |
125 | | - win = struct(hController.PlatformHost).CEF; |
126 | | - end |
127 | | - break |
128 | | - catch err |
129 | | - if strcmp(err.identifier, 'MATLAB:nonExistentField') |
130 | | - pause(0.01) |
131 | | - else |
132 | | - warning(warnState); % Restore warning state |
133 | | - rethrow(err) |
134 | | - end |
135 | | - end |
136 | | - end |
137 | | - warning(warnState); % Restore warning state |
| 112 | + mlapptools.waitTillFigureLoaded(hUIFig); |
| 113 | + % Since the above checks if a Controller exists, the below should work. |
138 | 114 |
|
139 | | - if toc >= to |
140 | | - msgID = 'mlapptools:getWidgetID:QueryTimeout'; |
141 | | - error(msgID, ... |
142 | | - 'WidgetID query timed out after %u seconds, UI needs more time to load', ... |
143 | | - to); |
| 115 | + hController = struct(struct(hUIFig).Controller); |
| 116 | + % Check for Controller version: |
| 117 | + switch subsref(ver('matlab'), substruct('.','Version')) |
| 118 | + case {'9.0','9.1'} % R2016a or R2016b |
| 119 | + win = hController.Container.CEF; |
| 120 | + otherwise % R2017a onward |
| 121 | + win = struct(hController.PlatformHost).CEF; |
144 | 122 | end |
| 123 | + |
| 124 | + warning(warnState); % Restore warning state |
145 | 125 |
|
146 | 126 | end % getWebWindow |
147 | 127 |
|
@@ -267,6 +247,23 @@ function textAlign(uiElement, alignment) |
267 | 247 | win.executeJS(alignSetStr); |
268 | 248 | end % textAlign |
269 | 249 |
|
| 250 | + function win = waitForFigureReady(hUIFig) |
| 251 | + % This blocking method waits until a UIFigure and its widgets have fully loaded. |
| 252 | + %% Make sure that the handle is valid: |
| 253 | + assert(mlapptools.isUIFigure(hUIFig),... |
| 254 | + 'mlapptools:getWebWindow:NotUIFigure',... |
| 255 | + 'The provided window handle is not of a UIFigure.'); |
| 256 | + assert(strcmp(hUIFig.Visible,'on'),... |
| 257 | + 'mlapptools:getWebWindow:FigureNotVisible',... |
| 258 | + 'Invisible figures are not supported.'); |
| 259 | + %% Wait for the figure to appear: |
| 260 | + mlapptools.waitTillFigureLoaded(hUIFig); |
| 261 | + %% Make sure that Dojo is ready: |
| 262 | + % Get a handle to the webwindow |
| 263 | + win = mlapptools.getWebWindow(hUIFig); |
| 264 | + mlapptools.waitTillWebwindowLoaded(win, hUIFig); |
| 265 | + end % waitForFigureReady |
| 266 | + |
270 | 267 | end % Public Static Methods |
271 | 268 |
|
272 | 269 | methods (Static = true, Access = private) |
@@ -350,29 +347,14 @@ function textAlign(uiElement, alignment) |
350 | 347 |
|
351 | 348 | function [widgetID] = getWidgetID(win, data_tag) |
352 | 349 | widgetquerystr = sprintf('dojo.getAttr(dojo.query("[data-tag^=''%s''] > div")[0], "widgetid")', data_tag); |
353 | | - |
354 | | - to = mlapptools.getTimeout(mlapptools.figFromWebwindow(win)); |
355 | | - tic |
356 | | - while true && (toc < to) |
357 | | - try |
358 | | - widgetID = win.executeJS(widgetquerystr); |
359 | | - widgetID = widgetID(2:end-1); |
360 | | - break |
361 | | - catch err |
362 | | - if ~isempty(strfind(err.message, 'JavaScript error: Uncaught ReferenceError: dojo is not defined')) || ... |
363 | | - ~isempty(strfind(err.message, 'Cannot read property ''widgetid'' of null')) |
364 | | - pause(0.01) |
365 | | - else |
366 | | - rethrow(err) |
367 | | - end |
368 | | - end |
369 | | - end |
370 | | - |
371 | | - if toc >= to |
372 | | - msgID = 'mlapptools:getWidgetID:QueryTimeout'; |
373 | | - error(msgID, ... |
374 | | - 'widgetID query timed out after %u seconds, UI needs more time to load', ... |
375 | | - to); |
| 350 | + hFig = mlapptools.figFromWebwindow(win); |
| 351 | + mlapptools.waitTillFigureLoaded(win, hFig); |
| 352 | + try % should work for most UI objects |
| 353 | + widgetID = win.executeJS(widgetquerystr); |
| 354 | + widgetID = widgetID(2:end-1); |
| 355 | + catch % fallback for problematic objects |
| 356 | + warning('Problematic control encountered with no fallback implemented yet. Please ') |
| 357 | + % TODO |
376 | 358 | end |
377 | 359 | end % getWidgetID |
378 | 360 |
|
@@ -460,7 +442,51 @@ function validateAlignmentStr(alignment) |
460 | 442 | error(msgID, 'Invalid font weight specified: ''%s''', weight); |
461 | 443 | end |
462 | 444 | end % validateFontWeight |
| 445 | + |
| 446 | + function waitTillFigureLoaded(hFig) |
| 447 | + % A blocking method that ensures a UIFigure has fully loaded. |
| 448 | + warnState = mlapptools.toggleWarnings('off'); |
| 449 | + to = mlapptools.getTimeout(hFig); |
| 450 | + tic |
| 451 | + while (toc < to) && isempty(struct(hFig).Controller) |
| 452 | + pause(0.01) |
| 453 | + end |
| 454 | + if toc > to |
| 455 | + msgID = 'mlapptools:waitTillFigureLoaded:TimeoutReached'; |
| 456 | + error(msgID, ... |
| 457 | + ['Waiting for the figure to load has timed out after %u seconds. ' ... |
| 458 | + 'Try increasing the timeout. If the figure clearly loaded in time, yet '... |
| 459 | + 'this error remains - it might be a bug in the tool! ' ... |
| 460 | + 'Please let the developers know through GitHub.'], ... |
| 461 | + to); |
| 462 | + end |
| 463 | + warning(warnState); |
| 464 | + end % waitTillFigureLoaded |
463 | 465 |
|
| 466 | + function waitTillWebwindowLoaded(hWebwindow, hFig) |
| 467 | + % A blocking method that ensures a certain webwindow has fully loaded. |
| 468 | + if nargin < 2 |
| 469 | + hFig = mlapptools.figFromWebwindow(hWebwindow); |
| 470 | + end |
| 471 | + |
| 472 | + to = mlapptools.getTimeout(hFig); |
| 473 | + tic |
| 474 | + while (toc < to) && ~jsondecode(hWebwindow.executeJS(... |
| 475 | + 'this.hasOwnProperty("require") && require !== undefined && typeof(require) === "function"')) |
| 476 | + pause(0.01) |
| 477 | + end |
| 478 | + if toc > to |
| 479 | + msgID = 'mlapptools:waitTillWebwindowLoaded:TimeoutReached'; |
| 480 | + error(msgID, ... |
| 481 | + ['Waiting for the webwindow to load has timed out after %u seconds. ' ... |
| 482 | + 'Try increasing the timeout. If the figure clearly loaded in time, yet '... |
| 483 | + 'this error remains - it might be a bug in the tool! ' ... |
| 484 | + 'Please let the developers know through GitHub.'], ... |
| 485 | + to); |
| 486 | + else |
| 487 | + hWebwindow.executeJS('require(["dojo/ready"], function(ready){});'); |
| 488 | + end |
| 489 | + end % waitTillWebwindowLoaded |
464 | 490 |
|
465 | 491 | end % Private Static Methods |
466 | 492 |
|
|
0 commit comments