www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/+xregbdrygui/BdrySlice1.m

    classdef BdrySlice1 < xregbdrygui.AbstractBdryView
    %xregbdrygui.BdrySlice1 class
    %   xregbdrygui.BdrySlice1 extends xregbdrygui.AbstractBdryView.
    %
    %    xregbdrygui.BdrySlice1 properties:
    %       Parent - Property is of type 'MATLAB array'
    %       Position - Property is of type 'rect'
    %       Enable - Property is of type 'on/off'
    %       Visible - Property is of type 'on/off'
    %       Userdata - Property is of type 'MATLAB array'
    %       Tag - Property is of type 'string'
    %       Display - Property is of type 'MATLAB array' (read only)
    %       MessageService - Property is of type 'handle'
    %       Options - Property is of type 'handle vector'
    %       Actions - Property is of type 'handle vector'
    %       UIContextMenu - Property is of type 'MATLAB array'
    %       InputFactors - Property is of type 'MATLAB array' (read only)
    %       hData - Property is of type 'handle' (read only)
    %       hGraphTable - Property is of type 'handle' (read only)
    %       hSlicePointTable - Property is of type 'handle' (read only)
    %       hEvaluationTable - Property is of type 'handle' (read only)
    %       hSelectButton - Property is of type 'MATLAB array' (read only)
    %
    %    xregbdrygui.BdrySlice1 methods:
    %       createDefaultWindowContainer - Create an appropriate container for the view
    %       gettitle - Return a suitable title for a window
    %       setSlicePoint - Set the point where the current slice is at.
    
    % Copyright 2005-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.

    properties (SetAccess=protected, AbortSet)
        %INPUTFACTORS Property is of type 'MATLAB array' (read only)
        InputFactors = [];
        %HDATA Property is of type 'handle' (read only)
        hData = [];
        %HGRAPHTABLE Property is of type 'handle' (read only)
        hGraphTable = [];
        %HSLICEPOINTTABLE Property is of type 'handle' (read only)
        hSlicePointTable = [];
        %HEVALUATIONTABLE Property is of type 'handle' (read only)
        hEvaluationTable = [];
        %HSELECTBUTTON Property is of type 'MATLAB array' (read only)
        hSelectButton = [];
    end
    
    
    methods  % constructor block
        function obj = BdrySlice1( varargin )
        % XREGBDRYGUI.BDRYSLICE1 class constructor
        %   Note that this class is NOT based on BdryAbstractSlice.
        
        % Call the inherited constructor
        obj@xregbdrygui.AbstractBdryView(varargin{ : }); % converted super class constructor call
        
        
        % -------------------------------------------------------------------------
        % MAIN GRAPH TABLE
        % -------------------------------------------------------------------------
        
        % Instantiate a new a data object for the pairwise projections
        obj.hData = xregbdrygui.BdrySlice1Data;
        obj.hData.MessageService = obj.MessageService;
        
        % Test to display when we can't display the plots
        nodisp = axestext( obj.Parent, ...
            'visible', 'off', ...
            'string', 'Unable to display 1D Slice View', ...
            'horizontalalignment', 'center', ...
            'verticalalignment', 'middle' );
        
        % The main table that drives the view
        lytAxesPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'Visible', obj.Visible, ...
            'BorderType', 'beveledin');
        obj.hGraphTable = mbcgui.widget.ClassicTable( ...
            'Parent',   lytAxesPanel, ...
            'ShowRowHeaders',    false, ...
            'ShowColumnHeaders', false,...
            'UseVectorDrawMethod', false,...
            'MainConstructor', @n_CreateMainObject,...
            'MainData', obj.hData, ...
            'RowGap', 0, 'ColumnGap', 0,...
            'MaximumObjectCacheSize',15);
        obj.hGraphTable.EmptyTableComponent = nodisp;
        set(lytAxesPanel, 'LayoutComponent', obj.hGraphTable);
        
            function h = n_CreateMainObject( P )
            h = xregbdrygui.BdrySlice1Graph( 'Parent', P, 'Visible', 'off' );
            h.addListener( event.listener( h, 'BlackDotClicked', ...
                @(s, evt) obj.pBlackDotClicked( evt ) ) );
            end
        
        % Setup some actions so that the user can change the graph size
        obj.Options.Actions = [
            mbcgui.actions.ToggleAction( @(s, e)n_SetGraphSize( 1,   0 ), '&Display All Graphs' )
            mbcgui.actions.ToggleAction( @(s, e)n_SetGraphSize( 2,  50 ), '&Small' )
            mbcgui.actions.ToggleAction( @(s, e)n_SetGraphSize( 3, 100 ), '&Medium' )
            mbcgui.actions.ToggleAction( @(s, e)n_SetGraphSize( 4, 150 ), '&Large' )
            ];
            function n_SetGraphSize( index, size )
            obj.hGraphTable.MinimumCellSize = [0, size];
            set( obj.Options.Actions, 'Selected', false );
            obj.Options.Actions(index).Selected = true;
            end
        % Set the default graphs size to medium
        n_SetGraphSize( 3, 150 );
        
        % -------------------------------------------------------------------------
        % SLICE SELECTION & CONTROL
        % -------------------------------------------------------------------------
        
        % Evaluation table
        % -- This table is what the user uses to control the evalution points for
        %    each of the factors.
        
        % Panel for the evaluation table
        evaluationPanel = mbcgui.container.titlebarpanel(...
            'Parent', obj.Parent, ...
            'Visible', obj.Visible, ...
            'BarTitle', 'Evaluation Points');
        obj.hEvaluationTable = mbcwidgets.VariableEditorTable( ...
            'Parent', evaluationPanel, ...
            'Visible', obj.Visible, ...
            'ValueColumnCount', 1, ...
            'ValueColumnHeader', {'Points'}, ...
            'ValueChangedCallback', @i_EvaluationTableEdited, ...
            'ValueConstraint', 'plot' );
        obj.hEvaluationTable.Peer.installBorderType('none');
        set(evaluationPanel, 'ContentHandle', obj.hEvaluationTable);
        
        
            function i_EvaluationTableEdited(~, ~)
            % We could probably work out some intelligent re-draw based on the
            % row selected by the user (evt.data.Row)
            obj.pUpdateDataEvaluationPoints;
            obj.pDrawConstraint;
            end
        
        
        % Slice control table
        % -- This table is what the user uses to control the location of and the
        %    tolerance on the slice.
        slicePointPanel = mbcgui.container.titlebarpanel(...
            'Parent', obj.Parent, ...
            'Visible', obj.Visible, ...
            'BarTitle', 'Slice Location');
        obj.hSlicePointTable = mbcwidgets.VariableEditorTable( ...
            'Parent', slicePointPanel, ...
            'ValueColumnCount', 2, ...
            'ValueColumnHeader', {'Value', 'Tolerance'}, ...
            'ValueChangedCallback', @i_SlicePointTableEdited, ...
            'ValueConstraint', 'plot' );
        obj.hSlicePointTable.Peer.installBorderType('none');
        
            function i_SlicePointTableEdited(~, evt)
            % If the user edits the first column (value) then a complete
            % re-draw is required. However, if they only edit a tolerance then
            % we only need to redisplay the points.
            if evt.data.Columns == 2,
                % The user is editing column one, the evaluation points
                obj.pUpdateDataSlicePoint;
                obj.pDrawConstraint;
            else
                % The user is editing column two, the tolerances
                obj.pUpdateDataSliceTolerance;
                obj.pDrawPoints;
            end
            end
        
        % Select Data Point Button
        % -- The button that allows the user to select and view any data point
        SelectPanel = mbcgui.container.layoutpanel(...
            'Parent', slicePointPanel, ...
            'BorderType', 'beveledout');
        obj.hSelectButton = uicontrol(...
            'Parent', SelectPanel, ...
            'Style','pushbutton',...
            'String','Select Data Point...',...
            'Interruptible','off',...
            'Callback', @i_SelectTest );
            function i_SelectTest( ~, ~ )
            point = obj.MessageService.guiSelectPoint;
            if ~isempty( point ),
                obj.setSlicePoint( point );
            end
            end
        
        % -------------------------------------------------------------------------
        % LAYOUT
        % -------------------------------------------------------------------------
        
        btnGrid = xreggridbaglayout(SelectPanel, ...
            'packgroup', 'XREG_PERM_ON', ...
            'packstatus', 'off', ...
            'dimension', [1 2], ...
            'border', [2 2 2 2], ...
            'colsizes', [-1 105], ...
            'elements', {[], obj.hSelectButton});
        set(SelectPanel, 'LayoutComponent', {btnGrid});
        
        lytSlicePointPanel = xreggridbaglayout( slicePointPanel, ...
            'packgroup', 'XREG_PERM_ON', ...
            'Dimension', [2, 1], ...
            'RowSizes', [31, -1], ...
            'elements', {SelectPanel, obj.hSlicePointTable});
        
        set(slicePointPanel,'ContentHandle', {lytSlicePointPanel});
        
        % SNAP
        lytSliceControl = xregsnapsplitlayout( obj.Parent, ...
            'Visible', obj.Visible, ...
            'packgroup', 'XREG_PERM_ON', ...
            'Split', [0.7, 0.3], ...
            'Orientation', 'ud', ...
            'Style', 'tobottom', ...
            'SnapStyle', 'tozero', ...
            'BarStyle', 1, ... % 1 == 'flat'
            'Top',    slicePointPanel, ...
            'Bottom', evaluationPanel, ...
            'State', 'center' );
        
        % Create the main layout for the view
        obj.ContentHandle = xregsplitlayout( obj.Parent,...
            'Visible', obj.Visible, ...
            'packgroup', 'XREG_PERM_ON',...
            'orientation', 'lr', ...
            'dividerstyle', 'flat', ...
            'dividerwidth', 4, ...
            'split', [0.2, 0.8], ...
            'left',  lytSliceControl,...
            'right', lytAxesPanel,...
            'position', obj.Position, ...
            'packstatus','on' );
        
        % -------------------------------------------------------------------------
        % INITIALIZATION
        % -------------------------------------------------------------------------
        
        % Set the message service
        obj.pPostSetMessageService;
        
        % When we create the view there is an effective "constraint change"
        % -- This will fire all the setup and draw commands required to give us an
        %    initial view.
        obj.pPostConstraintChange;
        
        end % of the main function
        
    end  % constructor block
    
    methods
    end   % set and get functions
    
    methods  % public methods
        %----------------------------------------
        function s = gettitle(obj) %#ok<MANU>
        %GETTITLE Return a suitable title for a window
        %  GETTITLE(OBJ) returns a string that can be used as a title for the view.
        
        s = '1D Slice';
        
        end  % gettitle
        
        %----------------------------------------
        function pBlackDotClicked(obj, evt)
        %PBLACKDOTCLICKED Respond to black dot being clicked
        %   PBLACKDOTCLICKED(OBJ, evt)
        %   If the user clicks on a black dot, then we display information about
        %   that dot, in particular we display the coordinates of that point and
        %   the distance from the constraint boundary. We use a tool-tip to display
        %   this info.
        %
        %   If the user double clicks on a black dot, then we move the slice point
        %   of the view so that that point is at the center of the slice.
        
        
        if ~obj.hasData,
            return
        end
        hFigure = obj.Parent;
        
        BMS = obj.MessageService;
        data = BMS.getDataPoints;
        cif  = BMS.getInputFactors;
        con  = BMS.getConstraint;
        
        % Switch the action based on what type click the user made
        switch lower( get(ancestor(hFigure,'figure'),'SelectionType') ),
            case 'normal', % left click
                n_Tooltip;
            case 'open', % double click
                n_SetSlicePoint;
            case {'alt', 'extend'}, % right, middle click
                %ignore
            otherwise
                warning(message('mbc:xregbdrygui:AbstractBdrySlice:InvalidState1'));
                return
        end
        
            function n_SetSlicePoint
            i = evt.data.ClosestIndex;
            obj.setSlicePoint( data(i,:) );
            end
        
            function n_Tooltip
            % Generate the text for the patch
            i = evt.data.NearIndex;
            if isempty( con ),
                space = repmat( blanks(1), length( cif ), 1 );
                txt = [space, char( cif.Symbol ), space, space, num2str( data(i,:).', 4 ), space ];
            else
                space = repmat( blanks(1), length( cif )+1, 1 );
                symbols = cif.Symbol;
                d = constraintDistance( con, data(i,:) );
                txt = [space, char( symbols{:}, 'Dist:' ), space, space, ...
                    num2str( [data(i,:), d].', 4 ), space ];
            end
            
            evt.data.hGraph.dataTooltip( txt );
            end
        end
        
        
        %----------------------------------------
        function setSlicePoint(obj, point)
        %SETSLICEPOINT Set the point where the current slice is at.
        %   SETSLICEPOINT(OBJ, POINT)
        
        obj.hSlicePointTable.VariableValues(:,1) = num2cell( point );
        obj.pUpdateDataSlicePoint;
        obj.pDrawConstraint;
        
        end  % setSlicePoint
        
    end  % public methods
    
    methods (Access=protected)
               %----------------------------------------
        function pDrawConstraint(obj)
        %PDRAWCONSTRAINT Draw the current constraint in the view
        %   PDRAWCONSTRAINT(OBJ)
        
        obj.hData.pUpdateConstraintBounds;
        obj.pDrawPoints;
        end  % pDrawConstraint
        
        %----------------------------------------
        function pDrawPoints(obj)
        %PDRAWPOINTS Draw data points on the view
        %   PDRAWPOINTS(OBJ)
        
        obj.hData.pUpdateDataPointIndices;
        obj.hData.pUpdateValidationPointIndices;
        obj.hGraphTable.update;
        end  % pDrawPoints
        
        %----------------------------------------
        function pPostConstraintChange(obj)
        %PPOSTCONSTRAINTCHANGE Respond to a change in constraint.
        %   PPOSTCONSTRAINTCHANGE(OBJ)
        
        obj.pSetInputFactors;
        obj.pDrawConstraint;
        end  % pPostConstraintChange
        
        %----------------------------------------
        function pPostSetMessageService(obj)
        %PPOSTSETMESSAGESERVICE Respond to change of MessageService
        %  PPOSTSETMESSAGESERVICE(OBJ) is called when the MessageService property
        %  is changed.
        %
        %  See also XREGBDRYGUI.BDRYSLICE1.
        
        % Clear the listeners
        obj.clearMessageServiceListeners;
        
        % Add new listeners
        obj.addMessageServiceListener( event.listener(obj.MessageService,'ConstraintChange',        @(src, evt) obj.pPostConstraintChange ));
        obj.addMessageServiceListener( event.listener(obj.MessageService,'BoundaryPointsHighlight', @(src, evt) obj.pShowBoundaryPoints ));
        obj.addMessageServiceListener( event.listener(obj.MessageService,'ValidationPointsToggled', @(src, evt) obj.pShowValidationPoints ));
        
        end  % pPostSetMessageService
        
        %----------------------------------------
        function pSetInputFactors(obj, cif)
        %PSETINPUTFACTORS Sets the input factors in the view
        %  PSETINPUTFACTORS(OBJ, CIF) sets the input factors that are stored in the
        %  view based on the input facots from the current node.
        %
        %  PSETINPUTFACTORS(OBJ) gets the input factors from the boundary message
        %  service.
        %
        %  If the old input factors in the view differ from those from the node
        %  then slice control table is reset with new variables and values.
        %
        %  See also XREGBDRYGUI.BDRYSLICE1.
        
        % #define
        TYPE_SCALAR    = 1;
        TYPE_LINEAR    = 2;
        TYPE_FREEFORM  = 3; %#ok -- not used
        TYPE_LINKED    = 4; %#ok -- not used
        
        % Check input arguments
        if nargin < 2,
            if obj.hasData,
                % Get the input factors from the BMS
                cif = obj.MessageService.getInputFactors;
            else
                % If no input factors are provided and the BMS can't provide us
                % with any, then we assume that the view is hidden and ignore the
                % request to reset the input factors.
                return
            end
        end
        
        % Check the new input factors and set properties as appropriate
        nCif = length( cif );
        
        % We only need to update the tables if there factors have changed
        if isequal( cif, obj.InputFactors ),
            % Nothing to do
        else
            % Need to update the stored input factors and the slice table
            obj.InputFactors = cif;
            
            % We will need to know the range of the input factors to fill in the
            % tables
            [lb, ub] = getRange( cif );
            
            % Update Slice Table (hSlicePointTable)
            %   Types -- single value (TYPE_SCALAR) in both the first and second
            %            column
            types = repmat( TYPE_SCALAR, nCif, 2 );
            %   Values -- these will be the mid points of the ranges of the input
            %             factors
            values = cell( nCif, 2 );
            for i = 1:nCif,
                values(i,:) = { 0.5*(lb(i)+ub(i)), 0.1*(ub(i)-lb(i)) };
            end
            %
            obj.hSlicePointTable.setVariables( cif.Name, types, values );
            
            % Update Evaluation Table (hEvaluationTable)
            %   We are going to put 51 evenly spaced points for each factor.
            %   Types -- linearly space (TYPE_LINEAR) vector
            types = repmat( TYPE_LINEAR, nCif, 2 );
            %   Values -- these will be 51 evenly spaced points
            values = cell( nCif, 1 );
            for i = 1:nCif,
                values{i} = [lb(i), ub(i), 51];
            end
            %
            obj.hEvaluationTable.setVariables( cif.Name, types, values );
            
            % Ensure that the view and the data are up-to-date
            obj.pUpdateDataSlicePoint;
            obj.pUpdateDataSliceTolerance;
            obj.pUpdateDataEvaluationPoints;
        end
        
        end  % pSetInputFactors
        
        %----------------------------------------
        function pShowBoundaryPoints(obj)
        %PSHOWBOUNDARYPOINTS Set the visibilty of the boundary points in the graph obejcts.
        %   PSHOWBOUNDARYPOINTS(OBJ)
        
        BMS = obj.MessageService;
        hGraphs = obj.hGraphTable.MainObjects;
        if ~isempty( hGraphs ),
            set( hGraphs, 'BoundaryPointsVisible', BMS.BoundaryPointHighlight )
        end
        
        end  % pShowBoundaryPoints
        
        %----------------------------------------
        function pShowValidationPoints(obj)
        %PSHOWVALIDATIONPOINTS Set the visibilty of the valdiation points in the graph objects.
        %   PSHOWVALIDATIONPOINTS(OBJ)
        
        BMS = obj.MessageService;
        hGraphs = obj.hGraphTable.MainObjects;
        if ~isempty( hGraphs ),
            set( hGraphs, 'ValidationPointsVisible', BMS.ValidationPointHighlight )
        end
        end  % pShowValidationPoints
        
        %----------------------------------------
        function pUpdateDataEvaluationPoints(obj)
        %PUPDATEDATAEVALUATIONPOINTS Set the evaluations in the data object from the evaluation point table.
        %   PUPDATEDATAEVALUATIONPOINTS(OBJ)
        
        points = obj.hEvaluationTable.getNumericValues;
        obj.hData.EvaluationPoints = points(:).';
        
        end  % pUpdateDataEvaluationPoints
        
        %----------------------------------------
        function pUpdateDataSlicePoint(obj)
        %PUPDATEDATASLICEPOINT Set the slice point in the data object from the slice point table.
        %   PUPDATEDATASLICEPOINT(OBJ)
        
        point = [obj.hSlicePointTable.getNumericValues{:,1}];
        obj.hData.SlicePoint = point(:).';
        
        end  % pUpdateDataSlicePoint
        
        %----------------------------------------
        function pUpdateDataSliceTolerance(obj)
        %PUPDATEDATASLICETOLERANCE Set the slice tolerance in the data object from the slice point table.
        %   PUPDATEDATASLICETOLERANCE(OBJ)
        
        tolerance = [obj.hSlicePointTable.getNumericValues{:,2}];
        obj.hData.SliceTolerance = tolerance(:).';
        
        end  % pUpdateDataSliceTolerance
 
    end
    
end  % classdef