www.gusucode.com > mbcguitools 工具箱 matlab 源码程序 > mbcguitools/+mbcgui/+multiview/MultiViewPanel.m
classdef MultiViewPanel < mbcgui.widget.BasicContainer %mbcgui.multiview.MultiViewPanel class % mbcgui.multiview.MultiViewPanel extends mbcgui.widget.BasicContainer. % % mbcgui.multiview.MultiViewPanel properties: % Parent - Property is of type 'MATLAB array' % Position - Property is of type 'rect' % Enable - Property is of type 'on/off' % Visible - Property is of type 'on/off' % UserData - Property is of type 'MATLAB array' % Tag - Property is of type 'string' % Actions - Property is of type 'MATLAB array' (read only) % MessageService - Property is of type 'handle' % ViewList - Property is of type 'handle' % ViewLayoutName - Property is of type 'string' % StatusBar - Property is of type 'handle' % GlobalViewOptions - Property is of type 'handle vector' % ContextActions - Property is of type 'handle vector' % AlwaysAllowPrintToFigure - Property is of type 'bool' % % mbcgui.multiview.MultiViewPanel methods: % addViewMenuItems - Add standard view management items to a menu % canPrint - Check whether component can be printed % changeView - Change the selected view to a different one % deleteView - Delete the currently selected view % getSelectedViewContainer - Get the handle of the selected ViewContainer % getSelectedViewTypeIndex - Get the index of the type of the selected view % getViewContainers - AGet all of the open ViewContainers % initViewLayout - Create a default view layout % printSize - Returns the preferred printing size for the component % printToFigure - Create a copy of the current view in a new figure. % printCopy - Create a new component for printing the component display % restoreViewLayout - Restore a saved layout % saveViewLayout - Save the current view layout % selectView - Select a view % splitView - Split the currently selected view % updateAvailableViews - Re-check which views can be created % Copyright 2005-2016 The MathWorks, Inc. and Ford Global Technologies, Inc. properties (AbortSet, SetObservable) %MESSAGESERVICE Property is of type 'handle' MessageService = []; %VIEWLIST Property is of type 'handle' ViewList = []; %VIEWLAYOUTNAME Property is of type 'string' ViewLayoutName = ''; %STATUSBAR Property is of type 'handle' StatusBar = []; %ALWAYSALLOWPRINTTOFIGURE Property is of type 'bool' AlwaysAllowPrintToFigure = false; end properties(AbortSet, Dependent) %GLOBALVIEWOPTIONS Property is of type 'handle vector' GlobalViewOptions = []; %CONTEXTACTIONS Property is of type 'handle vector' ContextActions = []; end properties(SetAccess=private, Dependent) %SelectedView selected view SelectedView end properties (SetAccess=protected, AbortSet) %VIEWGROUP Property is of type 'handle' ViewGroup = []; %HTOPLAYOUT Property is of type 'MATLAB array' hTopLayout = []; %HVIEWCONTEXTMENU Property is of type 'MATLAB array' hViewContextMenu = []; %GLOBALVIEWOPTIONGROUP Property is of type 'handle' GlobalViewOptionGroup = []; %CONTEXTACTIONGROUP Property is of type 'handle' ContextActionGroup = []; end properties (SetAccess=protected, AbortSet) %ACTIONS Property is of type 'MATLAB array' (read only) Actions = []; end methods % constructor block function obj = MultiViewPanel(varargin) %MULTIVIEWPANEL Construct a new MultiViewPanel % OBJ = MULTIVIEWPANEL(PROP, VALUE, ...) constructs a new MultiViewPanel. % This component contains a set of Views housed within ViewContainers % that are arranged in a hierarchy of splitlayouts. obj@mbcgui.widget.BasicContainer(varargin{ : }); % converted super class constructor call VG = mbcgui.multiview.ViewGroup; obj.ViewGroup = VG; obj.addListeners([... event.proplistener(VG, VG.findprop('ViewContainers'), ... 'PostSet',@(h,evt) i_checkcloseable(h,evt,obj)); ... event.listener(VG, 'SelectedViewChanged', @(h,evt) i_selviewchange(h,evt,obj)) ]... ); % Create an empty ViewList if one has not been set if isempty(obj.ViewList) obj.ViewList = mbcgui.multiview.ViewList; end % Actions the UI can perform A.CloseView = mbcgui.actions.StatefulAction(... {@i_closeview, obj}, '&Close View','Close current view'); A.SplitViewV = mbcgui.actions.StatefulAction(... {@i_split, obj, 'ud'}, 'Split View &Vertically', ... 'Split current view vertically', xregrespath('verticalSplit.bmp')); A.SplitViewH = mbcgui.actions.StatefulAction(... {@i_split, obj, 'lr'}, 'Split View &Horizontally', ... 'Split current view horizontally', xregrespath('horizontalSplit.bmp')); A.CopyView = mbcgui.actions.StatefulAction(... {@i_printview, obj, 'clipboard'}, '&Copy View', ... 'Copy current view to clipboard', xregrespath('copy.bmp')); A.PrintView = mbcgui.actions.StatefulAction(... {@i_printview, obj, 'printdialog'}, '&Print...', ... 'Print current view', xregrespath('print.bmp')); A.PrintViewQuiet = mbcgui.actions.StatefulAction(... {@i_printview, obj, 'printer'}, '&Print', ... 'Print current view', xregrespath('print.bmp')); A.PrintViewPreview = mbcgui.actions.StatefulAction(... {@i_printview, obj, 'printpreview'}, 'Print Pre&view','Print preview'); A.PrintViewFigure = mbcgui.actions.StatefulAction(... {@i_printtofig, obj}, 'Print To &Figure', ... 'Print to figure', xregrespath('printtofigure.bmp')); A.ChangeView = obj.pCreateViewListActions('change'); A.SplitToView = obj.pCreateViewListActions('split'); A.ViewOptions = mbcgui.actions.DynamicActionGroup('', 'View &Options', 'Current view options'); A.ViewOptions.MenuType = 'none'; A.ViewActions = mbcgui.actions.DynamicActionGroup('', 'View &Actions', 'Current view actions'); A.ViewActions.MenuType = 'separate'; obj.Actions = A; if isempty(obj.GlobalViewOptionGroup) obj.GlobalViewOptionGroup = mbcgui.actions.DynamicActionGroup('', 'Common View Options', 'Additional view options'); obj.GlobalViewOptionGroup.MenuType = 'none'; end if isempty(obj.ContextActionGroup) obj.ContextActionGroup = mbcgui.actions.DynamicActionGroup('', 'Additional Actions', 'Context menu actions'); obj.ContextActionGroup.MenuType = 'separate'; end % Create the context menu obj.hViewContextMenu = uicontextmenu('Parent', ancestor(obj.Parent, 'figure')); obj.pCreateContextMenu(obj.hViewContextMenu); % Create the container that will house the splittable views obj.hTopLayout = xreglayerlayout(obj.Parent, ... 'Position', obj.Position, ... 'Packstatus', 'off'); % Create the rest of the component's layout obj.ContentHandle = pCreateLayout(obj, obj.hTopLayout); % Create the initial set of view objects if obj.pHasSavedLayout obj.restoreViewLayout(obj.ViewLayoutName); else obj.initViewLayout; end set(obj.hTopLayout, 'packstatus', 'on'); % Enable the correct set of actions obj.pUpdateActions; end % MultiViewPanel end % constructor block methods function set.MessageService(obj,value) % DataType = 'handle' validateattributes(value,{'handle'}, {'scalar'},'','MessageService') obj.MessageService = value; hVC = obj.getViewContainers; if ~isempty(hVC) hV = get(hVC, {'View'}); hV = [hV{:}]; set(hV, 'MessageService', obj.MessageService); end end function set.GlobalViewOptions(obj,value) % DataType = 'handle vector' if isempty( obj.GlobalViewOptionGroup ) obj.GlobalViewOptionGroup = mbcgui.actions.DynamicActionGroup('', 'Common View Options', 'Additional view options'); obj.GlobalViewOptionGroup.MenuType = 'none'; end obj.GlobalViewOptionGroup.Actions = value; end function value = get.GlobalViewOptions(obj) if ~isempty( obj.GlobalViewOptionGroup ) value = obj.GlobalViewOptionGroup.Actions; else value = []; end end function set.ContextActions(obj,value) % DataType = 'handle vector' if isempty(obj.ContextActionGroup) obj.ContextActionGroup = mbcgui.actions.DynamicActionGroup('', 'Additional Actions', 'Context menu actions'); obj.ContextActionGroup.MenuType = 'separate'; end obj.ContextActionGroup.Actions = value; end function value = get.ContextActions(obj) value = obj.ContextActionGroup.Actions; end function v = get.SelectedView(obj) c = obj.getSelectedViewContainer; v = c.View; end end % set and get functions methods % public methods function addViewMenuItems(obj, hMenu) %ADDVIEWMENUITEMS Add standard view management items to a menu % ADDVIEWMENUITEMS(OBJ, HMENU) adds the standard set of view management % menu items to the parent menu HMENU. These menus allow the user to % change views, split views, delete views, access view options and copy % views. A = obj.Actions; Mchange = A.ChangeView.createMenuItem(hMenu); % Add separator if view changers are not the first menu item if length(get(hMenu, 'Children'))>1 set(Mchange(1), 'Separator', 'on'); end A.ViewOptions.createMenuItem(hMenu); obj.GlobalViewOptionGroup.createMenuItem(hMenu); m = A.SplitToView.createMenuItem(hMenu); set(m(1), 'Separator', 'on'); A.SplitViewV.createMenuItem(hMenu); A.SplitViewH.createMenuItem(hMenu); A.CloseView.createMenuItem(hMenu); m = A.PrintViewFigure.createMenuItem(hMenu); set(m, 'Separator', 'on'); end % addViewMenuItems function out = canPrint(obj) %CANPRINT Check whether component can be printed % CANPRINT(OBJ) calls canPrint on the selected view. if ~isempty(obj.ViewGroup.SelectedViewContainer) out = obj.ViewGroup.SelectedViewContainer.canPrint; else out = false; end end % canPrint function changeView(obj, ViewIndex) %CHANGEVIEW Change the selected view to a different one % CHANGEVIEW(OBJ, VIEWINDEX) changes the selected view to one of type % VIEWINDEX. hVC = obj.ViewGroup.SelectedViewContainer; if ~isempty(hVC) if obj.ViewList.isViewAvailable(obj.MessageService, ViewIndex); P = xregGui.PointerRepository; PtrID = P.stackSetPointer(obj.Parent, 'watch'); MsgID = obj.pAddStatusMessage('Changing current view...'); hNewVC = obj.pCreateView(ViewIndex); obj.ViewGroup.selectView(hNewVC); VCdata = get(hVC,'UserData'); replace(VCdata{1}, hNewVC, VCdata{2}); delete(hVC); hNewVC.UserData = VCdata; hNewVC.Visible = obj.Visible; obj.pRemoveStatusMessage(MsgID); P.stackRemovePointer(obj.Parent, PtrID); else errordlg(['This view is currently not available. ', ... 'Please select a different view.'], ... 'MBC Toolbox', 'modal'); end end end % changeView function deleteView(obj) %DELETEVIEW Delete the currently selected view % DELETEVIEW(OBJ) deletes the currently selected view so long as there is % more than one view present. if length(obj.ViewGroup.ViewContainers)>1 P = xregGui.PointerRepository; PtrID = P.stackSetPointer(obj.Parent, 'watch'); MsgID = obj.pAddStatusMessage('Closing current view...'); hVC = obj.ViewGroup.SelectedViewContainer; VCdata = get(hVC,'UserData'); hParent = VCdata{1}; delIndex = VCdata{2}; keepIndex = 3-delIndex; ParentData = get(hParent, 'UserData'); el = get(hParent, 'elements'); hVCKeep = el{keepIndex}; set(hVCKeep, 'UserData', ParentData); replace(ParentData{1}, hVCKeep, ParentData{2}); set(hParent,'elements', {}); delete(hParent); delete(hVC); obj.pRemoveStatusMessage(MsgID); P.stackRemovePointer(obj.Parent, PtrID); end end % deleteView function hasView = enableView(obj,viewClass,status) %enableView enable views % enableView(obj,viewClass,status) indexClass = findViewClass(obj.ViewList,viewClass); if ~isempty(indexClass) hasView = obj.ViewList.NumCreated(indexClass)>0; enableView(obj.ViewList,indexClass,status); ViewActions = obj.Actions; ViewActions.ChangeView.Actions(indexClass).Enabled = status; ViewActions.SplitToView.Actions(indexClass).Enabled = status; end end function generateReport(obj,rpt,lvl) %generateReport generate report for multiview % generateReport(obj,rpt,lvl) if nargin<3 lvl = 2; end el = get(obj.hTopLayout, 'elements'); if ~isempty(el) generateViewReport(el{1}) end function generateViewReport(hL) %generateViewReport recurse through views if isa(hL,'xregsplitlayout') generateViewReport(get(hL,'left')); generateViewReport(get(hL,'right')); else generateReport(hL.View,rpt,lvl); end end end function hVC = getSelectedViewContainer(obj) %GETSELECTEDVIEWCONTAINER Get the handle of the selected ViewContainer % HVC = GETSELECTEDVIEWCONTAINER(OBJ) returns the handle of the % ViewContainer that is selected. hVC = obj.ViewGroup.SelectedViewContainer; end % getSelectedViewContainer function idx = getSelectedViewTypeIndex(obj) %GETSELECTEDVIEWTYPEINDEX Get the index of the type of the selected view % IDX = GETSELECTEDVIEWTYPEINDEX(OBJ) returns the index into the current % ViewList of the currently selected view. hVC = obj.getSelectedViewContainer; data = hVC.MVP_Data; lbl = data.ConstructorLabel; idx = obj.ViewList.findViewLabel(lbl); end % getSelectedViewTypeIndex function hVC = getViewContainers(obj) %GETVIEWCONTAINERS AGet all of the open ViewContainers % GETVIEWCONTAINERS(OBJ) returns a handle vector containing all of the % ViewContainers that are in the layout. if ~isempty( obj.ViewGroup) hVC = obj.ViewGroup.ViewContainers; else hVC = []; end end % getViewContainers function initViewLayout(obj) %INITVIEWLAYOUT Create a default view layout % INITVIEWLAYOUT(OBJ) creates the default display. The base % implementation of this creates the first available view and displays % that. hVC = obj.pCreateView; obj.pSetViewLayout(hVC); hVC.Visible = obj.Visible; end % initViewLayout function delete(obj) %delete called when the view is being destroyed % if ~mbcgui.util.isBeingDestroyed(ancestor(obj.Parent, 'figure')) delete(obj.hViewContextMenu); end end % delete function sz = printSize(obj) %PRINTSIZE Returns the preferred printing size for the component % SZ = PRINTSIZE(OBJ) returns a two element vector containing the % preferred width and height for printing the component. This method % calls printSize on the selected view. if ~isempty(obj.ViewGroup.SelectedViewContainer) sz = obj.ViewGroup.SelectedViewContainer.printSize; else sz = printSize@mbcgui.widget.BasicContainer(obj); end end % printSize function H = printToFigure(obj) %PRINTTOFIGURE Create a copy of the current view in a new figure. % PRINTTOFIGURE(OBJ) creates a new figure that contains a copy of the % current view. The handle to the new figure is returned. hVC = obj.getSelectedViewContainer; if ~isempty(hVC) PR = xregGui.PointerRepository; PtrID = PR.stackSetPointer(obj.Parent, 'watch'); MsgID = obj.pAddStatusMessage('Printing current view to a new figure...'); hV = hVC.View; P = ancestor(obj.Parent, 'figure'); H = figure('Color', 'w', ... 'Visible', 'off', ... 'Renderer', get(P, 'Renderer'), ... 'Name', sprintf('%s - %s', hV.gettitle, obj.MessageService.getDataName), ... 'NumberTitle', 'off'); if hV.canPrint L = hV.printCopy(H); else hNewView = obj.ViewList.createView(obj.getSelectedViewTypeIndex, ... obj.MessageService.copy, ... 'Parent', H); L = mbcgui.multiview.PanelViewContainer('Parent', H, ... 'View', hNewView); end if ~isprop(L,'Units') || strcmpi(get(L,'Units'),'pixels') figpos = get(H, 'Position'); set(L, 'Position', [1 1 figpos(3:4)]); set(H, 'ResizeFcn', mbcutils.callback(@i_resizefig, H, L)); end set(H, 'Visible', 'on'); obj.pRemoveStatusMessage(MsgID); PR.stackRemovePointer(obj.Parent, PtrID); end end % printToFigure function newobj = printCopy(obj, fig) %PRINTCOPY Create a new component for printing the component display % NEWOBJ = PRINTCOPY(OBJ, FIG) creates and returns a handle to a new % component, NEWOBJ, parented by the specified figure, FIG. The new % object will be used for printing a copy of the component OBJ. % MultiViewPanel prints the selected view when it is printed. if ~isempty(obj.ViewGroup.SelectedViewContainer) newobj = obj.ViewGroup.SelectedViewContainer.printCopy(fig); else newobj = printCopy@mbcgui.widget.BasicContainer(obj,fig); end end % printcopy function removeViews(obj,viewClass) %removeViews remove named multiviews % removeViews(obj,viewClass) hVC = obj.getViewContainers; views = {hVC.View}; viewIndices = find(cellfun(@(v) isa(v,viewClass),views)); for i=viewIndices if isscalar(obj.getViewContainers) % can't delete last view so add another one before deleting % This won't work if we add a view of the same kind as we % are removing obj.splitView; end selectView(obj,hVC(i)); deleteView(obj); end end function restoreViewLayout(obj, LayoutName,LytStructure) %RESTOREVIEWLAYOUT Restore a saved layout % RESTOREVIEWLAYOUT(OBJ, LAYOUTNAME) restores a layout that has been saved % in the preferences. PR = xregGui.PointerRepository; Pid = PR.stackSetPointer(obj.Parent, 'watch'); existingLytStruct = saveViewLayout(obj, obj.ViewLayoutName); if nargin<3 % restore layouts from preferences P = mbcprefs('mbc'); if ispref(P, 'MultiViewPanel') s = getpref(P, 'MultiViewPanel'); if isfield(s, 'Layouts') s_L = s.Layouts; if isfield(s_L, LayoutName) ReuseContainers=hasSameViews(existingLytStruct,s_L.(LayoutName)); obj.pInstallLayoutStructure(s_L.(LayoutName),ReuseContainers); end end end else % use structure passed in ReuseContainers=hasSameViews(existingLytStruct,LytStructure); obj.pInstallLayoutStructure(LytStructure,ReuseContainers); end PR.stackRemovePointer(obj.Parent, Pid); end % restoreViewLayout function varargout = saveViewLayout(obj, LayoutName) %SAVEVIEWLAYOUT Save the current view layout % SAVEVIEWLAYOUT(OBJ, LAYOUTNAME) saves a structure that defines the % current set and layout of views in the preferences. The layout can then % be restored in the future by RESTOREVIEWLAYOUT. if nargin<2 || isempty(LayoutName) LayoutName = obj.ViewLayoutName; end PR = xregGui.PointerRepository; Pid = PR.stackSetPointer(obj.Parent, 'watch'); lytStruc = obj.pGetLayoutStructure; if nargout==0 % save layout to preferences P = mbcprefs('mbc'); if ispref(P, 'MultiViewPanel') s = getpref(P, 'MultiViewPanel'); else addpref(P, 'MultiViewPanel'); s = struct('Layouts', []); end s.Layouts.(LayoutName) = lytStruc; setpref(P, 'MultiViewPanel', s); else varargout{1} = lytStruc; end PR.stackRemovePointer(obj.Parent, Pid); end % saveViewLayout function selectView(obj, hVC) %SELECTVIEW Select a view % SELECTVIEW(OBJ, HVIEW) selects a view. HVIEW is a handle to either a % View or a ViewContainer. if isa(hVC,'mbcgui.multiview.View') hAllVC = obj.ViewGroup.ViewContainers; hAllView = get(hAllVC, {'View'}); hAllView = [hAllView{:}]; hVC = obj.ViewGroup.ViewContainers(hAllView==hVC); end obj.ViewGroup.selectView(hVC); end % selectView function splitView(obj, Orient, ViewIndex) %SPLITVIEW Split the currently selected view % SPLITVIEW(OBJ, ORIENT, VIEWINDEX) splits the currently selected view. % ORIENT specifies which direction to split the view in. If this is left % empty the view will be split in its preferred direction. VIEWINDEX % specifies the new view that should be created. If this is left empty, % the next view will be chosen automatically. hVC = obj.ViewGroup.SelectedViewContainer; if ~isempty(hVC) if nargin<3 || obj.ViewList.isViewAvailable(obj.MessageService, ViewIndex); P = xregGui.PointerRepository; PtrID = P.stackSetPointer(obj.Parent, 'watch'); MsgID = obj.pAddStatusMessage('Splitting current view...'); if nargin<3 || isempty(ViewIndex) hNewVC = obj.pCreateView; else hNewVC = obj.pCreateView(ViewIndex); end obj.ViewGroup.selectView(hNewVC); if nargin<2 || isempty(Orient) Orient = hVC.View.defaultSplitDirection; end obj.pSplitView(hVC, Orient, hNewVC); hNewVC.Visible = obj.Visible; obj.pRemoveStatusMessage(MsgID); P.stackRemovePointer(obj.Parent, PtrID); else errordlg(['This view is currently not available. ', ... 'Please select a different view.'], ... 'MBC Toolbox', 'modal'); end end end % splitView function updateAvailableViews(obj) %UPDATEAVAILABLEVIEWS Re-check which views can be created % UPDATEAVAILABLEVIEWS(OBJ) checks whether each view type can be created % and updates the state of the creation actions accordingly. % % This method is called automatically before showing the menu that allows % view creation. If you create toolbar buttons for creating views then % you should manually call this method to update the toolbar button % states whenever they may have changed. AG = obj.Actions.ChangeView; avail = obj.ViewList.isViewAvailable(obj.MessageService); if length(avail)==length(AG.Actions) set(AG.Actions, {'Enabled'}, num2cell(avail(:))); end end % updateAvailableViews end % public methods methods (Access=protected) function messageID = pAddStatusMessage(obj, str) %PADDSTATUSMESSAGE Add a message to the status bar % MESSAGEID = PADDSTATUSMESSAGE(OBJ, STR) adds the string STR to the status % bar if one has been provided, and returns the ID of the message added so % that it can be removed later. If no status bar has been set, an empty % message id is returned. if ~isempty(obj.StatusBar) && ishandle(obj.StatusBar) messageID = obj.StatusBar.addMessage(str); else messageID = []; end end % pAddStatusMessage function hVC = pCreateContainer(obj, varargin) %PCREATECONTAINER Construct a view container for a view % HVC = PCREATECONTAINER(OBJ, INDEX) constructs and returns the a % ViewContainer with a view. The ViewContainer will be set up ready for % insertion into the GUI. INDEX should be the index of the view type in % the ViewList. If this is omitted or empty there will be no label on the % container to identify its type. hPanel = mbcgui.container.layoutpanel('Parent', obj.Parent, ... 'Units', 'pixels', ... 'BorderType', 'beveledin', ... 'Visible',obj.Visible,... 'UIContextMenu',obj.hViewContextMenu); mbcgui.util.setAutoBackgroundColor(hPanel); [hV, Index] = obj.ViewList.createView(varargin{:}, ... obj.MessageService, ... 'UIContextMenu',obj.hViewContextMenu,... 'Visible',obj.Visible,... 'Parent', hPanel); hVC = hV.createDefaultWindowContainer(hPanel); hVC.UIContextMenu = obj.hViewContextMenu; data.ConstructorLabel = ''; if ~isempty(Index) data.ConstructorLabel = obj.ViewList.Labels{Index}; end % Add action listeners data.CloseListener = event.listener(hVC, 'Close', @(h,evt) i_deleteview(h,evt, obj)); data.SplitListener = event.listener(hVC, 'Split', @(h,evt) i_splitView(h,evt, obj)); hVC.MVP_Data = data; obj.ViewGroup.addView(hVC); end % pCreateContainer function pCreateContextMenu(obj, hMenu) %PADDVIEWMENUITEMS Add standard view context menu items to a menu % PADDVIEWMENUITEMS(OBJ, HMENU) adds the set of menu items that appear on % the standard context menu to HMENU. A = obj.Actions; A.ChangeView.createMenuItem(hMenu); A.ViewOptions.createMenuItem(hMenu); obj.GlobalViewOptionGroup.createMenuItem(hMenu); A.ViewActions.createMenuItem(hMenu); m = A.SplitToView.createMenuItem(hMenu); set(m(1), 'Separator', 'on'); A.SplitViewV.createMenuItem(hMenu); A.SplitViewH.createMenuItem(hMenu); A.CloseView.createMenuItem(hMenu); m = A.CopyView.createMenuItem(hMenu); set(m, 'Separator', 'on'); A.PrintViewFigure.createMenuItem(hMenu); obj.ContextActionGroup.createMenuItem(hMenu); end % pCreateContextMenu function L = pCreateLayout(~, ViewLayout) %PCREATELAYOUT Create the main layout for the component % L = PCREATELAYOUT(OBJ, VIEWLAYOUT) creates a alyout L that must contain % the given layout VIEWLAYOUT. VIEWLAYOUT is the layout that will contain % all of the views. The default implementation simply returns VIEWLAYOUT % as the main layout. L = ViewLayout; end % pCreateLayout function hVC = pCreateView(obj, varargin) %PCREATEVIEW Create a view % HVC = PCREATEVIEW(OBJ, VIEWINDEX) creates the specified view. The view % will be invisible. A handle to a viewcontainer that contains the view % will be returned. % % HVIEW = PCREATEVIEW(OBJ) chooses the view that will be created % automatically. if ~isempty(obj.ViewList) hVC = obj.pCreateContainer(varargin{:}); else error(message('mbc:mbcmultiview:MultiViewPanel:InvalidState')); end end % pCreateView function AG = pCreateViewListActions(obj, ActionType) %PCREATEVIEWLISTACTIONS Create an ActionGroup for View creation % AG = PCREATEVIEWLISTACTIONS(OBJ, ACTIONTYPE) creates and returns an % action group that contains an action for creating each of the available % views. ACTIONTYPE defines the type of creation that will occur: % 'change' means that the actions will change the current view and 'split' % means that the actions will split the current view. if nargin<2 ActionType = 'change'; end switch ActionType case 'change' objfun = @mbcgui.actions.ToggleAction; cb = @i_changeview; lbl = '&Current View'; groupcb = @i_checkviewers; case 'split' objfun = @mbcgui.actions.StatefulAction; cb = @i_splitViewNum; lbl = '&Split View'; groupcb = @i_checkviewers; otherwise error(message('mbc:mbcmultiview:MultiViewPanel:InvalidArgument')); end VL = obj.ViewList; A(VL.numViews)= mbcgui.actions.Action; for n = 1:length(A) A(n) = objfun({cb, obj, n}, VL.Labels{n}, VL.Descriptions{n}, VL.IconFiles{n}); end AG = mbcgui.actions.ActionGroup({groupcb, obj}, lbl); set(AG, 'Actions', A, 'MenuType', 'submenu'); end % pCreateViewListActions function struc = pGetLayoutStructure(obj) %PGETLAYOUTSTRUCTURE Create a structure that defines the current layout % STRUC = PGETLAYOUTSTRUCTURE(OBJ) creates a data structure that contains % the information required to recreate the current setup of views in the % object. el = get(obj.hTopLayout, 'elements'); if ~isempty(el) struc = i_getviewdata(el{1}); else struc.Type = 'new'; end end % pGetLayoutStructure function ret = pHasSavedLayout(obj) %PHASSAVEDLAYOUT Check whether a layout exists for the current layout name % RET = PHASSAVEDLAYOUT(OBJ) returns true if a saved layout exists with % the name specified in the ViewLayoutName property. ret = false; P = mbcprefs('mbc'); if ispref(P, 'MultiViewPanel') s = getpref(P, 'MultiViewPanel'); if isfield(s, 'Layouts') s_L = s.Layouts; if isfield(s_L, obj.ViewLayoutName) && isstruct(s_L.(obj.ViewLayoutName)) ret = true; end end end end % pHasSavedLayout function pInstallLayoutStructure(obj, struc,ReuseContainers) %PINSTALLLAYOUTSTRUCTURE Set up the display from a saved layout % PINSTALLLAYOUTSTRUCTURE(OBJ, STRUC) recreates the display described by % the structure STRUC. STRUC must have been created by % PGETLAYOUTSTRUCTURE. if ~isempty(struc) el = get(obj.hTopLayout,'elements'); if isempty(el) % in construction - no containers ReuseContainers = false; el = {[]}; end if ~ReuseContainers set(obj.hTopLayout,'Visible','off') end hL = i_createViewObject(obj, struc,ReuseContainers,el{1}); if ~ReuseContainers obj.pSetViewLayout(hL); set(obj.hTopLayout, 'Visible', obj.Visible); end end end % pInstallLayoutStructure function pRemoveStatusMessage(obj, messageID) %PREMOVESTATUSMESSAGE Remove a status bar message % PREMOVESTATUSMESSAGE(OBJ, MESSAGEID) removes the message associated with % MESSAGEID from the status bar, if one has been set, if ~isempty(obj.StatusBar) && ishandle(obj.StatusBar) obj.StatusBar.removeMessage(messageID); end end % pRemoveStatusMessage function pSetViewLayout(obj, hDisplay) %PSETVIEWLAYOUT Set the layout to display % PSETVIEWLAYOUT(OBJ, HDISPLAY) sets HDISPLAY as the view for the % component. HDISPLAY may be either a View object or a splitlayout. el = get(obj.hTopLayout, 'elements'); if ~isempty(el) delete(el{1}); end set(hDisplay, 'UserData', {obj.hTopLayout, 1}); set(obj.hTopLayout, 'elements', {hDisplay}); end % pSetViewLayout function pSplitView(obj, hVC, Orient, hNewVC) %PSPLITVIEW Split a view and attach a new one % PSPLITVIEW(OBJ, HVC, ORIENT, HNEWVC) splits the ViewContainer hVC in the % direction specified by Orient and places the ViewContainer HNEWVC in the % other half of the new splitlayout. VCdata = get(hVC, 'UserData'); hParent = VCdata{1}; ElIndex = VCdata{2}; hLayout = xregsplitlayout(obj.Parent, ... 'packstatus', 'off', ... 'Visible', obj.Visible, ... 'Left', hVC, ... 'Right', hNewVC, ... 'Orientation', Orient, ... 'DividerStyle', 'flat', ... 'DividerWidth', 4, ... 'Userdata', VCdata); replace(hParent, hLayout, ElIndex); set(hVC, 'UserData', {hLayout, 1}); set(hNewVC, 'UserData', {hLayout, 2}); set(hParent, 'packstatus', 'on'); end % pSplitView function pUpdateActions(obj) %PUPDATEACTIONS Update action statuses % PUPDATEACTIONS(OBJ) updates the enable status of the component's % actions. % Disable actions when the component is invisible boolEn = strcmpi(obj.Visible, 'on'); sA = obj.Actions; if boolEn if length(obj.ViewGroup.ViewContainers)>1 sA.CloseView.Enabled = true; else sA.CloseView.Enabled = false; end A = [sA.SplitViewV; sA.SplitViewH; sA.ChangeView; sA.SplitToView]; set(A, 'Enabled', true); else A = [sA.CloseView; sA.SplitViewV; sA.SplitViewH; sA.ChangeView; sA.SplitToView]; set(A, 'Enabled', false); end obj.pViewSelected; end % pUpdateActions function pViewSelected(obj) %PVIEWSELECTED Update object when the selected view changes % PVIEWSELECTED(OBJ) is called when the selected view is changed. This % method updates the enabled status of actions and puts the view-specific % actions in the correct place. A = obj.Actions; hVC = obj.ViewGroup.SelectedViewContainer; printActions = [A.CopyView; ... A.PrintView; ... A.PrintViewQuiet; ... A.PrintViewPreview]; if ~isempty(hVC) && strcmpi(obj.Visible, 'on') set(printActions, 'Enabled', hVC.canPrint); if obj.AlwaysAllowPrintToFigure A.PrintViewFigure.Enabled = true; else A.PrintViewFigure.Enabled = hVC.canPrint; end hV = hVC.View; A.ViewOptions.Actions = hV.Options; A.ViewActions.Actions = hV.Actions; else set(printActions, 'Enabled', false); A.PrintViewFigure.Enabled = false; A.ViewOptions.Actions = []; A.ViewActions.Actions = []; end % Check the create action for the currently selected view AG = A.ChangeView; idx = obj.getSelectedViewTypeIndex; sel = false(size(AG.Actions)); if ~isempty(idx) && idx<=length(sel) && idx>0 sel(idx) = true; end set(AG.Actions, {'Selected'}, num2cell(sel(:))); end % pViewSelected function setVisible(obj, val) %setVisible Respond to visible being set % setVisible(OBJ, val) is called after the object's visible % property has been set. setVisible@mbcgui.widget.BasicContainer(obj,val) obj.pUpdateActions; end % pSetVisible end % protected methods end % classdef function i_checkcloseable(~, evt,obj) % When there is only one view available, make it not closeable hVC = evt.AffectedObject.ViewContainers; A = obj.Actions; hasMultipleViews = (length(hVC)>1); set(hVC, 'Closeable', hasMultipleViews); A.CloseView.Enabled = (hasMultipleViews || strcmpi(obj.Visible, 'off')); end % i_checkcloseable function i_selviewchange(~, ~, obj) % Update Actions enabled status obj.pViewSelected; end % i_selviewchange function i_closeview(~, ~, obj) obj.deleteView; end % i_closeview function i_split(~, ~, obj, orient) obj.splitView(orient); end % i_split function i_printview(~, ~, obj, dest) P = xregGui.PointerRepository; ptrID = P.stackSetPointer(obj.Parent, 'watch'); msg = ''; switch dest case 'clipboard' msg = 'Copying current view to clipboard...'; case {'printer', 'printdialog'} msg = 'Printing current view...'; case 'printpreview' msg = 'Generating print preview for current view...'; end if ~isempty(msg) MsgID = obj.pAddStatusMessage(msg); end obj.print(dest); if ~isempty(msg) obj.pRemoveStatusMessage(MsgID); end P.stackRemovePointer(obj.Parent, ptrID) end % i_printview function i_printtofig(~, ~, obj) obj.printToFigure; end % i_printtofig function i_deleteview(~, ~, obj) obj.deleteView; end % i_deleteview function i_splitView(~, evt, obj) obj.splitView(evt.data.Orientation); end % i_splitview function i_splitViewNum(~, ~, obj, viewnum) obj.splitView([], viewnum); end % i_splitview function i_changeview(~, ~, obj, viewnum) obj.changeView(viewnum); end % i_changeview function i_checkviewers(~, ~, obj) obj.updateAvailableViews; end % i_checkviewers function s = i_getviewdata(hL) if isa(hL, 'xregsplitlayout') s = struct('Type', 'split', ... 'Split', get(hL, 'split'), ... 'Orientation', get(hL, 'Orientation'), .... 'Left', i_getviewdata(get(hL, 'left')), ... 'Right', i_getviewdata(get(hL, 'right'))); else hV = hL.View; data = hL.MVP_Data; s = struct('Type', 'view', ... 'ViewLabel', data.ConstructorLabel, ... 'ViewClass', class(hV), ... 'ViewData', {hV.serializeView}); end end % i_getviewdata function hL = i_createViewObject(obj, struc,ReuseContainers,hL) if strcmp(struc.Type, 'split') if ReuseContainers hLeft = get(hL,'Left'); hRight = get(hL,'Right'); else hLeft = []; hRight = []; end hLeft = i_createViewObject(obj, struc.Left,ReuseContainers,hLeft); hRight = i_createViewObject(obj, struc.Right,ReuseContainers,hRight); if ~ReuseContainers hL = xregsplitlayout(obj.Parent, ... 'Visible', 'off', ... 'Left', hLeft, ... 'Right', hRight, ... 'Orientation', struc.Orientation, ... 'DividerStyle', 'flat', ... 'DividerWidth', 4, ... 'Split', struc.Split); set(hLeft, 'UserData', {hL, 1}); set(hRight, 'UserData', {hL, 2}); else end else Index = obj.ViewList.findViewLabel(struc.ViewLabel); if ~ReuseContainers % Construct a view from the stored information if ~isempty(Index) % Construct using current view definition hL = obj.pCreateView(Index); else % Fall back on the view class as a constructor hL = obj.pCreateContainer(struc.ViewClass); end end % just deserialize if layouts are the same deserializeView(hL.View,struc.ViewData); end end % i_createViewObject function OK = hasSameViews(s1,s2) %hasSameViews checks if the multiview has the same layout % ViewData is ignored in this comparison if ~isstruct(s1) || ~isstruct(s2) OK = false; elseif strcmp(s1.Type, 'split') && strcmp(s2.Type, 'split') % same splot and left and right the same OK = strcmp(s1.Orientation,s2.Orientation) && ... hasSameViews(s1.Left,s2.Left) && ... hasSameViews(s1.Right,s2.Right); else % compare Type, ViewLabel and ViewClass but not data OK = strcmp(s1.Type, s2.Type) && ... strcmp(s1.ViewLabel, s2.ViewLabel) && ... strcmp(s1.ViewClass, s2.ViewClass); end end % hasSameViews function i_resizefig(~, ~, H, L) figpos = get(H, 'Position'); set(L, 'Position', [1 1 figpos(3:4)]); end % i_resizefig