2222 % Dialog Size
2323 Size (1 ,2 ) double {mustBePositive } = [350 200 ]
2424
25+ % Modal (block other figure interaction)
26+ Modal (1 ,1 ) logical = false
27+
2528 end % properties
2629
2730
2831 properties (AbortSet , Dependent , Access = public )
2932
30- % Modal (block other figure interaction)
31- Modal
32-
3333 % Dialog Title
3434 Title
3535
36- % Background Color
37- % TitleBackgroundColor
38-
39- % Background color mode
40- % TitleBackgroundColorMode (1,1) wt.enum.AutoManualState = 'auto'
41-
4236 end % properties
4337
4438
4539 % Accessors
4640 methods
4741
48- function value = get .Modal(obj )
49- value = obj .ModalImage .Visible ;
50- end
5142 function set .Modal(obj , value )
52- obj.ModalImage.Visible = value ;
43+ obj.Modal = value ;
44+ obj .updateModalImage();
5345 end
5446
5547 function value = get .Title(obj )
5951 obj.OuterPanel.Title = value ;
6052 end
6153
62- % function value = get.TitleBackgroundColor(obj)
63- % value = obj.OuterPanel.BackgroundColor;
64- % end
65- % function set.TitleBackgroundColor(obj, value)
66- % obj.OuterPanel.BackgroundColor = value;
67- % end
68-
69- % function value = get.TitleBackgroundColorMode(obj)
70- % value = wt.enum.AutoManualState(obj.OuterPanel.BackgroundColorMode);
71- % end
72- % function set.TitleBackgroundColorMode(obj, value)
73- % obj.OuterPanel.BackgroundColorMode = char(value);
74- % end
75-
76- % function value = get.Size(obj)
77- % value = obj.Position(3:4);
78- % end
79- % function set.Size(obj, value)
80- % obj.Position(3:4) = value;
81- % end
82-
8354 end % methods
8455
8556
210181 end % properties
211182
212183
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
184+ %% Destructor
225185 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-
186+ function delete(obj )
187+
188+ % Delete the modal image
189+ delete(obj .ModalImage )
190+
297191 end % function
298-
299192 end % methods
300193
301194
@@ -313,8 +206,13 @@ function positionOver(obj, refComp)
313206 % Reference component size and position
314207 refPos = getpixelposition(refComp , true );
315208 refSize = refPos(3 : 4 );
316- refCornerA = refPos(1 : 2 );
317- % refCornerB = refPos(1:2) + refPos(:,3:4) - 1;
209+
210+ % Lower left corner depends if it's a figure
211+ if isa(refComp , " matlab.ui.Figure" )
212+ refCornerA = [1 1 ];
213+ else
214+ refCornerA = refPos(1 : 2 );
215+ end
318216
319217 % Dialog size
320218 dlgPos = getpixelposition(obj );
@@ -400,7 +298,7 @@ function positionOver(obj, refComp)
400298
401299
402300 %% Public Methods
403- methods
301+ methods ( Access = public )
404302
405303 function [output , lastAction ] = waitForOutput(obj )
406304 % Puts MATLAB in a wait state until the dialog buttons trigger
@@ -429,6 +327,31 @@ function positionOver(obj, refComp)
429327 end % methods
430328
431329
330+ %% Protected methods
331+ methods (Sealed , Access = public )
332+
333+ function attachLifecycleListeners(obj , owners )
334+ % Delete the dialog automatically upon destruction of the
335+ % specified "owner" graphics objects
336+
337+ arguments
338+ obj (1 ,1 ) wt.abstract.BaseInternalDialog
339+ owners (1 ,: ) matlab.graphics.Graphics
340+ end
341+
342+ % Create listeners
343+ % The dialog will be deleted if the listenObj is deleted
344+ newListeners = listener(owners , " ObjectBeingDestroyed" ,...
345+ @(src ,evt )forceCloseDialog(obj ));
346+
347+ % Add to any existing listeners
348+ obj.LifecycleListeners = horzcat(obj .LifecycleListeners , newListeners );
349+
350+ end % function
351+
352+ end % methods
353+
354+
432355 %% Protected methods
433356 methods (Access = protected )
434357
@@ -532,9 +455,7 @@ function setup(obj)
532455 obj.ModalImage.ImageSource = " overlay_gray.png" ;
533456 obj.ModalImage.ScaleMethod = " stretch" ;
534457 obj.ModalImage.Visible = " off" ;
535- posF = getpixelposition(obj .Figure );
536- szF = posF(3 : 4 );
537- obj.ModalImage.Position = [1 1 szF ];
458+ obj.ModalImage.Position = [1 1 1 1 ];
538459
539460 % Add lower buttons
540461 obj.DialogButtons = wt .ButtonGrid(obj .InnerGrid ," Text" ,[]," Icon" ,[]);
@@ -544,9 +465,6 @@ function setup(obj)
544465 obj.DialogButtons.ButtonPushedFcn = ...
545466 @(src ,evt )onDialogButtonPushed(obj ,evt );
546467
547- % Bring the dialog back to the top
548- uistack(obj ," top" );
549-
550468 % Ensure it fits in the figure
551469 obj .resizeToFitFigure();
552470
@@ -584,26 +502,6 @@ function updateBackgroundColorableComponents(obj)
584502
585503 methods (Sealed , Access = protected )
586504
587-
588- function attachLifecycleListeners(obj , owners )
589- % Delete the dialog automatically upon destruction of the specified "owner" graphics objects
590-
591- arguments
592- obj (1 ,1 ) wt.abstract.BaseInternalDialog
593- owners handle
594- end
595-
596- % Create listeners
597- % The dialog will be deleted if the listenObj is deleted
598- newListeners = listener(owners , " ObjectBeingDestroyed" ,...
599- @(src ,evt )forceCloseDialog(obj ));
600-
601- % Add to any existing listeners
602- obj.LifecycleListeners = horzcat(obj .LifecycleListeners , newListeners );
603-
604- end % function
605-
606-
607505 function forceCloseDialog(obj )
608506 % Should the dialog be deleted?
609507
@@ -646,6 +544,35 @@ function checkDeletionCriteria(obj)
646544 %% Private methods
647545 methods (Access = private )
648546
547+ function updateModalImage(obj )
548+ % Triggered when the Modal property is changed
549+
550+ % If toggled on, do the following
551+ if obj .Modal
552+
553+ % Bring the dialog above the modal image
554+ if isMATLABReleaseOlderThan(" R2025a" )
555+ isDlg = obj .Figure .Children == obj ;
556+ isModalImage = obj .Figure .Children == obj .ModalImage ;
557+ otherChild = obj .Figure .Children(~isDlg & ~isModalImage );
558+ obj.Figure.Children = vertcat(obj , obj .ModalImage , otherChild );
559+ else
560+ uistack(obj ," top" ); % Works in 25a but not earlier
561+ end
562+
563+ % Set position to match the figure
564+ posF = getpixelposition(obj .Figure );
565+ szF = posF(3 : 4 );
566+ obj.ModalImage.Position = [1 1 szF ];
567+
568+ end % if
569+
570+ % Toggle visibility
571+ obj.ModalImage.Visible = obj .Modal ;
572+
573+ end % function
574+
575+
649576 function repositionCloseButton(obj )
650577 % Triggered on figure resize
651578
@@ -707,7 +634,9 @@ function resizeToFitFigure(obj)
707634 posLowerLeft = max(posLowerLeft , 1 );
708635
709636 % Update modal image position
710- set(obj .ModalImage ," Position" ,[1 1 szF ]);
637+ if obj .Modal
638+ set(obj .ModalImage ," Position" ,[1 1 szF ]);
639+ end
711640
712641 % Update dialog position
713642 posNew = [posLowerLeft szD ];
0 commit comments