www.gusucode.com > mbcview 工具箱matlab源码程序 > mbcview/cg_model_wizard.m

    function varargout = cg_model_wizard(action, varargin)
%CG_MODEL_WIZARD  Model import/creation wizard
%
%  CG_MODEL_WIZARD provides the cards and interface functions required by
%  xregwizard to display the model import wizard in cage
%
%  [OK, OUT] = XREGWIZARD(FIGPARENT , TITLE, {@cg_model_wizard 'cardxxx'}, localdata);

%  Copyright 2000-2011 The MathWorks, Inc. and Ford Global Technologies, Inc.

switch lower(action)
    case 'cardtwo' 
        % select models to import
        [varargout{1:nargout}] = i_createCardTwo(varargin{:});
    case 'cardthree'
        % signal assignment
        [varargout{1:nargout}] = i_createCardThree(varargin{:});
    case 'cardfour'
        % enter formula for function model
        [varargout{1:nargout}] = i_createCardFour(varargin{:});
end


%------------------------------------------------------------------------
% CARD TWO FUNCTIONS BELOW
%------------------------------------------------------------------------

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function layout = i_createCardTwo(fh, iFace, localData)

% Have we been called to create the layout or simply update?
if isa(fh, 'xregcontainer')
    layout = fh;
    layoutUD = get(layout, 'UserData');
else
    check = uicontrol('Parent', fh,...
        'Callback', {@i_automatic, iFace},...
        'Style', 'checkbox',...
        'String', 'Automatically assign/create inputs', ...
        'Value', 0,...
        'Visible', 'off');   
    button = uicontrol('Parent', fh,...
        'Callback', {@i_selectall, iFace},...
        'Style', 'pushbutton',...
        'String', 'Select All',...
        'Visible', 'off');    
    txModels = uicontrol('Parent', fh,...
        'Style', 'text',...
        'String', 'Select models:',...
        'Visible', 'off',...
        'HorizontalAlignment', 'left');
    
    list = mbcwidgets.Table1D( 'list', 'Parent', fh, 'SelectionMode', 'MultiRow' );
    cols = {'Model Name', 'Inputs', 'Description'};
    width = [100 270 190];
    list.Peer.setColumnData( cols );
    list.Peer.setColumnWidths( width );
        
    layout = xreggridbaglayout(fh,...
        'dimension', [7 2], ...
        'rowsizes', [15 2 -1 10 5 25 5], ...
        'colsizes', [65 -1], ...
        'border', [7 0 7 7], ...
        'gapx', 20, ...
        'mergeblock', {[1 1] [1 2]}, ...
        'mergeblock', {[3 3] [1 2]}, ...
        'mergeblock', {[5 7] [1 1]}, ...
        'elements', {txModels [] list [] [] button [], ...
        [] [] [] [] [] check [] });
            
    layoutUD.autoCheck = check;
    layoutUD.txModels = txModels;
    layoutUD.ModelList = list;
    layoutUD.nextFcn = @i_cardTwoNext;
    layoutUD.finishFcn = @i_cardTwoFinish;  
end

if nargin > 2
    layoutUD.models   = localData.models;
    layoutUD.modptr   = localData.modptr;
end

feval(iFace.setFinishButton, 0);
feval(iFace.setNextButton, 1);

i_cardTwoUpdate(layoutUD, iFace);
set(layout, 'UserData', layoutUD);

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function i_cardTwoUpdate(layoutUD, ~)
modelInfo = cell( 0, 3 );
% Set model information
for i = 1:length(layoutUD.models)
    modelInfo{i,1} = getname(layoutUD.models{i});
    Symbols = getsymbols(layoutUD.models{i});
    varstr = sprintf( '%s, ', Symbols{:} );
    modelInfo{i,2} = varstr(1:end-2);
    % This is the function string for cgfuncmodel, and the 'created by' info
    % for xregexportmodes.
    modelInfo{i,3} = description( layoutUD.models{i} );
end
layoutUD.ModelList.Peer.setData( modelInfo );
layoutUD.ModelList.selectRows( 1 );

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function i_automatic(obj, ~, iFace)

% when automatic wiring is checked
flag = get(obj, 'Value');

if flag 
    feval(iFace.setFinishButton, 1);
    feval(iFace.setNextButton, 0);
else
    feval(iFace.setFinishButton, 0);
    feval(iFace.setNextButton, 1);
