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

    function varargout = GuiUtilities(varargin)
%GUIUTILITIES Create the CGDATASETNODE menu and callbacks
%
%  VD  = GUIUTILITIES(ND, 'CREATE', VD) creates the menus for the
%  cgdatasetnode, ND. The modified view data structure is returned in VD.
% 
%  CBS = GUIUTILITIES(ND, 'GET_CALLBACKS') returns handles to the menu
%  callbacks for the cgdatasetnode, ND, in the structure CBS.
%
%  See also CGDATASETNODE/CREATEGUI

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


if nargin==0
    error(message('mbc:guiUtilities:InvalidArgument'));
elseif isa(varargin{1},'cgdatasetnode')
    if nargin>1 && ischar(varargin{2})
        switch lower(varargin{2})
            case 'create'
                varargout{1} = i_Create(varargin{3:end});
            case 'get_callbacks'
                varargout{1} = i_GetCallbacks;
            otherwise
                error(message('mbc:guiUtilities:InvalidArgument1'));
        end
    end
end

%------------------------------------------------------------------
function d = i_Create(d)
%------------------------------------------------------------------
Handles = d.Handles;

% -------- context menus

cb = i_GetCallbacks;

m = uicontextmenu('Parent',Handles.Figure,'Visible','off',...
    'Callback',@cb_SetupMenus);

fm.Overwrite = uimenu(m,'Label','Treat as &Input',...
    'Callback',{cb.overwrite,1});
fm.Evaluate = uimenu(m,'Label','Treat as &Output',...
    'Callback',{cb.evaluate,0});

% Callback set up in menu setup
fm.AddError = uimenu(m,'Label','Create &Error',...
    'Separator','on');
fm.CopyDataset = uimenu(m,'Label','&Copy Current Values',...
    'Callback',{cb.copy_dataset});
fm.Remove = uimenu(m,'Label','&Remove from Data Set',...
    'Callback',cb.remove);
fm.AddDataset = uimenu(m,'Label','Add to &Data Set',...
    'Separator','on', ...
    'Callback',{cb.add_expr});

vis = [fm.AddError fm.Remove fm.CopyDataset];

fm.PlotVis = [vis ...
    fm.AddDataset];

fm.FactorVisBm = [vis ...
    fm.AddDataset];
fm.FactorVisTp = [vis ...
    fm.Overwrite fm.Evaluate];

fn = fieldnames(fm);
h = [];
for i = 1:length(fn)
    this = fm.(fn{i});
    f = isgraphics(this);
    for j = 1:length(f)
        if f(j)
            h = [h this(j)];
        end
    end
end
fm.h = h;
fm.menu = m;
Handles.fm = fm;


% ------- tools menu
m = uimenu(d.ToolsMenu,'Label','&Factors','Separator','on',...
    'Callback',@cb_SetupMenus);
fm.Factors = m;

fm.Overwrite(2) = uimenu(m,'Label','Treat as &Input',...
    'Callback',{cb.overwrite,1});
fm.Evaluate(2) = uimenu(m,'Label','Treat as &Output',...
    'Callback',{cb.evaluate,0});

% Callback set up in menu setup
fm.AddError(2) = uimenu(m,'Label','Create &Error', 'Separator', 'on');
fm.CopyDataset(2) = uimenu(m,'Label','&Copy Current Values',...
    'Callback',{cb.copy_dataset});

fm.Remove(2) = uimenu(m,'Label','&Remove from Data Set',...
    'Callback',cb.remove);
fm.AddDataset(2) = uimenu(m,'Label','Add to &Data Set',...
    'Callback',{cb.add_expr},...
    'Separator','on');


tm.h = [fm.Factors];
tm.FactorBits = tm.h;
tm.PlotBits = tm.h;
tm.LinkBits = [fm.Factors ];
tm.NotLinkBits = [fm.Overwrite(2) fm.Evaluate(2)];

Handles.fm = fm;
Handles.tm = tm;


d.Handles = Handles;
d.CB.EndLinkMain = cb.end_link;

d.Exprs.Linking = 0;


