www.gusucode.com > mbcview 工具箱matlab源码程序 > mbcview/+cageview/+optimoutput/MessageService.m

    classdef MessageService < mbcmodelview.MessageService
    %cageview.optimoutput.MessageService class
    %   cageview.optimoutput.MessageService extends mbcgui.multiview.AbstractMessageService.
    %
    %    cageview.optimoutput.MessageService properties:
    %       CurrentRun - Property is of type 'MATLAB array' (read only)
    %       CurrentSolution - Property is of type 'MATLAB array' (read only)
    %       FocusPoint - Property is of type 'MATLAB array' (read only)
    %       CurrentSliceDirection - Property is of type 'string' (read only)
    %
    %    cageview.optimoutput.MessageService methods:
    %       getDataName - Get a name for the data being displayed
    %       getFocusPoint - Get the currently focussed point.
    %       getFocusRun - Get the currently focussed run.
    %       getFocusSolution - Get the currently focussed solution.
    %       getOptimOutput - Get the optimisation output object
    %       hasData - Check whether the MessageService contains viewable data
    %       hasFocusIndex - Check whether there is a focussed set of free values.
    %       reset - Reset the message service to default values.
    %       sendEvent - Send the appropriate events for a change's root cause
    %       setCurrentIndex - Set the currently viewed run, solution and focus point
    %       setCurrentRun - Set the currently viewed run.
    %       setCurrentSlice - Set the current slice direction.
    %       setCurrentSolution - Set the currently viewed solution.
    %       setFocusPoint - Set the currently focussed point.
    %       setOptimOutput - Set a new optimization object
    
    %  Copyright 2005-2016 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (Access=protected, AbortSet)
        %DESTRUCTIONLISTENER Property is of type 'handle'
        DestructionListener = [];
    end
    
    properties (SetAccess=protected, AbortSet)
        %CURRENTRUN Property is of type 'MATLAB array' (read only)
        CurrentRun = 1;
        %CURRENTSOLUTION Property is of type 'MATLAB array' (read only)
        CurrentSolution = 1;
        %FOCUSPOINT Property is of type 'MATLAB array' (read only)
        FocusPoint = 1;
        %CURRENTSLICEDIRECTION Property is of type 'string' (read only)
        CurrentSliceDirection = 'solution';
        %OPTIMOUTPUTPOINTER Property is of type 'MATLAB array'
        OptimOutputPointer = [];        
    end
    
    properties(Dependent,SetAccess=private)
        %Title
        Title
    end
    
    properties (Dependent,SetAccess=private)
        %ProjectPointer pointer to CAGE project
        ProjectPointer
    end    
    
    events (NotifyAccess=private)
        ObjectChanged
        CurrentIndexChanged
        RunIndexChanged
        SolutionIndexChanged
        FocusPointChanged
        CurrentFocusChanged
        RunFocusChanged
        SolutionFocusChanged
        FocusOrFocusPointChanged
        SliceDirectionChanged
        ObjectPropertyChanged
        SelectedSolutionChanged
        WeightsChanged
        FeasibleToleranceChanged
        AcceptableChanged
        PreserveChanged
    end  % events
    
    methods  % constructor block
        
        function obj = MessageService(OptimOutput)
        %MessageService Create an instance of an MessageService object
        %  H = MessageService(OPTIMOUT) constructs a new
        %  MessageService object.
        
        % h = cageview.optimoutput.MessageService;
        obj.OptimOutputPointer = xregpointer([]);
        if nargin
            obj.OptimOutputPointer.info = OptimOutput;
            % Attach a listener to free the pointer when this object is destroyed
            obj.DestructionListener = event.listener(obj, 'ObjectBeingDestroyed', @(h,evt) iFree(h,evt,h.OptimOutputPointer));
        end
        
        % create actions for output node
        obj.Actions = cageview.optimoutput.Actions(obj);
        
        end  % MessageService
        
    end  % constructor block
    
    methods  % public methods
        
        function s = get.Title(obj)
        if obj.hasData
            s = name(obj.Node);
        else
            s = '';
        end        
        end        
        
        function p = get.ProjectPointer(obj)
        %ProjectPointer pointer to CAGE project
        if ~isnull(obj.Pointer)
            p = obj.Pointer.root;
        else
            p = xregpointer;
        end
        
        end        
        
        function OK = leaveNode(obj)
        %leaveNode get ready to leave node
        
        OK = leaveNode@mbcmodelview.MessageService(obj);
        if OK
            obj.OptimOutputPointer = xregpointer;
        end
        end
        function initialize(obj,pNode)
        %initialize initialize MessageService with new cgoptimoutnode
        
        obj.Pointer = pNode;
        obj.OptimOutputPointer = getdata(info(obj.Pointer));
        reset(obj,info(obj.OptimOutputPointer));

        end
        
        %----------------------------------------
        function nm = getDataName(obj)
        %GETDATANAME Get a name for the data being displayed
        %  NM = GETDATANAME(OBJ) returns a string that is the name of the data
        %  that is being encapsulated by the message service.  By default this
        %  returns the string '<Unknown>'.
        
        if obj.hasData
            nm = getname(obj.getOptimOutput);
        else
            nm = '<Unknown>';
        end
        
        end  % getDataName
        
        %----------------------------------------
        function FocusPointIdx = getFocusPoint(obj)
        %GETFOCUSPOINT Get the currently focussed point.
        %   FOCUSPOINTIDX = GETFOCUSPOINT(OBJ) returns the current focus point.
        
        FocusPointIdx = obj.FocusPoint;
        
        end  % getFocusPoint
        
        %----------------------------------------
        function Idx = getFocusRun(obj)
        %GETFOCUSRUN Get the currently focussed run.
        %   IDX = GETFOCUSRUN(OBJ) returns a scalar index indicating which run is
        %   currently focussed.  If there is currently no selection of runs then
        %   the index will be zero.
        
        % Focus is defined as the last selection index
        if ~isempty(obj.CurrentRun) && ~strcmpi(obj.CurrentSliceDirection, 'weightedsolution')
            if strcmpi(obj.CurrentSliceDirection, 'selectedsolution')
                % Check that selected solution is initialised
                out = getOptimOutput(obj);
                if hasSelectedSolution(out)
                    % The focus is valid
                    Idx = obj.CurrentRun(end);
                else
                    Idx = 0;
                end
            else
                Idx = obj.CurrentRun(end);
            end
            
        else
            Idx = 0;
        end
        
        end  % getFocusRun
        
        %----------------------------------------
        function Idx = getFocusSolution(obj)
        %GETFOCUSSOLUTION Get the currently focussed solution.
        %   IDX = GETFOCUSSOLUTION(OBJ) returns a scalar index indicating which
        %   solution is currently focussed.  If there is currently no selection of
        %   solutions then the index will be zero.
        
        % Focus is defined as the last selection index
        if ~isempty(obj.CurrentSolution)
            if strcmpi(obj.CurrentSliceDirection, 'selectedsolution')
                % Check that selected solution is initialised
                out = getOptimOutput(obj);
                if hasSelectedSolution(out)
                    % The focus is valid
                    Idx = obj.CurrentSolution(end);
                else
                    Idx = 0;
                end
            else
                Idx = obj.CurrentSolution(end);
            end
        else
            Idx = 0;
        end
        
        end  % getFocusSolution
        
        %----------------------------------------
        function OptimOut = getOptimOutput(obj)
        %GETOPTIMOUTPUT Get the optimisation output object
        %  OPTIM = GETOPTIMOUTPUT(OBJ) returns the optimization output object that
        %  is currently being viewed.
        
        OptimOut = obj.OptimOutputPointer.info;
        
        end  % getOptimOutput
        
        %----------------------------------------
        function ret = hasData(obj)
        %HASDATA Check whether the MessageService contains viewable data
        %  RET = HASDATA(OBJ) returns true if the MessageService object contains
        %  a data object that can provide any viewing data.
        
        if ~isnull(obj.Pointer)
            ret = ~isempty(obj.getOptimOutput);
        else
            ret = false;
        end
        
        end  % hasData
        
        %----------------------------------------
        function val = hasFocusIndex(obj)
        %HASFOCUSINDEX Check whether there is a focussed set of free values.
        %   VAL = HASFOCUSINDEX(OBJ) returns true if there is a set of focussed
        %   free values, i.e. there is a both a valid focus run and a valid focus
        %   solution.
        
        val = obj.hasData ...
            && ~isempty(obj.CurrentRun) ...
            && ~isempty(obj.CurrentSolution) ...
            && ~isempty(obj.FocusPoint) ...
            && ~strcmpi(obj.CurrentSliceDirection, 'weightedsolution');
        
        if val && strcmpi(obj.CurrentSliceDirection, 'selectedsolution')
            out = getOptimOutput(obj);
            val = val && hasSelectedSolution(out);
        end
        
        end  % hasFocusIndex
        
        %----------------------------------------
        function ev = pSelectedSolutionCheck(obj)
        %PSELECTEDSOLUTIONCHECK Update solution selection.
        %   EV = PSELECTEDSOLUTIONCHECK(OBJ) sets the current solution to be the
        %   selection solution for the focussed runs.  A cell array of events that
        %   need to be sent is returned.
        
        ev = {};
        if strcmpi(obj.CurrentSliceDirection, 'selectedsolution') ...
                && obj.hasData ...
                && hasSelectedSolution(obj.getOptimOutput)
            % The solution index is locked to a particular value for each run
            OldFocus = obj.getFocusSolution;
            obj.CurrentSolution = getSelectedSolutionNumber(obj.getOptimOutput, obj.getFocusRun);
            ev = [ev {'SolutionIndexChanged'}];
            if obj.getFocusSolution~=OldFocus
                ev = [ev, {'SolutionFocusChanged'}];
            end
        end
        
        end  % pSelectedSolutionCheck
        
        %----------------------------------------
        function reset(obj, OptimOut)
        %RESET Reset the message service to default values.
        %   RESET(OBJ, OPTIMOUT) resets the message service indices to their
        %   default values and sets the specified output object.
        
        obj.CurrentRun = 1;
        obj.CurrentSolution = 1;
        obj.FocusPoint = 1;
        obj.setOptimOutput(OptimOut, 'ObjectChanged');
        
        if ~isempty(OptimOut)
            % Check whether slice setting is appropriate
            nSol = getNumSolutions(OptimOut);
            nRuns = getNumSolutions(OptimOut);
            if nSol>1 && strcmpi(obj.CurrentSliceDirection, 'solution')
                % Switch to pareto automatically
                obj.setCurrentSlice('pareto');
            elseif nSol==1 && any(strcmpi(obj.CurrentSliceDirection, {'pareto','selectedsolution'}))
                % Switch to solution automatically
                obj.setCurrentSlice('solution');
            elseif nRuns>1 && strcmpi(obj.CurrentSliceDirection, 'weightedsolution')
                % only 1 run so switch from weightedsolution to solution slice
                obj.setCurrentSlice('solution');
            end
            
        end
        
        end  % reset
        
        %----------------------------------------
        function sendEvent(obj, Event)
        %SENDEVENT Send the appropriate events for a change's root cause
        %  SENDEVENT(OBJ, EVENT) sends the event specified by EVENT.  Valid
        %  settings for EVENT are:
        %
        %    'ObjectChanged'         : Send when the object changes.
        %    'CurrentIndexChanged'   : Sent when either the current run or solution
        %                              is changed.
        %    'SolutionIndexChanged'  : Sent when the current solution is changed.
        %    'RunIndexChanged'       : Sent when the current run is changed.
        %    'CurrentFocusChanged'   : Sent when either the current run or solution
        %                              focus is changed.
        %    'SolutionFocusChanged'  : Sent when the current solution focus is changed.
        %    'RunFocusChanged'       : Sent when the current run focus is changed.
        %    'FocusPointChanged'     : Sent when the focus point is changed.
        %    'FocusOrFocusPointChanged': Sent when either the current focus or
        %                                focus point is changed.
        %    'SliceDirectionChanged' : Sent when the preferred slice direction is
        %                              changed.
        %    'SelectedSolutionChanged': Sent when the set of selected solution is
        %                              changed.
        %    'WeightsChanged'        : Sent when the weights for the weighted view
        %                              are changed.
        %    'FeasibleToleranceChanged': Sent when the tolerance that is used for
        %                              deciding feasibility is changed.
        %    'AcceptableChanged'     : Sent when the set of acceptable flags is
        %                              changed.
        %    'ObjectPropertyChanged' : Sent when any property of the object is
        %                              altered.
        %    'PreserveChanged'       : Sent when the node's 'Preserved' flag is
        %                              changed.
        if ~iscell(Event)
            ev = {Event};
        else
            ev = Event;
        end
        
        % Check whether the ObjectChanged event should be added
        ObjectPropEvents = { ...
            'SelectedSolutionChanged', ...
            'WeightsChanged', ...
            'FeasibleToleranceChanged', ...
            'AcceptableChanged'};
        if ~isempty(intersect(ObjectPropEvents, ev)) ...
                && ~ismember('ObjectPropertyChanged', ev)
            ev = [ev, {'ObjectPropertyChanged'}];
        end
        
        
        for n = 1:length(ev)
            obj.notify(ev{n});
        end
        
        end  % sendEvent
        
        %----------------------------------------
        function setCurrentIndex(obj, RunIdx, SolIdx, FocusPoint)
        %SETCURRENTINDEX Set the currently viewed run, solution and focus point
        %   SETCURRENTINDEX(OBJ, RUNIDX, SOLIDX, FOCUSPOINT) sets the current run,
        %   current solution and focus point. This method fires the following
        %   events
        %
        %   Quantity changed                      Event
        %   -------------------------------+--------------------------
        %   Run index                      :  "RunIndexChanged"
        %   Solution index                 :  "SolutionIndexChanged"
        %   Run or solution index          :  "CurrentIndexChanged"
        %   Focus run                      :  "FocusRunChanged"
        %   Focus solution                 :  "FocusSolutionChanged"
        %   Focus point                    :  "FocusPointChanged"
        %   Focus run, solution            :  "CurrentFocusChanged"
        %   Focus run, solution, point     :  "FocusOrFocusPointChanged"
        
        OldRunFocus = obj.getFocusRun;
        OldSolFocus = obj.getFocusSolution;
        OldRun = obj.CurrentRun;
        OldSol = obj.CurrentSolution;
        OldFocusPoint = obj.FocusPoint;
        
        % Set new indices
        obj.CurrentRun = RunIdx;
        if ~strcmp(obj.CurrentSliceDirection, 'selectedsolution')
            obj.CurrentSolution = SolIdx;
        else
            obj.CurrentSolution = getSelectedSolutionNumber(obj.getOptimOutput, RunIdx);
        end
        obj.FocusPoint = FocusPoint;
        
        % Set up any index changed events
        ev = {};
        RunIC = ~isequal(obj.CurrentRun, OldRun);
        SolIC = ~isequal(obj.CurrentSolution, OldSol);
        if RunIC || SolIC
            ev = [ev, {'CurrentIndexChanged'}];
        end
        if RunIC
            ev = [ev, {'RunIndexChanged'}];
        end
        if SolIC
            ev = [ev, {'SolutionIndexChanged'}];
        end
        
        % Set up any focus changed events
        RunFC = obj.getFocusRun~=OldRunFocus;
        SolFC = obj.getFocusSolution~=OldSolFocus;
        if RunFC
            ev = [ev, {'RunFocusChanged'}];
        end
        if SolFC
            ev = [ev, {'SolutionFocusChanged'}];
        end
        if RunFC || SolFC
            ev = [ev, {'CurrentFocusChanged'}];
        end
        
        % Set up any focus point changed events
        PointFC = obj.FocusPoint~=OldFocusPoint;
        if PointFC
            ev = [ev, {'FocusPointChanged'}];
        end
        
        % Set up an event to capture either the focus or focus point changing
        if RunFC || SolFC || PointFC
            ev = [ev, {'FocusOrFocusPointChanged'}];
        end
        
        % Send the events
        obj.sendEvent(ev);
        
        end  % setCurrentIndex
        
        %----------------------------------------
        function setCurrentRun(obj, RunIdx)
        %SETCURRENTRUN Set the currently viewed run.
        %   SETCURRENTRUN(OBJ, RUNIDX) sets the current run index to RUNIDX and
        %   fires the "CurrentIndexChanged" and "RunIndexChanged" events.  If the
        %   current slice is set to 'selectedsolution', the solution is also set to
        %   the appropriate value.
        
        % There is no concept of a run to select when looking at weighted solution
        if ~strcmp(obj.CurrentSliceDirection, 'weightedsolution')
            OldFocus = obj.getFocusRun;
            OldRun = obj.CurrentRun;
            obj.CurrentRun = RunIdx;
            ev = {};
            if ~isequal(obj.CurrentRun, OldRun)
                ev = {'CurrentIndexChanged', 'RunIndexChanged'};
            end
            if obj.getFocusRun~=OldFocus
                ev = [ev, {'CurrentFocusChanged', 'RunFocusChanged', ...
                    'FocusOrFocusPointChanged'}];
            end
            
            % Check whether solution chould change too
            ev = [ev, obj.pSelectedSolutionCheck];
            
            obj.sendEvent(ev);
        end
        
        end  % setCurrentRun
        
        %----------------------------------------
        function setCurrentSlice(obj, Value)
        %SETCURRENTSLICE Set the current slice direction.
        %   SETCURRENTSLICE(OBJ, SLICEDIR) sets the current slice direction.
        %   SLICEDIR must be one of 'solution' or 'pareto'.
        
        obj.CurrentSliceDirection = Value;
        ev ={'SliceDirectionChanged'};
        ev = [ev, obj.pSelectedSolutionCheck];
        obj.sendEvent(ev);
        
        end  % setCurrentSlice
        
        %----------------------------------------
        function setCurrentSolution(obj, SolIdx)
        %SETCURRENTSOLUTION Set the currently viewed solution.
        %   SETCURRENTSOLUTION(OBJ, SOLIDX) sets the current solution index to
        %   SOLIDX and fires the "CurrentIndexChanged" and "SolutionIndexChanged"
        %   events.
        
        if ~strcmp(obj.CurrentSliceDirection, 'selectedsolution')
            OldFocus = obj.getFocusSolution;
            OldSolution = obj.CurrentSolution;
            obj.CurrentSolution = SolIdx;
            ev = {};
            if ~isequal(obj.CurrentSolution, OldSolution)
                ev = {'CurrentIndexChanged', 'SolutionIndexChanged'};
            end
            if obj.getFocusSolution~=OldFocus
                ev = [ev, {'CurrentFocusChanged', 'SolutionFocusChanged', ...
                    'FocusOrFocusPointChanged'}];
            end
            obj.sendEvent(ev);
        end
        
        end  % setCurrentSolution
        
        %----------------------------------------
        function setFocusPoint(obj, FocusPointIdx)
        %SETFOCUSPOINT Set the currently focussed point.
        %   SETFOCUSPOINT(OBJ, FOCUSPOINTIDX) sets the current focus point index to
        %   FOCUSPOINTIDX and fires the "FocusOrFocusPointChanged" and
        %   "FocusPointChanged" events.
        
        % Only set the focus point if it is in the range [1, Nmax], where Nmax is
        % the maximum length of all the optimization quantities
        out = obj.getOptimOutput;
        data = getSolution(out, 1, 'OutputFormat', 'cell', ...
            'OutputContents', {'FixedVars', 'FreeVars', 'Objectives', 'Constraints'});
        Nmax = max(cellfun('length', data));
        if FocusPointIdx >= 1 && FocusPointIdx <= Nmax
            OldFocus = obj.FocusPoint;
            obj.FocusPoint = FocusPointIdx;
            % Only fire event if the focus point has actually changed
            if obj.FocusPoint~=OldFocus
                ev = {'FocusPointChanged', 'FocusOrFocusPointChanged'};
                obj.sendEvent(ev);
            end
        end
        
        end  % setFocusPoint
        
        %----------------------------------------
        function setOptimOutput(obj, OptimOut, Event)
        %SETOPTIMOUTPUT Set a new optimization object
        %  SETOPTIMOUTPUT(OBJ, OPTIM, EVENT) sets an updated optimization output
        %  object to be viewed.  The optional argument EVENT specifies which set of
        %  events should be sent to notify views of the changes.  See the SENDEVENT
        %  method for the valid EVENT settings.
        %
        %  Additional events may be added to the list automatically if the new
        %  object causes run or solution selection or slice direction changes in
        %  the message service.
        
        OldHasAFocus = obj.hasFocusIndex;
        
        obj.OptimOutputPointer.info = OptimOut;
        
        ev = {};
        
        
        % Check whether selected solution should change
        evSol = obj.pSelectedSolutionCheck;
        
        % Add appropriate additional focus events
        HasAFocus = obj.hasFocusIndex;
        if OldHasAFocus~=HasAFocus
            %The focus run and solution have both altered from 0 to a valid value
            ev = [ev, {'CurrentFocusChanged', 'FocusOrFocusPointChanged'}];
        else
            % Just add in the selection solution event if there is one.
            ev = [ev, evSol];
        end
        
        if nargin>2
            obj.sendEvent(Event);
        end
        if ~isempty(ev)
            obj.sendEvent(ev);
        end
        
        end  % setOptimOutput
        
    end  % public methods
    
end  % classdef

function iFree(~, ~, p)
freeptr(p);
end  % iFree