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

    classdef MultiObjectDialog < mbcgui.dialog.StandardDialog
    %mbcgui.dialog.MultiObjectDialog class
    %   mbcgui.dialog.MultiObjectDialog extends mbcgui.dialog.StandardDialog.
    %
    %    mbcgui.dialog.MultiObjectDialog properties:
    %       Parent - Property is of type 'MATLAB array'
    %       Figure - Property is of type 'MATLAB array' (read only)
    %       Title - Property is of type 'ustring'
    %       Object - Property is of type 'MATLAB array' (read only)
    %       HasObjectChanged - Property is of type 'bool' (read only)
    %       HelpHandler - Property is of type 'string'
    %       HelpCode - Property is of type 'string'
    %       DisplayHelp - Property is of type 'bool'
    %       UserData - Property is of type 'MATLAB array'
    %       PageInfoFunction - Property is of type 'MATLAB array'
    %       DisplaySinglePageAsTab - Property is of type 'bool'
    %       ChooserLabel - Property is of type 'string'
    %       ChooserLabelWidth - Property is of type 'int'
    %       OptionStrings - Property is of type 'MATLAB array'
    %       OptionFunctions - Property is of type 'MATLAB array'
    %       OptionDestructors - Property is of type 'MATLAB array'
    %       OptionPageFunctions - Property is of type 'MATLAB array'
    %       CurrentOption - Property is of type 'int'
    %       DialogPanelSize - Property is of type 'MATLAB array'
    %       LayoutFunction - Property is of type 'MATLAB array'
    %
    %    mbcgui.dialog.MultiObjectDialog methods:
    %       getDialogPanelSize - Return the desired size of the display panel
    %       getOptionObject - Get the object for a specific option.
    %       isOptionCreated - Check whether an option has been created yet.
    %       updateOptionObject - Set a new object for a specific option.
    
    %  Copyright 2000-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (AbortSet)
        %OPTIONSTRINGS Property is of type 'MATLAB array'
        OptionStrings = {  };
        %OPTIONFUNCTIONS Property is of type 'MATLAB array'
        OptionFunctions = {  };
        %OPTIONDESTRUCTORS Property is of type 'MATLAB array'
        OptionDestructors = {  };
        %OPTIONPAGEFUNCTIONS Property is of type 'MATLAB array'
        OptionPageFunctions = {  };
    end
    
    properties (AbortSet, SetObservable)
        %CHOOSERLABEL Property is of type 'string'
        ChooserLabel = 'Select item:';
        %CHOOSERLABELWIDTH Property is of type 'int'
        ChooserLabelWidth = 150;
        %CURRENTOPTION Property is of type 'int'
        CurrentOption
        %DIALOGPANELSIZE Property is of type 'MATLAB array'
        DialogPanelSize = [ 380, 400 ];
        %LAYOUTFUNCTION Property is of type 'MATLAB array'
        LayoutFunction = [];
    end
    
    properties (Access=protected, AbortSet)
        %HCARDLAYOUT Property is of type 'MATLAB array'
        hCardLayout = [];
        %HMODLAYOUT Property is of type 'MATLAB array'
        hMODLayout = [];
        %OPTIONOBJECTS Property is of type 'MATLAB array'
        OptionObjects = {  };
        %OPTIONGROUPS Property is of type 'MATLAB array'
        OptionGroups = [];
        %OPTIONSMADE Property is of type 'MATLAB array'
        OptionsMade = false( 0 );
        %MOD_LISTENERS Property is of type 'handle vector'
        MOD_Listeners = [];
    end
    
    events
        OptionChanged
    end  % events
    
    methods  % constructor block
        function obj = MultiObjectDialog(varargin)
        %MULTIOBJECTDIALOG Constructor for MultiObjectDialog object
        %  OBJ = MULTIOBJECTDIALOG(Prop, Value, ...) creates a new
        %  MultiObjectDialog object for selecting from a series of objects.
        %
        %  During creation you should specify values for the OptionStrings and
        %  OptionFunctions properties.  Each object option corresponds to a string
        %  in the OptionStrings cell array. The OptionFunctions property is a cell
        %  array the same size as OptionStrings where each cell must contain either
        %  (a) a function handle that can generate a particular option's object on
        %  demand or (b) an actual instance of an object to use for that option.
        %
        %  The functions specified for OptionFunctions should have the signature:
        %
        %     obj = FUNC(hDialog)
        %
        %  Each object can provide multiple pages of information for the dialog.
        %  If the OptionPageFunctions property is empty, the PageInfoFunction
        %  property is called to generate the DialogPageInfo objects for each
        %  option object.
        %
        %  If the OptionPageFunctions property is non-empty, it must be a cell
        %  array of function handles that is the same length as the OptionStrings
        %  property.  The function handle corresponding to the current option is
        %  then automatically set as the PageInfoFunction.
        
        
        obj@mbcgui.dialog.StandardDialog(varargin{: }); % converted super class constructor call
        
        if length(obj.OptionStrings)~=length(obj.OptionFunctions)
            error(message('mbc:xregGui:MultiObjectDialog:InvalidArgument'));
        end
        
        % Set up container for objects to be edited
        obj.OptionObjects = cell(size(obj.OptionStrings));
        
        % Set up array of handles to page groups
        obj.OptionGroups = mbcgui.dialog.PageGroup.empty;
        
        % Set up boolean flags that indicate which pages have been made
        obj.OptionsMade = false(size(obj.OptionStrings));
        
        Nopts = length(obj.OptionStrings);
        
        % Make basic UI
        SC = xregGui.SystemColorsDbl;
        hChooser = uicontrol('Parent', obj.Figure, ...
            'Tag', 'ObjectChooserPopup',...
            'Style', 'popupmenu', ...
            'BackgroundColor', SC.WINDOW_BG, ...
            'Visible', 'off', ...
            'String', obj.OptionStrings, ...
            'Value', obj.CurrentOption, ...
            'Callback', @i_changeOption);
        hLabel = xregGui.labelcontrol('parent', obj.Figure, ...
            'Visible', 'off', ...
            'String', obj.ChooserLabel, ...
            'LabelSize', obj.ChooserLabelWidth, ...
            'LabelSizeMode', 'absolute', ...
            'ControlSize', 1, ...
            'ControlSizeMode', 'relative', ...
            'Gap', 5, ...
            'Control', hChooser);
        hCards = xregcardlayout(obj.Figure, ...
            'packstatus', 'off', ...
            'visible', 'off', ...
            'numcards', Nopts+1, ...
            'CurrentCard', Nopts+1);
        obj.hCardLayout = hCards;
        
        % Call a method to create the layout.  This allows subclasses to overload
        % the basic look
        obj.hMODLayout = obj.pCreateChooserLayout(hLabel, hCards);
        % Functions that destroy the appropriate option objects when the dialog is
        % destroyed
        KeepCurrent = false;
        
        % Hook up listeners
        obj.MOD_Listeners = [ ...
            event.proplistener(obj, obj.findprop('ChooserLabel'), 'PostSet', @i_setLabel); ...
            event.proplistener(obj, obj.findprop('CurrentOption'), 'PostSet', @i_setOption); ...
            event.listener(obj, 'ObjectBeingDestroyed', @i_destroyobj); ...
            event.listener(obj, 'Finalize', @(h,evt) i_setkeepcurrent(h,evt,true)); ...
            event.listener(obj, 'Cancel', @(h,evt) i_setkeepcurrent(h,evt,false)); ...
            ];
        
        % Create the first object and switch to it.
        obj.pSelectOption;

        
            function i_changeOption(src, ~)
            obj.CurrentOption = get(src, 'Value');
            end
        
            function i_setLabel(~, ~)
            hLabel.String = obj.ChooserLabel;
            end
        
            function i_setOption(~, evt)
            set(hChooser, 'Value', obj.CurrentOption);
            obj.pSelectOption;
            end
        

            function i_setkeepcurrent(~, ~, setting)
            KeepCurrent = setting;
            end
            function i_destroyobj(~, ~)
            if KeepCurrent
                obj.pDestroyOptions(obj.CurrentOption);
            else
                obj.pDestroyOptions;
            end
            end
        end
        
    end  % constructor block
    
    
    methods  % public methods
        %----------------------------------------
        function sz = getDialogPanelSize(obj)
        %GETDIALOGPANELSIZE Return the desired size of the display panel
        %  SZ = GETDIALOGPANELSIZE(OBJ) returns a 2-element vector containing the
        %  width and height of the dialog panel.  This is taken as the maximum
        %  values from all of the preferred widths and heights of the
        %  DialogPageInfo objects.
        
        sz = obj.DialogPanelSize;
        
        end  % getDialogPanelSize
        
        %----------------------------------------
        function OptObj = getOptionObject(obj, OptionIdx)
        %GETOPTIONOBJECT Get the object for a specific option.
        %   OPTOBJ = GETOPTIONOBJECT(OBJ, OPTIONIDX) returns the current object for
        %   the specified index.  If the option has not yet been created then this
        %   function will return an empty.
        
        if obj.isOptionCreated(OptionIdx)
            OptObj = obj.OptionGroups(OptionIdx).getObject;
        else
            OptObj = [];
        end
        
        end  % getOptionObject
        
        %----------------------------------------
        function ret = isOptionCreated(obj, OptionIdx)
        %ISOPTIONCREATED Check whether an option has been created yet.
        %   ISOPTIONCREATED(OBJ, OPTIONIDX) returns true if the option specified
        %   has been created for the user.  Options are only created when a user
        %   first selects them from the list.
        
        ret = obj.OptionsMade(OptionIdx);
        
        end  % isOptionCreated
        
        %----------------------------------------
        function updateOptionObject(obj, OptionIdx, OptObj)
        %UPDATEOPTIONOBJECT Set a new object for a specific option.
        %   UPDATEOPTIONOBJECT(OBJ, OPTIONIDX, OPTOBJ) update the specified option
        %   to use the new object OPTOBJ.  If the specified option has not yet been
        %   created then this will set the initial object for an option.
        
        if obj.isOptionCreated(OptionIdx)
            obj.OptionGroups(OptionIdx).updateObject(OptObj);
        else
            obj.OptionObjects{OptionIdx} = OptObj;
        end
        
        end  % updateOptionObject
        
    end  % public methods
    
    methods (Access=protected)
        %----------------------------------------
        function pCancel(obj, ~)
        %PCANCEL Cancel the dialog
        %  PCANCEL(OBJ, EVT) is called in response to the cancel event in the
        %  dialog.  The contained DialogPageGroup is cancelled.
        
        % Cancel all DialogPageGroups
        for n = 1:length(obj.OptionGroups)
            if iscomponent(obj.OptionGroups(n))
                obj.OptionGroups(n).cancel;
            end
        end
        obj.updateObject(obj.OptionGroups(obj.CurrentOption).Object);
        
        end  % pCancel
        
        %----------------------------------------
        function lyt = pCreateChooserLayout(obj, hLabel, hCards)
        %PCREATECHOOSERLAYOUT Create the layout for the object chooser controls
        %  LYT = PCREATECHOOSERLAYOUT(OBJ, HLABEL, HCARDS) creates a layout
        %  that contains the labelcontrol HLABEL and the cardlayout HCARDS.
        %  Subclasses may override this method to provide customized layout.  The
        %  layout that is returned should contain HLABEL and HCARDS.
        
        if ~isempty(obj.LayoutFunction)
            % Defer layout generation to provided function
            lyt = obj.LayoutFunction(obj, hLabel, hCards);
        else
            lyt = xreggridbaglayout(obj.Figure, ...
                'dimension', [2 1], ...
                'rowsizes', [20 -1], ...
                'gapy', 10, ...
                'elements', {hLabel, hCards});
        end
        end  % pCreateChooserLayout
        
        %----------------------------------------
        function hPanel = pCreateDialogPanel(obj)
        %PCREATEDIALOGPANEL Create and return a display object
        %  HPANEL = PCREATEDIALOGPANEL(OBJ) creates and returns a handle to an
        %  object that is used as the gui for displaying and/or editing the
        %  dialog's object.
        
        if ~isobject(obj.Object) && isempty(obj.Object)
            set(obj.hCardLayout, 'CurrentCard', get(obj.hCardLayout, 'NumCards'));
        else
            if ~obj.OptionsMade(obj.CurrentOption)
                % Get the layout to embed from the superclass.  We need to always do this
                % to make sure that the superclass links things up correctly for the
                % current object.
                hGroup = pCreateDialogPanel@mbcgui.dialog.StandardDialog(obj);
                obj.OptionGroups(obj.CurrentOption) = hGroup;
                attach(obj.hCardLayout, hGroup, obj.CurrentOption);
                obj.OptionsMade(obj.CurrentOption) = true;
            else
                hGroup = obj.OptionGroups(obj.CurrentOption);
                obj.pAttachToPanel(hGroup);
            end
            
            % Switch to the correct card
            set(obj.hCardLayout, 'CurrentCard', obj.CurrentOption);
        end
        
        hPanel = obj.hMODLayout;
        
        end  % pCreateDialogPanel
        
        %----------------------------------------
        function pDestroyDialogPanel(obj, hPanel)
        %PDESTROYDIALOGPANEL Destroys the specified display object
        %  PDESTROYDIALOGPANEL(OBJ, HPANEL) destroys the display object HPANEL.
        %  This method is called if the display object is swapped for a different
        %  one and the display needs to be re-created.
        
        % Shift the card to the blank one and do not destroy the panel
        set(obj.hCardLayout, 'CurrentCard', get(obj.hCardLayout, 'NumCards'));
        
        end  % pDestroyDialogPanel
        
        %----------------------------------------
        function pDestroyOptions(obj, KeepIdx)
        %PDESTROYOPTIONS Destroy the options that are no longer needed
        %  PDESTROYOPTIONS(OBJ, SELIDX) destroys the objects for the options that
        %  are not specified in SELIDX and that were created by the dialog.  If
        %  destructor functions have been provided then these are called on the
        %  objects before they are cleared from the store of visited options.  If
        %  SELIDX is omitted then all objects are destroyed.
        
        if nargin<2
            KeepIdx = [];
        end
        
        dfun = obj.OptionDestructors;
        optobj = obj.OptionObjects;
        
        if isempty(dfun) || length(dfun)~=length(optobj)
            % No actions to perform
            return
        end
        
        cfun = obj.OptionFunctions;
        
        for n = setdiff(1:length(optobj), KeepIdx)
            if isobject(optobj{n}) && ~isempty(dfun{n}) && isa(cfun{n}, 'function_handle')
                dfun{n}(optobj{n});
            end
        end
        
        end  % pDestroyOptions
        
        %----------------------------------------
        function pFinalize(obj, evt)
        %PFINALIZE Finalize the dialog
        %  PFINALIZE(OBJ, EVT) is called in response to the finalize event in the
        %  dialog.  The contained DialogPageGroup is finalized.
        
        % Cancel all DialogPageGroups except for the curent one, which is finalized
        for n = 1:length(obj.OptionGroups)
            if iscomponent(obj.OptionGroups(n))
                if n==obj.CurrentOption
                    obj.OptionGroups(n).finalize;
                else
                    obj.OptionGroups(n).cancel;
                end
            end
        end
        obj.updateObject(obj.OptionGroups(obj.CurrentOption).Object);
        
        end  % pFinalize
        
        %----------------------------------------
        function pSelectOption(obj)
        %PSELECTOPTION Implements the selection of a new object option
        %  PSELECTOPTION(OBJ) switches the dialog to display the currently selected
        %  option.  If the object is not already created, this method will first
        %  create it.
        
        PR = xregGui.PointerRepository;
        ptrID = PR.stackSetPointer(obj.Figure, 'watch');
        
        index = obj.CurrentOption;
        if isempty(obj.OptionObjects{index})
            % Need to create the object
            if isa(obj.OptionFunctions{index}, 'function_handle')
                obj.OptionObjects{index} = obj.OptionFunctions{index}(obj);
            else
                obj.OptionObjects{index} = obj.OptionFunctions{index};
            end
            NewOptionObj = obj.OptionObjects{index};
        else
            NewOptionObj = obj.OptionGroups(index).Object;
        end
        
        % Set page creation function if required
        if ~isempty(obj.OptionPageFunctions)
            obj.PageInfoFunction = obj.OptionPageFunctions{index};
        end
        
        % Switch dialog to new object display
        obj.switchObject(NewOptionObj);
        
        % Send event to notify users of change
        obj.notify('OptionChanged');
        
        PR.stackRemovePointer(obj.Figure, ptrID);
        
        end  % pSelectOption 
    end
    
end  % classdef