%------------------------------------------------------------------
function fstr = i_prettycell(namec)
%------------------------------------------------------------------
fstr = sprintf('%s, ', namec{:});
if ~isempty(fstr)
    fstr = fstr(1:end-2);
end


%-----------------------------------------------------------------------
function cb = i_GetCallbacks
%-----------------------------------------------------------------------
cb.assign = @cb_Assign;
cb.unassign = @cb_Unassign;
cb.factor_type = @cb_FactorType;
cb.add_error = @cb_AddError;
cb.remove = @cb_Remove;
cb.add_expr = @cb_AddExpr;

cb.show_error = @cb_ShowError;

% treat as input
cb.overwrite = @cb_Overwrite;
%treat as output
cb.evaluate = @cb_Overwrite;
cb.copy_dataset = @cb_CopyDataset;

% not used
cb.link = @cb_StartLink;
cb.make_link = @cb_MakeLink;
cb.end_link = @cb_EndLink;
cb.break_link = @cb_BreakLink;
cb.link_menu = @i_SetupLinkMenu;

% factor menus
cb.SetupMenus = @i_SetupMenus;

%-----------------------------------------------------------------------
function cb_SetupMenus(varargin)
%-----------------------------------------------------------------------
% Callback from tools menu
d = pr_GetViewData;
% Work out whether top stuff is selected, or bottom stuff.
page = d.ViewInfo(d.currentviewinfo);
if ~isempty(page.tpselection)
    top_sel = feval(page.tpselection,d);
else
    top_sel = [];
end
if ~isempty(top_sel)
    i_SetupMenus(d,'top',top_sel);
else
    i_SetupMenus(d,'bottom',[]);
end

%-----------------------------------------------------------------------
function i_SetupMenus(d,list,factor_ind)
%-----------------------------------------------------------------------
% find indices to internal data store
expr_ind = d.Handles.ExprList.Selected;

if nargin<3
    factor_ind = [];
end
switch lower(list)
    case 'bottom'
        sel_ind = expr_ind;
        % Check which menu is being displayed - may need
        %  to make some items invisible.
        set(d.Handles.fm.h,'Visible','off');
        set(d.Handles.fm.BmVis,'Visible','on');
    case 'top'
        sel_ind = factor_ind;
        set(d.Handles.fm.h,'Visible','off');
        set(d.Handles.fm.FactorVisTp,'Visible','on');
end
if strcmp(get(d.Handles.fm.AddDataset(1),'Visible'),'on')
    set(d.Handles.fm.AddError(1),'Separator','off');
else
    set(d.Handles.fm.AddError(1),'Separator','on');
end
sel_fact_i = d.Exprs.factor_index(sel_ind);
top_fact_i = d.Exprs.factor_index(factor_ind);

%%%%%%% BEGINNING OF CHECKING FOR THE MENUS %%%%%%%%%

% Possible to set overwrite flag? (Only need to do this for a factor-click)
f = find(canOverwrite(d.pD.info,top_fact_i));
if ~isempty(f)
    set(d.Handles.fm.Overwrite,'Enable','on','UserData',factor_ind(f));
    needTick = find(canOverwrite(d.pD.info, top_fact_i(f)) == 2, 1);
    if ~isempty(needTick)
        set(d.Handles.fm.Overwrite,'Enable', 'off');
    end
else
    set(d.Handles.fm.Overwrite,'Enable','off');
end

% Possible to clear overwrite flag? (Evaluate)
f = find(canEvaluate(d.pD.info,top_fact_i));
if ~isempty(f)
    set(d.Handles.fm.Evaluate,'Enable','on','UserData',factor_ind(f));
    needTick = find(canEvaluate(d.pD.info, top_fact_i(f)) == 2, 1);
    if ~isempty(needTick)
        set(d.Handles.fm.Evaluate,'Enable', 'off');
    end
else
    set(d.Handles.fm.Evaluate,'Enable','off');
end

% Possible to remove factor?
remove_ind = sel_ind(find(sel_fact_i)); %#ok<FNDSB>
if ~isempty(remove_ind)
    set(d.Handles.fm.Remove,'Enable','on','UserData',remove_ind);