end

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function i_selectall(~, ~, iFace)

% select all models
layoutUD = feval(iFace.getCardUserdata);
layoutUD.ModelList.selectRows( 1:length(layoutUD.models) );

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function i_cardTwoFinish(layoutUD, iFace)

%get the selected models
indices = layoutUD.ModelList.getSelectedRows();
models = layoutUD.models(indices);

layoutUD.CageModels = [];

% Find existing models
proj = get( cgbrowser, 'RootNode' );
modp = proj.getmodels();
modNames = pveceval( modp, @getname );
dd = get( cgbrowser, 'DataDictionary' );

for i = 1:length(models)
    M = models{i};
    R = getranges(M);
    str = getname(M);
    if isempty(str)
        str = 'New_Model';
    end
    %Now, we want to get the inputs sorted out.
    symbols = getsymbols(M);
    nf = length(symbols);
    Minput = null( xregpointer, 1, nf );
    for j = 1:nf
        factorSymbol = symbols{j};
        matchptr = dd.find(factorSymbol);
        if ~isempty(matchptr) %matches a variable in the dictionary, including aliases
            Minput(j) = matchptr;
        else 
            index = find( strcmp( factorSymbol,modNames ) );
            if ~isempty(index) %factor name matches a model
                Minput(j) = modp(index);
            else % nothing matched
                % and add a variable called factorSymbol
                Minput(j) = i_CreateNewVariable( dd, factorSymbol, R(:,j) );
            end
        end
    end
    
    if ~isempty(layoutUD.modptr)
        modptr = layoutUD.modptr;
        %update the model inside the modexpr
        modptr.info = modptr.set('model',M); 
        modptr.info = modptr.set('ptrlist' , Minput);
    else % when a new model is being created
        cagemod = cgmodexpr;
        cagemod = setname(cagemod , str);
        cagemod = set(cagemod , 'model' , M);
        cagemod = set(cagemod , 'ptrlist' , Minput);
        layoutUD.CageModels{i} = cagemod;
    end
end

outputUD.CageModels= layoutUD.CageModels;
feval(iFace.setOutputData, outputUD);

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function [nextCardID, localData] = i_cardTwoNext(layoutUD, ~)

% get selected models
indices = layoutUD.ModelList.getSelectedRows();

% check for no selections
if (length(indices)==1 && indices==-1) || isempty(indices)
    uiwait(errordlg('You must select at least one model before continuing.', ...
        'Model Selection Error', 'modal'));
    nextCardID = [];
    localData = [];
    return
end

models = layoutUD.models(indices);

localData.models = models;
localData.modptr = layoutUD.modptr; 

nextCardID = @i_createCardThree;

%------------------------------------------------------------------------
% CARD THREE FUNCTIONS BELOW
%------------------------------------------------------------------------

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function layout = i_createCardThree(fh, iFace, localData)
% Have we been called to create the layout or simply update?
if isa(fh, 'xregcontainer')
    layout = fh;
    layoutUD = get(layout, 'UserData');
else
    % Create the card
    List = mbcwidgets.Table1D( 'list',....
        'Parent', fh,...
        'SelectionMode', 'SingleRow',...
        'SelectionChangedCallback', {@i_ModelInputSelectionChanged, iFace} );
    List.Peer.setColumnData( {'Model Input','Assigned Input'} );
    List.Peer.setColumnWidths( [120 120] );
   
    selbutton= xregGui.iconuicontrol('parent',fh,...
        'imageFile',cgrespath('leftarrow.bmp'),...
        'transparentColor', [0 255 0],...
        'ToolTip','Assign Input',...
        'visible','off',...
        'callback',{@i_select,iFace});    

    delbutton = xregGui.iconuicontrol('parent',fh,...
        'imageFile',cgrespath('delete.bmp'),...
        'transparentColor', [0 255 0],...
        'ToolTip','Unassign Input',...
        'visible','off',...
        'callback',{@i_unselect,iFace});    
    
    titleText = uicontrol('Parent',fh,...
        'Style','text',...
        'Visible','off',...
        'HorizontalAlignment','left',...
        'String','Assign Cage items to use as the model inputs:');
    
    % listbox with all variables and models
    namelist = cgtools.exprList(...
        'Parent', fh, ...
        'DisplayHeaderRow', true,... 
        'DisplayTypeColumn', false,...
        'ItemHeaderText', 'Available Inputs' );
    namelist.addListeners( handle.listener( namelist, 'SelectionChanged', {@i_SelectedCageItemChanged, iFace} ) );

    layout = xreggridbaglayout( fh,...
        'Dimension', [6, 3],...
        'Rowsizes', [15 -1 25 10 25 -1],...
        'Colsizes', [-1 25 -1],...
        'gapx', 25,...
        'gapy', 2,...
        'border', [7 7 7 7],... 
        'Mergeblock', {[2 6], [1 1]},...
        'Mergeblock', {[2 6], [3 3]},...
        'Mergeblock', {[1 1], [1 3]},...
        'Elements', {titleText, [],        [];
                     List,      [],        namelist;
                     [],        selbutton, [];
                     [],        [],        [];          
                     [],        delbutton, [];            
                     [],        [],        []} );            
    
    layoutUD.List = List;
    layoutUD.namelist = namelist;
    layoutUD.selbutton = selbutton;
    layoutUD.delbutton = delbutton;
    
    set(layout,'packstatus','on');
