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

    classdef Editor < mbcgui.Application
    %xregbdrygui.Editor class 
    %    xregbdrygui.Editor extends mbcgui.Application
    %
    %    xregbdrygui.Editor properties:
    %       MessageService - xregbdrygui.BdryMessageService (read only)
    %       Actions - Actions for boundary editor (read only)
    %       Toolbar - Toolbar layout for boundary editor (read only)
    %       View - View components (read only)
    %
    %    xregbdrygui.Editor methods:
    %       restore - Restore the boundary editor after a sleep
    %       create - static method to start the boundary editor (Static)
    
    % Copyright 2005-2016 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (Access=private, AbortSet)
        PointerStack = cell(0,2);
    end

    properties (SetAccess=protected, AbortSet)
        %MESSAGESERVICE xregbdrygui.BdryMessageService
        MessageService = [];
        %ACTIONS Actions for boundary editor
        Actions = [];
        %TOOLBAR Toolbar layout for boundary editor
        Toolbar = [];
        %VIEW View components
        %   Card, Tree, Info, Panel, TestSelector
        View = [];
    end
    
    properties(Dependent)
        %Root Root of boundary tree
        %   Root is a convenience dependent property for setting the
        %   boundary tree in the boundary editor
        Root
    end    
    
    methods (Access=protected) % constructor block
        function obj = Editor(varargin)
        %XREGBDRYGUI.EDITOR class constructor
        %  OBJ = EDITOR(VARARGIN)
        
        obj@mbcgui.Application('Tag','BoundaryEditor',varargin{:});
        
        end  % Editor
        
    end  % constructor block
    
    methods % set/get methods
        
        function broot = get.Root(obj)

        % root of boundary tree is stored in the MessageService
        broot = obj.MessageService.Root;
        
        end
        
        function set.Root(obj,broot)
        %set.Root update root of boundary tree in MessageService
        obj.MessageService.setRoot(broot)
        end
        
    end    
    
    methods (Static)
        function obj = create(varargin)
        %create create or restore data editor
        %    obj = xregbdrygui.Editor.create('Root',broot); 
        
        Tag = 'BoundaryEditor';
        obj = xregbdrygui.Editor.find(Tag);
        if isempty(obj)
            % initial default size
            deSize =   [50 100 800 600];
            obj = xregbdrygui.Editor('Tag',Tag,...
                'Visible','off',...   % create the figure invisible and turn on when done
                'Position',deSize);
            obj.SleepOnClose = true;
        else
            restore(obj);
        end
        if nargin
            busy(obj.MessageService,'Initializing...')
            set(obj,'Title','Boundary Editor',varargin{:});
            idle(obj.MessageService)
            setStatusMessage(obj,'Ready');
            obj.Figure.Visible = 'on';
        end
        end
        
    end    
    
    methods  % public methods
        function restore(obj)
        %RESTORE Make window visible again
        %   RESTORE(OBJ) will re-open an application that has been put into a
        %   "sleep" mode when closed.
        
        if strcmp(get(obj.Figure, 'Visible'), 'on')
            % Fake a close event before restoring the application
            obj.close(true);
        end
        
        obj.restore@mbcgui.Application();
        end

    end
    
    methods (Access=protected)
        
        function C = createContent(obj)
        %CREATECONTENT Create content layout.
        %   C = CREATECONTENT(OBJ) constructs the basic content layout for the Data
        %   Editor.
        
        % Set-up the message service
        obj.MessageService = xregbdrygui.BdryMessageService;
        
        obj.Listeners = [obj.Listeners(:); event.listener(obj.MessageService,'Busy',@obj.onBusy)
            event.listener(obj.MessageService,'Idle',@obj.onIdle)];
        
        % Create the view, the actions, the menus and the toolbar
        obj.pCreateActions;
        obj.pCreateView;
        obj.pCreateMenus;
        obj.pCreateToolbar;
        
        % Create the layout
        lyt = obj.pCreateLayout;     
        
        % Link the visible components together
        C = xreggridbaglayout(obj.Figure,...
            'dimension', [2 1],...
            'elements', {obj.Toolbar.Layout lyt},...
            'rowsizes', [31 -1],...
            'gapy', 2);        
        
        end
        
        function onBusy(obj,~,evt)
        %onBusy listen for MessageService.Busy and change the figure pointer
        ptrID = setPointer(obj,'watch');
        msgID = setStatusMessage(obj,evt.Data.Message);
        
        obj.PointerStack(end+1,:) = {ptrID,msgID};
        
        end
        
        function onIdle(obj,~,~)
        %onIdle listen for MessageService.Idle and change the figure pointer
        if ~isempty(obj.PointerStack)
            removePointer(obj,obj.PointerStack{end,1})
            removeStatusMessage(obj,obj.PointerStack{end,2})
            obj.PointerStack(end,:) = [];
        end
        end
        
        %----------------------------------------
        function onClose(obj,evt)
        %CLOSE Close method for boundary editor
        %  CLOSE(OBJ) sets the boundary editor to invisible
        %  Before setting the editor invisible, a check is performed to see if
        %  there is a best constraint set, i.e., if there is a constraint from at
        %  root node. If there is not, then the user is presented with the
        %  opportunity to return to the editor and set a best constraint. If there
        %  is only one xregbdrydev node in the whole tree, then this can be set at
        %  best automagically. However, in this case the user is asked if this is
        %  what they want.
        %
        %  See also mbcgui.Application.close
        
        % If there is no best contsraint, then ask the user if they really want to
        % close things down
        state = 'on';
        if obj.MessageService.hasData,
            root = obj.MessageService.Root;
            if isvalid(root) && root.isa('xregbdryroot')
                bestConstraint = root.getconstraint;
                if isempty( bestConstraint ),
                    leaves = root.leaves;
                    if length( leaves ) == 1 && isa( leaves, 'xregbdrydev' )
                        i_BringFigureToFront( obj );
                        state = i_AskAboutTheOneAndOnlyNode( root.info, leaves );
                    else
                        i_BringFigureToFront( obj );
                        state = i_AskAboutLackOfBestConstraint( root.info );
                    end
                end
            end
        end
        if strcmpi(state,'off')
            evt.CancelClose = true;
        end
        
        end  % close
        
        %----------------------------------------
        function pAddListener(obj, varargin)
        %PADDLISTENER Add a listener to the list held by the boundary editor
        %  PADDLISTENER(OBJ, LISTENER) adds the given LISTENER to the list of
        %  listeners held by the Editor (OBJ).
        %
        %  if you want PADDLISTENER( OBJ, handle.listener( <arguments> ) ), then use
        %  PADDLISTENER( OBJ, <arguments> ).
        
        obj.Listeners = cat(1,obj.Listeners, varargin{:} );

        end  % pAddListener
        
        %----------------------------------------
        function pCreateActions(obj)
        %PCREATEACTIONS Create the actions for a Boundary Editor
        % PCREATEACTIONS(OBJ)
        
        % Set the Actions property of the editor (object)
        obj.Actions = xregbdrygui.Actions(obj.MessageService);
        
        end  % pCreateActions
        
        %----------------------------------------
        function lyt = pCreateLayout(obj)
        %PCREATELAYOUT Create the layout for a Boundary Editor
        %  PCREATELAYOUT(OBJ)
        
        SC = mbcgui.util.SystemColorsDbl;
        
        figh = obj.Figure;
        
        % The layout is something like this
        %    +-------++--------------------+
        %    |       ||                    |
        %    | tree  ||                    |
        %    |       ||    multi           |
        %    +=======++                    |
        %    | info  ||    panel           |
        %    |       ||                    |
        %    +-------++                    |
        %    | test  ||                    |
        %    +-------++--------------------+
    
        % The double lines, i.e., = and || are the adjustable splits
        
        % The first layout is the adjustable split between the tree view and the
        % info view
        lyt = xregsplitlayout( figh,...
            'Orientation', 'ud',...
            'Top', obj.View.Tree,...
            'Bottom', obj.View.Info,...
            'Split', [0.7, 0.3],...
            'DividerStyle', 'flat',...
            'DividerWidth', 4 );
        
        % The second layout is the non-adjustable split between tree+info and the
        % test selector.
        % -- We need a oblong that forms the fake split between thw two
        %    sub-layouts.
        hFakeSplitPanel = uicontrol('Parent', figh, ...
            'Visible',  'off', ...
            'Style', 'text', ...
            'BackgroundColor', SC.CTRL_BG, ...
            'HitTest', 'off', ...
            'Enable', 'inactive');
        lyt = xreggridbaglayout( figh, ...
            'Dimension', [3, 1], ...
            'rowsizes', [-1, 2, 130], ...
            'elements', {lyt, hFakeSplitPanel, obj.View.TestSelector} );
        
        % The adjustable split between the tree+info+test and the multi-panel
        lyt = xregsplitlayout( figh,...
            'Left', lyt,...
            'Right', obj.View.Card,...
            'Split', [0.2, 0.8],...
            'MinWidth', [30, 30], ...
            'DividerStyle', 'flat',...
            'DividerWidth', 4 );
        
        set( obj.Toolbar.Layout, ...
            'ToolBarDraw', 'on', ...
            'packstatus', 'on', ...
            'Visible', 'on');
        
        end  % pCreateLayout
        
        %----------------------------------------
        function pCreateMenus(obj)
        %PCREATEMENUS Create the menus for a Boundary Editor
        %  PCREATEMENUS(OBJ)
        
        figh = obj.Figure;
        
        % Top level menus
        menuFile       = uimenu( 'Parent', figh, 'Label', '&File' );
        menuEdit = uimenu( 'Parent', figh, 'Label', '&Edit' );
        menuView       = uimenu( 'Parent', figh, 'Label', '&View' );
        
        % add window menu
        xregwinlist( figh );
        
        createFileMenu(obj.Actions,menuFile)
        
        uimenu('Parent',menuFile,...
            'Label','&Close',...
            'Separator','on',...
            'Accelerator','w',...
            'Callback', @( src, evt ) obj.close,...
            'Interruptible','off');

        createEditMenu(obj.Actions,menuEdit)
        
        % View Menu items
        obj.View.Panel.addViewMenuItems( menuView );
        
        % Tools menu items
        %  --- Search for additional tools
        ext = mbcextensions.Extensions.Model;
        bdryTools = ext.BoundaryEditorTools;
        if length( bdryTools ) >= 1,
            menuTools = uimenu( 'Parent', figh, 'Label', '&Tools' );
            mbccreateaddonmenus( bdryTools, menuTools, obj );
        end
        
        % Add help menu
        mv_helpmenu( figh, {'&Boundary Editor Help', 'xreg_bdrymodeleditor'} );
        
        end  % pCreateMenus
        
        %----------------------------------------
        function pCreateToolbar(obj)
        %PCREATETOOLBAR Create the toolbar for a Boundary Editor
        %  PCREATETOOLBAR(OBJ)
        
        tblyt = xregtoolbarlayout( obj.Figure, ...
            'toolbardraw', 'off', ...
            'ResourceLocation', xregrespath, ...
            'spacerwidth', 2 );
        tb.Layout = tblyt;
        
        toolbar = get( tblyt, 'ToolBar' );
        
        toolbarGroup = mbcgui.actions.ActionGroup;
        toolbarGroup.Actions = [obj.Actions.FileActionGroup
            obj.Actions.EditActionGroup
            obj.Actions.BestActionGroup
            obj.View.Panel.Actions.ChangeView
            obj.Actions.AllViewGroup
            ];
        tb.handles = toolbarGroup.createToolbutton( toolbar );
        
        % Help
        mv_helptoolbutton( tblyt, 'xreg_bdrymodeleditor' );
        
        % Store in object
        obj.Toolbar = tb;
        
        end  % pCreateToolbar
        
        %----------------------------------------
        function pCreateView(obj)
        %PCREATEVIEW Create the views for a Boundary Editor
        %  PCREATEVIEW(OBJ)
        
        % Create a MultiViewPanel that is setup for the boundary editor views
        obj.View.Panel = mbcgui.multiview.MultiViewPanel( ...
            'Parent', obj.Figure, ...
            'MessageService', obj.MessageService, ...
            'ViewLayoutName', 'BoundaryEditor', ...
            'StatusBar', obj.StatusBar, ...
            'GlobalViewOptions', obj.Actions.AllViewGroup, ...
            'ViewList', xregbdrygui.BdryViewList, ...
            'AlwaysAllowPrintToFigure', false);
        
        % Set up a "card" object so we can display a nice nothing in the "null" case
        sc = mbcgui.util.SystemColorsDbl;
        obj.View.Card = xregcardlayout( obj.Figure, 'numcards', 2 );
        noview = uipanel('Parent', obj.Figure, ...
            'Units', 'pixels', ...
            'BorderType', 'beveledin', ...
            'BackgroundColor', sc.CTRL_SHADOW);
        attach( obj.View.Card, noview,         1 );
        attach( obj.View.Card, obj.View.Panel, 2 );
        
        % If the constraint changes then we might want to switch cards, i.e.,
        % display the "null" view if there is no constraint and the proper view if
        % there is a constraint. Thus we listen to the "ConstraintChange" event.
        obj.pAddListener( event.listener( obj.MessageService, 'ConstraintChange', ...
            @( s, e ) i_cardSwitcher ) );
        
            function i_cardSwitcher
            if isempty( obj.MessageService ) || ~obj.MessageService.hasData,
                % No view
                set( obj.View.Card, 'currentcard', 1 );
                set( obj.Actions.AllViewGroup, 'Enabled', false );
            else
                % There is something to see, so turn on the view
                set( obj.View.Card, 'currentcard', 2 );
            end
            end
        
        % Create a TreeView to display the tree of constraints
        obj.View.Tree = xregbdrygui.TreeView( ...
            'Parent', obj.Figure, ...
            'MessageService', obj.MessageService );
        
        % Create an InfoView to display information about the current constraint
        obj.View.Info = xregbdrygui.InfoView( ...
            'Parent', obj.Figure, ...
            'MessageService', obj.MessageService );
        
        % Create an InfoView to display information about the current constraint
        obj.View.TestSelector = xregbdrygui.TestSelector( ...
            'Parent', obj.Figure, ...
            'MessageService', obj.MessageService );
        
        end
        
    end  % protected methods
    
    
