www.gusucode.com > mbcguitools 工具箱 matlab 源码程序 > mbcguitools/xregfigure.m
function h=xregfigure(varargin) %XREGFIGURE Create an MBC application figure % % h=xregfigure(prop,value...) creates a modified figure window % and returns the handle to it. Enhancements on the figure % include: % % * Useful default properties: MenuBar = 'none' % ToolBar = 'none' % IntegerHandle = 'off' % Color = default UI background % NumberTitle = 'off' % HandleVisibility = 'callback' % % * Automatic resizing. Use the property 'MinimumSize' to set a minimum % [height width] for the figure. Use the property 'LayoutManager' to % set a layout for the figure which will be repacked during resize. % To turn off the resizing function set the property 'ManageResize' to % 'off'. % % SEE ALSO: XREGDIALOG % Copyright 2000-2016 The MathWorks, Inc. and Ford Global Technologies, Inc. % Pull out properties that we add - these can't be set at construction ThisClassProps = {'MinimumSize', 'LayoutManager', 'ContentHandle'}; isThisClassProp = false(2, length(varargin).*0.5); isThisClassProp(1,:) = ismember(lower(varargin(1:2:end)), lower(ThisClassProps)); isThisClassProp(2,:) = isThisClassProp(1,:); isThisClassProp = reshape(isThisClassProp, 1, length(varargin)); sc = xregGui.SystemColorsDbl; UIFontSize = 8; AxesFontSize = 8; h = figure( ... 'DefaultUicontrolInterruptible','off',... 'DefaultUimenuInterruptible','off',... 'DefaultUipushtoolInterruptible','off',... 'DefaultUitoggletoolInterruptible','off',... 'DefaultAxesInterruptible','off',... 'DefaultLineInterruptible','off',... 'DefaultRectangleInterruptible','off',... 'DefaultTextInterruptible','off',... 'DefaultImageInterruptible','off',... 'DefaultSurfaceInterruptible','off',... 'DefaultPatchInterruptible','off',... 'DefaultUicontrolBusyAction','cancel',... 'DefaultUimenuBusyAction','cancel',... 'DefaultUipushtoolBusyAction','cancel',... 'DefaultUitoggletoolBusyAction','cancel',... 'DefaultAxesBusyAction','cancel',... 'DefaultLineBusyAction','cancel',... 'DefaultRectangleBusyAction','cancel',... 'DefaultTextBusyAction','cancel',... 'DefaultImageBusyAction','cancel',... 'DefaultSurfaceBusyAction','cancel',... 'DefaultPatchBusyAction','cancel',... 'DefaultUicontrolFontSize',UIFontSize,... 'DefaultAxesFontSize',AxesFontSize,... 'DefaultTextFontSize',AxesFontSize, ... 'DefaultUipanelFontSize',UIFontSize,... 'DefaultUipanelBackgroundColor',sc.CTRL_BACK,... 'DefaultUicontrolBackgroundColor',sc.CTRL_BACK,... 'DefaultUitabBackgroundColor',sc.CTRL_BACK,... 'Color', sc.CTRL_BACK,... 'WindowStyle', 'normal', ... 'DockControls', 'off', ... 'MenuBar', 'none',... 'ToolBar', 'none',... 'IntegerHandle', 'off',... 'HandleVisibility', 'callback',... 'NumberTitle', 'off',... 'Serializable','off',... 'Interruptible', 'off', ... 'DefaultUicontrolBackgroundColor',sc.CTRL_BACK,... varargin{~isThisClassProp}); set(h,'Renderer','opengl',... 'DefaultAxesTitleFontSizeMultiplier',1,... 'DefaultAxesTitleFontWeight','normal',... 'DefaultAxesLabelFontSizeMultiplier',1) % Ensure that h is a handle in all cases h = mbcgui.hgclassesutil.toHandle(h); % Add custom properties mbcgui.hgclassesutil.addprop(h, 'MinimumSize'); mbcgui.hgclassesutil.addprop(h, 'LayoutManager', ... % Deprecated interface 'Hidden', true, ... 'Transient',true,... 'SetMethod', @iSetLM, ... 'GetMethod', @iGetLM); mbcgui.hgclassesutil.addprop(h, 'ContentHandle', 'SetMethod', @iSetContent); mbcgui.hgclassesutil.addprop(h, 'LastValidResizePosition', 'Hidden', true); mbcgui.hgclassesutil.addprop(h, 'LastInvalidResizePosition', 'Hidden', true); mbcgui.hgclassesutil.addprop(h, 'OldPosition', 'Hidden', true); mbcgui.hgclassesutil.addprop(h, 'MBCFigureListeners', 'Hidden', true,'Transient',true); mbcgui.hgclassesutil.addprop(h, 'showDialog'); mbcgui.hgclassesutil.addprop(h, 'MotionManagerStore', 'Hidden', true); mbcgui.hgclassesutil.addprop(h, 'ControlHook', 'Hidden', true); mbcgui.hgclassesutil.addprop(h, 'Timer', 'Hidden', true); % Set default minimum size set(h, 'MinimumSize', [1 1], 'showDialog', iCreateShowDialog(h)); % Set any other input properties if any(isThisClassProp) set(h, varargin{isThisClassProp}); end % Initialize private properties set(h,'OldPosition',get(h, 'Position')); set(h,'LastInvalidResizePosition',get(h, 'Position')); set(h,'LastValidResizePosition',get(h, 'Position')); set(h, 'MBCFigureListeners', ... {... mbcgui.hgclassesutil.locationlistener(h, @i_setPosition, 'PreSet'), ... mbcgui.hgclassesutil.listener(h, 'SizeChanged', @i_sizechange), ... }); function restartResizeTimer(src) T = xregGui.getUITimer; setContentPosition(src); figTimer = get(src, 'Timer'); if isempty(figTimer) newFigTimer = T.scheduleAt(300, {@iResizeOnFinishTimer, src}); %0.3s else newFigTimer = T.restartTask(figTimer); end set(src, 'Timer', newFigTimer); function iResizeOnFinishTimer(~,~,fig) if ishghandle(fig) set(fig, 'Timer', []) iResize(fig, true) end % Respond to Content being set function iSetLM(obj, hContent) obj.ContentHandle = hContent; function hContent = iGetLM(obj) hContent = obj.ContentHandle; function iSetContent(obj, hContent) obj.ContentHandle = hContent; setContentPosition(obj); % Dialog showing function hFcn = iCreateShowDialog(obj) hFcn = @(varargin) mbcgui.util.showDialog(obj, varargin{:}); % Layout re-positioning function i_setPosition(~, event) iResize(event.Source, false); function i_sizechange(src, ~) restartResizeTimer(src); function iResize(obj, IsResizeEvent) %IRESIZE React to figure position changes % % IRESIZE(OBJ) is called whenever the figure is moved. if nargin<2 IsResizeEvent = true; end pos = get(obj, 'Position'); oldpos = get(obj, 'OldPosition'); if all(pos == oldpos) % This shouldn't even occur elseif all(pos(3:4) == oldpos(3:4)) % This corresponds to a pure movement. We just need to track the fact % that it occurred set(obj, 'OldPosition', pos); else if IsResizeEvent % Resize event pos = protectAgainstDoubleResizePosition(obj,pos); pos = makeWindowValidSize(obj,pos,oldpos); % Store the current position so we can detect which edges are resized % in future set(obj, 'OldPosition', pos); set(obj, 'LastValidResizePosition', pos); end end function [resizeIsInvalid,pos] = iCheckResize(obj,pos) % The figure been resized and we need to check the size and sync % the layout MinSize = get(obj, 'MinimumSize'); resizeIsInvalid = false; if pos(3) < MinSize(1) pos(3) = MinSize(1); resizeIsInvalid = true; end if pos(4) < MinSize(2) pos(4) = MinSize(2); resizeIsInvalid = true; end function pos = calcMinSizePos(pos,oldpos) if pos(1) ~= oldpos(1); % need to move left edge back as well pos(1) = oldpos(1) + oldpos(3) - pos(3); end if pos(2) ~= oldpos(2); % need to move bottom edge back as well pos(2) = oldpos(2) + oldpos(4) - pos(4); end % The way that position property changes are structured means % that we might misinterpret a resize as a move followed by a % resize, and this can lead to the wrong window edge being % moved back. One thing we can do that reduces the severity is % to explicitly check whether the window is off the right or % bottom edge of the screen. scr = get(0, 'ScreenSize'); if pos(1)+pos(3)>scr(3) pos(1) = scr(3)-pos(3); end if pos(2)<1 pos(2) = 1; end function pos = makeWindowValidSize(obj,pos,oldpos) origPos = pos; [resizeIsInvalid,pos] = iCheckResize(obj,pos); if resizeIsInvalid pos = calcMinSizePos(pos,oldpos); setPosition(obj,pos); set(obj, 'LastInvalidResizePosition', origPos); end function setContentPosition(obj) pos = get(obj,'Position'); hContent = get(obj, 'ContentHandle'); if ~builtin('isempty',hContent) % Re-calculate the layout set(hContent, 'Position', [1 1 pos(3:4)]); end function pos = protectAgainstDoubleResizePosition(obj,pos) % If the current position is identical to the previous (invalid) position % then we could be in the situation where the user has resized the figure % and held the mouse down (until the timer fired) then let go. % In this case we should use the last valid resize position, to prevent % resizing on the wrong side lastinvalidpos = get(obj, 'LastInvalidResizePosition'); if all(pos == lastinvalidpos) pos = get(obj, 'LastValidResizePosition'); setPosition(obj,pos); end function setPosition(obj,pos) set(obj, 'Position', pos); setContentPosition(obj);