|
6 | 6 |
|
7 | 7 | % Copyright 2022-2025 The MathWorks Inc. |
8 | 8 |
|
9 | | - % To do: |
10 | | - % - finish importing old BaseDialog |
11 | | - % - make examples |
12 | | - % - handle theme changes |
13 | | - |
14 | 9 |
|
15 | 10 | %% Events |
16 | 11 | events (HasCallbackProperty) |
|
158 | 153 | properties (AbortSet, Access = public) |
159 | 154 |
|
160 | 155 | % Dialog button action names that trigger deletion (button tags/names) |
161 | | - DeleteActions (1,:) string = ["close","ok","cancel","exit"] |
| 156 | + DeleteActions (1,:) string = ["delete","close","ok","cancel","exit"] |
162 | 157 |
|
163 | 158 | end %properties |
164 | 159 |
|
|
215 | 210 | end %properties |
216 | 211 |
|
217 | 212 |
|
| 213 | + properties (Transient, Hidden) |
| 214 | + |
| 215 | + % Optional parent component creating the dialog. The component must |
| 216 | + % be provided to constructor, and the dialog will be centered on |
| 217 | + % the component where possible. The lifecycle will be tied so that |
| 218 | + % the dialog will be deleted if the component is deleted. |
| 219 | + ParentComponent matlab.graphics.Graphics |
| 220 | + |
| 221 | + end %properties |
| 222 | + |
| 223 | + |
| 224 | + %% Constructor / Destructor |
| 225 | + methods |
| 226 | + function obj = BaseInternalDialog(parentComponent) |
| 227 | + % Construct a dialog |
| 228 | + |
| 229 | + arguments |
| 230 | + parentComponent matlab.graphics.Graphics ... |
| 231 | + {mustBeScalarOrEmpty} = gobjects(0) |
| 232 | + end |
| 233 | + |
| 234 | + % Get ancestor figure, if possible |
| 235 | + % If no figure available, place dialog in a new figure |
| 236 | + id = "wt:abstract:BaseInternalDialog:InvalidParent"; |
| 237 | + msg = "Input to BaseInternalDialog must be a uifigure or a component within a uifigure."; |
| 238 | + if isempty(parentComponent) |
| 239 | + % No component or figure, make a new figure |
| 240 | + |
| 241 | + parent = uifigure; |
| 242 | + hasComponent = false; |
| 243 | + |
| 244 | + elseif isa(parentComponent,"matlab.ui.Figure") |
| 245 | + % Given a figure for the parent |
| 246 | + |
| 247 | + parent = parentComponent; |
| 248 | + hasComponent = false; |
| 249 | + |
| 250 | + elseif isa(parentComponent, "matlab.graphics.Graphics") |
| 251 | + % Given a component (it must be in a figure) |
| 252 | + |
| 253 | + parent = ancestor(parentComponent,'figure'); |
| 254 | + if isempty(parent) |
| 255 | + % Component not in a figure |
| 256 | + error(id,parent) |
| 257 | + else |
| 258 | + hasComponent = true; |
| 259 | + end |
| 260 | + |
| 261 | + else |
| 262 | + |
| 263 | + error(id,msg) |
| 264 | + |
| 265 | + end |
| 266 | + |
| 267 | + % Call superclass |
| 268 | + if hasComponent |
| 269 | + addedArgs = {"ParentComponent", parentComponent}; |
| 270 | + else |
| 271 | + addedArgs = {}; |
| 272 | + end |
| 273 | + [email protected]( parent, addedArgs{ :}); |
| 274 | + |
| 275 | + |
| 276 | + % Did it have a component argument? |
| 277 | + if hasComponent |
| 278 | + |
| 279 | + % Store the parent component |
| 280 | + %obj.ParentComponent = parentComponent; |
| 281 | + |
| 282 | + % Position over the component |
| 283 | + %obj.positionOver(parentComponent) |
| 284 | + |
| 285 | + % Set dialog lifecycle to that of the parent component |
| 286 | + % The dialog will be deleted if the parent component is deleted |
| 287 | + obj.attachLifecycleListeners(parentComponent); |
| 288 | + |
| 289 | + else |
| 290 | + |
| 291 | + % Set dialog lifecycle to that of the parent |
| 292 | + % The dialog will be deleted if the parent component is deleted |
| 293 | + obj.attachLifecycleListeners(parent); |
| 294 | + |
| 295 | + end |
| 296 | + |
| 297 | + end %function |
| 298 | + |
| 299 | + end %methods |
| 300 | + |
| 301 | + |
218 | 302 | %% Public methods |
219 | 303 | methods (Sealed, Access = public) |
220 | 304 |
|
@@ -267,9 +351,15 @@ function positionOver(obj, refComp) |
267 | 351 |
|
268 | 352 | end %if |
269 | 353 |
|
| 354 | + % Disable warning |
| 355 | + warnState = warning('off','MATLAB:ui:components:noPositionSetWhenInLayoutContainer'); |
| 356 | + |
270 | 357 | % Set final position |
271 | 358 | obj.Position = [dlgPos dlgSize]; |
272 | 359 |
|
| 360 | + % Restore warning |
| 361 | + warning(warnState) |
| 362 | + |
273 | 363 | end %function |
274 | 364 |
|
275 | 365 |
|
@@ -365,19 +455,25 @@ function assignOutput(~) |
365 | 455 | function setup(obj) |
366 | 456 | % Configure the dialog |
367 | 457 |
|
| 458 | + % Disable warning |
| 459 | + warnState = warning('off','MATLAB:ui:components:noPositionSetWhenInLayoutContainer'); |
| 460 | + |
368 | 461 | % Defaults |
369 | 462 | obj.Position(3:4) = [350,200]; |
370 | 463 |
|
| 464 | + % Restore warning |
| 465 | + warning(warnState) |
| 466 | + |
371 | 467 | % Outer grid to enable the dialog panel to fill the component |
372 | 468 | obj.OuterGrid = uigridlayout(obj,[1 1]); |
373 | 469 | obj.OuterGrid.Padding = [0 0 0 0]; |
374 | 470 |
|
375 | 471 | % Outer dialog panel |
376 | 472 | obj.OuterPanel = uipanel(obj.OuterGrid); |
377 | 473 | obj.OuterPanel.Title = "Dialog Title"; |
378 | | - obj.OuterPanel.FontSize = 14; |
| 474 | + obj.OuterPanel.FontSize = 16; |
379 | 475 | obj.OuterPanel.FontWeight = "bold"; |
380 | | - obj.OuterPanel.BorderWidth = 1; |
| 476 | + %obj.OuterPanel.BorderWidth = 1; |
381 | 477 | obj.OuterPanel.AutoResizeChildren = false; |
382 | 478 | obj.OuterPanel.ResizeFcn = @(~,~)onOuterPanelResize(obj); |
383 | 479 | obj.OuterPanel.ButtonDownFcn = @(~,evt)onTitleButtonDown(obj,evt); |
@@ -414,6 +510,9 @@ function setup(obj) |
414 | 510 | obj.getThemeColor("--mw-borderColor-secondary"); |
415 | 511 | obj.OuterPanel.BackgroundColor = ... |
416 | 512 | obj.getThemeColor("--mw-backgroundColor-secondary"); |
| 513 | + elseif isMATLABReleaseOlderThan("R2023a") |
| 514 | + obj.OuterPanel.ForegroundColor = [0.38 0.38 0.38]; |
| 515 | + obj.OuterPanel.BackgroundColor = [.9 .9 .9]; |
417 | 516 | else |
418 | 517 | obj.OuterPanel.ForegroundColor = [0.38 0.38 0.38]; |
419 | 518 | obj.OuterPanel.BorderColor = [.5 .5 .5]; |
@@ -490,21 +589,41 @@ function attachLifecycleListeners(obj, owners) |
490 | 589 | % Delete the dialog automatically upon destruction of the specified "owner" graphics objects |
491 | 590 |
|
492 | 591 | arguments |
493 | | - obj (1,1) wt.abstract.BaseDialog |
| 592 | + obj (1,1) wt.abstract.BaseInternalDialog |
494 | 593 | owners handle |
495 | 594 | end |
496 | 595 |
|
497 | 596 | % Create listeners |
498 | 597 | % The dialog will be deleted if the listenObj is deleted |
499 | 598 | newListeners = listener(owners, "ObjectBeingDestroyed",... |
500 | | - @(src,evt)delete(obj)); |
| 599 | + @(src,evt)forceCloseDialog(obj)); |
501 | 600 |
|
502 | 601 | % Add to any existing listeners |
503 | 602 | obj.LifecycleListeners = horzcat(obj.LifecycleListeners, newListeners); |
504 | 603 |
|
505 | 604 | end %function |
506 | 605 |
|
507 | 606 |
|
| 607 | + function forceCloseDialog(obj) |
| 608 | + % Should the dialog be deleted? |
| 609 | + |
| 610 | + obj.Output = []; |
| 611 | + obj.LastAction = 'delete'; |
| 612 | + |
| 613 | + if ~obj.IsWaitingForOutput |
| 614 | + |
| 615 | + % Delete the dialog |
| 616 | + delete(obj) |
| 617 | + |
| 618 | + else |
| 619 | + |
| 620 | + obj.IsWaitingForOutput = false; |
| 621 | + |
| 622 | + end |
| 623 | + |
| 624 | + end %function |
| 625 | + |
| 626 | + |
508 | 627 | function checkDeletionCriteria(obj) |
509 | 628 | % Should the dialog be deleted? |
510 | 629 |
|
|
0 commit comments