end

if nargin >2
    layoutUD.models = localData.models;
    layoutUD.modptr = localData.modptr;
end

% fill the card with information
layoutUD = i_cardThreeUpdate(layoutUD, iFace);
set(layout, 'UserData', layoutUD);


%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function layoutUD = i_cardThreeUpdate(layoutUD, iFace)

% fill the rhs list
layoutUD = i_InputList(layoutUD);

% And then fill the lhs list
if ~isempty(layoutUD.modptr)
    % We are rewiring an existing model - get everythng from the model.
    pExistingModel = layoutUD.modptr;
    inputPtrs = pExistingModel.getinputs();
    Symbols = getsymbols( pExistingModel.get('model') );
else
    % We have a new model - need to do some 'guessing' of inputs.
    models = layoutUD.models;
    Symbols = cellfun( @getsymbols, models, 'UniformOutput', false );    
    Symbols = unique( vertcat( Symbols{:} ) );
    pDD = get(cgbrowser, 'DataDictionary');
    inputPtrs = null( xregpointer, length(Symbols), 1 );
    for n = 1:length(Symbols)
        pExistingVariable = pDD.find( Symbols{n} );
        if ~isempty( pExistingVariable )
            inputPtrs(n) = pExistingVariable;
        end
    end
end

layoutUD.Symbols = Symbols;
layoutUD.matchedInputs = inputPtrs;
%Update the list based on these Symbols/inputPtrs
i_updateList( layoutUD );
% Select stuff
layoutUD.selectedIndex = 1;
layoutUD.List.selectRows( 1 );

% Sync selections in each list
i_SyncLists( layoutUD );
% Make sure the UnSelect button is correct given the left list selection
iEnableUnSelectButton( layoutUD );

layoutUD.finishFcn = @i_cardThreeFinish;

% enable the finish button, disable the next button
feval(iFace.setNextButton, 'off');
feval(iFace.setFinishButton, 'on');

% --------------------------------------------------------
function i_updateList( layoutUD )

Symbols  = layoutUD.Symbols;
inputPtrs  = layoutUD.matchedInputs;

numSymbols = length(Symbols);
listData= cell( numSymbols, 2 );
listIcons(1:numSymbols,1) = {''};
listData(:,1) = Symbols;
hasMatch = isvalid( inputPtrs );
if any( hasMatch )
    listData(hasMatch,2) = pveceval( inputPtrs(hasMatch), @getname );
    listIcons(hasMatch) = pveceval( inputPtrs(hasMatch), @(e)cgrespath(iconfile(e)) );
end
layoutUD.List.Peer.setData( listData );
layoutUD.List.Peer.setIconData( listIcons, 1);

% --------------------------------------------------------
function i_SyncLists( layoutUD )
% Synchronize the selection in the right hand list based on the selection
% in the left hand list. Also make sure the Select and unSelect buttons are
% correctly enabled.

% Get the matched Cage variable for the selected model input.
pSelectedInput = layoutUD.matchedInputs( layoutUD.selectedIndex );
% if pSelectedInput is null then this input has nothing assigned. In this
% case we won't update the right hand list. It is possible that the user
% has selected the item they want on that list first, and removing that
% selection is annoying.
if ~isnull( pSelectedInput )
    set( layoutUD.namelist, 'SelectedItems', pSelectedInput );
end

% As we may have changed the selection in the right hand list we need to
% correctly enable/disable the Select button.
iEnableSelectButton( layoutUD );

