www.gusucode.com > mbcguitools 工具箱 matlab 源码程序 > mbcguitools/+mbcgui/+actions/Action.m

    classdef Action < matlab.mixin.SetGet & matlab.mixin.Copyable & matlab.mixin.Heterogeneous
    %mbcgui.actions.Action class
    %    mbcgui.actions.Action 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'
    %
    %    mbcgui.actions.Action methods:
    %       attachToMenu - Take over a menu item for the action
    %       createButton - Create a uicontrol button for the action
    %       createMenuItem - Create a menu item for the action
    %       createToolbutton - Create a toolbar button for the action
    %       enableStateChange - Enable state change checking on properties
    %       execute - Perform the action command
    %       numRequiredMenus - Get the number of menus that this action requires
    %       setButtonProperties - Set button properties to match the action
    %       setMenuProperties - Set menu item properties to match the action
    %       setToolbuttonProperties - Set toolbar button properties to match the action
    %       shouldSeparate - Return true if action should be separated in menus/toolbars

    %  Copyright 2005-2016 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (AbortSet, SetObservable)
        %COMMAND Property is of type 'MATLAB callback'
        Command = [];
        %LABEL Property is of type 'string'
        Label = '';
        %DESCRIPTION Property is of type 'string'
        Description = '';
        %ICONFILE Property is of type 'string'
        IconFile = '';
        %TransparentColor transparency color for icons
        TransparentColor = [0 255 0]
        %ActiveLabel active form of label. 
        %    For example, Create Optimization instead of Optimization.
        %    Defaults to Label if undefined.
        ActiveLabel = ''
    end
    
    properties (Access=protected, AbortSet)
        %STATECHANGELISTENERS Property is of type 'handle vector'
        StateChangeListeners = [];
    end
    
    events (NotifyAccess=protected)
        StateChanged
    end  % events
    
    methods  % constructor block
        function obj = Action(varargin)
        %ACTION Construct a new Action object
        %
        %  OBJ = ACTION(COMMAND, LABEL, DESCRIPTION, ICONFILE) creates a new
        %  Action object for the specified COMMAND.  If any arguments are omitted
        %  the action will be created with them unset.
        %
        %  An Action encapsulates a command to run, in the form of a callback, and
        %  an associated label and longer description.
        
        numArgs = length(varargin);
        
        if numArgs>3
            obj.IconFile = varargin{4};
        end
        if numArgs>2
            obj.Description = varargin{3};
        end
        if numArgs>1
            obj.Label = varargin{2};
        end
        if numArgs
            obj.Command = varargin{1};
        end
        
        end  % Action
        
    end  % constructor block
    
    methods
        function set.Command(obj,value)
        % DataType = 'MATLAB callback'
        % no MATLAB callback checks yet'
        obj.Command = value;
        end
        
        function set.Label(obj,value)
        % DataType = 'string'
        validateattributes(value,{'char'}, {'row'},'','Label')
        obj.Label = value;
        end
        
        function set.Description(obj,value)
        % DataType = 'string'
        validateattributes(value,{'char'}, {'row'},'','Description')
        obj.Description = value;
        end
        
        function set.IconFile(obj,value)
        % DataType = 'string'
        validateattributes(value,{'char'}, {'row'},'','IconFile')
        obj.IconFile = value;
        end
        
        function set.StateChangeListeners(obj,value)
        % DataType = 'handle vector'
        validateattributes(value,{'handle'}, {'vector'},'','StateChangeListeners')
        obj.StateChangeListeners = value;
        end
        
        function a = get.ActiveLabel(obj)
        if isempty(obj.ActiveLabel)
            % use label if ActiveLabel not defined
            a = obj.Label;
        else
            a = obj.ActiveLabel;
        end
        end
        
    end   % set and get functions
    
    methods(Sealed)
        % matlab.mixin.Heterogeneous requires set and get to be sealed
        % to work with Heterogeneous arrays
        function varargout = set(varargin)
        if nargout
            [varargout{1:nargout}]=set@matlab.mixin.SetGet(varargin{:});
        else
            set@matlab.mixin.SetGet(varargin{:});
        end
        end
        
        function varargout = get(varargin)
        if nargout
            [varargout{1:nargout}]=get@matlab.mixin.SetGet(varargin{:});
        else
            get@matlab.mixin.SetGet(varargin{:});
        end
        end
        
        function OK = eq(varargin)
        
        OK = eq@matlab.mixin.SetGet(varargin{:});

        end
        
        function OK = ne(varargin)
        
        OK = ne@matlab.mixin.SetGet(varargin{:});

        end
        
        function h = findobj(obj,varargin)
        
        h = findobj@matlab.mixin.SetGet(obj,varargin{:});
        
        end

        
    end
    
    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.
        
        set(hMenu, 'Callback', @obj.onExecute);
        obj.setMenuProperties(hMenu);
        
        % Attach a listener to keep menu state matching the action
        StateList = event.listener(obj, 'StateChanged', @(h,evt) obj.onResetMenu(hMenu));
        set(hMenu, 'UserData', StateList);
        end  % attachToMenu
        
        %----------------------------------------
        function hButton = createButton(obj, hParent)
        %CREATEBUTTON Create a uicontrol button for the action
        %
        %  HBUTTON = CREATEBUTTON(OBJ, HPARENT) creates a new  button for the
        %  action in the given parent.  When the button is clicked the action will
        %  execute.
        
        hButton = uicontrol('Parent', hParent, ...
            'Style', 'pushbutton', ...
            'Callback', @obj.onExecute);
        obj.setButtonProperties(hButton);
        
        % Attach a listener to keep state matching the action
        StateList = event.listener(obj, 'StateChanged', @(h,evt) obj.onResetButton(hButton));
        set(hButton, 'UserData', StateList);
        end  % createButton
        
        %----------------------------------------
        function hMenu = createMenuItem(obj, hParent)
        %CREATEMENUITEM Create a menu item for the action
        %
        %  HMENU = CREATEMENUITEM(OBJ, HPARENT) creates a new uimenu object with
        %  HPARENT as a parent.  When the menu item is selected it will execute the
        %  action.
        
        nMenus = obj.numRequiredMenus;
        hMenu = gobjects(1,nMenus);
        for n = 1:nMenus
            hMenu(n) = uimenu('Parent', hParent);
        end
        obj.attachToMenu(hMenu);
        
        end  % createMenuItem
        
        function wf = createWorkflowItems(obj,hWorkflow)
        %createWorkflowItems create items on Common Task pane
        %    hWorkflow is a mbcWorkflowPanel object
        nMenus = obj.numRequiredMenus;
        wf = addItem( hWorkflow,nMenus );     
        attachToWorkfow(obj,wf)
        end  
        
        function attachToWorkfow(obj,wf)
        %attachToWorkfow attach action to mbcWorkflowItem 
        
        set(wf, 'Callback', @obj.onExecute);
        obj.setWorkflowProperties(wf);
        
        % Attach a listener to keep menu state matching the action
        StateList = event.listener(obj, 'StateChanged', @(h,evt) obj.onResetWorkflow(wf));
        set(wf, 'UserData', StateList);
        
        end
        
        function setWorkflowProperties(obj,wf)
        %setWorkflowProperties set properties of workflow panel
        
        lbl = obj.pRemoveMnemonic(obj.Label);
        set(wf,...
            'TransparentColor', obj.TransparentColor,...
            'IconFile',obj.IconFile,...
            'Label',lbl,...
            'Enable', 'on', ...
            'Visible', 'on');
        
        end
        
        
        %----------------------------------------
        function hButton = createToolbutton(obj, hParent)
        %CREATETOOLBUTTON Create a toolbar button for the action
        %
        %  HBUTTON = CREATETOOLBUTTON(OBJ, HPARENT) creates a new toolbar button
        %  for the action.  When the button is clicked the action will execute.
        
        hButton = xregGui.uipushtool(hParent, ...
            'ClickedCallback', @obj.onExecute, ...
            'TransparentColor', obj.TransparentColor);
        obj.setToolbuttonProperties(hButton);
        
        % Attach a listener to keep menu state matching the action
        StateList = event.listener(obj, 'StateChanged', @(h,evt) obj.onResetToolbar(hButton));
        set(hButton, 'UserData', StateList);
        end  % createToolbutton
        
        %----------------------------------------
        function enableStateChange(obj, props)
        %ENABLESTATECHANGE Enable state change checking on properties
        %
        %  ENABLESTATECHANGE(OBJ, PROPS) adds listeners that will fire the state
        %  change event when any one of the properties listed in the cell array
        %  PROPS is altered.
        
        if ischar(props)
            props = {props};
        end
        
        hList = obj.StateChangeListeners;
        
        % Remove properties that are already being listened to
        pDone = [];
        if ~isempty(hList)
            pDone = [hList.Source];
            pDone = [pDone{:}];
        end
        
        for n = 1:length(props)
            hProp = obj.findprop(props{n});
            if ~any(hProp==pDone)
                newList = event.proplistener(obj, hProp, 'PostSet', @obj.onSendState);
                hList = [hList; newList];  %#ok<AGROW>
                pDone = [pDone, hProp]; %#ok<AGROW>
            end
        end
        
        obj.StateChangeListeners = hList;
        end  % enableStateChange
        
        %----------------------------------------
        function execute(obj)
        %EXECUTE Perform the action command
        %
        %  EXECUTE(OBJ) evaluates the action's callback command.
        
        xregcallback(obj.Command,obj,[])
        
        end  % execute
        
        %----------------------------------------
        function N = numRequiredMenus(obj) %#ok<MANU>
        %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.
        
        N = 1;
        end  % numRequiredMenus
        
        %----------------------------------------
        function setButtonProperties(obj, hButton)
        %SETBUTTONPROPERTIES Set button properties to match the action
        %
        %  SETBUTTONPROPERTIES(OBJ, HBUTTON) is called when the uicontrol button's
        %  properties need to be set up to match the action's state.
        
        set(hButton, ...
            'Enable', 'on', ...
            'Visible', 'on');
                
        xregGui.iconuicontrol(hButton,'ImageFile',obj.IconFile,...
            'TransparentColor',obj.TransparentColor);        
        if isempty(hButton.CData)
            lbl = obj.pRemoveMnemonic(obj.Label);
            set(hButton,'String',lbl)
        else
            set(hButton,'TooltipString',obj.Description)
        end

        end  % setButtonProperties
        
        %----------------------------------------
        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(hCh==hMenu) = [];
            OtherLabels = get(hCh, {'Label'});
            lbl = obj.pUniqueMnemonic(obj.Label, OtherLabels);
        else
            lbl = obj.Label;
        end
        
        set(hMenu, ...
            'Enable', 'on', ...
            'Visible', 'on', ...
            'Checked', 'off', ...
            'Label', lbl);
        
        end  % setMenuProperties
        
        %----------------------------------------
        function setToolbuttonProperties(obj, hButton)
        %SETTOOLBUTTONPROPERTIES Set toolbar button properties to match the action
        %
        %  SETTOOLBUTTONPROPERTIES(OBJ, HBUTTON) is called when the menu item's
        %  properties need to be set up to match the action's state.
        
        set(hButton, ...
            'Enable', 'on', ...
            'Visible', 'on', ...
            'ImageFile', obj.IconFile, ...
            'ToolTipString', obj.Description);
        
        end  % setToolbuttonProperties
        
        %----------------------------------------
        function ret = shouldSeparate(obj) %#ok<MANU>
        %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 = false;
        
        end  % shouldSeparate
        
    end  % public methods
    
    methods(Access=protected) % protected methods
        %----------------------------------------
        function str = pRemoveMnemonic(obj, str) %#ok<INUSL>
        %PREMOVEMNEMONIC Remove the mnemonic mark from a label
        %
        %  STR = PREMOVEMNEMONIC(OBJ, STR) removes the first '&' from the string
        %  STR.  This allows use of labels on objects that do not support
        %  mnemonics.
        
        MnemonicIdx = strfind(str, '&');
        if ~isempty(MnemonicIdx)
            str(MnemonicIdx(1)) = [];
        end
        
        end  % pRemoveMnemonic
        
        %----------------------------------------
        function str = pUniqueMnemonic(obj, str, PreStr) %#ok<INUSL>
        %PUNIQUEMNEMONIC Ensure that the mnemonic in a string is unique
        %
        %  STR = PUNIQUEMNEMONIC(OBJ, STR, PRESTR) ensures that the mnemonic
        %  character in the string STR is unique to those in the strings in the
        %  cell array PRESTR.
        
        MnemonicIdx = strfind(str, '&');
        if ~isempty(MnemonicIdx)
            MnemonicIdx = MnemonicIdx(1);
            MnemonicChar = str(MnemonicIdx+1);
            
            PreChars = cell(size(PreStr));
            PreIdx = strfind(PreStr, '&');
            for n = 1:length(PreIdx)
                if ~isempty(PreIdx{n})
                    PreChars{n} = PreStr{n}(PreIdx{n}+1);
                else
                    PreChars{n} = '';
                end
            end
            if any(strcmpi(MnemonicChar, PreChars))
                % Remove current mnemonic
                str(MnemonicIdx) = [];
                
                % Split into words and look for new mnemonic places
                Wstart = regexp(str, '\<\w');
                Wend = regexp(str, '\w\>');
                Wlength = Wend-Wstart+1;
                
                LetterOffset = 0;
                NewMnemonicIdx = 0;
                while any(LetterOffset<Wlength) && NewMnemonicIdx==0
                    for n = 1:length(Wstart)
                        Idx = Wstart(n)+LetterOffset;
                        if LetterOffset<Wlength(n) && ~any(strcmpi(str(Idx), PreChars))
                            NewMnemonicIdx = Idx;
                            break
                        end
                    end
                    LetterOffset = LetterOffset+1;
                end
                
                if NewMnemonicIdx>0
                    str = [str(1:NewMnemonicIdx-1), '&', str(NewMnemonicIdx:end)];
                end
            end
        end
        
        end  % pUniqueMnemonic

        %----------------------------------------
        function onResetMenu(obj, hMenu,~)
        obj.setMenuProperties(hMenu);
        end  % i_resetmenu
        
        function onResetWorkflow(obj, hMenu,~)
        obj.setWorkflowProperties(hMenu);
        end  % i_resetmenu        
        
        %----------------------------------------
        function onResetButton(obj, hButton,~)
        obj.setButtonProperties(hButton);
        end  % i_resetbutton
        
        %----------------------------------------
        function onResetToolbar(obj, hButton,~)
        obj.setToolbuttonProperties(hButton);
        end  % i_resetbutton        
        
        %----------------------------------------
        function onExecute(obj, ~,~)
        obj.execute;
        end  % i_resetbutton
        
        %----------------------------------------
        function onSendState(obj,~,~)
        obj.notify('StateChanged');
        end
    end % protected methods
    
end  % classdef