else
    set(d.Handles.fm.Remove,'Enable','off');
end

% Check if any of selection in bottom list are not in dataset
%  We can add these as new factors.
f = find(~sel_fact_i);
if ~isempty(f)
    set(d.Handles.fm.AddDataset,'Enable','on','UserData',sel_ind(f));
else
    set(d.Handles.fm.AddDataset,'Enable','off');
end




[ptrs,linkptrs,~,~,~,~,return_ind] = ...
    ExpandPtrs(d.pD.info,d.Exprs.ptrs(sel_ind),sel_fact_i);
sel_return_ind = sel_ind(return_ind);


% Copy to dataset: Single item selected?
% Additionally - don't allow this feature if the dataset is empty
if length(ptrs)==1 && length(sel_ind)==1 && d.Exprs.eval(sel_ind) && ~isempty(get(d.pD.info, 'Data'))
    set(d.Handles.fm.CopyDataset,'Enable','on','UserData',sel_ind);
else
    set(d.Handles.fm.CopyDataset,'Enable','off');
end

% Specials (eg features) use actual ptrs, not link.
if ~isempty(linkptrs)
    sp = find(isvalid(linkptrs));
    ptrs(sp) = linkptrs(sp);
end

% two items plotted - generate error?
%  Ensure both can be evaluated.
set(d.Handles.fm.AddError,'Enable','off');
if length(ptrs)==2 && all(d.Exprs.eval(sel_return_ind))
    % find matching error
    [~,ind] = i_SubExprExists(d.Exprs.ErrPtrs,ptrs(1),ptrs(2),'reverse');
    if isempty(ind)
        set(d.Handles.fm.AddError,'Enable','on',...
            'Callback',@cb_AddError,'UserData',sel_ind);
    else
        set(d.Handles.fm.AddError,'Enable','on','Callback',@cb_ShowError,...
            'UserData',ind);
    end
end


%-------------------------------------------------
function [exists,ind,dir] = i_SubExprExists(ErrPtrs,ptr2,ptr1,opt)
%-------------------------------------------------

dir = 0; exists = 0; ind = [];

