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

    classdef Component < mbcgui.widget.AbstractComponent
    %COMPONENT Base widget class for MBC
    %   mbcgui.widget.Component is the base class for all user interface
    %   components in MBC.  This class provides a basic set of component
    %   properties - Parent, Position, Visible, Enable and UserData - as well
    %   as a printing interface and utility methods for managing event
    %   listeners.
    %
    %   Component properties:
    %      Parent        - Handle to a parent container.
    %      Position      - [X Y W H] position rectangle.
    %      Enable        - on/inactive/off
    %      Visible       - on/off
    %      UserData      - Freeform field for use by the user.
    %      Tag           - Freeform string for use by the user.
    %
    %   Property notification (protected)
    %      setParent     - Called when the Parent property is altered.
    %      setPosition   - Called when the Position property is altered.
    %      setEnable     - Called when the Enable property is altered.
    %      setVisible    - Called when the Visible property is altered.
    %
    %   Printing interface:
    %      canPrint      - Test whether the component supports printing
    %      print         - print the component
    %      printCopy     - (Protected) Generate a copy of the component that is
    %                      suitable for printing.
    %      printSize     - Return a [W H] preferred aspect ratio for the
    %                      printed component.
    %
    %   Listener utilities (protected):
    %   These utilities can be used to manage listeners in subclasses.
    %
    %      storeListeners   - Save a copy of specified listeners.
    %      enableListeners  - Enable all the saved listeners.
    %      disableListeners - Disable all the saved listeners.
    %
    %   Dependent property utilities (protected):
    %   These utilities are useful when you want to create dependent properties
    %   that map directly to properties on contained objects.
    %
    %      forwardProperty  - Forward a property value to a contained object or
    %                         store in a temporary location if the object does
    %                         not exist yet.
    %      retrieveProperty - Retrieve a property value from a contained object
    %                         or look up a value from the temporary store if
    %                         the object does not exist yet.
    %      getPVPairs       - Retrieve specified property-value pairs from the
    %                         temporary store and remove the values from the
    %                         store.
    
    %   Copyright 2008-2016 The MathWorks, Inc.
    
    properties(SetObservable,GetObservable, AbortSet)
        %PARENT Handle to a parent container
        %   H.Parent contains a handle to a container that the component is
        %   positioned in.  Valid containers are either a figure handle or a
        %   uipanel handle.
        %
        %   If no parent is specified during construction then the the
        %   component automatically parents itself to the handle returned by
        %   'gcf'.
        %
        %   See also gcf, uicontrol.Parent.
        Parent = -1;
        
        %POSITION Position rectangle
        %   H.Position contains a 4-element vector ([X Y W H])that specifies
        %   the position of a component in pixel units.
        %
        %   See also uicontrol.Position.
        Position = [1 1 10 10];
        
        %ENABLE Enable setting
        %   H.Enable contains one of the strings 'on', 'inactive' or 'off'.
        %
        %   See also uicontrol.Enable.
        Enable = 'on';
        
        %VISIBLE Visible setting
        %   H.Visible contains one of the strings 'on' or 'off'.  When a
        %   component has its Visible property set to 'off', it should make all
        %   of its contained control invisible.
        %
        %   See also uicontrol.Visible.
        Visible = 'on';
        
        %USERDATA User-defined data store
        %   H.UserData may be set to any Matlab array.  It is not used by the
        %   component and can be used to store associated application data.
        %
        %   See also uicontrol.UserData.
        UserData = [];
        
        %TAG User-defined tag
        %   H.Tag may be set to any Matlab string.  It is not used by the
        %   component and can be used to label controls to aid later finding
        %   them.
        %
        %   See also uicontrol.Tag.
        Tag = '';
    end
    
    
    properties(SetAccess=private, GetAccess=private)
        %COMPONENTLISTENERS Store of event listeners
        ComponentListeners = cell(0,1);
        
        %CONSTRUCTEDFLAG Flag to indicate whether object is post construction
        ConstructedFlag = false;
        
        %PARENTLISTENER Event listener for reacting to parent deletion
        ParentListener = [];
        
        %CONSTRUCTPROPMAP Map that temporarily contains dependent properties
        %that are set at construction time.
        ConstructPropMap = [];
    end
    
    
    methods(Access=protected)
        function obj = Component(varargin)
        %COMPONENT Construct a new Component
        %   H = COMPONENT(PROP1, VAL1, ...) constructs a new component and sets
        %   the specified property-value pairs.  Property set functions are not
        %   triggered during construction.
        
        if ~isempty(varargin)
            set(obj, varargin{:});
        end
        
        if isempty(obj.Parent)
            obj.Parent = gcf;
        end
        
        obj.ConstructedFlag = true;
        end
    end
    
    methods
        function delete(obj)
        try
            P = obj.Parent;
        catch E
            if strcmp(E.identifier, 'MATLAB:class:InvalidHandle')
                % Assume that the object is invalid
                return
            else
                rethrow(E);
            end
        end
        
        if isgraphics(P) && ~mbcgui.util.isBeingDestroyed(P)
            removeFromComponentStore(obj, P);
        end
        end
        
    end
    
    
    % Property set notification.  These methods check for valid settings
    % and then notify subclasses by calling an associated protected method.
    methods
        function set.Parent(obj, P)
        if ~mbcgui.util.isComponentParent(P)
            error(message('mbc:mbcgui:widget:Component:InvalidPropertyValue'));
        end
        if isnumeric(P)
            % TODO
            P = mbcgui.hgclassesutil.toHandle(P);
        end
        
        % Register the component handle in a store on the new figure.  This
        % will prevent the component from being destroyed if the handle is
        % cleared from the Matlab workspace.
        OldP = obj.Parent;
        if ~isempty(OldP)
            removeFromComponentStore(obj, OldP);
        end
        
        addToComponentStore(obj, P)
        
        obj.Parent = P;
        if obj.ConstructedFlag %#ok<*MCSUP>
            obj.setParent(P);
        end
        end
        
        function set.Position(obj, Pos)
        if ~isnumeric(Pos) || ~isequal(size(Pos), [1 4])
            error(message('mbc:mbcgui:widget:Component:InvalidPropertyValue1'));
        end
        if Pos(3)<1
            Pos(3) = 1;
        end
        if Pos(4)<1
            Pos(4) = 1;
        end
        
        obj.Position = Pos;
        if obj.ConstructedFlag
            obj.setPosition(Pos);
        end
        end
        
        function set.Enable(obj, En)
        En = lower(En);
        if ~strcmp(En, 'on') && ~strcmp(En, 'off') && ~strcmp(En, 'inactive')
            error(message('mbc:mbcgui:widget:Component:InvalidPropertyValue2'));
        end
        
        obj.Enable = En;
        if obj.ConstructedFlag
            obj.setEnable(En);
        end
        end
        
        function set.Visible(obj, Vis)
        Vis = lower(Vis);
        if ~strcmp(Vis, 'on') && ~strcmp(Vis, 'off')
            error(message('mbc:mbcgui:widget:Component:InvalidPropertyValue3'));
        end
        
        obj.Visible = Vis;
        if obj.ConstructedFlag
            obj.setVisible(Vis);
        end
        end
        
        function set.Tag(obj, Tag)
        if isempty(Tag)
            Tag = '';
        end
        if ~ischar(Tag)
            error(message('mbc:mbcgui:widget:Component:InvalidPropertyValue4'));
        end
        obj.Tag = Tag;
        end
        
    end
    
    methods (Access = protected)
        
        
        function ok = isvalidcomponent(obj) 
        %isvalidcomponent component exists 
        %   called from Heterogeneous method 
        %
        %   See also mbcgui.widget.AbstractComponent.iscomponent
        ok = isgraphics(obj.Parent);
        end
        
        function setParent(obj, P) %#ok<INUSD>
        %SETPARENT Notification of new parent
        %   SETPARENT(H, PARENT) is called when the component's Parent property
        %   is changed to PARENT.  The Parent property is automatically set to
        %   contain the new value before this method is called.  Subclasses
        %   should override this method to perform component-specific actions
        %   when the parent is changed.
        %
        %   See also Parent.
        end
        
        function setPosition(obj, Pos) %#ok<INUSD>
        %SETPOSITION Notification of new position setting
        %   SETPOSITION(H, POS) is called when the component's Position
        %   property is changed to POS.  The Position property is automatically
        %   set to contain the new value before this method is called.
        %   Subclasses should override this method to perform
        %   component-specific actions when the position value is changed.
        %
        %   See also Position.
        end
        
        function setEnable(obj, En) %#ok<INUSD>
        %SETENABLE Notification of new enable setting
        %   SETENABLE(H, EN) is called when the component's Enable property
        %   is changed to EN.  The Enable property is automatically set to
        %   contain the new value before this method is called.  Subclasses
        %   should override this method to perform component-specific actions
        %   when the enable value is changed.
        %
        %   See also Enable.
        end
        
        function setVisible(obj, Vis) %#ok<INUSD>
        %SETVISIBLE Notification of new visible setting
        %   SETVISIBLE(H, VIS) is called when the component's Visible property
        %   is changed to VIS.  The Visible property is automatically set to
        %   contain the new value before this method is called.  Subclasses
        %   should override this method to perform component-specific actions
        %   when the visible value is changed.
        %
        %   See also Visible.
        end
    end
    
    
    % Utility methods
    methods
        function ret = isShowing(obj)
        ret = mbcgui.util.isShowing(obj);
        end
    end
    methods(Access=protected)
        function ret = isConstructed(obj)
        ret = obj.ConstructedFlag;
        end
    end
    
    % Printing
    methods
        function ret = canPrint(obj) %#ok<MANU>
        %CANPRINT Check whether component can be printed
        %   CANPRINT(H) returns true if the component supports being printed.
        %   Printable components should overload the printCopy method and
        %   possibly the printSize method.
        %
        %   See also print, printCopy, printSize.
        
        ret = false;
        end
        
        function print(obj, dest)
        %PRINT Prints a component
        %   PRINT(H, DEST) prints out a copy of the component.  DEST specifies
        %   where the copy should be sent and must be one of 'clipboard',
        %   'printer', 'printdialog' or 'printpreview'.  See MBCPRINT for more
        %   details on these options.  If DEST is not specified, 'printer' will
        %   be assumed'.
        %
        %   This method calls the PRINTCOPY and PRINTSIZE methods of the
        %   component.
        %
        %   See also canPrint, printCopy, printSize.
        
        if nargin<2
            dest = 'printer';
        end
        
        hFig = figure('Visible', 'off', ...
            'Renderer', get(ancestor(obj.Parent, 'figure'), 'Renderer'), ...
            'Color','w', ...
            'MenuBar', 'none', ...
            'ToolBar', 'none', ...
            'NumberTitle', 'off', ...
            'Name', 'MBC Printing Figure', ...
            'Tag', 'MBCPrintFig',...
            'IntegerHandle', 'off', ...
            'HandleVisibility', 'off');
        pObj = obj.printCopy(hFig);
        set(pObj, 'Visible', 'on');
        if isa(pObj, 'xregcontainer')
            set(pObj, 'packstatus', 'on');
        end
        mbcprint(pObj, obj.printSize, dest);
        delete(hFig);
        end
        
        function newobj = printCopy(obj, fig) %#ok<INUSL>
        %PRINTCOPY Create a printable version of the component
        %   NEWOBJ = PRINTCOPY(H, 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 this component.
        %
        %   Normally the printable version of a component is not a complete
        %   copy of the object.  There are often controls that should not
        %   appear, such as popup menus, or components whose information needs
        %   to be transformed, such as edit boxes.
        %
        %   See also canPrint, print, printSize.
        
        newobj = uicontrol('Parent', fig, ...
            'Style', 'text', ...
            'HorizontalAlignment', 'center', ...
            'String', sprintf('This component does not\nsupport printing'));
        end
        
        function sz = printSize(obj)
        %PRINTSIZE Returns the preferred printing size for the component
        %   SZ = PRINTSIZE(H) returns a two element vector containing the
        %   preferred width and height for printing the component.
        %
        %   This default implementation returns the current width and height of
        %   the component and this is likely to be adequate for many
        %   subclasses. However, some classes may want to modify this, for
        %   example scrolling components that want to print their entire
        %   visible area.
        %
        %   See also canPrint, print, printCopy.
        
        sz = obj.Position(3:4);
        end
    end
    
    % Listener utilities
    methods(Access=protected)
        function addListeners(obj, List)
        %addListeners Add listeners for storage.
        %   addListeners(H, LIST) adds listeners to be stored by the object.
        %   LIST may be either a scalar listener handle, a vector of listeners
        %   or a cell array.
        %
        %   See also storeListeners, enableListeners, disableListeners.
        
        storeListeners(obj, List)
        end
        function storeListeners(obj, List)
        %STORELISTENERS Add listeners for storage.
        %   STORELISTENERS(H, LIST) adds listeners to be stored by the object.
        %   LIST may be either a scalar listener handle, a vector of listeners
        %   or a cell array.
        %
        %   See also enableListeners, disableListeners.
        
        % Convert non-cell input to a cell for storage
        if ~iscell(List)
            ListVect = List;
            NumNew = numel(List);
            List = cell(NumNew, 1);
            for n = 1:NumNew
                List{n} = ListVect(n);
            end
        end
        
        obj.ComponentListeners = [obj.ComponentListeners; List(:)];
        end
        
        function enableListeners(obj)
        %ENABLELISTENERS Enable stored listeners.
        %   ENABLELISTENERS(H) enables all listeners that have been added to
        %   this object using the storeListeners method.
        %
        %   See also storeListeners, disableListeners.
        
        L = obj.ComponentListeners;
        for n=1:numel(L)
            if isa(L{n},'handle.listener')
                L{n}.Enabled = 'on';
            else
                L{n}.Enabled = true;
            end
        end
        
        end
        
        function disableListeners(obj)
        %DISABLELISTENERS Disable stored listeners.
        %   DISABLELISTENERS(H) disables all listeners that have been added to
        %   this object using the storeListeners method.
        %
        %   See also storeListeners, enableListeners.
        
        L = obj.ComponentListeners;
        for n=1:numel(L)
            if isa(L{n},'handle.listener')
                L{n}.Enabled = 'off';
            else
                L{n}.Enabled = false;
            end
        end
        
        end
        
        function L = addPropertyListeners(obj, Prop, Callback, Event)
        %ADDPROPERTYLISTENERS Create and add listeners to object properties
        %  L = ADDPROPERTYLISTENERS(OBJ, PROP, CALLBACK, EVENT) creates a new
        %  listener, L, that is attached to the EVENT event of property PROP
        %  and that fires CALLBACK. L = ADDPROPERTYLISTENERS(OBJ, PROPS,
        %  CALLBACKS, EVENT) where PROPS and CALLBACKS are cell arrays of
        %  properties and corresponding callbacks will create a vector of
        %  listeners. The EVENT argument defaults to 'PropertyPostSet' if not
        %  supplied.
        
        if nargin < 4
            Event = 'PostSet';
        end
        
        if ischar(Prop)
            % Single listener being created.
            if iscell(Callback)
                Callback = mbcutils.callback(Callback{:});
            end
            L = {event.proplistener(obj, obj.findprop(Prop), Event, Callback)};
        else
            % Lots of listeners being created.
            nL = numel(Prop);
            L = cell(nL,1);
            for n = 1:nL
                if iscell(Callback{n})
                    Callback{n} = mbcutils.callback(Callback{n}{:});
                end

                L{n} =  event.proplistener(obj, obj.findprop(Prop{n}), Event, Callback{n});
            end
        end
        
        obj.ComponentListeners = [obj.ComponentListeners; L];
        end
        
    end
    
    % Dependent property utilities
    methods(Access=protected)
        function forwardProperty(obj, hComp, PropName, PropValue)
        %FORWARDPROPERTY Forward a property value to a contained object
        %   FORWARDPROPERTY(OBJ, H, PROPNAME, PROPVALUE) sets the sepecified
        %   property on the component H.  If H is empty, as is typical for
        %   contained components during construction, the property value is
        %   saved in a temporary store and can be retrieved when H is
        %   constructed using GETDEPPROPPAIRS.
        %
        %   This method is design to be called in the property set function for
        %   dependent properties that directly map to the property of a
        %   contained object.  All properties that use this function should
        %   also be listed in a GETDEPPROPPAIRS in the constructor to retrieve
        %   and clear temporary stored values.
        %
        %   See also RETRIEVEPROPERTY, GETDEPPROPPAIRS.
        
        if isempty(hComp)
            % Store the property
            if isempty(obj.ConstructPropMap)
                obj.ConstructPropMap = containers.Map;
            end
            obj.ConstructPropMap(PropName) = PropValue;
        else
            set(hComp, PropName, PropValue);
        end
        end
        
        function PropValue = retrieveProperty(obj, hComp, PropName, DefaultValue)
        %RETRIEVEPROPERTY Retrieve a property value from a contained object
        %   RETRIEVEPROPERTY(OBJ, H, PROPNAME) gets the specified property from
        %   the component H.  If H is empty, as is typical for contained
        %   components during construction, the property value is looked for in
        %   the temporary store,  If a value is not found here then an empty
        %   matrix is returned.
        %
        %   RETRIEVEPROPERTY(OBJ, H, PROPNAME, DEFAULT) specifies a default
        %   value to return if a property value cannot be found elsewhere.
        %
        %   This method is design to be called in the property get function for
        %   dependent properties that directly map to the property of a
        %   contained object.
        %
        %   See also FORWARDPROPERTY, GETDEPPROPPAIRS.
        
        if isempty(hComp)
            % Retrieve from the temporary store if possible
            if isempty(obj.ConstructPropMap) || ~isKey(obj.ConstructPropMap, PropName)
                if nargin>3
                    PropValue = DefaultValue;
                else
                    PropValue = [];
                end
            else
                PropValue = obj.ConstructPropMap(PropName);
            end
        else
            PropValue = get(hComp, PropName);
        end
        end
        
        function PVPairs = getDepPropPairs(obj, PropNames)
        %GETDEPPROPPAIRS Get a list of property-value pairs for construction
        %   GETDEPPROPPAIRS(OBJ, PROPNAMES) checks the temporary store for the
        %   specified property names.  Any that are found are assembled in a
        %   cell array of property-value pairs that is returned.  The property
        %   values are removed from the temporary store.
        %
        %   This method is design to be called in subclass constructors to
        %   retrieve contained object property values that have been set at
        %   construction and saved by the FORWARDPROPERTY method.
        %
        %   See also FORWARDPROPERTY, RETRIEVEPROPERTY.
        PropMap = obj.ConstructPropMap;
        
        if isempty(PropMap) || isempty(PropNames)
            PVPairs = {};
            return
        end
        if ischar(PropNames)
            PropNames = {PropNames};
        end
        
        % Find known properties and retrieve their values
        KnownProps = intersect(PropNames, PropMap.keys);
        PVPairs = cell(2, numel(KnownProps));
        for n=1:numel(KnownProps)
            PVPairs{1,n} = KnownProps{n};
            PVPairs{2,n} = PropMap(KnownProps{n});
        end
        PVPairs = PVPairs(:)';
        
        PropMap.remove(KnownProps);
        
        if PropMap.Count==0;
            % Destroyed the map object since it is no longer needed
            obj.ConstructPropMap = [];
        end
        
        end
        
    end
    
    
    % Methods that manage a private store of Components in a parent
    methods(Access=protected)
        %TODO: These should be private, a bug in MCOS means that they can't be: g582234
        function S = makeComponentStore(obj, hParent) %#ok<INUSL>
        if ~isprop(hParent, 'mbcguiComponentStore')
            mbcgui.hgclassesutil.addprop(hParent, 'mbcguiComponentStore', 'Hidden', true);
            S.Handles = mbcgui.widget.Component.empty;
            S.DeletionListener = mbcgui.hgclassesutil.listener( ...
                hParent, 'ObjectBeingDestroyed', @iDeleteObjects);
            set(hParent, 'mbcguiComponentStore', S);
        else
            S = get(hParent, 'mbcguiComponentStore');
        end
        end
        
        
        function addToComponentStore(obj, hParent)
        if isgraphics(hParent)
            S = makeComponentStore(obj, hParent);
            S.Handles(end+1) = obj;
            set(hParent, 'mbcguiComponentStore', S);
        end
        end
        
        
        function removeFromComponentStore(obj, hParent)
        if isgraphics(hParent)
            S = get(hParent, 'mbcguiComponentStore');
            S.Handles(S.Handles==obj)=[];
            set(hParent, 'mbcguiComponentStore', S);
        end
        end
    end
    
end

function iDeleteObjects(src, evt) %#ok<INUSD>
% Delete all objects in the store of this parent
if isgraphics(src) && ~strcmp(src.BeingDeleted,'on')
    S = get(src, 'mbcguiComponentStore');
    for n=1:numel(S.Handles)
        h = S.Handles(n);
        if isvalid(h)
            delete(h);
        end
    end
end
end