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

    function varargout = mbcMatchDialog(action, varargin)
%mbcMatchDialog Allow the user to match one set of input factors to another
%
%  [I, OK] = mbcMatchDialog(ACTION, A, B)
%  [I, OK] = mbcMatchDialog(ACTION, A, B, A_TITLE, B_TITLE)
%
%  The output I is the indices into B that A matches to, i.e., A is matched to
%  B(I). The size of I is the same as the size of A.  The output OK is required
%  because we are dealing with a GUI and this output records whether the user
%  clicked ''OK'' or ''Cancel''.  The optional title arguments, A_TITLE and
%  B_TITLE allow for titles or labels to placed at the top of each of the lists
%  of input factors.
%  
%  See also CONBASE, CONINPUTFACTOR, XREGMODEL/GUI_SIGNALCHOOSER.

%  Copyright 2004-2015 The MathWorks, Inc. 

switch action
    case 'figure'
        % create modal dialog
        [varargout{1:2}] = dialog(varargin{:});
    case 'layout'
        % create layout for matching inputs
        varargout{1} = createLayout(varargin{:});
    case 'finalise'
        % finalise matching output
        [varargout{1:2}] = finalise(varargin{:}); 
    case 'validate'
        % validate that there is a valid matching
        varargout{1} = validate(varargin{:});
    case 'initialise'
        % initialise to use new input factors
        initialise(varargin{:});
end

%------------------------------------------------------------------------------|
function figureTitle = i_FigureTitle
figureTitle = 'Match Constraint Inputs';

%------------------------------------------------------------------------------|
function [matches, OK] = dialog(varargin)
%dialog Creates GUI inside a dialog

dlg = mbcgui.container.Dialog( ...
    'Name', i_FigureTitle, ...
    'Size',[600 300],...
    'Resize','off' );

dlg.Content = createLayout(dlg.Figure,varargin{:});

dlg.ValidationFcn = @()validate(dlg.Content);

closeAction = dlg.showDialog();
if strcmp(closeAction,'OK')
    % get updated sweepset from layout userdata
    matches = finalise(dlg.Content);
    OK = true;
else
    matches = finalise(dlg.Content);
    OK = false;
end
delete(dlg);


function layout = createLayout(Parent, cifA, cifB, titleA, titleB)
%createLayout Create the layout
if nargin < 3
    error(message('mbc:coninputfactor:InvalidArguments8'));
end
if nargin < 4
    titleA = 'New Factors';
end
if nargin < 5
    titleB = 'Existing Factors';
end

if length( cifA ) > length( cifB ),
    error(message('mbc:coninputfactor:InvalidArguments9'));
end

layout = i_Layout( Parent, cifA, cifB, titleA, titleB );


function [matches,OK] = finalise(layout)
%finalise Get final values from GUI
ud = get(layout, 'UserData');
matches = ud.info.pMatches;
OK = true;

%------------------------------------------------------------------------------|
function ok = validate(layout)
%validate Check that state of the GUI is valid
udp = get(layout, 'UserData');
matches = udp.info.pMatches;

if any( matches == 0 ),
    xregerror( i_FigureTitle, 'All input factors must be matched' );
    ok = false;
else
    matches = matches(matches~=0);
    if numel( matches ) == numel( unique( matches ) ), 
        ok = true;
    else
        xregerror( i_FigureTitle, 'Factors must be unique' );
        ok = false;
    end
end

function initialise( layout, cifA, cifB )
udp = get(layout, 'UserData');
i_Initialise( udp, cifA, cifB );

%------------------------------------------------------------------------------|
function lyt = i_Layout( parent, cifA, cifB, titleA, titleB )
%i_Layout create layout
if isa( parent, 'xregcontainer' ),
    lyt = parent;