if ~isempty(ErrPtrs)
    compare = double([ptr2 ptr1]);
    % find matching error
    cmat = repmat(compare,size(ErrPtrs,1),1);
    f = find(~any((ErrPtrs(:,2:3) - cmat)'));
    if ~isempty(f)
        ind = ErrPtrs(f(1),1);
        dir = 1;
        exists = 1;
    elseif strcmpi(opt,'reverse')
        % check reverse order too
        f = find(~any((ErrPtrs(:,[3 2]) - cmat)'));
        if ~isempty(f)
            ind = ErrPtrs(f(1),1);
            dir = -1;
            exists = 1;
        end
    end
end

%-----------------------------------------------------------------------
function [unlinkind, invalidind] = i_InvOrUnlink(op, inv_i, cause_i)
%-----------------------------------------------------------------------
unlinkind = []; invalidind = [];
lptrs = get(op, 'linkptrlist');
ptrs = get(op, 'ptrlist');
for count = 1:length(inv_i)
    if ~any(ismember( double(ptrs(inv_i(count))) , double(ptrs(cause_i{count})) ))
        if all( ismember( double(ptrs(cause_i{count})) , double(lptrs(inv_i(count))) ) )
            % The only reason this factor is invalidated is that its link
            % will be broken
            unlinkind = [unlinkind inv_i(count)];
        else
            % This factor is invalidated because it will not be evaluatable
            invalidind = [invalidind inv_i(count)];
        end
    end
end

%-----------------------------------------------------------------------
function cb_Remove(varargin)
%-----------------------------------------------------------------------
% args:  call handle, []
d = pr_GetViewData;
ind = get(varargin{1},'UserData');
fact_i = d.Exprs.factor_index(ind);
factors = d.pD.get('factors');
overwrite = d.pD.get('isoverwrite');
if ~isempty(fact_i)
    f = find(d.pD.isDataOnly(fact_i));
    if ~isempty(f)
        if length(f)<4
            if length(f)==1
                factor_str = 'factor ';
            else
                factor_str = 'factors ';
            end
            fstr = ['Removing data set ', factor_str, ...
                i_prettycell(factors(fact_i(f)))];
        else
            fstr = 'Removing these factors';
        end
        but = questdlg( sprintf( '%s will permanently delete imported data.', fstr),...
            'Data set Viewer',...
            'Remove','Cancel','Cancel');
        % return UNLESS they've pressed remove
        if ~strcmpi( but, 'Remove' )
            return
        end

    end
    [inv_i,cause_i] = CheckRemove(d.pD.info,fact_i);
    if ~isempty(inv_i)
        [unlinkind, invalidind] = i_InvOrUnlink(d.pD.info, inv_i, cause_i);
        cause_i = [cause_i{:}];
        cstr = i_prettycell(factors(unique(sort(cause_i))));
        istr = i_prettycell(factors(invalidind));
        ustr = i_prettycell(factors(unlinkind));
        if isempty(istr) && isempty(ustr)
            dialog = false;
        else
            dialog = true;
        end
        if dialog
            but = i_AsktoDeleteInvalidatedItems(cstr, istr, ustr);
            switch lower(but)
                case 'cancel'
                    return
                case 'continue'
                    % Adding invalid indices below now
            end
        end
        fact_i = union(fact_i,inv_i);
    end

    % Addition - Check the inv_i to see if any are linked pointers.
    % If so, find out if the original factor was an input/output
    currPtrs = get(d.pD.info, 'ptrlist');
    for count = 1:length(inv_i)
        f = find(currPtrs == currPtrs(inv_i(count)));
        f = setdiff(f,inv_i(count));
        overwrite = get(d.pD.info,'iseditable');
        ftype = get(d.pD.info, 'factor_type');
        if overwrite(f)
            ftype(f) = 1;
        else
            ftype(f) = 2;
        end
        d.pD.info = set(d.pD.info, 'factor_type', ftype);
    end

    d.pD.info = d.pD.removefactor(fact_i);

    % Have we removed all imported data ?
    % Ensure the block length is correct
    d.pD.info = d.pD.setblocklen;

    % Did we remove any inputs or overwritten outputs?
    %  Have to re-evaluate the exprlist.
    recalc = 0;
    if any(overwrite(fact_i))
        recalc = 1;
    end
    d.Exprs.recalc = [0 recalc 1 0];
    pr_SetViewData(d);
    ViewNode(d.CGBH);
end

%-----------------------------------------------------------------------
function but = i_AsktoDeleteInvalidatedItems(cstr, istr, ustr)
%-----------------------------------------------------------------------
CGBH = cgbrowser;
% data is still referenced elsewhere
dh= xregdialog('name','Remove Factor from Data Set',...
    'resize','off');
xregcenterfigure(dh,[350 300],CGBH.Figure);
txt1=uicontrol('Parent',dh,...
    'Style','text',...
    'HorizontalAlignment','left',...
    'String',['Removing factor(s) ', cstr, ' will delete and/or unlink the following factors']);
txt2=uicontrol('Parent',dh,...
    'Style','text',...
    'HorizontalAlignment','left',...
    'String','Factors that will be deleted:');
% Generate cell array for list box
lististr = i_GetListContents(istr);
lst1=uicontrol('Parent',dh,...
    'Style','listbox',...
    'String',lististr,...
    'BackgroundColor','w');
txt3=uicontrol('Parent',dh,...
    'Style','text',...
    'HorizontalAlignment','left',...
    'String','Factors that will be unlinked:');
listustr = i_GetListContents(ustr);
lst2=uicontrol('Parent',dh,...
    'Style','listbox',...
    'String',listustr,...
    'BackgroundColor','w');
cont=uicontrol('Parent',dh,...
    'Style','pushbutton',...
    'String','Continue',...
    'Callback',';set(gcbf,''visible'',''off'', ''userdata'', ''continue'');');
cls=uicontrol('Parent',dh,...
    'Style','pushbutton',...
    'String','Cancel',...
    'Callback','set(gcbf,''visible'',''off'', ''userdata'', ''cancel'');');

lyt=xreggridbaglayout(dh,'dimension',[8 3],...
    'rowsizes',[45 15 -1 20 15 -1 20 25],...
    'colsizes',[-1 65 65],...
    'mergeblock',{[1 1],[1 3]},...
    'mergeblock',{[2 2],[1 3]},...
    'mergeblock',{[3 3],[1 3]},...
    'mergeblock',{[4 4],[1 3]},...
    'mergeblock',{[5 5],[1 3]},...
    'mergeblock',{[6 6],[1 3]},...
    'gapx',10, ...
    'border',[10 10 10 10],...
    'packstatus','off',...
    'elements',{txt1,txt2,lst1,[],txt3,lst2,[], [],...
    [],[],[],[],[],[],[],cont, ...
    [],[],[],[],[],[],[],cls});
dh.LayoutManager=lyt;
set(lyt,'packstatus','on');
dh.showDialog(cls);

but = get(dh, 'UserData');
if isempty(but)
    % Have hit kill on the dialog
    but = 'cancel';
end
delete(dh);


%-----------------------------------------------------------------------
function lististr = i_GetListContents(istr)
%-----------------------------------------------------------------------
cp = strfind(istr,',');
if isempty(cp)
    lististr = istr;
else
    for i = 1:length(cp)
        if i==1
            lististr{1} = istr(1:cp(i) - 1);
        end
        if i < length(cp)
            lististr = [lististr; {istr(cp(i)+1:cp(i+1)-1)}];
        else
            lististr = [lististr; {istr(cp(i)+1:end)}];
        end
    end
end

%-----------------------------------------------------------------------
function cb_AddExpr(varargin)
%-----------------------------------------------------------------------

d = pr_GetViewData;
ind = get(varargin{1},'UserData');
ptrs = d.Exprs.ptrs(ind);
needptrs = d.Exprs.need_ptrs(ind);

% Going to have to loop through each expression we want to add
% to ensure all the required inputs exist
fact_i = [];expsNotadd = [];
for i=1:length(ptrs)
    if isddvariable(ptrs(i).info) || isempty(needptrs{i})
        % Adding a DD variable or an expression with no required inputs
        [d.pD.info,ind_fact_i,mess] = AddExpr(d.pD.info,ptrs(i));
        fact_i = [fact_i ind_fact_i];
    else
        expsNotadd = [expsNotadd i];
    end
end

if ~isempty(expsNotadd)
    namesNotadd = [];
    for i=1:length(expsNotadd)
        namesNotadd = [namesNotadd, ptrs(expsNotadd(i)).getname, ', '];
    end
    namesNotadd = namesNotadd(1:end-2);
    messstr  = 'The following expressions need to have their inputs added to the data set before they can be added :';
    messstr = [messstr, char(10), char(10), namesNotadd];
    msgbox(messstr, 'Data set Viewer');
end

if ~isempty(fact_i)
    overwrite = d.pD.get('isoverwrite');
    recalc = any(overwrite(fact_i));
    d.Exprs.recalc = [0 recalc 1 0];
    % Switch to view the new factor(s)
    pr_SetViewData(d);
    ViewNode(d.CGBH,fact_i);

    % Added any values? Do we have any imported data?
    %  Pop up a message saying this might not be the thing to do.
    if ~isempty(mess)
        h=msgbox(mess,'Data set Viewer','help');
        uiwait(h);
    end
end


%-------------------------------------------------------------------
function cb_AddError(varargin)
%-------------------------------------------------------------------
d = pr_GetViewData;

index = get(varargin{1},'UserData');
[ptrs,linkptrs,names] = ...
    ExpandPtrs(d.pD.info,d.Exprs.ptrs(index),d.Exprs.factor_index(index));

if length(ptrs)~=2
    return
end

val = isvalid(linkptrs);
ptrs(val) = linkptrs(val);

% Work out a name for the error.
errname = [names{2} '_minus_' names{1}];

right = ptrs(1);
left = ptrs(2);
if any(~isvalid([right left]))
    if length(index)~=2
        error(message('mbc:guiUtilities:UnknownError'));
    end
    if ~isvalid(right)
        right = d.Exprs.factor_index(index(1));
        if right==0, error(message('mbc:guiUtilities:UnknownError')); end
    end
    if ~isvalid(left)
        left = d.Exprs.factor_index(index(2));
        if left==0, error(message('mbc:guiUtilities:UnknownError')); end
    end
end
d.pD.info = CreateError(d.pD.info,[0 0 1],left,right,errname);

d.Exprs.recalc = [0 0 1 0];
pr_SetViewData(d);
ViewNode(d.CGBH,[]);




%-------------------------------------------------------------------
function cb_ShowError(varargin)
%-------------------------------------------------------------------
d = pr_GetViewData;

index = get(varargin{1},'UserData');

page = d.ViewInfo(d.currentviewinfo);
if ~isempty(page.showindex)
    d = feval(page.showindex,d,index);
    pr_SetViewData(d);
end

%-----------------------------------------------------------------------
function cb_Overwrite(varargin)
%-----------------------------------------------------------------------
d = pr_GetViewData;
ind = get(varargin{1},'UserData');

fact_i = d.Exprs.factor_index(ind);
if ~isempty(fact_i)
    new_val = varargin{3};
    if new_val == 0
        % Check whether any imported data is being set to evaluate.
        %  This will delete the imported data - flag a warning.
        % (NB canOverwrite already prevents errors being altered)
        f = find(d.pD.isUniqueToDataset(fact_i));
        if ~isempty(f)
            factors = get(d.pD.info,'factors');
            fstr = i_prettycell(factors(fact_i(f)));
            but = questdlg({['Setting factors ' fstr] ,...
                'to evaluate will delete imported data.' ...
                'Continue?'},'Data Set Viewer','Continue','Cancel','Cancel');
            switch but
                case 'Continue'
                    % destroy import flag
                    d.pD.info = set(d.pD.info,fact_i(f),'orig_name','');
                otherwise
                    return
            end
        end
        % Check if current factor can be evaluated
        % 10/9/01 - Addition to handle ignored factors
        indinfactor_index = find(ismember(d.Exprs.factor_index, fact_i));
        if ~d.Exprs.eval(indinfactor_index)
            % If not, set to zero.
            d.pD.info = d.pD.set(fact_i,'data',0);
        end
    end
    if new_val==0
        ftype = 'output';
        gflag = 0;
    else
        ftype = 'input';
        gflag = 7;
        d.pD.info = convertGridToBlock(d.pD.info);
    end
    d.pD.info = set(d.pD.info,fact_i,'overwrite',new_val,'grid_flag',gflag,'factor_type',ftype);
    if new_val==0
        % Setting something to evaluate - recalc.
        d.pD.info = d.pD.eval_fill;
    end
    d.Exprs.recalc = [0 0 1 0];
    pr_SetViewData(d);
    ViewNode(d.CGBH);
end

%-----------------------------------------------------------------------
function cb_CopyDataset(varargin)
%-----------------------------------------------------------------------
% Create a new column in dataset, linked to a new value.
% Copy evaluation of ptr into new column.
d = pr_GetViewData;
ind = get(varargin{1},'UserData');
ptr = d.Exprs.ptrs(ind);

d.pD.info = copyfactor(d.pD.info, ptr);

% rebuild picture
d.Exprs.recalc = [0 0 1 0];
pr_SetViewData(d);
ViewNode(d.CGBH); 


%-----------------------------------------------------------------------
%
% Link stuff
%
%-----------------------------------------------------------------------

%-----------------------------------------------------------------------
function cb_StartLink(varargin)
%-----------------------------------------------------------------------
d = pr_GetViewData;
d.Dlg.tmp = d.pD.info;
d = pr_ChangeView(d,'linkdlg');
pr_SetViewData(d);