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

    classdef StorageView < xregdatagui.AbstractDataView
    %xregdatagui.StorageView class
    %   xregdatagui.StorageView extends xregdatagui.AbstractDataView.
    %
    %    xregdatagui.StorageView 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'
    %       MessageService - Property is of type 'handle' (read only)
    %       Container - Property is of type 'handle'
    %       UIContextMenu - Property is of type 'MATLAB array'
    %       Listeners - Property is of type 'handle vector' (read only)
    %       ObjectListview - Property is of type 'handle' (read only)
    %       DataListview - Property is of type 'handle' (read only)
    %       Buttons - Property is of type 'MATLAB array' (read only)
    %       StorageCache - Property is of type 'MATLAB array'
    %
    %    xregdatagui.StorageView methods:
    %       gettitle - returns string describing this view
    
    %  Copyright 2015-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (AbortSet, SetObservable)
        %STORAGECACHE Property is of type 'MATLAB array'
        StorageCache = [];
        %DataEditor data editor
        DataEditor
    end
    
    properties (SetAccess=protected, AbortSet)
        %OBJECTLISTVIEW Property is of type 'handle' (read only)
        ObjectListview = [];
        %DATALISTVIEW Property is of type 'handle' (read only)
        DataListview = [];
        %BUTTONS Property is of type 'MATLAB array' (read only)
        Buttons = [];
        %TableListeners store for table listeners
        TableListeners
        %Figure storage figure
        Figure
        ProjectStorage
        CurrentMode = 'none';
        %hProjectName display of current MBC project name
        hProjectName
        %hDataSelector popup to select data item
        hDataSelector
    end
    
    methods  % constructor block
        function obj = StorageView(varargin)
        %STORAGEVIEW constructor
        %
        %  OBJ = STORAGEVIEW(VARARGIN)
        
        % Do the setup stuff from inside the AbstractDataView constructor
        obj@xregdatagui.AbstractDataView(varargin{ : }); % converted super class constructor call
        
        % Create the graphical objects and put in the Display field
        obj.pCreateDisplay;
        
        % Get the current storage cache
        s = obj.pUpdateStorageVersion(getpref(mbcprefs('mbcstorage'), 'storage'));
        
        end  % storageview
        
    end  % constructor block
    
    
    methods
    
        function set.StorageCache(obj,Cache)
        obj.StorageCache = Cache;
        obj.pStorageCacheChanged
        end
    end   % set and get functions
    
    methods (Static) 
        function [f,obj] = createFigure(DataEditor)
        % Try getting the storage handle
        f = mvf('storage');
        
        % Do we already have a valid storage handle?
        if isgraphics(f)
            figure(f);
            obj = f.LayoutManager;
            return
        end
        
        % Create a figure to hold the storage view
        f = xregfigure('Visible', 'off',...
            'Name', 'Import Variables, Filters and Editor Layout',...
            'Tag', 'storage');
        obj = xregdatagui.StorageView('Parent',f,...
            'MessageService', DataEditor.MessageService,...
            'DataEditor',DataEditor);
        f.CloseRequestFcn = @obj.onStorageClosed;
        % Listen to the visibility of the parent to ensure that we are invisible
        % when they are - i.e. simulate a close clicked
        deFig = obj.DataEditor.Figure;
        listeners = [event.proplistener(deFig, deFig.findprop('Visible'), 'PostSet',@obj.onStorageClosed);
            event.listener(deFig, 'ObjectBeingDestroyed',@obj.onDataEditorDeleted)];
        obj.Figure = f;
        xregcenterfigure(f,[550 500],deFig);
        % Push the view into the new figure
        set(f, 'LayoutManager', obj,...
            'UserData', listeners,...
            'Visible', 'on');
        obj.pSetAppendStatus
        end
        
    end
    
    methods  % public methods
        
        function delete(obj)
        %delete destructor - delete figure
        if isgraphics(obj.Figure)
            delete(obj.Figure)
        end
        
        pObjectBeingDestroyed(obj)
        
        end
        %----------------------------------------
        function out = gettitle(obj) %#ok<MANU>
        %GETTITLE returns string describing this view
        %  OUT = GETTITLE(OBJ)
        
        out = 'Storage';
        end  % gettitle
        
        %----------------------------------------
        function pAppendCurrentObject(obj, dataIndex,index)
        %PAPPENDCURRENTOBJECT Append the current object in the correct place
        %  PAPPENDCURRENTOBJECT(OBJ) adds the current object to the sweepsetfilter.
        
        % Get the currently selected item
        if nargin<3
            index = obj.pGetListviewIndex();
        end
        % Could anything have been clicked?
        if ~isscalar(index)
            return
        end
        % Get the object to be added
        data = obj.StorageCache{index};
        
        % Set default for dataIndex which is the index of the data objcts in the
        % current item which are to be added - all of them
        if nargin < 2 || isequal(dataIndex,-1) 
            dataIndex = 1:size(data.data, 1);
        end
        
        set(obj.Figure,'Pointer','watch');
        drawnow update
        % Which function should be called for the type of object being added
        switch data.type
            case 'filter'
                addSweepsetfilterObject(obj, data, dataIndex, @addFilter);
            case 'variable'
                addSweepsetfilterObject(obj, data, dataIndex, @addVariable);
            case 'sweepfilter'
                addSweepsetfilterObject(obj, data, dataIndex, @addSweepFilter);
            case 'sweepnote'
                addSweepsetfilterObject(obj, data, dataIndex, @addSweepNote);
            case 'sweepvariable'
                addSweepsetfilterObject(obj, data, dataIndex, @addSweepVariable);
            case 'xregdataeditorlayout'
                % indices are ignored for layouts
                updateEditorLayout(obj, data);
            case {'resampling','xregmonitorplotproperties'}
                % obsolete storage types
            otherwise
                error(message('mbc:xregdatagui:storageview:InvalidProperty'));
        end
        set(obj.Figure,'Pointer','arrow');
        end  % pAppendCurrentObject
        
        
        %----------------------------------------
        function pCreateDisplay(obj)
        %PCREATEDISPLAY Create the storageview UI
        %  PCREATEDISPLAY(OBJ) creates the UI for the storageview.

        % project and data selector
        obj.hProjectName = uicontrol('Parent',obj.Parent,...
            'Style','text',...
            'HorizontalAlignment','left');
        ProjectLabel = xregGui.labelcontrol( 'Parent', obj.Parent,...
            'String', 'MBC project: ',...
            'ControlSizeMode', 'relative',...
            'LabelSizeMode', 'absolute',...
            'LabelSize', 100,...
            'ControlSize', 1,...
            'Control', obj.hProjectName );
        obj.hDataSelector = uicontrol('Parent',obj.Parent,...
            'Style','popupmenu',...
            'Callback',@obj.onSelectData,...
            'Enable','off',...
            'String','<none>');
        DataLabel = xregGui.labelcontrol( 'Parent', obj.Parent,...
            'String', 'Data set: ',...
            'ControlSizeMode', 'relative',...
            'LabelSizeMode', 'absolute',...
            'LabelSize', 100,...
            'ControlSize', 1,...
            'Control', obj.hDataSelector );
        DataGrid = xreggridbaglayout(obj.Parent,...
            'packgroup', 'xregdatagui.storageview',...
            'dimension', [2 1],...
            'elements', {ProjectLabel DataLabel},...
            'rowsizes', [25 25],...
            'Border',[20 5 20 5],...
            'gapy', 2);
        
        objectPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'BorderType', 'beveledin');
        
        obj.ObjectListview = mbcwidgets.List('Parent',objectPanel,...
            'UIContextMenu',obj.UIContextMenu,...
            'SelectionMode','SingleRow',...
            'IconLocation',xregrespath,...
            'Editable',true,...
            'IconTransparentColor',[0 255 0]);
        obj.ObjectListview.ColumnHeaders ={'Stored Information Types'};
        obj.ObjectListview.ColumnWidths = 200;
        obj.ObjectListview.EditableColumns = 1;
        
        dataPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'BorderType', 'beveledin');
        
        % Create the list
        control = mbcwidgets.List('Parent',dataPanel,...
            'UIContextMenu',obj.UIContextMenu,...
            'SelectionMode','MultiRow',...
            'IconLocation',xregrespath,...
            'IconTransparentColor',[0 255 0]);
        
        control.ColumnHeaders = {''};
        control.ColumnWidths = 200;
        % Hold the object
        obj.DataListview = control;
        
        % Put the controls in panels
        set(objectPanel, 'LayoutComponent', obj.ObjectListview);
        set(dataPanel, 'LayoutComponent', obj.DataListview );
        
        % Split them
        splitLayout = xregsplitlayout(obj.Parent,...
            'packgroup', 'xregdatagui.storageview',...
            'packstatus', 'on',...
            'orientation', 'lr',...
            'left', objectPanel,...
            'right', dataPanel,...
            'dividerstyle', 'flat',...
            'dividerwidth', 4);
        
        % Add a toolbar
        toolbarPanel = mbcgui.container.layoutpanel(...
            'Parent', obj.Parent, ...
            'BorderType', 'beveledin');
        tb = obj.pCreateToolbar(toolbarPanel);
        set(toolbarPanel, 'LayoutComponent', tb);
        
        % And Create the main Display object
        grid = xreggridbaglayout(obj.Parent,...
            'packgroup', 'xregdatagui.storageview',...
            'dimension', [2 1],...
            'elements', {DataGrid splitLayout},...
            'rowsizes', [60 -1],...
            'gapy', 2);
        
        infoString = sprintf(['Use the toolbar buttons to import variables, filters, and plot layouts. ',...
            'You can import from other data sets in the current project, or from files ',...
            '(MBC project files or MAT files exported from the Data Editor). ',...
            'After you import, if there are multiple data sets, select one in the list.\n\n',...
            'To use all items in the data set in your current session, select the ''Apply in Data Editor'' button. ',...
            'To use individual settings, double-click the left or right list items.']);
        
        infoPane = mbcgui.container.InfoPane('Parent',obj.Parent,...
            'Center',grid,...
            'InfoHeight',100,...
            'InfoString',infoString);
        
        obj.ContentHandle = xreggridbaglayout(obj.Parent,...
            'packgroup', 'xregdatagui.storageview',...
            'dimension', [2 1],...
            'elements', {toolbarPanel infoPane},...
            'rowsizes', [31 -1],...
            'gapy', 2);
        
        
        % Listen to changes in the storage cache to update the displays
        listeners = {...
            handle.listener(obj.ObjectListview, 'SelectionChanged', @obj.onItemClick);...
            handle.listener(obj.ObjectListview, 'ValueChanged', @obj.onLabelEdit);...
            handle.listener(obj.ObjectListview, 'ActionPerformed', @obj.onDoubleClick);...
            handle.listener(obj.DataListview,   'ActionPerformed', @obj.onDataDoubleClick);...
            handle.listener(obj.ObjectListview, 'KeyTyped', @obj.onKeyPressed);...
            };
        
        obj.TableListeners = [obj.TableListeners ; listeners];
        end  % pCreateDisplay
        
        %----------------------------------------
        function [toolbar] = pCreateToolbar(obj, hParent)
        %PCREATETOOLBAR Create the toolbar for the storageview
        %  TOOLBAR = PCREATETOOLBAR(OBJ) creates the toolbar for the storageview.
        
        % Create the toolbar
        toolbar = xregGui.uitoolbar('Parent', hParent, 'resourcelocation', xregrespath);
        
        % Turn off redrawing whilst adding buttons
        toolbar.setRedraw(false);
        
        % Define a transparent colour
        transparentColor = [0 255 0];
        
        
        % Get the callback functions
        funs = obj.pToolbarCallbacks;
        
        obj.Buttons.ImportCurrent = xregGui.uipushtool(toolbar,...
            'TooltipString', 'Import from data sets in current project',...
            'ClickedCallback', @obj.onImportCurrentProject,...
            'imageFile', 'mbcmodelapp.bmp',...
            'Separator', 'off',...
            'Interruptible', 'off',...
            'transparentcolor', transparentColor);        
        
        obj.Buttons.ImportStorage = xregGui.uipushtool(toolbar,...
            'TooltipString', 'Import from file',...
            'ClickedCallback', funs.ImportStorage,...
            'imageFile', 'importStorage.bmp',...
            'Separator', 'off',...
            'Interruptible', 'off',...
            'transparentcolor', transparentColor);
        
        obj.Buttons.DeleteObject = xregGui.uipushtool(toolbar,...
            'TooltipString', 'Delete selected item',...
            'ClickedCallback', funs.DeleteObject,...
            'imageFile', 'delete.bmp',...
            'Separator', 'on',...
            'Interruptible', 'off',...
            'transparentcolor', transparentColor);
        
        obj.Buttons.AppendObject = xregGui.uipushtool(toolbar,...
            'TooltipString', 'Apply in data editor',...
            'ClickedCallback', funs.AppendObject,...
            'imageFile', 'Confirm_16.bmp',...
            'Separator', 'on',...
            'Interruptible', 'off',...
            'transparentcolor', transparentColor);
        
        % Add a help toolbar button
        mv_helptoolbutton(toolbar, 'xreg_data_storage');
        
        % Turn on drawing and redraw the bar
        toolbar.setRedraw(true);
        toolbar.drawToolBar;
        
        end  % pCreateToolbar
        
        %----------------------------------------
        function pDeleteCurrentObject(obj,index)
        %PDELETECURRENTOBJECT Delete the currently selected object
        %   OUT = PDELETECURRENTOBJECT(IN)
        
        % Get the currently selected item
        if nargin<2
            index = obj.pGetListviewIndex();
        end
        % Could anything have been clicked?
        if isempty(index)
            return
        end
        % Delete from the cache
        obj.StorageCache(index) = [];
        end  % pDeleteCurrentObject
        
        %----------------------------------------
        function index = pGetListviewIndex(obj)
        %PGETLISTVIEWINDEX gets the currently selected index from the listview
        %   OUT = PGETLISTVIEWINDEX(IN)
        
        index = obj.ObjectListview.getSelectedRows;
        
        end  % pGetListviewIndex
        
        %----------------------------------------
        function pObjectBeingDestroyed(obj, ~,~)
        %POBJECTBEINGDESTROYED called when the view is being destroyed
        %   POBJECTBEINGDESTROYED(OBJ, EVENT)
        
        % Save the current storage cache and version number
        store.data = obj.StorageCache;
        store.version = 1;
        setpref(mbcprefs('mbcstorage'), 'storage', store);
        
        end  % pObjectBeingDestroyed
        
        %----------------------------------------
        function pPostSetDmsIsReadOnly(obj , ~,~)
        %PPOSTSETDMSISREADONLY A short description of the function
        %   PPOSTSETDMSISREADONLY(OBJ, EVENT)
        
        % keep data layout storage
        obj.StorageCache = filterDisplayStorage(obj.StorageCache);

        end  % pPostSetDmsIsReadOnly
        
        %----------------------------------------
        function pSetAppendStatus(obj)
        %PSETAPPENDSTATUS Check whether selected item can be appended
        %  PSETAPPENDSTATUS(OBJ) checks whether the currently selected item can be
        %  appended to the sweepsetfilter and sets the enable status of the
        %  associated toolbar button appropriately.
        
        enableAppend = mbconoff( ~isempty(obj.StorageCache) );
        % Set the Append Button state
        set(obj.Buttons.AppendObject, 'Enable', enableAppend);
        
        end  % pSetAppendStatus
        
        %----------------------------------------
        function pStorageCacheChanged(obj)
        %PSTORAGECACHECHANGED storache cache has changed
        %  PSTORAGECACHECHANGED(OBJ)
        
        % First update the Object Listview
        obj.pUpdateObjectListview;
        % Need to redraw the data listview
        obj.pUpdateDataListview;
        % Update the current item can append status
        obj.pSetAppendStatus;
        % Default position
        enable = 'off';
        % Can anything be deleted or saved to file
        if ~isempty(obj.StorageCache)
            enable = 'on';
        end
        % Set the buttons state
        set(obj.Buttons.DeleteObject, 'Enable', enable);
        
        end  % pStorageCacheChanged
        
        %----------------------------------------
        function [funs] = pToolbarCallbacks(obj)
        %PTOOLBARCALLBACKS Callbacks for the toolbar buttons
        %  FUNS = PTOOLBARCALLBACKS(OBJ) provides a structure containing callbacks
        %  for the toolbar.
        
        funs.ImportStorage   = @obj.onImportStorage;
        funs.AppendObject    = @obj.onAppendObject;
        funs.DeleteObject    = @obj.onDeleteObject;
        end  % pToolbarCallbacks
        
        %----------------------------------------
        function pUpdateDataListview(obj,selectedIndex)
        %PUPDATEDATALISTVIEW Update the data list
        %  PUPDATEDATALISTVIEW(OBJ) updates the list that displays information
        %  about the currently selected item.
        
        % What is selected in the object listview
        if nargin<2
            selectedIndex = obj.pGetListviewIndex();
        end
        
        % If noting is selected then do nothing
        if isempty(selectedIndex)
            obj.DataListview.setData([]);
            return
        end
        
        IconList = {'filterIcon.bmp'
            'variableIcon.bmp'
            'sweepFilterIcon.bmp'
            'sweepNoteIcon.bmp'
            'editorLayoutIcon.bmp'
            'sweepVariableIcon.bmp'};
        
        % What are we going to display
        data = obj.StorageCache{selectedIndex}.data;
        % Which Icon and column headers to use, plus a bit of pre-display massaging
        switch obj.StorageCache{selectedIndex}.type
            case 'filter'
                icon = 1;
                columnNames = {'Filter Definitions'};
            case 'variable'
                icon = 2;
                columnNames = {'Variable Definitions' 'Units'};
            case 'sweepfilter'
                icon = 3;
                columnNames = {'Test Filter Definitions'};
            case 'sweepnote'
                icon = 4;
                columnNames = {'Test Note Definitions', 'Note String'};
            case 'xregdataeditorlayout'
                icon = 5;
                columnNames = {'Views'};
                % Re-arrange this to look nicer
                data = i_getLayoutsFromSerializedData(obj, data);
            case 'sweepvariable'
                icon = 6;
                columnNames = {'Test Variable Definitions', 'Units'};
            otherwise
                icon = 0;
                columnNames = {};
        end
        
        if ~isempty(columnNames)
            obj.DataListview.ColumnHeaders = columnNames;
            % Iterate through the data and display it
            for i = 1:size(data, 1)
                % Add the item
                for j = 1:size(data,2);
                    data{i,j} = i_getDisplayString(data{i,j});
                end
            end
            Icons(1:size(data,1),1)= IconList(icon);
            obj.DataListview.setData(data,Icons);
            if size(data,2)==1
                listPos = obj.DataListview.Position;
                obj.DataListview.setColumnWidths(listPos(3)-20);
            end
        else
            % empty table
            obj.DataListview.setData([]);
        end
        end  % pUpdateDataListview
        
        %----------------------------------------
        function pUpdateObjectListview(obj)
        %PUPDATEOBJECTLISTVIEW Update list of stored objects
        %  PUPDATEOBJECTLISTVIEW(OBJ) updates the list of stored objects that can
        %  be loaded.
        
        % Which item is currently selected
        currentSelectedIndex = obj.ObjectListview.getSelectedRows;
        
        % What are we going to display
        objects = obj.StorageCache;
        
        IconList = {'filterIcon.bmp'
            'variableIcon.bmp'
            'sweepFilterIcon.bmp'
            'sweepNoteIcon.bmp'
            'editorLayoutIcon.bmp'
            'sweepVariableIcon.bmp'};
        
        Data = cell(length(objects),1);
        iconIndex = zeros(length(objects),1);
        % Iterate through the objects and display them
        for i = 1:length(objects)
            % What sort of icon should it have
            Data{i}= objects{i}.name;
            switch objects{i}.type
                case 'filter'
                    iconIndex(i) = 1;
                case 'variable'
                    iconIndex(i) = 2;
                case 'sweepfilter'
                    iconIndex(i) = 3;
                case 'sweepnote'
                    iconIndex(i) = 4;
                case 'xregdataeditorlayout'
                    iconIndex(i) = 5;
                case 'sweepvariable'
                    iconIndex(i) = 6;
                otherwise
                    iconIndex(i) = 1;
            end
            % Set it's name and icon
        end
        
        obj.ObjectListview.setData(Data,IconList(iconIndex));
        listPos = obj.ObjectListview.Position;
        obj.ObjectListview.setColumnWidths(listPos(3));
        if ~isempty(Data)
            if isempty(currentSelectedIndex) || currentSelectedIndex>length(Data)
                currentSelectedIndex = 1;
            end
            obj.ObjectListview.selectRows( currentSelectedIndex );
        end
        
        end  % pUpdateObjectListview
        
    end  % public methods
    
    
    methods (Hidden) % possibly private or hidden
        %----------------------------------------
        function pPostSetDataMessageService(obj, ~,~)
        %PPOSTSETDATAMESSAGESERVICE setup MessageService listeners
        %  PPOSTSETDATAMESSAGESERVICE(OBJ, SRC, EVENT)
        
        % Call the super pPostSetDataMessageService
        pPostSetDataMessageService@xregdatagui.AbstractDataView(obj);

        end  % pPostSetDataMessageService
        
        %----------------------------------------
        function store = pUpdateStorageVersion(obj, store) 
        %PUPDATESTORAGEVERSION update storage version
        %  STORE = PUPDATESTORAGEVERSION(OBJ, STORE)
        
        % ------------------------------------------------------------------------------
        % See pObjectBeingDestroyed and pToolbarCallbacks for the saving of stores
        % to file and preferences
        % ------------------------------------------------------------------------------
        
        % Nothing in the store then don't worry and return
        if isempty(store)
            store = {};
            return
        end
        % Previous versions of the store were cells but now it is properly
        % versioned
        if iscell(store)
            version = 0;
        elseif isstruct(store)
            version = store.version;
            store = store.data;
        else
            warning(message('mbc:xregdatagui:storageview:InvalidState'));
            store = {};
            return
        end
        
        if version<1
            version = 1;
        end
        
        if version<2
            % Added resampling and sweep variables.  No upgrades are necessary.
            version = 2;
        end
        
        if version>2
            warning(message('mbc:xregdatagui:storageview:InvalidState1'));
            store = {};
        end
        
        % remove monitor plots and resampling
        remItem = false(1,length(store));
        for i = 1:length(store)
            remItem(i) =  any(strcmp(store{i}.type, {'xregmonitorplotproperties','resampling'}));
        end
        store(remItem) = [];
        
        % return only display layout if read-only
        if obj.MessageService.IsReadOnly
            store = filterDisplayStorage(store);
        end
        end  % pUpdateStorageVersion
        
        % ------------------------------------------------------------------------------
        %onItemClick click on storage item list
        % ------------------------------------------------------------------------------
        function onItemClick(obj, ~,evt)
        % Update the Data display to reflect the new selection
        obj.pUpdateDataListview(evt.data.SelectedDataRows);
        end
        
        % ------------------------------------------------------------------------------
        % Edit filters by changing the listview test
        % ------------------------------------------------------------------------------
        function onLabelEdit(obj, ~,event)
        % Get the currently selected item
        index = event.data.Rows;
        % Turn off the storage cache listener since I know the listview will
        % display the correct name
        L = obj.Listeners.findobj('EventName', 'PostSet');
        [L.Enabled] = deal(false);
        % Need to get the new name and set it in the StorageCache
        obj.StorageCache{index}.name = event.data.NewValue;
        % Turn the listener back on
        [L.Enabled] = deal(true);
        end
        
        % ------------------------------------------------------------------------------
        % Double click listview items to edit in a dialog
        % ------------------------------------------------------------------------------
        function onDoubleClick(obj, ~,evt)
        % Check that append is currently enabled
        
        TypeIndex = evt.data.SelectedRows;
        if ~isempty(TypeIndex) 
            % Which sub items are selected?

            CurrentType = obj.StorageCache{TypeIndex}.type;
            if obj.MessageService.isaSSF && obj.MessageService.IsReadOnly
                OK = strcmp(CurrentType,'xregdataeditorlayout');
            else
                OK =  any(strcmp(CurrentType,{'filter', 'sweepfilter', 'variable', 'sweepnote', 'sweepvariable','xregdataeditorlayout'}));
            end
            
            if OK
                obj.pAppendCurrentObject(-1,TypeIndex);
            end
        end
    end
        
        
        
        % ------------------------------------------------------------------------------
        % Double click listview items to edit in a dialog
        % ------------------------------------------------------------------------------
        function onDataDoubleClick(obj, ~, evt)
        % Check that append is currently enabled
        
        TypeIndex = obj.pGetListviewIndex;
        ItemIndex = evt.data.SelectedRows;
        
        if ~isempty(TypeIndex) && ~isempty(ItemIndex)
            % Which sub items are selected?

            CurrentType = obj.StorageCache{TypeIndex}.type;
            if obj.MessageService.isaSSF && obj.MessageService.IsReadOnly
                OK = false;
            else
                OK =  any(strcmp(CurrentType,{'filter', 'sweepfilter', 'variable', 'sweepnote', 'sweepvariable'}));
            end
            
            if OK
                obj.pAppendCurrentObject(ItemIndex,TypeIndex);
            end
        end
        end
        
        % ------------------------------------------------------------------------------
        % Keys pressed in the listview
        %
        %  DELETE - to delete a filter
        % ------------------------------------------------------------------------------
        function onKeyPressed(obj, ~,evt)

        % First check no modifiers were pressed
        if evt.data.Modifiers == 0
            % Which key was pressed
            switch evt.data.KeyCode
                case mbcgui.util.KeyCode.DELETE
                    obj.pDeleteCurrentObject(evt.data.Rows);
            end
        end
        end
        
        function onStorageClosed(obj,~,~) %#ok<INUSD>
        f = mvf('storage');
        if isgraphics(f)
            set(f,'Visible','off');
        end
        end
        
        function onDataEditorDeleted(obj,~,~)
        %delete storage
        delete(obj);
        end
        
        function pImportMBCProject(obj,MP)
        %pImportMBCProject import data storage from MBC project
        
        dp = dataptrs(MP);
        
        ssf = obj.MessageService.SweepsetFilter;
        vars = get(ssf,'name');
        if ~isempty(obj.DataEditor.UserData)
            pCurrent = obj.DataEditor.UserData.ObjectBeingEdited;
            % remove current data set
            dp = dp(dp~=pCurrent);
        end
        if ~isempty(dp)
            s = cell(1,length(dp));
            for i=1:length(dp)
                s{i} = getStorage(dp(i).info,vars);
            end
            OK = ~cellfun(@isempty,s);
            dp = dp(OK);
            s = s(OK);
        else
            s = {};
        end
        
        if ~isempty(s)
           obj.ProjectStorage.DataNames = pveceval(dp,@(ssf) get(ssf,'label'));
           set(obj.hDataSelector,...
               'String',obj.ProjectStorage.DataNames,...
               'Value',1,...
               'Enable','on');
           set(obj.hProjectName,'String',projectfile(MP));
           obj.ProjectStorage.Cache = s;
           selectData(obj,1) 
        else
           errordlg(sprintf('There are no data expressions to import in %s.',projectfile(MP)),...
               'Import','modal');
        end
        
        end % pImportMBCProject
        
        function onImportCurrentProject(obj,~,~)
        %onImportCurrentProject select data from current project
        pRoot = get(MBrowser,'RootNode');
        pImportMBCProject(obj,info(pRoot))
        
        set(obj.hProjectName,'String','Current MBC project');

        end
        
        function selectData(obj,index)
        %selectData select data 
        s = obj.ProjectStorage.Cache{index};
        
        if obj.MessageService.IsReadOnly
            s = filterDisplayStorage(s);
        end
        obj.StorageCache = s;
        
        end
        
        function onSelectData(obj,h,~)
        %onSelectData select data from 
        selectData(obj,h.Value)
        end
        
        function addSweepsetfilterObject(obj, object, index, addFunction)
        % Get the current data object
        ssf = obj.MessageService.DataObject;
        % Iterate on the data adding the functionallity
        for i = index
            ssf = feval(addFunction, ssf, object.data{i, :});
        end
        % And write back to the MessageService
        obj.MessageService.flushEventQueue(ssf);
        end  % i_addSweepsetfilterObject
        
        % ------------------------------------------------------------------------------
        function updateEditorLayout(obj, object)
        % Get the figure handle and the DataEditor handle
        % Indicate this task might take a little time
        busy(obj.MessageService,'Replacing Data Editor layout...');
        
        % Lets try swapping the current layout for this one
        obj.DataEditor.replaceDisplayLayout(object.data{1});
        
        % Remove the message and the pointer
        idle(obj.MessageService)
        end  % onUpdateEditorLayout
        
        % ------------------------------------------------------------------------------
        function onImportStorage(obj,~, ~)
        % Open the load file dialog
        
        AP= mbcprefs('mbc');
        allfiles = getpref(AP,'FileDefaults');
        filespecMat = '*.mat';
        if ~isempty(allfiles.mbcmodel.Data)
            filespecMat = fullfile(allfiles.mbcmodel.Data,filespecMat);
        end
        [filename, pathname] = uigetfile(filespecMat , 'Import Expressions from MBC project or user MAT file');
        % Did the user cancel
        if isequal(pathname, 0) || isequal(filename, 0)
            return
        end
        set(obj.Figure,'Pointer','watch');
        drawnow update
        % Load the file
        in = load(fullfile(pathname,filename));
        % Check that the file loaded contains a valid storage format
        if isfield(in, 'storage')
            obj.CurrentMode = 'file';
            obj.StorageCache = obj.pUpdateStorageVersion(in.storage);
            set(obj.hProjectName,'String','User MAT file');
            set(obj.hDataSelector,'String',{'<none>'},'Value',1,'Enable','off');
        elseif isfield(in,'MP') && isa(in.MP,'mdevproject')
            obj.CurrentMode = filename;
            pImportMBCProject(obj,in.MP);
            delete(in.MP);
        else
            errordlg('File is not a valid data expression format', 'File Loading Error','modal')
        end
        set(obj.Figure,'Pointer','arrow');
        end  % onImportStorage
        
        
        % ------------------------------------------------------------------------------
        function onAppendObject(obj,~, ~)
        % Call the private append object function
        
        isReadOnly = obj.MessageService.isaSSF && obj.MessageService.IsReadOnly;
        for i=1:obj.ObjectListview.getRowCount
            if ~isReadOnly || strcmp(obj.StorageCache{i}.type,'xregdataeditorlayout')
                % only apply editor layout for read-only 
                obj.pAppendCurrentObject(-1,i);
            end
        end
        end  % onAppendObject
        
        % ------------------------------------------------------------------------------
        function onDeleteObject(obj,~, ~)
        % Call the private delete object function
        obj.pDeleteCurrentObject;
        end  % onDeleteObject
        
        end  % possibly private or hidden
    
end  % classdef

function string = i_getDisplayString(element)
% Default return
string = '';
% Can it be displayed simply
if ischar(element)
    string = element;
elseif ~isempty(element) && iscellstr(element)
    % Place a comma and space after every element
    string = strjoin(element,', ');
else
    % Show other data as an empty string
end
end  % i_getDisplayString

% ------------------------------------------------------------------------------
function views = i_getLayoutsFromSerializedData(obj, data)
% Which views are contained in the data
views = data{2};
% Convert the constructor names to menu labels
constructors = cellfun(@(f) (func2str(f)), obj.DataEditor.MultiView.ViewList.ConstructorFcns,'UniformOutput',false)';
names        = obj.DataEditor.MultiView.ViewList.Labels;
% Look for contained views in the constructors
[found, location] = ismember(lower(views), lower(constructors));
% Replace the views found by correct names
views(found) = names(location(found));
% And remove any & from the Menu Labels
views = strrep(views,'&','');
end  % i_getLayoutsFromSerializedData

function s = filterDisplayStorage(s)

OK = false(1,length(s));
for i=1:length(s)
    OK(i) = strcmp( s{i}.type , 'xregdataeditorlayout');
end
s = s(OK);
end