77 % window. The dialog's lifecycle is tied to the app that launched it.
88 %
99 % This enables compatibility with web apps.
10+ %
11+ % The dialog may flicker when resizing the figure if
12+ % AutoResizeChildren is on. Disabling this is recommended.
1013
1114 % ** This is a prototype component that may change in the future.
1215
132135 MinimumSize (1 ,2 ) double {mustBePositive } = [30 20 ];
133136
134137 % Buffer border space required on each side when sizing in figure
135- Buffer (1 ,1 ) double {mustBeNonnegative } = 0
138+ % Buffer (1,1) double {mustBeNonnegative} = 0
136139
137140 end % properties
138141
181184 function obj = BaseInternalDialog(fig , varargin )
182185
183186 arguments
184- fig matlab.ui.Figure
187+ % Figure parent - Create a figure if not provided
188+ fig (1 ,1 ) matlab.ui.Figure = uifigure(" AutoResizeChildren" ," off" );
185189 end
186190
187- arguments (Repeating )
191+ arguments (Repeating )
192+ % Property-value pairs
188193 varargin
189194 end
190195
209214 % Update the modal image positioning
210215 obj .updateModalImage();
211216
212- % Listen to resizing of OuterPanel
213- % (non needed until we make the dialog resizable by user)
214- % obj.OuterPanel.ResizeFcn = @(~,~)onOuterPanelResize(obj);
215-
216- % Position over figure by default
217- if isscalar(obj .Figure ) && isvalid(obj .Figure )
218- obj .positionOver(obj .Figure )
219- end
220-
221217 end % function
222218
223219 end % methods
@@ -247,58 +243,28 @@ function positionOver(obj, refComp)
247243
248244 % Reference component size and position
249245 refPos = getpixelposition(refComp , true );
250- refSize = refPos(3 : 4 );
246+ % refSize = refPos(3:4);
251247
252248 % Lower left corner depends if it's a figure
253249 if isa(refComp , " matlab.ui.Figure" )
254- refCornerA = [1 1 ];
250+ % refCornerA = [1 1];
251+ refPos(1 : 2 ) = [1 1 ];
255252 else
256- refCornerA = refPos(1 : 2 );
253+ % refCornerA = refPos(1:2);
257254 end
258255
259- % Dialog size
260- dlgPos = getpixelposition(obj );
261- dlgSize = dlgPos(3 : 4 );
262-
263- % Does it fit entirely within the reference component?
264- if all(refSize >= dlgSize )
265- % Yes - center it over the component
266-
267- % Calculate lower-left corner
268- dlgPos = floor((refSize - dlgSize ) / 2 ) + refCornerA ;
269-
270- else
271- % NO - position within the figure
272-
273- % Get the corners of the figure (bottom left and top right)
274- figPos = getpixelposition(obj .Parent );
275- figSize = figPos(3 : 4 );
276-
277- % Start with dialog position in lower-left of widget
278- dlgPos = refCornerA ;
279- dlgCornerB = dlgPos + dlgSize ;
280-
281- % Move left and down as needed to fit in figure
282- adj = figSize - dlgCornerB ;
283- adj(adj > 0) = 0 ;
284- dlgPos = max(dlgPos + adj , [1 1 ]);
285- dlgCornerB = dlgPos + dlgSize ;
286-
287- % If it doesn't fit in the figure, shrink it
288- adj = figSize - dlgCornerB ;
289- adj(adj > 0) = 0 ;
290- dlgSize = dlgSize + adj ;
256+ % Dialog position
257+ posNew = obj .Position ;
291258
292- end % if
293-
294- % Disable warning
295- warnState = warning(' off' ,' MATLAB:ui:components:noPositionSetWhenInLayoutContainer' );
259+ % Calculate the dialog position
260+ % Request to center over refPos
261+ posNew = calculatePositionWithinBounds(obj , posNew , refPos );
296262
297- % Set final position
298- obj.Position = [ dlgPos dlgSize ];
299-
300- % Restore warning
301- warning( warnState )
263+ % Update dialog position
264+ if ~isequal( obj .Position , posNew )
265+ fprintf( " Change position: posOld = %f posNew = %f\n " , obj . Position , posNew );
266+ obj.Position = posNew ;
267+ end
302268
303269 end % function
304270
@@ -497,9 +463,16 @@ function setup(obj)
497463 obj.TitleFontStyledComponents = [obj .OuterPanel ];
498464 obj.FontStyledComponents = [obj .DialogButtons ];
499465
466+ % Listen to resizing of OuterPanel
467+ % This enables the close button to stay in the correct spot
468+ obj.OuterPanel.ResizeFcn = @(~,~)onOuterPanelResize(obj );
469+
500470 % Ensure it fits in the figure
501471 obj .resizeToFitFigure();
502472
473+ % Reposition the close button
474+ repositionCloseButton(obj )
475+
503476 end % function
504477
505478
@@ -513,7 +486,10 @@ function update(obj)
513486 end
514487
515488 % Ensure it fits in the figure
516- obj .resizeToFitFigure();
489+ % This is only needed if AutoResizeChildren is on
490+ if obj .Figure .AutoResizeChildren
491+ obj .resizeToFitFigure();
492+ end
517493
518494 end % function
519495
@@ -585,45 +561,86 @@ function resizeToFitFigure(obj)
585561 obj .updateModalImage();
586562
587563 % Get the current positioning
588- posD = obj .Position ;
589- szRequest = obj .Size ;
590- posLowerLeft = posD(1 : 2 );
564+ posNew = obj .Position ;
565+ % posLowerLeft = posOld(1:2);
566+
567+ % Calculate the dialog size
568+ szDlg = calculateDialogSize(obj );
569+ posNew(3 : 4 ) = szDlg ;
570+
571+ % Calculate the dialog position
572+ if obj .SetupFinished
573+ posNew = calculatePositionWithinBounds(obj , posNew );
574+ else
575+ % Try to center over figure by default
576+ posFig = getpixelposition(obj .Figure );
577+ posFig(1 : 2 ) = 1 ;
578+ posNew = calculatePositionWithinBounds(obj , posNew , posFig );
579+ end
580+
581+ % Update dialog position
582+ if ~isequal(obj .Position , posNew )
583+ obj.Position = posNew ;
584+ end
585+
586+ end % function
587+
588+
589+ function szDlg = calculateDialogSize(obj )
590+ % Calculate the dialog size to use, given the set Size and
591+ % figure constraints
591592
592593 % Get figure size
593594 posFig = getpixelposition(obj .Figure );
594- szFig = posFig(3 : 4 );
595- maxSize = szFig - (2 * obj .Buffer );
596595
597- % Size is the smaller of requested size and figure size with
598- % buffer space
599- szDlg = min(szRequest , maxSize );
596+ % Calculate allowed dialog size
597+ szDlg = max( min(obj .Size , posFig(3 : 4 )), obj .MinimumSize );
598+
599+ end % function
600+
600601
601- % Restrict a minimum size also
602- szDlg = max( szDlg , obj . MinimumSize );
602+ function posOut = calculatePositionWithinBounds( obj , posIn , posCenter )
603+ % Confirm and verify the position is within the figure bounds
603604
604- % Calculate fit within figure
605- posUpperRight = posLowerLeft + szDlg ;
606- if any(posUpperRight > szFig )
607- posAdjust = szFig - posUpperRight ;
608- posLowerLeft = posLowerLeft + posAdjust ;
605+ arguments
606+ obj (1 ,1 ) wt.abstract.BaseInternalDialog
607+ posIn (1 ,4 ) double {mustBeFinite } % requested [x,y,w,h] location
608+ posCenter (1 ,4 ) double = nan(1 ,4 ) % optional - center over this [x,y,w,h]
609609 end
610610
611- % Don't go below 1
612- posLowerLeft = max( posLowerLeft , 1 ) ;
611+ % Default output
612+ posOut = posIn ;
613613
614- % Update dialog position
615- posNew = [ posLowerLeft szDlg ] ;
616- set( obj , " Position " , posNew );
614+ % Get figure size
615+ figPos = getpixelposition( obj . Figure ) ;
616+ figSize = figPos( 3 : 4 );
617617
618- % Reposition the close button
619- obj .repositionCloseButton();
618+ % Center over a component? (optional posCenter)
619+ if ~any(ismissing(posCenter ))
620+ centerPoint = floor(posCenter(1 : 2 ) + posCenter(3 : 4 )/2 );
621+ posOut(1 : 2 ) = floor(centerPoint - posOut(3 : 4 )/2 );
622+ end
623+
624+ % Ensure upper right corner is within the figure
625+ dlgUpperRight = posOut(1 : 2 ) + posOut(3 : 4 ) - [1 1 ];
626+ if any(dlgUpperRight > figSize )
627+ dlgAdjust = dlgUpperRight - figSize ;
628+ dlgAdjust(dlgAdjust < 0 ) = 0 ;
629+ posOut(1 : 2 ) = posOut(1 : 2 ) - dlgAdjust ;
630+ end
631+
632+ % Ensure lower left corner is within the figure
633+ posOut(1 : 2 ) = max(posOut(1 : 2 ), [1 1 ]);
620634
621635 end % function
622636
623637
624638 function repositionCloseButton(obj )
625639 % Called at end of resize
626640
641+ % Get current position
642+ oldPos = obj .CloseButton .Position ;
643+
627644 % Outer panel inner/outer position
628645 outerPos = obj .OuterPanel .OuterPosition ;
629646 wO = outerPos(3 );
@@ -642,9 +659,12 @@ function repositionCloseButton(obj)
642659 yB = hO - 2 * wBorder - hB - 1 ;
643660 wB = hB ;
644661 xB = wO - 2 * wBorder - wB - 1 ;
662+ newPos = floor([xB yB wB hB ]);
645663
646664 % Move the close button
647- set(obj .CloseButton ," Position" ,[xB yB wB hB ]);
665+ if ~isequal(oldPos , newPos )
666+ obj.CloseButton.Position = newPos ;
667+ end
648668
649669 end % function
650670
@@ -750,11 +770,11 @@ function onFigureResized(obj,~)
750770 end % function
751771
752772
753- function onOuterPanelResize(~ )
773+ function onOuterPanelResize(obj )
754774 % Triggered when the dialog window is resized
755775
756- % Ensure it fits in the figure
757- % obj.resizeToFitFigure();
776+ % Reposition the close button
777+ repositionCloseButton( obj )
758778
759779 end % function
760780
0 commit comments