www.gusucode.com > mbcguitools 工具箱 matlab 源码程序 > mbcguitools/+mbcgui/+actions/ActionGroup.m
classdef ActionGroup < mbcgui.actions.StatefulAction %mbcgui.actions.ActionGroup class % mbcgui.actions.ActionGroup extends mbcgui.actions.StatefulAction. % % mbcgui.actions.ActionGroup properties: % Command - Property is of type 'MATLAB callback' % Label - Property is of type 'string' % Description - Property is of type 'string' % IconFile - Property is of type 'string' % Visible - Property is of type 'bool' % Enabled - Property is of type 'bool' % Actions - Property is of type 'handle vector' % MenuType - Property is of type 'string' % % mbcgui.actions.ActionGroup methods: % attachToMenu - Take over a menu item for the action % createToolbutton - Create a toolbar button for the action % numRequiredMenus - Get the number of menus that this action requires % setMenuProperties - Set menu item properties to match the action % shouldSeparate - Return true if action should be separated in menus/toolbars % Copyright 2005-2014 The MathWorks, Inc. and Ford Global Technologies, Inc. properties (AbortSet,SetObservable) %ACTIONS Property is of type 'handle vector' Actions = mbcgui.actions.StatefulAction.empty(0,1); %MENUTYPE Property is of type 'string' MenuType = 'auto'; end methods % constructor block function obj = ActionGroup(varargin) %ACTIONGROUP Create a new ActionGroup object % % OBJ = ACTIONGROUP(COMMAND, LABEL, DESCRIPTION, ICONFILE) creates a new % ActionGroup object for the specified COMMAND. If any arguments are omitted % the action will be created with them unset. % % ActionGroups contain a set of associated actions. When added to menus, % ActionGroups will either created a separated set of menus or a submenu, % depending on the value of the MenuType property. If a command is % defined for an ActionGroup, it will be executed when the submenu parent % is opened. The command will not be executable from a toolbar or if the % ActionGroup does not create a submenu group. obj@mbcgui.actions.StatefulAction(varargin{ : }); % converted super class constructor call end % ActionGroup end % constructor block methods function set.MenuType(obj,value) % DataType = 'string' validateattributes(value,{'char'}, {'row'},'','MenuType') obj.MenuType = i_enforcemenutype(obj,value); end function set.Actions(obj,value) if any(value(:)==obj) error('Recursive assignment for ActionGroup Actions') end obj.Actions = value(:); end end % set and get functions methods % public methods %---------------------------------------- function attachToMenu(obj, hMenu) %ATTACHTOMENU Take over a menu item for the action % % ATTACHTOMENU(OBJ, HMENU) sets the properties of HMENU to reflect the % action OBJ. if length(hMenu)~=obj.numRequiredMenus error(message('mbc:mbcmultiview:ActionGroup:InvalidArgument', obj.numRequiredMenus)); end if obj.pShouldMakeSubMenus hThisMenu = hMenu(1); if length(hMenu)>1 childMenus = hMenu(2:end); set(childMenus, 'Parent', hThisMenu); else childMenus = []; end set(hThisMenu, 'Callback', @obj.onExecute); obj.setMenuProperties(hThisMenu); if strcmpi(obj.MenuType, 'separatesubmenu') set(hThisMenu, 'Separator', 'on'); end % Attach a listener to keep menu state matching the action StateList = event.listener(obj, 'StateChanged', @(h,evt) obj.onResetMenu(hThisMenu)); set(hThisMenu, 'UserData', StateList); else childMenus = hMenu; if strcmpi(obj.MenuType, 'separate') && ~isempty(childMenus) % Need to set a separator if there is a preceding menu. hFirstMenu = childMenus(1); hPrecedingMenu = iGetMenuBefore(hFirstMenu); if ~isempty(hPrecedingMenu) set(hFirstMenu, 'Separator', 'on'); end end end % Iterate over subactions A = obj.Actions; nUsed = 0; for n=1:length(A) nMenus = A(n).numRequiredMenus; A(n).attachToMenu(childMenus((nUsed+1):(nUsed+nMenus))); if length(childMenus)<nUsed && (A(n).shouldSeparate ... || n>1 && A(n-1).shouldSeparate ) set(childMenus((nUsed+1)), 'Separator', 'on'); end nUsed = nUsed+nMenus; end end % attachToMenu function attachToWorkfow(obj,wf) A = obj.Actions; nUsed = 0; for n=1:length(A) nMenus = A(n).numRequiredMenus; A(n).attachToWorkfow(wf((nUsed+1):(nUsed+nMenus))); if length(wf)<nUsed && (A(n).shouldSeparate ... || n>1 && A(n-1).shouldSeparate ) set(wf((nUsed+1)), 'Separator', 'on'); end nUsed = nUsed+nMenus; end end %---------------------------------------- function hButton = createToolbutton(obj, hParent) %CREATETOOLBUTTON Create a toolbar button for the action % % HBUTTON = CREATETOOLBUTTON(OBJ, HPARENT) creates toolbar buttons for each % action that is contained in the ActionGroup. % Iterate over subactions A = obj.Actions; hButton = []; for n = 1:length(A) newbtns = A(n).createToolbutton(hParent); if A(n).shouldSeparate ... || n>1 && A(n-1).shouldSeparate set(newbtns(1), 'Separator', 'on'); end hButton = [hButton, newbtns]; end end % createToolbutton %---------------------------------------- function N = numRequiredMenus(obj) %NUMREQUIREDMENUS Get the number of menus that this action requires % % N = NUMREQUIREDMENUS(OBJ) returns an integer that is the number of menus % that an action will make when createMenuItem is called. % Iterate over all contained actions and count the menus required for each N = 0; A = obj.Actions; for n = 1:length(A) N = N + A(n).numRequiredMenus; end % Add one if a menu is needed for self if obj.pShouldMakeSubMenus N = N+1; end end % numRequiredMenus %---------------------------------------- function setMenuProperties(obj, hMenu) %SETMENUPROPERTIES Set menu item properties to match the action % % SETMENUPROPERTIES(OBJ, HMENU) is called when the menu item's properties % need to be set up to match the action's state. hP = get(hMenu, 'Parent'); if ~isempty(hP) hCh = get(hP, 'Children'); hCh = findobj( hCh, 'flat', 'Type', 'uimenu' ); hCh(hCh==hMenu) = []; OtherLabels = get(hCh, {'Label'}); lbl = obj.pUniqueMnemonic(obj.Label, OtherLabels); else lbl = obj.Label; end set(hMenu, ... 'Enable', mbconoff(~isempty(obj.Actions) && obj.Enabled), ... 'Visible', mbconoff(obj.Visible), ... 'Checked', 'off', ... 'Label', lbl); end % setMenuProperties %---------------------------------------- function ret = shouldSeparate(obj) %SHOULDSEPARATE Return true if action should be separated in menus/toolbars % % RET = SHOULDSEPARATE(OBJ) returns true if the action should have % separators placed before and after it. ret = ~obj.pShouldMakeSubMenus; end % shouldSeparate end % public methods methods (Access=protected) % protected methods %---------------------------------------- function ret = pShouldMakeSubMenus(obj) %PSHOULDMAKESUBMENUS Return true if submenus should be made % % RET = PSHOULDMAKESUBMENUS(OBJ) returns true of this group should % consist of a menu that contains other sub-menus, and false if the % contained Actions should be added as a separated group. ret = strcmp(obj.MenuType, 'submenu') ... || strcmp(obj.MenuType, 'separatesubmenu') ... || (strcmp(obj.MenuType, 'auto') && length(obj.Actions)>3); end % pShouldMakeSubMenus %---------------------------------------- function onExceute(obj,~,~) obj.execute; end % i_execute %---------------------------------------- function onResetMenu(obj, hMenu) obj.setMenuProperties(hMenu); end % i_resetmenu function onSendState(obj,~,~) set(obj.Actions,'Enabled',obj.Enabled) onSendState@mbcgui.actions.StatefulAction(obj); end end % protected methods end % classdef function val = i_enforcemenutype(obj, val) %#ok<INUSL> % Check for valid settings of property if ~any(strcmpi(val, {'auto', 'submenu', 'separate', 'separatesubmenu', 'none'})) error(message('mbc:mbcmultiview:ActionGroup:InvalidPropertyValue')); else val = lower(val); end end % i_enforcemenutype function hPreceding = iGetMenuBefore(hSrc) hPreceding = []; hP = get(hSrc, 'Parent'); if isgraphics(hP, 'uimenu') || isgraphics(hP, 'uicontextmenu') hAll = get(hP, 'Children'); hPreceding = findobj(hAll, 'Position', get(hSrc, 'Position')-1); end end % iGetMenuBefore