www.gusucode.com > mbcdesign 工具箱 matlab 源码程序 > mbcdesign/+xregdesgui/SliceControl.m

    classdef SliceControl < mbcgui.widget.BasicContainer
    %xregdesgui.SliceControl class
    %   xregdesgui.SliceControl extends mbcgui.widget.BasicContainer
    %
    %    xregdesgui.SliceControl 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'
    %       Design - Property is of type 'MATLAB array'
    %       NumAxes - Property is of type 'int'
    %       Axes - Property is of type 'MATLAB array'
    %       SlicePoint - Property is of type 'MATLAB array'
    %
    %    xregdesgui.SliceControl methods:
    %       canPrint - Check whether component can be printed
    %       hasSlice - Check whether there is a valid slice defined
    
    %   Copyright 2015-2016 The MathWorks, Inc.
    
    properties (AbortSet, SetObservable)
        %DESIGN Property is of type 'MATLAB array'
        Design = [];
        %NUMAXES Property is of type 'int'
        NumAxes = 2;
        %AXES Property is of type 'MATLAB array'
        Axes = [ 1, 2 ];
        %SLICEPOINT Property is of type 'MATLAB array'
        SlicePoint = [];
    end
    
    properties (Access=protected, AbortSet)
        %HTABLE Property is of type 'handle'
        hTable = [];
        %HAXISCONTROLS Property is of type 'handle vector'
        hAxisControls = [];
    end
    
    
    events
        AxisChanged
        PointChanged
    end  % events
    
    methods  % constructor block
        function obj = SliceControl(varargin)
        %SLICECONTROL Constructor for slicecontrol object
        %  SLICECONTROL(PROP, VALUE, ...) constructs a new slicecontrol object.
        
        obj@mbcgui.widget.BasicContainer(varargin{ : }); % converted super class constructor call
        
        hTopPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'BorderType', 'beveledout', ...
            'LayoutBorder', [5 5 5 5]);
        hBottomPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'BorderType', 'beveledout', ...
            'LayoutBorder', [5 5 5 5]);
        
        obj.hTable = mbcwidgets.VariableEditorTable( ...
            'Parent', hTopPanel, ...
            'ValueChangedCallback', @i_tableedited, ...
            'ValueConstraint', 'plot');
        obj.hAxisControls = i_makeaxislabels;
        
        % Create the layout
        hBottomGrid = xreggridbaglayout(hBottomPanel, ...
            'packgroup', 'XREG_PERM_ON', ...
            'dimension', [obj.NumAxes 1], ...
            'rowsizes', repmat(21, 1, obj.NumAxes), ...
            'gapy', 5, ...
            'elements', num2cell(obj.hAxisControls));
        set(hBottomPanel, 'LayoutComponent', {hBottomGrid});
        set(hTopPanel, 'LayoutComponent', obj.hTable);
        
        obj.ContentHandle = xreggridbaglayout(obj.Parent, ...
            'packgroup', 'XREG_PERM_ON', ...
            'Dimension', [3 1], ...
            'rowsizes', [50 -1 obj.NumAxes*26+7], ...
            'mergeblock', {[1 2], [1 1]}, ...
            'elements', {hTopPanel, [], hBottomPanel}, ...
            'packstatus', 'on');
        
        % Force update to match current settings
        obj.pCheckAxes;
        obj.pCheckPoint;
        obj.pDrawTable;
        obj.pDrawAxisSel;
        
        % Add listeners to properties
        obj.addPropertyListeners({'Design', 'NumAxes', 'Axes', 'SlicePoint'}, ...
            {@i_setdesign, @i_setnumaxes, @i_setaxes, @i_setpoint});
        
        % Flag that controls whether listener events should execute any action
        DO_EVENT_CODE = true;
        
            function ctrl = i_makeaxislabels
            SC = mbcgui.util.SystemColorsDbl;
            AxisNames = {'X', 'Y', 'Z'};
            ctrl = cell( 1, obj.NumAxes);
            for n = 1:obj.NumAxes
                hEdit = uicontrol('Parent', hBottomPanel, ...
                    'Style', 'popupmenu', ...
                    'String', {}, ...
                    'Value', 0, ...
                    'Tag',sprintf('SliceControl%d',n),...
                    'BackgroundColor', SC.WINDOW_BG, ...
                    'Callback', {@i_editaxis, n});
                ctrl{n} = xregGui.labelcontrol('Parent', hBottomPanel, ...
                    'String', sprintf('%s-axis:', AxisNames{n}), ...
                    'LabelSize', 40, ...
                    'LabelSizeMode', 'absolute', ...
                    'ControlSize', 1, ...
                    'ControlSizeMode', 'relative', ...
                    'Control', hEdit);
            end
            ctrl = [ctrl{:}];
            end
        
        
            function i_setdesign(src, evt) %#ok<INUSD>
            DO_EVENT_CODE = false;
            obj.pCheckAxes;
            obj.pCheckPoint;
            obj.pDrawTable;
            obj.pDrawAxisSel;
            DO_EVENT_CODE = true;
            end
        
            function i_setnumaxes(src, evt) %#ok<INUSD>
            % Reset to old value
            warning(message('mbc:xregdesgui:slicecontrol:InvalidPropertyValue1'));
            obj.NumAxes = length(obj.Axes);
            end
        
            function i_setaxes(src, evt) %#ok<INUSD>
            if DO_EVENT_CODE
                obj.pCheckAxes;
                obj.pDrawAxisSel;
                obj.pDrawTable;
            end
            end
        
            function i_setpoint(src, evt) %#ok<INUSD>
            if DO_EVENT_CODE
                obj.pCheckPoint;
                obj.pDrawTable;
            end
            end
        
            function i_tableedited(src, evt) %#ok<INUSL>
            row = evt.data.Rows;
            newval = zeros(length(row), 1);
            for n = 1:length(newval)
                newval(:) = evt.data.NewValue(n).getValue;
            end
            
            % Transform row so it is the correct factor index
            editfact = setdiff(1:length(obj.SlicePoint), obj.Axes);
            row = editfact(row);
            
            % Save change without causing a table redraw
            DO_EVENT_CODE = false;
            obj.SlicePoint(row) = newval;
            DO_EVENT_CODE = true;
            
            % Send a value change event
            data = struct('FactorIndex', row, 'NewValue', newval);
            obj.notify('PointChanged', xregEventData(data));
            end
        
            function i_editaxis(src, evt, axis) %#ok<INUSL>
            NewAxisFactor = get(src, 'Value');
            ax = obj.Axes;
            
            % Unset any axes that are already set to this factor.  They will be
            % fixed by the Axes set listener.
            ax(ax==NewAxisFactor) = 0;
            ax(axis) = NewAxisFactor;
            
            obj.Axes = ax;
            
            % Send axis change event
            % Send a value change event
            data = struct('Axis', axis, 'NewFactor', NewAxisFactor);
            obj.notify('AxisChanged', xregEventData(data));
            end
        end
        
    end  % constructor block
    
    methods
        function set.NumAxes(obj,value)
        % DataType = 'int'
        validateattributes(value,{'numeric'},{'scalar'},'','NumAxes')
        value = round(value); %  round to obtain an integer
        obj.NumAxes = i_checknumaxes(obj,value);
        end
        
        function set.hTable(obj,value)
        % DataType = 'handle'
        validateattributes(value,{'handle'}, {'scalar'},'','hTable')
        obj.hTable = value;
        end
        
        function set.hAxisControls(obj,value)
        % DataType = 'handle vector'
        validateattributes(value,{'handle'}, {'vector'},'','hAxisControls')
        obj.hAxisControls = value;
        end
        
    end   % set and get functions
    
    methods  % public methods
        %----------------------------------------
        function out = canPrint(obj) %#ok<MANU>
        %CANPRINT Check whether component can be printed
        %  CANPRINT(OBJ) returns true for slicecontrol objects.
        
        out = true;
        
        end  % canPrint
        
        %----------------------------------------
        function out = hasSlice(obj)
        %HASSLICE Check whether there is a valid slice defined
        %  HASSLICE(OBJ) returns true if the control is defining a valid slice.
        %  For this to be true the control must be displaying a design with enough
        %  factors to have one per axis.
        
        out = ~isempty(obj.Design) && nfactors(obj.Design)>=obj.NumAxes;
        
        end  % hasSlice
        
        %----------------------------------------
        function pCheckAxes(obj)
        %PCHECKAXES Check that axis selection matches the number of axes
        %  PCHECKAXES(OBJ) checks that the length of the Axes property matches the
        %  setting of NumAxes and that all axes are different numbers.
        
        ax = obj.Axes;
        nAx = obj.NumAxes;
        
        if ~isempty(obj.Design)
            nF = nfactors(obj.Design);
            if nF<nAx
                ax = 1:nAx;
            else
                
                % Sort out length
                if length(ax)<nAx
                    ax = [ax zeros(1, nAx-length(ax))];
                elseif length(ax)>nAx
                    ax = ax(1:nAx);
                end
                
                % Check all are unique.
                Used = false(1, nF);
                for n = 1:length(ax)
                    if ax(n)~=0
                        if Used(ax(n))
                            % Find an unused axis number
                            ax(n) = find(~Used, 1, 'first');
                        end
                        % Mark as used
                        Used(ax(n)) = true;
                    end
                end
                
                % Find axes for any zeros
                nMissing = sum(ax==0);
                if nMissing>0
                    ax(ax==0) = find(~Used, nMissing, 'first');
                end
            end
        else
            ax = 1:nAx;
        end
        
        obj.Axes = ax;
        
        end  % pCheckAxes
        
        %----------------------------------------
        function pCheckPoint(obj)
        %PCHECKPOINT Check that slice point value is valid
        %  PCHECKPOINT(OBJ) checks that the slice point value is valid.  If there
        %  are too few values it will be reset to match the number of factors in
        %  the design.
        
        if ~isempty(obj.Design)
            nf = nfactors(obj.Design);
            if nf~=length(obj.SlicePoint)
                obj.SlicePoint = invcode(model(obj.Design), midpoint(obj.Design));
            end
        else
            obj.SlicePoint = [];
        end
        
        end  % pCheckPoint
        
        %----------------------------------------
        function pDrawAxisSel(obj)
        %PDRAWAXISSEL Update the axis selection gui elements
        %  PDRAWAXISSEL(OBJ) updates the axis selection popups to display the
        %  current axis settings and design factors.
        
        nf = length(obj.SlicePoint);
        if nf<obj.NumAxes
            % Set all controls to empty
            for n=1:obj.NumAxes
                set(obj.hAxisControls(n).Control, 'String', {''}, 'Value', 1);
            end
            set(obj.hAxisControls, 'Enable', 'off');
        else
            names = factors(obj.Design);
            ax = obj.Axes;
            for n=1:obj.NumAxes
                set(obj.hAxisControls(n).Control, 'String', names, 'Value', ax(n));
            end
            set(obj.hAxisControls, 'Enable', 'on');
        end
        
        end  % pDrawAxisSel
        
        %----------------------------------------
        function pDrawTable(obj)
        %PDRAWTABLE Update the table of evaluation point numbers
        %  PDRAWTABLE(OBJ) updates the table that contains the current evaluation
        %  point.
        
        if ~isempty(obj.Design)
            vals = obj.SlicePoint;
            names = factors(obj.Design);
            if length(names)<length(obj.Axes)
                obj.hTable.setVariables({}, [], {});
            else
                vals(obj.Axes) = [];
                names(obj.Axes) = [];
                obj.hTable.setVariables(names, ones(size(names)), num2cell(vals));
            end
        else
            obj.hTable.setVariables({}, [], {});
        end
        
        end  % pDrawTable
        
        %----------------------------------------
        function sz = printSize(obj)
        %PRINTSIZE Returns the preferred printing size for the component
        %  SZ = PRINTSIZE(OBJ) returns a two element vector containing the
        %  preferred width and height for printing the component.
        
        % Want enough height to print out the table values, no more.
        if isempty(obj.Design)
            n = 1;
        else
            nf = nfactors(obj.Design);
            n = max(1, nf-obj.NumAxes);
        end
        sz = [obj.Position(3), n*17+10];
        
        end  % printSize
        
        %----------------------------------------
        function newobj = printCopy(obj, fig)
        %PRINTCOPY Create a new component for printing the component display
        %  NEWOBJ = PRINTCOPY(OBJ, 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 the component OBJ.
        
        % Create a box containing details of non-axis variable values
        axwrap = mbcgui.widget.AxesContainer(...
            'Parent',fig);
        axvar = axwrap.AxesHandle;
        set(axvar,...
            'Color','none',...
            'XLim',[0 1],...
            'YLim',[-1 0],...
            'XTick',[],...
            'YTick',[],...
            'Box','on',...
            'Units','pixels', ...
            'HandleVisibility', 'off');
        
        if isempty(obj.Design)
            hExtObj = text('Parent',axvar,'Position',[0.5 0],...
                'VerticalAlignment','top',...
                'HorizontalAlignment','center',...
                'FontAngle', 'italic', ...
                'String','No design factors',...
                'Clipping','on');
        else
            nf = nfactors(obj.Design);
            numValues = nf-obj.NumAxes;
            
            if numValues==0
                hExtObj = text('Parent',axvar,'Position',[0.5 0],...
                    'VerticalAlignment','top',...
                    'HorizontalAlignment','center',...
                    'FontAngle', 'italic', ...
                    'String','No additional factors',...
                    'Clipping','on');
            else
                factind = setdiff(1:nf, obj.Axes);
                names = factors(obj.Design);
                values = obj.SlicePoint;
                valstr = cell(numValues,1);
                for n = 1:numValues
                    valstr{n} = sprintf('%g', values(factind(n)));
                end
                
                text('Parent',axvar,'Position',[0.05 0],...
                    'VerticalAlignment','top',...
                    'HorizontalAlignment','left',...
                    'String',names(factind),...
                    'Clipping','on');
                hExtObj = text('Parent',axvar,'Position',[0.5 0],...
                    'VerticalAlignment','top',...
                    'HorizontalAlignment','left',...
                    'String',repmat({':'}, numValues, 1),...
                    'Clipping','on');
                text('Parent',axvar,'Position',[0.55 0],...
                    'VerticalAlignment','top',...
                    'HorizontalAlignment','left',...
                    'String',valstr,...
                    'Clipping','on');
            end
        end
        
        oldunits = get(hExtObj, 'Units');
        set(hExtObj, 'Units', 'pixels');
        ext = get(hExtObj, 'Extent');
        set(hExtObj, 'Units', oldunits);
        
        % Need to add a border to make the box properly visible
        newobj = xreggridbaglayout(fig, ...
            'dimension', [1 1], ...
            'rowsizes', ext(4)+2, ...
            'elements', {axwrap}, ...
            'border', [1 1 1 1]);
        
        end  % printcopy
        
    end  % public methods
    
end  % classdef

function val = i_checknumaxes(obj, val) %#ok<INUSL>
if val<2 || val>3
    error(message('mbc:xregdesgui:slicecontrol:InvalidPropertyValue'));
end
end  % i_checknumaxes