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

    classdef TssfInfoView < xregdatagui.AbstractDataView
    %xregdatagui.TssfInfoView class
    %   xregdatagui.TssfInfoView extends xregdatagui.AbstractDataView.
    %   xregdatagui.TssfInfoView is part of xregdatagui.TssfClusterView
    %
    %    xregdatagui.TssfInfoView 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' (read only)
    %       UIContextMenu - Property is of type 'MATLAB array'
    %       Listeners - Property is of type 'handle vector' (read only)
    %       DataListview - Property is of type 'handle' (read only)
    %       DesignListview - Property is of type 'handle' (read only)
    %       Interactive - Property is of type 'bool'
    %       COMListeners - Property is of type 'handle vector' (read only)
    %
    %    xregdatagui.TssfInfoView methods:
    %       gettitle - returns string describing this view
    %       pPostSetDmsIsReadOnly - A short description of the function
    %       pPostSetInteractive - A short description of the function
    %       pUpdateDisplay - complete update of the view display
    %       pUpdateListviews - A short description of the function
    %       pdmsDataTypeChangedUpdate - event handler for the dmsDataTypeChanged event
    %       ptssfActualDesignChangedUpdate -  update of the view display for design changes
    
    %  Copyright 2015 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (AbortSet, SetObservable)
        %INTERACTIVE Property is of type 'bool'
        Interactive = true;
    end
    
    properties (SetAccess=protected, AbortSet, SetObservable)
        %DATALISTVIEW Property is of type 'handle' (read only)
        DataListview = [];
        %DESIGNLISTVIEW Property is of type 'handle' (read only)
        DesignListview = [];
        %COMLISTENERS Property is of type 'handle vector' (read only)
        COMListeners = [];
    end
    
    methods  % constructor block
        function obj = TssfInfoView(varargin)
        %TssfInfoView constructor
        %   OUT = TssfInfoView(VARARGIN)
        
        % Do the setup stuff from inside the abstractDataView constructor
        obj@xregdatagui.AbstractDataView(varargin{ : }); % converted super class constructor call
        
        % Create the graphical objects and put in the Display field
        obj.pCreateDisplay;
        
        % Update the display
        obj.pUpdateDisplay
        
        % Set up property listeners on the interactive property
        addlistener(obj,obj.findprop('Interactive'),'PostSet',@obj.pPostSetInteractive);
        
        end  % tssfclusterview
        
    end  % constructor block
    
    methods  % public methods
        %----------------------------------------
        function pPostSetDmsIsReadOnly(obj, ~,~)
        %PPOSTSETDMSISREADONLY disable actions if IsReadOnly changes
        %   PPOSTSETDMSISREADONLY(OBJ,SRC, EVENT)
        
        % Set the Append status of the storage view
        obj.Interactive = ~obj.MessageService.IsReadOnly;
        end  % pPostSetDmsIsReadOnly
        
        %----------------------------------------
        function pPostSetInteractive(obj, ~,~)
        %PPOSTSETINTERACTIVE A short description of the function
        %  PPOSTSETINTERACTIVE(OBJ, SRC, EVT)
        
        if obj.MessageService.isaTSSF
            boolInteractive = obj.Interactive;
            if boolInteractive
                strInteractive = 'on';
            else
                strInteractive = 'off';
            end
        else
            boolInteractive = false;
            strInteractive = 'off';
        end
        
        % Ensure that the listviews are set correctly
        obj.DataListview.Peer.setDisplayChecks(boolInteractive);
        obj.DesignListview.Peer.setDisplayChecks(boolInteractive);
        
        set(obj.COMListeners, 'Enable', strInteractive);
        obj.DesignListview.UIContextMenu = obj.UIContextMenu;
        obj.DataListview.UIContextMenu = obj.UIContextMenu;
        
        end  % pPostSetInteractive
        
        %----------------------------------------
        function pUpdateDisplay(obj)
        %PUPDATEDISPLAY complete update of the view display
        %
        %  PUPDATEDISPLAY(OBJ)
        %
        
        if hasData(obj)
            % Simulate a data type changed update
            obj.pdmsDataTypeChangedUpdate;
            % Check the class of the current data object
            if obj.MessageService.isaTSSF
                obj.ptssfActualDesignChangedUpdate;
                obj.pUpdateListviews
            end
        end
        
        end  % pUpdateDisplay
        
        %----------------------------------------
        function pUpdateListviews(obj)
        %PUPDATELISTVIEWS A short description of the function
        %  OUT = PUPDATELISTVIEWS(IN)
        
        % Make sure it's a valid cluster index
        if obj.MessageService.CurrentClusterIndex < 1
            return
        end
        % Get the data object
        tssf = obj.MessageService.TestplanSweepsetFilter;
        % OK - Get the cluster information
        thisCluster = get(tssf, 'clusters', obj.MessageService.CurrentClusterIndex);
        
        [alldata, data, design, tolerance] = get(tssf, {'actualdata', 'meandata', 'actualdesign' 'tolerances'});
        % Subsample the design, data and testnums
        design   = design(thisCluster.design, :);
        data     = data(thisCluster.data, :);
        % Get the testnumbers
        testnums = testnum(alldata);
        testnums = testnums(thisCluster.data);
        % Set the tolerances
        designTol = repmat(tolerance, size(design, 1), 1);
        dataTol   = repmat(tolerance, size(data, 1), 1);
        % Add items to the data listview
        ListData = cell(length(thisCluster.data),2+size(data,2));
        DataChecks = false(length(thisCluster.data),1);
        for i = 1:length(thisCluster.data)
            % Find which design elements are in tolerance of this point
            designIndicesInTolerance = i_inTolerance(data(i,:), design, designTol);
            ListData{i,1} = sprintf('%d', testnums(i));
            str = sprintf('%d, ', thisCluster.design(designIndicesInTolerance));
            ListData{i,2} = str(1:end-2);
            for j = 1:size(data, 2)
                ListData{i,2+j} = sprintf('%.4g', data(i, j));
            end
            DataChecks(i) = ismember(thisCluster.data(i), thisCluster.selecteddata);
        end
        obj.DataListview.Peer.setData(ListData);
        if obj.Interactive
            obj.DataListview.Peer.setChecks(DataChecks);
        end
        
        ListDesign = cell(length(thisCluster.design),2+size(design,2));
        DataChecks = false(length(thisCluster.design),1);
        % Add items to the design listview
        for i = 1:length(thisCluster.design)
            % Find which design elements are in tolerance of this point
            dataIndicesInTolerance = i_inTolerance(design(i,:), data, dataTol);
            ListDesign{i,1} = sprintf('%d', thisCluster.design(i));
            dataStr = sprintf('%d, ', testnums(dataIndicesInTolerance));
            
            ListDesign{i,2} = dataStr(1:end-2);
            for j = 1:size(data, 2)
                ListDesign{i,2+j} = sprintf('%.4g', design(i, j));
            end
            DataChecks(i) = ismember(thisCluster.design(i), thisCluster.selecteddesign);
        end
        obj.DesignListview.Peer.setData(ListDesign);
        if obj.Interactive
            obj.DesignListview.Peer.setChecks(DataChecks);
        end
        
        % Check for a design only cluster and ensure that the design checkboxes are
        % turned off in that case.
        dms = obj.MessageService;
        obj.Interactive = ~strcmp(thisCluster.status, 'unmatcheddesign') & dms.isaTSSF & ~dms.IsReadOnly ;
        end  % pUpdateListviews
        
        %----------------------------------------
        function pdmsDataTypeChangedUpdate(obj, ~,~)
        %PDMSDATATYPECHANGEDUPDATE event handler for the dmsDataTypeChanged event
        %   PDMSDATATYPECHANGEDUPDATE(OBJ, SRC, EVT)
        
        % Find the tssfFiltersChanged listener
        tssfListeners = obj.MessageService.findListeners(obj.Listeners, 'TestplanSweepsetFilter');
        % If the dataObject isn't a sweepsetfilter then...
        if obj.MessageService.isaTSSF
            % Turn on the TestplanSweepsetFilter listener
            [tssfListeners.Enabled] = deal(true);
            
            % Check if the view is interactive or not
            obj.Interactive = ~obj.MessageService.IsReadOnly;
        else
            % Clear the views
            obj.DataListview.setColumnData({});
            obj.DesignListview.setColumnData({});
            obj.DesignListview.setData({});
            % Turn off the TestplanSweepsetFilter listener
            [tssfListeners.Enabled] = deal(false);
            % Ensure the view is non-interactive
            obj.Interactive = false;
        end
        
        end  % pdmsDataTypeChangedUpdate
        
        %----------------------------------------
        function ptssfActualDesignChangedUpdate(obj, ~,~)
        %ptssfActualDesignChangedUpdate  update of the view display for design changes
        %   ptssfActualDesignChangedUpdate(OBJ)
        
        % Re-create the column headers for the new global variables
        names = globalsignalnames(obj.MessageService.TestplanSweepsetFilter);
        
        % Make the names for the Data and the Design listviews
        dataNames   = [{'Test Number' 'Design Indices in Tolerance'} names'];
        designNames = [{'Design Index' 'Test Numbers in Tolerance'} names'];
        widths = [80 150 60*ones(1, length(names))];
        obj.DataListview.setColumnData(dataNames);
        obj.DataListview.setColumnWidths(widths);
        obj.DesignListview.setColumnData(designNames);
        obj.DesignListview.setColumnWidths(widths);
        
        end  % ptssfActualDesignChangedUpdate
        
    end  % public methods
    
    
    methods (Hidden) % possibly private or hidden
        %----------------------------------------
        function pCreateDisplay(obj)
        %PCREATEDISPLAY create main display
        
        % We need two side by side listviews to display info about the current cluster
        
        obj.DataListview = mbcwidgets.List( 'Parent', obj.Parent,...
            'Editable', false, ...
            'UIContextMenu', obj.UIContextMenu,...
            'ValueChangedCallback',@obj.onDataListviewCheck,...
            'SelectionMode', 'MultiRow');
        
        obj.DataListview.setColumnData({'Test Number' 'Design Indices in Tolerance'});
        obj.DataListview.setColumnWidths([80 150]);
        obj.DataListview.Peer.setDisplayChecks(obj.Interactive);
        
        obj.DesignListview = mbcwidgets.List( 'Parent', obj.Parent,...
            'Editable', false, ...
            'UIContextMenu', obj.UIContextMenu,...
            'ValueChangedCallback',@obj.onDesignListviewCheck,...
            'SelectionMode', 'MultiRow');
        obj.DesignListview.setColumnData({'Design Index' 'Test Numbers in Tolerance'});
        obj.DesignListview.setColumnWidths([80 150]);
        obj.DesignListview.Peer.setDisplayChecks(obj.Interactive);
        
        % Create a split layout for the two listviews
        split = xregsplitlayout(obj.Parent, ...
            'packgroup', 'xregdatagui.tssfinfoview',...
            'orientation', 'lr',...
            'split', [0.5 0.5],...
            'dividerstyle', 'flat',...
            'dividerwidth', 4,...
            'left', obj.DataListview,...
            'right', obj.DesignListview,....
            'enable', obj.Enable);
        
        obj.ContentHandle = split;
        comListeners= [
            handle.listener(obj.DataListview.Peer, 'MousePressed', @obj.onListBtnDown)
            handle.listener(obj.DesignListview.Peer, 'MousePressed', @obj.onListBtnDown)];
        
        obj.COMListeners = [obj.COMListeners ; comListeners];
        end  % pCreateDisplay
        
        function onDataListviewCheck(obj,~, evt)
        %onDataListviewCheck callback to check data listview item
        ClusterIdx = obj.MessageService.CurrentClusterIndex;
        
        % Check the cluster index is valid
        if obj.Interactive && ClusterIdx > 0
            % Get the data object
            tssf = obj.MessageService.TestplanSweepsetFilter;
            % Get the current cluster information
            thisCluster = get(tssf, 'clusters', ClusterIdx);
            % Has anything changed
            state = ismember(thisCluster.data, thisCluster.selecteddata);
            % update state
            state(evt.data.Rows) = ~state(evt.data.Rows);
            % Indicate this task might take a little time
            busy(obj.MessageService,'Updating Cluster Information...');
            try
                % Update the selected data
                tssf = setClusterSelectedData(tssf, thisCluster.data(state), ClusterIdx);
                % And flush the event queue
                obj.MessageService.flushEventQueue(tssf);
                % And let everyone know that the tests have changed
                obj.pSendSelectedTestsChanged;
            end
            % Remove the message and the pointer
            idle(obj.MessageService);
        end
        end  % onDataListviewCheck
        
        
        %------------------------------------------------------------------------
        function onDesignListviewCheck(obj,~, evt)
        %onDesignListviewCheck  callback to check data listview item
        
        ClusterIdx = obj.MessageService.CurrentClusterIndex;
        
        % Check the cluster index is valid
        if obj.Interactive && ClusterIdx > 0
            % Get the data object
            tssf = obj.MessageService.TestplanSweepsetFilter;
            % Get the current cluster information
            thisCluster = get(tssf, 'clusters', ClusterIdx);
            % Has anything changed
            state = ismember(thisCluster.design, thisCluster.selecteddesign);
            % Has anything happened to the listview
            % update state
            state(evt.data.Rows) = ~state(evt.data.Rows);
            % Indicate this task might take a little time
            busy(obj.MessageService,'Updating Cluster Information...');
            try
                % Update the selected design points
                tssf = setClusterSelectedDesign(tssf, thisCluster.design(state), ClusterIdx);
                % And flush the event queue
                obj.MessageService.flushEventQueue(tssf);
            end
            % Remove the message and the pointer
            idle(obj.MessageService);
        end
        end  % onDesignListviewCheck
        
        function onListBtnDown(obj,~, ~)
        notify(obj, 'ButtonDown');
        end  % onListBtnDown
        
        %----------------------------------------
        function pPostSetDataMessageService(obj, ~,~)
        %PPOSTSETDATAMESSAGESERVICE setup MessageService listeners
        %    PPOSTSETDATAMESSAGESERVICE(OBJ, SRC, EVT)
        
        % Call the super pPostSetDataMessageService
        pPostSetDataMessageService@xregdatagui.AbstractDataView(obj)
        dms = obj.MessageService;
        
        dmsListeners = [...
            event.listener(dms, 'dmsDataTypeChanged',  @obj.pdmsDataTypeChangedUpdate);...
            event.listener(dms, 'tssfActualDesignChanged', @obj.ptssfActualDesignChangedUpdate);...
            event.listener(dms, 'tssfClustersCreated', @obj.onUpdateCurrentCluster);...
            event.listener(dms, 'CurrentClusterChanged', @obj.onUpdateCurrentCluster);...
            ];
        obj.Listeners = [obj.Listeners(:); dmsListeners(:)];
        end  % pPostSetDataMessageService
        
        %----------------------------------------
        function pSendSelectedTestsChanged(obj)
        %PSENDSELECTEDTESTSCHANGED set global test selection
        %   PSENDSELECTEDTESTSCHANGED(obj)
        
        dms = obj.MessageService;
        tssf = dms.TestplanSweepsetFilter;
        % Get the information about the clusters
        if ~dms.isOneStage
            % updte selected tests for two-stage data only
            thisCluster = get(dms.TestplanSweepsetFilter, 'clusters', dms.CurrentClusterIndex);
            dms.setSelectedTests(convertTestIndices(tssf, thisCluster.selecteddata));
        end
        end  % pSendSelectedTestsChanged
        
        function onUpdateCurrentCluster(obj, ~,~)
        % Update the listviews
        obj.pUpdateListviews;
        end  % iUpdateCurrentCluster
        
    end  % possibly private or hidden
    
end  % classdef

function indices = i_inTolerance(value, data, tol)
% Ensure that value is the same size as data
value = repmat(value, size(data, 1), 1);
% Form a distance metric
distance = abs((value - data)./tol);
% Where are all in tolerance
indices = find(all((distance < 1), 2));
end  % i_inTolerance