else
    % Set up pointer to hold user data
    udp = xregGui.RunTimePointer;
    udp.LinkToObject( parent );
    
    % A (left hand) list view
    listviewA = i_ListView( parent, {'Name', 'Matches'}, [100, 100] );
    txtA = i_ListTitle( parent, titleA );
    listviewA.SelectionChangedCallback = {@i_ListCallback, udp};

    % B (right hand) list box
    listboxB = uicontrol( 'Parent', parent,...
        'Style', 'listbox',...
        'BackgroundColor', [1, 1, 1],... % white
        'String', '',... % set this later
        'Min', 0, 'Max', 0, ... % single selection
        'Callback', {@i_ListBoxCallback, udp}, ...
        'Tag', 'RightListBox');
    txtB = i_ListTitle( parent, titleB );

    % Selection buttons
    btnSelect = xregGui.iconuicontrol( 'Parent', parent, ...
        'ImageFile', [xregrespath,'\leftarrow.bmp'], ...
        'TransparentColor', [255, 255, 0], ...
        'ToolTip', 'Match current factor to chosen factor', ...
        'Callback', {@i_Select, udp, 'open'}, ...
        'Tag', 'SelectButton');

    lytSelect = xreggridlayout( parent, ...
        'CorrectAlg', 'on', ...
        'Dimension', [3, 1],...
        'Elements', {[], btnSelect, []},...
        'RowSizes', [10, 80, -1]);
    
    % Frame that can hold extra information about the selected signals
    [lytAInfo, aInfo] = i_InfoLayout( parent, 'Factor information' );
    [lytBInfo, bInfo] = i_InfoLayout( parent, 'Factor information' );

    % Principal layout
    elements = { 
        txtA,      [],        txtB; 
        listviewA, lytSelect, listboxB; 
        lytAInfo,  [],        lytBInfo 
    };
    lyt = xreggridlayout( parent,...
        'Dimension', [3, 3],...
        'Correctalg', 'on',...
        'Border', [10, 10, 10, 0],...
        'GapX', 10,...
        'RowSizes', [18, -1, 75],...
        'ColSizes', [-1, 80, -1], ...
        'Elements', elements);
   
    % Setup user data structure and store at end of pointer
    ud = struct( ...
        'figh', parent, ...
        'pMatches', [], ...
        'cifA', [], ...
        'cifB', [], ...
        'listviewA', listviewA, ...
        'listboxB', listboxB, ...
        'btnSelect',btnSelect,...
        'aInfo', aInfo, ...
        'bInfo', bInfo );
    udp.info = ud;
    
    % Initialize the lists
    i_Initialise( udp, cifA, cifB );
    
    set(lyt, 'UserData', udp);
end

%------------------------------------------------------------------------------|
function txt = i_InfoText( parent, string )
%i_InfoText Creates a uicontrol containing text
txt = uicontrol( ...
    'Parent', parent, ...
    'Style', 'text', ...
    'String', string, ...
    'HorizontalAlignment', 'left', ...
    'Callback', '' );

%------------------------------------------------------------------------------|
function [frame, ud] = i_InfoLayout( parent, title )
%i_InfoLayout create information panel

frame = mbcgui.container.layoutpanel('Parent', parent, ...
    'BorderType', 'etchedin', ...
    'Title', title, ...
    'LayoutBorder', [7 0 7 5]);

lbSymbol = i_InfoText( frame, 'Symbol:' );
lbUnit   = i_InfoText( frame, 'Units:' );
lbRange  = i_InfoText( frame, 'Range:' );

ud.Symbol = i_InfoText( frame, '' );
ud.Unit   = i_InfoText( frame, '' );
ud.Range  = i_InfoText( frame, '' );

lyt = xreggridlayout( frame,...
    'Dimension', [3, 2],...
    'Correctalg', 'on',...
    'GapX', 5, ...
    'GapY', 0, ...
    'ColSizes', [40, -1],...
    'RowSizes', [15, 15, 15],...
    'Elements', {lbSymbol, lbUnit, lbRange, ud.Symbol, ud.Unit, ud.Range} );
set(frame, 'LayoutComponent', {lyt});


%------------------------------------------------------------------------------|
function h = i_ListTitle( parent, str )
%i_ListTitle create list title

h = uicontrol( 'Parent', parent,...
        'Style', 'text',...
        'HorizontalAlignment', 'left',...
        'FontWeight', 'bold',...
        'String', str );
    
%------------------------------------------------------------------------------|
function h = i_ListView( parent, colHeaders, colSizes )
% create list view

h = mbcwidgets.List( 'Parent', parent,...
    'Editable', false, ...
    'SelectionMode', 'SingleRow', ...
    'Tag', 'matchList');
    
h.Peer.setColumnData(colHeaders);
h.Peer.setColumnWidths(colSizes);



%------------------------------------------------------------------------------|
function i_Initialise( udp, cifA, cifB )

% update the user data with cifA, cifB information
ud = udp.info;
ud.cifA = cifA;
ud.cifB = cifB;
ud.pMatches = p_Match( cifA, cifB );
udp.info = ud;

matches = ud.pMatches;
aNames = ud.cifA.Name;
bNames = ud.cifB.Name;