end  % classdef


%------------------------------------------------------------------------------|
function i_BringFigureToFront( obj )
figure( obj.Figure );
end  % i_BringFigureToFront

%------------------------------------------------------------------------------|
function state = i_AskAboutTheOneAndOnlyNode( root, leaf )

question = {
    sprintf( 'There is no boundary model set as best for the %s test plan.', name( root ) )
    sprintf( 'Do you want to set %s as the best boundary model for this test plan?', name( leaf ) )
    };

answer = questdlg( question, 'Boundary Model', 'Yes', 'No', 'Cancel', 'Yes' );

switch lower( answer ),
    case 'yes',
        % "Yes" means set the leaf node as best and proceed, i.e., close the
        % editor
        state = 'off';
        pParent = Parent( leaf );
        pParent.setbest( leaf );
        % It could be that there is an extra layer between the leaf and the
        % root
        if pParent ~= address( root ),
            setbest( root, pParent );
        end
    case 'no',
        % "No" means proceed without a best constraint, i.e., don't set a
        % best but close the editor
        state = 'off';
    case 'cancel',
        state = 'on';
    otherwise
        % Probably managed to "cancel" the dialog. This is a "no"
        state = 'on';
end
end  % i_AskAboutTheOneAndOnlyNode


%------------------------------------------------------------------------------|
function state = i_AskAboutLackOfBestConstraint( root )

question = {
    sprintf( 'There is no boundary model set as best for the %s test plan.', name( root ) )
    'Do you want to proceed without a boundary model for this test plan?'
    };

answer = questdlg( question, 'Boundary Model', 'Yes', 'No', 'Yes' );
switch lower( answer ),
    case 'yes',
        % "Yes" means proceed without a best constraint, i.e., close the
        % editor
        state = 'off';
    case 'no',
        % "No" means don't proceed, i.e., keep the editor open
        state = 'on';
    otherwise
        % Probably managed to "cancel" the dialog. This is a "no"
        state = 'on';
end
end  % i_AskAboutLackOfBestConstraint