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

    classdef VariableSliceTable < mbcgui.widget.BasicContainer
    %mbccrosssectiongui.VariableSliceTable Creates a stand alone panel
    % containing a table that can be used to specify the slice value and
    % tolerance of model inputs for a cross-section plot
    
    %  Copyright 2015 The MathWorks, Inc.
    
    properties (Access=private)
        %DataModel Holds instance of the data model
        DataModel;
        %EventListener Contains event listeners on data model
        EventListener;
        %SliceTable Table containing inputs and slice values
        SliceTable;
        %LowerBound Contains lower bounds of input values
        LowerBound;
        %UpperBound Contains upper bounds of input values
        UpperBound;
        %DoUpdate Flag used to prevent looping when updating a property
        DoUpdate = true;
    end
    
    events
        Refresh;
        GraphChanged;
    end
    
    methods
        
        function obj = VariableSliceTable(parent, dataModel)
            %VariableSliceTable Constructor for class
            obj@mbcgui.widget.BasicContainer('Parent', parent);
            
            obj.DataModel = dataModel;
            addEventListeners(obj);
            
            layoutPanel = mbcgui.container.layoutpanel('Parent', parent, ...
                'Tag', 'CrossSectionSlicePanel');
            
            obj.SliceTable = mbcwidgets.VariableEditorTable( ...
                'Parent', layoutPanel, ...
                'ValueColumnCount', 2, ...
                'ValueColumnHeader', {'Value', 'Tolerance'}, ...
                'ValueChangedCallback', @(src,evt)tableValueUpdated(src,evt,obj), ...
                'ValueConstraint', 'plot');
            
            set(layoutPanel,'LayoutComponent',{obj.SliceTable})
            
            obj.ContentHandle = layoutPanel;
            
            redrawTable(obj);
        end
    end
    
    methods (Access=private)
        function redrawTable(obj)
            %redrawTable setup object and table table based on data model
            names = obj.DataModel.ColumnItemLabels;
            values = obj.DataModel.ColumnItemValues;
            limits = obj.DataModel.XLimits;
            obj.LowerBound = limits(:,1);
            obj.UpperBound = limits(:,2);
            tol = obj.DataModel.ColumnItemTolerance;
            nf = obj.DataModel.NumInputs;
            tableValues = [values', tol'];
            obj.SliceTable.setVariables(names, ones(nf, 2), num2cell(tableValues));
        end
        
        function updateTableValues(obj)
            %updateTableValues update the values in the table based on the
            % data model
            val = obj.DataModel.ColumnItemValues;
            tol = obj.DataModel.ColumnItemTolerance;
            
            tableValues = [val', tol'];
            obj.SliceTable.setValueColumn({'Value', 'Tolerance'}, num2cell(tableValues), ones(size(tableValues)))
        end
        
        function onRefresh(obj,~,~)
            %onRefresh React to Refresh event by updating the values in
            % tables
            if obj.DoUpdate
                updateTableValues(obj);
            end
        end
        
        function onGraphChanged(obj,~,~)
            %onGraphChanged React to GraphChanged event by redrawing table
            redrawTable(obj);
        end
        
        function addEventListeners(obj)
            %addEventListeners Setup listeners to events from the data model
            obj.EventListener = [...
                event.listener(obj.DataModel,'Refresh',@obj.onRefresh),...
                event.listener(obj.DataModel,'GraphChanged',@obj.onGraphChanged),...
                ];
        end
        
        function isValid = isValueValid(obj, inputIndex, value)
            %isValueValid Returns a boolean indicating if a value for an
            % input is within range
            if value < obj.LowerBound(inputIndex) || value > obj.UpperBound(inputIndex)
                isValid = false;
            else
                isValid = true;
            end
        end
    end
end

function tableValueUpdated(~,evt,obj)
    %tableValueUpdated callback when listctrl is updated
    evtData = evt.data;
    values = obj.SliceTable.getNumericValues;
    obj.DoUpdate = false;
    if evtData.Columns == 2
        % value column was changed
        newValue = values{evtData.Rows,1};
        isValid = obj.isValueValid(evtData.Rows, newValue);
        if isValid
            obj.DataModel.setColumnItemValue(evtData.Rows, newValue);
        else
            updateTableValues(obj)
        end
    elseif evtData.Columns == 3
        % tolerance column was changed
        newValue = values{evtData.Rows,2};
        if isValidTolerance(newValue)
            obj.DataModel.ColumnItemTolerance = [values{:,2}];
        else
            updateTableValues(obj)
        end
    end
    obj.DoUpdate = true;    
end

function OK = isValidTolerance(newTol)
%isValidTolerance returns boolean indicating if newTol is a valid
% tolerance
    OK = newTol > 0;
end