% Set the list of symbols that need to be matched to
Data = [aNames(:) cell(length(aNames),1)];
for i = 1:numel( aNames ),
    if matches(i)
        Data{i,2} = bNames{matches(i)};
    end
end
ud.listviewA.Peer.setData(Data);
ud.listviewA.selectRows(1);

% Set the list of possible symbols from the  chosen model
set( ud.listboxB, 'String', bNames );

% Set the initial value of the list box
if matches(1),
    set( ud.listboxB, 'Value', matches(1) );
else
    set( ud.listboxB, 'Value', 1 );
end

i_UpdateInfoDisplays( ud )

%------------------------------------------------------------------------------|
function i_ListBoxCallback( src, evt, udp )
ud = udp.info;

selectionType = get( ud.figh, 'SelectionType' );
i_Select( src, evt, udp, selectionType );

% Is the user double clicked, then select the next item on the list view
if strcmpi( 'open', selectionType ), 
    i_IncrementListView( ud );
end

%------------------------------------------------------------------------------|
function i_Select( ~, ~, udp, selectionType )
% selectionType is one of {normal} | extend | alt | open.
%   'normal' is a regular mouse click
%   'extended' is a shift left click or middle button click
%   'alt' is a control left click or right  button click
%   'open' is a double click
ud = udp.info;
if strcmpi( 'normal', selectionType ),
    % Update the information display
    i_UpdateInfoDisplays( ud )
elseif ~isempty(ud.listviewA.getSelectedRows)
    % Match the chosen symbol to selected current symbol
    i_MatchSymbols( udp );
end

%------------------------------------------------------------------------------|
function i_UpdateInfoDisplays( ud )

aIndex = ud.listviewA.getSelectedRows;
i_UpdateOneInfoDisplay( ud.aInfo, ud.cifA, aIndex )

bIndex = get( ud.listboxB, 'Value' );
i_UpdateOneInfoDisplay( ud.bInfo, ud.cifB, bIndex )
    
%------------------------------------------------------------------------------|
function i_UpdateOneInfoDisplay( info, cif, index )

set( info.Symbol, 'String', cif.Symbol{index} );
set( info.Unit, 'String', cif.Unit{index} );
set( info.Range, 'String', sprintf( '[%.4g, %.4g]', cif.Min(index), cif.Max(index) ) );

%------------------------------------------------------------------------------|
function i_MatchSymbols( udp )
ud = udp.info;

% Get the selected item from the A (left hand) list 
tgtIndex = ud.listviewA.getSelectedRows;

% Get the selected item from the B (left hand) list 
chosen = get( ud.listboxB, 'Value' );

% Updated A (left hand) listview
chosenNames = get( ud.listboxB, 'String' );
ud.listviewA.Peer.setDataAt(chosenNames{chosen},tgtIndex-1,1)

% Update the matches vector
matches = ud.pMatches;
matches(tgtIndex) = chosen;
ud.pMatches = matches;
udp.info = ud;

i_UpdateInfoDisplays( ud )

%------------------------------------------------------------------------------|
function i_IncrementListView( ud )

% Get the current matches vector
matches = ud.pMatches;
nFactors = numel( matches );

% Get the selected item from the list of current symbols
currentIndex = ud.listviewA.getSelectedRows;

% Make the next item in the list the current item
newIndex = mod( currentIndex, nFactors ) + 1;
ud.listviewA.selectRows(newIndex);

% Select the matching factor in this list box
if matches(newIndex),
    set( ud.listboxB, 'Value', matches(newIndex) );
else 
    nB = size( ud.cifB, 2 );
    unmatched = setdiff( 1:nB, matches );
    if any( unmatched ),
        set( ud.listboxB, 'Value', min( unmatched ) );
    else
        set( ud.listboxB, 'Value', 1 );
    end
end

i_UpdateInfoDisplays( ud )

%------------------------------------------------------------------------------|
function i_ListCallback( ~, ~, udp )
% Get the user data 
% If the selected symbol is matched, update the chosen list box
% Call i_UpdateInfoDisplays

% Get the user data
ud = udp.info;

% Get the selected item from the list of current symbols
tgtIndex = ud.listviewA.getSelectedRows;
if ~isempty(tgtIndex)
    % If the slected symbol is matched, update the chosen list box
    matches = ud.pMatches;
    if matches(tgtIndex),
        set( ud.listboxB, 'Value', matches(tgtIndex) );
    end
    
    % Update the info displays
    i_UpdateInfoDisplays( ud );
   set(ud.btnSelect,'Enable','on'); 
else
   set(ud.btnSelect,'Enable','off'); 
end