Skip to content

Commit 13088af

Browse files
committed
BaseInternalDialog: update modality implementation, remove parentcomponent infrastructure
1 parent 65357f9 commit 13088af

File tree

1 file changed

+77
-148
lines changed

1 file changed

+77
-148
lines changed

widgets/+wt/+abstract/BaseInternalDialog.m

Lines changed: 77 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,26 @@
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)
@@ -59,27 +51,6 @@
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

@@ -210,92 +181,14 @@
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-
% [email protected](parent);
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

Comments
 (0)