% --------------------------------------------------------
function iEnableUnSelectButton( layoutUD )
% If the matched input is NULL then nothing is matched and we disable the
% unselect button.
pSelectedInput = layoutUD.matchedInputs( layoutUD.selectedIndex );
if isnull( pSelectedInput )
    unselectButtonStatus = 'off';
else
    unselectButtonStatus = 'on';        
end
set( layoutUD.delbutton, 'Enable', unselectButtonStatus );

% --------------------------------------------------------
function iEnableSelectButton( layoutUD )
% We've selected no cage items in the rhs list - disable the 'Select'
% button.
if isempty( layoutUD.namelist.SelectedItems )
    selectButtonStatus = 'off';
else
    selectButtonStatus = 'on';
end
set( layoutUD.selbutton, 'Enable', selectButtonStatus );

% --------------------------------------------------------
% function i_InputList
% --------------------------------------------------------
function layoutUD = i_InputList(layoutUD)

%Set up a list of available inputs to the exportmodel
proj = get(cgbrowser, 'RootNode');

pVariables = proj.getvars();
pModels = proj.getmodels();

if ~isempty( layoutUD.modptr )
    % If we are wiring an existing model we cannot use that model, or models
    % that contain that model, as inputs to this model.    
    allowedModels = @(m)~anymember( layoutUD.modptr, [address(m); getptrs(m)] );
    pModels = pfilter( pModels, allowedModels );
end

pInputs = [pVariables, pModels];
set( layoutUD.namelist, 'Items', pInputs );
if isempty( pInputs )
    set(layoutUD.selbutton,'Enable', 'off'); 
end

% --------------------------------------------------
% function i_select
% --------------------------------------------------
function i_select(~, ~, iFace)

layoutUD = feval(iFace.getCardUserdata);
pInput = get( layoutUD.namelist, 'SelectedItems' );
layoutUD = i_SetSelection( layoutUD, pInput );
feval(iFace.setCardUserdata, layoutUD);

% --------------------------------------------------
% function i_unselect
% --------------------------------------------------
function i_unselect(~, ~, iFace)

layoutUD = feval(iFace.getCardUserdata);
layoutUD = i_SetSelection( layoutUD, xregpointer );
feval(iFace.setCardUserdata, layoutUD);

%------------------------------------------------------------------------
function layoutUD = i_SetSelection( layoutUD, pInput )
% Get the current selection
selectedIndex = layoutUD.selectedIndex;
layoutUD.matchedInputs( selectedIndex ) = pInput;
%Update the list based on new matchedPtrs
i_updateList( layoutUD );
% Since we changed the selection (either changed or removed a match we need
% to update the enabled status of the Unselect button.
iEnableUnSelectButton( layoutUD );
% restore the selection
layoutUD.List.selectRows( layoutUD.selectedIndex );

%------------------------------------------------------------------------
%  Callbacks from the signal list
%------------------------------------------------------------------------
function i_ModelInputSelectionChanged(~, evt, iFace)
layoutUD = feval(iFace.getCardUserdata);
layoutUD.selectedIndex = evt.data.SelectedDataRows;

% Select the current matched item in the right-hand list
i_SyncLists( layoutUD )
% Make sure the UnSelect button is correct given the left list selection
iEnableUnSelectButton( layoutUD );

feval(iFace.setCardUserdata, layoutUD);

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function i_SelectedCageItemChanged(~, ~, iFace)
layoutUD = iFace.getCardUserdata();
% As we changed the selection in the right hand list we need to correctly
% enable/disable the Select button.
iEnableSelectButton( layoutUD );
    
%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function i_cardThreeFinish(layoutUD, iFace)

%get the selected models
models = layoutUD.models;
pDD = get( cgbrowser, 'DataDictionary');

% Initialize the output
CageModels = {};

% A lookup table for the input variables we create.
createdInputs = struct();
for n = 1:length( models )
    M = models{n};
    S = getsymbols( M );
    R = getranges( M );
    modelName = getname( M );
    if isempty( modelName )
        modelName = 'model';
    end
    modelInputPtrs = null( xregpointer, 1, length(S) );
    for factorIndex = 1:length( S )
        factorSymbol = S{factorIndex};
        ind = strcmp( layoutUD.Symbols, factorSymbol );
        inputPtr = layoutUD.matchedInputs( ind );
        if isnull( inputPtr )            
            % We have no matched input - if we already created a variable
            % for this symbol we will use that, otherwise we'll create a
            % new variable.
            if isfield( createdInputs, factorSymbol )
                inputPtr = createdInputs.(factorSymbol);
            else
                inputPtr = i_CreateNewVariable( pDD, factorSymbol, R(:,factorIndex) );
                createdInputs.(factorSymbol) = inputPtr;
            end
        end
        modelInputPtrs(factorIndex) = inputPtr;        
    end
    
    if ~isempty(layoutUD.modptr)
        modptr = layoutUD.modptr;
        %update the model inside the modexpr
        modptr.info = modptr.set('model',M); 
        modptr.info = modptr.set('ptrlist' , modelInputPtrs);
    else % when a new model is being created
        cagemod = cgmodexpr;
        cagemod = setname(cagemod, modelName);
        cagemod = set(cagemod, 'model' , M);
        cagemod = set(cagemod, 'ptrlist' , modelInputPtrs);
        CageModels{n} = cagemod;
    end    
    
end

outputUD.CageModels= CageModels;
feval(iFace.setOutputData, outputUD);

%------------------------------------------------------------------------
%
%------------------------------------------------------------------------

function layout = i_createCardFour(fh, iFace, localData)

if isa(fh, 'xregcontainer')
    layout = fh;
else
    txPrompt = uicontrol('Parent', fh,...
        'Style', 'text',...
        'HorizontalAlignment','left',...
        'String', 'Enter formula for function model (e.g. ratio = x/y):',...
        'Visible','off');   
    txEdFormula =  uicontrol('Parent', fh,...
        'Style', 'edit',...
        'HorizontalAlignment','left',...
        'BackgroundColor',[1 1 1],...
        'Visible','off');
    layout = xreggridbaglayout(fh,...
        'dimension', [4 1],...
        'rowsizes', [-1 15 20 -1],...
        'gapy', 2, ...
        'border', [30 0 30 0], ...
        'elements', {[] txPrompt txEdFormula []});
    
    layoutUD.txEdFormula = txEdFormula;
    layoutUD.nextFcn    = @i_cardFourNext;
 
    if nargin > 2
        layoutUD.models = localData.models;
        layoutUD.modptr = localData.modptr;   

        if ~isempty(layoutUD.modptr) % if we are adjusting an existing function model
            rhs = get(layoutUD.models{1},'function');
            name = getname(layoutUD.models{1});
            set(layoutUD.txEdFormula, 'String', [name ' = ' rhs]);
        end
    else
        layoutUD.models = [];
        layoutUD.modptr = [];   
    end

    set(layout, 'UserData', layoutUD);
end

feval(iFace.setFinishButton, 'off');
feval(iFace.setNextButton,   1);


%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function [nextCardID, localData] = i_cardFourNext(layoutUD, iFace)

[OK, layoutUD] = i_Parse(layoutUD, iFace);

if OK
    localData.models = layoutUD.models;
    localData.modptr = layoutUD.modptr;

    nextCardID = @i_createCardTwo;
else
    nextCardID = [];
    localData = [];
end


%------------------------------------------------------------------------
%
%------------------------------------------------------------------------
function [ok, layoutUD]=i_Parse(layoutUD, iFace)

ok = 0;

string = get(layoutUD.txEdFormula,'String');
if isempty(string)
    uiwait( errordlg('You must enter a formula string.' , ...
        'Function Model Error' , 'modal') );
    return
end

eqindx = strfind(string,'=');

% If there is no '=' sign then eqindx will be empty.
if isempty(eqindx)
    uiwait( errordlg('Your formula should include an equals sign.' , ...
        'Function Model Error' , 'modal') );
    return
end

% split on the '='
name = string(1:eqindx-1);
func = string(eqindx+1:end);

model = cgfuncmodel;
model = setname( model, name );
[model, ok, msg] = setfunction( model, func );
if ok
    layoutUD.models = {model};
    feval(iFace.setCardUserdata, layoutUD);
else
    uiwait( errordlg(msg , 'Function Model Error' , 'modal') );
end

%------------------------------------------------------------------------
function newVal = i_CreateNewVariable( dd, name, range )
[dd.info, newVal] = add(dd.info, name);
newVal.info = newVal.set('range',    range(:).');
newVal.info = newVal.set('value',    range(1) );
newVal.info = newVal.set('setpoint', mean(range) );