www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/+xregdatagui/DataTableView.m
classdef DataTableView < xregdatagui.AbstractDataView %xregdatagui.DataTableView class % xregdatagui.DataTableView extends xregdatagui.AbstractDataView. % % xregdatagui.DataTableView 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) % Table - Property is of type 'handle' % AllowEdit - Property is of type 'bool' % ShowRemovedData - Property is of type 'bool' % TStarts - Property is of type 'MATLAB array' % TNums - Property is of type 'MATLAB array' % ColumnNames - Property is of type 'MATLAB array' % OutlierRows - Property is of type 'MATLAB array' % % xregdatagui.DataTableView methods: % copyRequest - Execute a copy operation on the table selection % gettitle - returns string describing this view % pPostSetDmsIsReadOnly - Recalculate whether table cells should be editable or not % pRequestUpdate - Request updates to the table % pUndoEdit - Reverts any edited cells in the selected region % pUpdateOptionsMenus - Setup the options menus correctly % pasteRequest - Execute a paste operation on the table selection % serializeView - Returns selected column names for storage % Copyright 2015-2016 The MathWorks, Inc. and Ford Global Technologies, Inc. properties (Constant) %ViewInfo view description ViewInfo = { @xregdatagui.DataTableView; '&Data Table'; xregrespath('dataimport_array_ok.bmp'); 'Data Table'; 1}; end properties (AbortSet) %TABLE Property is of type 'handle' Table = []; %ALLOWEDIT Property is of type 'bool' AllowEdit = 0; %ShowRemovedData show removed data in table ShowRemovedData = false; %TSTARTS Property is of type 'MATLAB array' TStarts = []; %TNUMS Property is of type 'MATLAB array' TNums = []; %COLUMNNAMES storage of column names to display % The columns in the Java table can be rearranged by dragging so you should DisplayedColumnNames ColumnNames = []; %OUTLIERROWS Property is of type 'MATLAB array' OutlierRows = []; end properties (Access=protected, AbortSet) %UPDATESREQUESTED Property is of type 'MATLAB array' UpdatesRequested = [ false, false, false ]; end properties(Dependent,SetAccess=private) %DisplayedColumnNames columns displayed in Java (allowing for rearrangement) DisplayedColumnNames end methods % constructor block function obj = DataTableView(varargin) %DATATABLEVIEW constructor % OUT = DATATABLEVIEW(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; obj.pUpdateTable end % datatableview end % constructor block methods function colNames = get.DisplayedColumnNames(obj) % need to get names from Java as the columns might have been % rearranged colNames = javaMethodEDT('getColumnNames',obj.Table.Peer); colNames = cellstr(char(colNames)); if isequal(colNames, get(obj.MessageService.Sweepset,'name')) % all names in correct order colNames = []; end end end % set and get functions methods % public methods %---------------------------------------- function copyRequest(obj, ~,evt) %COPYREQUEST Execute a copy operation on the table selection % COPYREQUEST(OBJ, hTable, evt) copies the data specified by the rows and % columns in the event object evt. if obj.MessageService.isaSSF && ~obj.AllowEdit && ~obj.ShowRemovedData data = obj.MessageService.SweepsetFilter; elseif obj.MessageService.isaSSF data = obj.MessageService.SweepsetWithBadData; else data = obj.MessageService.Sweepset; end row_selection = evt.JavaEvent.getRowIndices+1; col_selection = evt.JavaEvent.getColumnIndices+1; updateColumnNames(obj); if isempty(obj.ColumnNames) data = data(row_selection, col_selection); else % get indices of visible columns in the sweepset data = data(row_selection, obj.ColumnNames(col_selection)); end % Insert the real data where data is bad. This operation must match % the data being viewed, ie the data created in asyncDataRequest badCells = isbad(data); isBadRow = all(badCells, 2); if any(isBadRow) badData = spalloc(size(badCells, 1), size(badCells, 2), sum(badCells(:))); badData(badCells) = baddata(data); data(isBadRow, :) = badData(isBadRow, :); end % place data in clipboard mbcutils.Clipboard.guiCopy(double(data)); end % copyRequest %---------------------------------------- function out = gettitle(obj) %#ok<MANU> %GETTITLE returns string describing this view % OUT = GETTITLE(OBJ) out = 'Data Table'; end % gettitle %---------------------------------------- function pPostSetDmsIsReadOnly(obj, ~,~) %PPOSTSETDMSISREADONLY Recalculate whether table cells should be editable or not % PPOSTSETDMSISREADONLY(OBJ, src,EVENT) obj.pUpdateOptionsMenus; obj.Table.Editable = obj.AllowEdit; end % pPostSetDmsIsReadOnly %---------------------------------------- function pRequestUpdate(obj, updates) %PREQUESTUPDATE Request updates to the table % PREQUESTUPDATE(OBJ, UPDATES) requests that updated data be sent to the % table. UPDATES is a 3-element logical vector where the value of each % element indicates whether a part of the table needs to be updated: % % Element 1: Column data required % Element 2: Row data required % Element 3: Cell data required % % PREQUESTUPDATE(OBJ) requests that completely new data is sent to the % table. if nargin<2 updates = [true true true]; end % Combine update with any outstanding requests updates = updates | obj.UpdatesRequested; obj.UpdatesRequested = updates; % Check data message queue for outstanding events that will be processed. % If there are any there then defer this update request if ~i_findevents(obj) obj.pUpdateTable; end end % pRequestUpdate function pUndoEdit(obj) %PUNDOEDIT Reverts any edited cells in the selected region % PUNDOEDIT(OBJ) reverts the currently selected cells to their unedited % values. rows = obj.Table.getSelectedRows; % all selected rows columns = obj.Table.getSelectedColumns; % all selected columns if isempty(rows) || isempty(columns) return % no selection end % Get the sweepset currently on view, so that we can find the GUIDs of the selected rows ss = obj.pGetCurrentViewData; busy(obj.MessageService); updateColumnNames(obj) if ~isempty(obj.ColumnNames) names = obj.ColumnNames; else names = get(ss,'name'); end clear_guids = getGuids(ss(rows)); clear_vars = names(columns); ssf = obj.MessageService.SweepsetFilter; vars = get(ssf,'variables'); sweepvars = get(ssf,'sweepvariables'); % remove any columns which are derived variables and sweep variables, and aren't modifiable clear_vars = setdiff(clear_vars, {vars.varName,sweepvars.varName}); % Clear the selected portion of the modified data. ssf = modifyData(ssf,clear_guids,clear_vars(:)',[]); obj.MessageService.flushEventQueue(ssf); idle(obj.MessageService); end % pUndoEdit function pUpdateOptionsMenus(obj) %PUPDATEOPTIONSMENUS Setup the options menus correctly % PUPDATEOPTIONSMENUS(OBJ) sets the enable status of the options menu % items to match the current data status. % the "Allow Editing" menu if ~isempty(obj.MessageService) ... && obj.MessageService.isaSSF ... && ~obj.MessageService.isReadOnly % Enable the "Allow Edit" menu, but "Undo" or "Duplicate" % actions depend whether editing is on obj.Options.Actions(3).Enabled = true; obj.Options.Actions(3).Selected = obj.AllowEdit; set(obj.Options.Actions(4:5),'Enabled',obj.AllowEdit); else % Sweepset or no data. Disable and un-check "Allow Edit", and disable % "Undo" and "Duplicate" too. set(obj.Options.Actions(3:5),'Enabled',false); obj.AllowEdit = false; obj.Options.Actions(3).Selected = false; end % show removed data obj.Options.Actions(2).Selected = obj.ShowRemovedData; end % pUpdateOptionsMenus %---------------------------------------- function pasteRequest(obj, ~, evt) %PASTEREQUEST Execute a paste operation on the table selection % PASTEREQUEST(OBJ, hTable, evt) pastes the data specified by the rows % and columns in the event object. % The appropriate-ness of the data to be pasted should already have % been checked. The isNumeric check here is just the last hurdle prior % to performing the paste if mbcutils.Clipboard.isNumeric() new_data = mbcutils.Clipboard.paste(); row_selection = evt.JavaEvent.getRowIndices+1; col_selection = evt.JavaEvent.getColumnIndices+1; if length(row_selection)==1 && size(new_data, 1)>1 % Expand the row selection from the single cell selection row_selection = row_selection : (row_selection + size(new_data, 1) - 1); end if length(col_selection)==1 && size(new_data, 2)>1 % Expand the column selection from the single cell selection col_selection = col_selection : (col_selection + size(new_data, 2) - 1); end % Use names instead of indices updateColumnNames(obj) if ~isempty(obj.ColumnNames) col_selection = obj.ColumnNames(col_selection); end % Which sweepset are we viewing - to get the correct guids to indicate % where the change is occurring g = getGuids(obj.MessageService.SweepsetWithBadData); ssf = obj.MessageService.SweepsetFilter; ssf = modifyData(ssf,g(row_selection), col_selection, new_data); obj.MessageService.flushEventQueue(ssf); end end % pasteRequest %---------------------------------------- function out = serializeView(obj) %SERIALIZEVIEW Returns selected column names for storage if obj.MessageService.hasData updateColumnNames(obj) out = {'ColumnNames' obj.ColumnNames,'ShowRemovedData',obj.ShowRemovedData}; else out = {}; end end % serializeView function deserializeView(obj,varargin) %deserializeView appled saved settings for multiple data plots deserializeView@xregdatagui.AbstractDataView(obj,varargin{:}); if nargin>1 obj.pRequestUpdate([true true true]); end end end % public methods methods (Hidden) % possibly private or hidden %---------------------------------------- function asyncDataRequest(obj, ~,evt) %ASYNCDATAREQUEST Private method % ASYNCDATAREQUEST(OBJ, EVT) is called when a dataRequest event is % received from the table. if obj.MessageService.isaSSF showRemoved = obj.AllowEdit || obj.ShowRemovedData; if showRemoved data = obj.MessageService.SweepsetWithBadData; else data = obj.MessageService.SweepsetFilter; end else showRemoved = false; data = obj.MessageService.Sweepset; end je = evt.JavaEvent; startRow = je.getRow+1; endRow = je.getLastRow+1; if startRow<1 startRow = 1; end if endRow>size(data, 1) endRow = size(data, 1); end updateColumnNames(obj) colNames = obj.ColumnNames; names = get(data,'Name'); if isempty(colNames) colNames = names; end subset_names = colNames; [isok, idx] = ismember(subset_names, names); if any(~isok) subset = NaN(endRow-startRow+1, length(colNames)); subset(:, isok) = data(startRow:endRow, idx(isok)); else subset = data(startRow:endRow, idx); end isOutlier = i_getOutliers(obj, subset); if ~showRemoved isBad = []; isModified = []; else badCells = isbad(subset); isBad = all(badCells, 2); if any(isBad) badData = spalloc(size(badCells, 1), size(badCells, 2), sum(badCells(:))); badData(badCells) = baddata(subset); subset(isBad, :) = badData(isBad, :); end % Find modified data. We must retrieve the modifications % from the SSF, regardless of what we are displaying m = get(obj.MessageService.SweepsetFilter,'modifieddata'); [modRowToCopy, modRowInSubSet] = ismember(m.rowGuid, getGuids(subset)); [modColToCopy, modColInSubSet] = ismember(m.columnName, get(subset, 'Name')); isModified = false(size(subset, 1), size(subset, 2)); isModified(modRowInSubSet(modRowToCopy), modColInSubSet(modColToCopy)) = ... m.dataPosition(modRowToCopy, modColToCopy); end obj.Table.Peer.setAsyncData(double(subset), isOutlier, isBad, isModified, ... je, startRow-1, 0); end % asyncDataRequest %---------------------------------------- function pAllowEdit(obj) %PALLOWEDIT Private method that switches between edit and view modes. % PALLOWEDIT(obj) toggles the current editable state. % duplicate rows and undo edits are only valid when editing set(obj.Options.Actions(4:5),'Enabled',obj.AllowEdit); pShowRemovedData(obj) end function pShowRemovedData(obj) %pShowRemovedData show removed data sel_row = obj.Table.getSelectedRows; % first selected row if ~isempty(sel_row) sel_row = sel_row(1); sel_test = find( obj.TStarts > sel_row,1,'first' ) - 1; % test containing this row if isempty(sel_test) && ~isempty(obj.TStarts) sel_test = obj.TStarts(end); else sel_test = []; end else sel_test = []; end % find GUID of selected record ss = obj.pGetCurrentViewData; if ~isempty(ss) && ~isempty(sel_row) guid = getGuids(ss(sel_row)); else guid = []; end % The outliers have not changed, but their row indices may have ss = obj.pGetCurrentViewData; % changed since ss above outlier_guids = obj.MessageService.OutlierLine.OutlierGuids; outlier_rows = getIndices( getGuids(ss) , outlier_guids ); outlier_rows(outlier_rows==0) = []; % remove any unmatched entries obj.OutlierRows = outlier_rows; dispNames = obj.DisplayedColumnNames; if isequal(dispNames,obj.ColumnNames) || (isempty(obj.ColumnNames) && isequal(get(ss,'name'),dispNames)) % quick redraw is possible if display order is the same as % column order updates = [false true true]; else updateColumnNames(obj); updates = [true true true]; end % redraw obj.pRequestUpdate(updates); % find the row containing the selected record in the updated table if ~isempty(guid) new_sel_row = getIndices( getGuids(obj.pGetCurrentViewData) , guid ); if new_sel_row~=0 obj.Table.selectRows(new_sel_row); elseif ~isempty(sel_test) && any(sel_test>0) % record is no longer present. use the first one in the test x = find(obj.TNums==sel_test); if (x>0) row = obj.TStarts(x); obj.Table.selectRows(row); end end end end % pAllowEdit %---------------------------------------- function pCreateDisplay(obj) %PCREATEDISPLAY create display % PCREATEDISPLAY(OBJ) creates all uicontrols and visual components for % this view. dataEditor = com.mathworks.toolbox.mbc.gui.peer.DataEditorTablePeer; obj.Table = mbcwidgets.Table2D(dataEditor, ... 'Parent', obj.Parent, ... 'UIContextMenu', obj.UIContextMenu, ... 'ValueChangedCallback', @obj.onEditTable); % Add a listener to select this view on a table mouse-press event obj.addListeners(handle.listener(obj.Table.Peer, 'MousePressed', {@i_SelectCallback,obj})); % Attach to asynchronous data requests asyncList = [... handle.listener(obj.Table.Peer, 'DataRequested', @obj.asyncDataRequest); ... handle.listener(obj.Table.Peer, 'CopyRequested', @obj.copyRequest); ... handle.listener(obj.Table.Peer, 'PasteRequested', @obj.pasteRequest); ]; set(asyncList, 'CallbackTarget', obj); obj.addListeners(asyncList); obj.ContentHandle = obj.Table; createActions(obj) obj.pRequestUpdate; obj.pUpdateOptionsMenus; end % pCreateDisplay function createActions(obj) %createActions create view actions obj.Options.Actions = [ mbcgui.actions.StatefulAction(@obj.onSelectColumns,... 'Select &Columns to Display...','Select columns to display',[]) mbcgui.actions.ToggleAction(@obj.onShowRemovedData,... 'Show &Removed Data','Show removed data',[]) mbcgui.actions.ToggleAction(@obj.onAllowEdit,... '&Allow Editing','Allow data editing',[]) mbcgui.actions.StatefulAction(@obj.onUndoEdits,... '&Undo Edits in Selected Region','Undo edits in selected region',[]) mbcgui.actions.StatefulAction(@obj.onDuplicateRecords,... '&Duplicate Selected Records','Duplicate selected records',[]) ]; end %---------------------------------------- function ss = pGetCurrentViewData(obj) %PGETCURRENTVIEWDATA get data for view if obj.MessageService.isaSSF && (obj.AllowEdit || obj.ShowRemovedData) ss = obj.MessageService.SweepsetWithBadData; else ss = obj.MessageService.Sweepset; end end % pGetCurrentViewData %---------------------------------------- function pPostSetDataMessageService(obj, ~) %PPOSTSETDATAMESSAGESERVICE setup MessageService listeners % PPOSTSETDATAMESSAGESERVICE(OBJ, SRC, EVT) % Call the super pPostSetDataMessageService pPostSetDataMessageService@xregdatagui.AbstractDataView(obj); dms = obj.MessageService; dmsListeners = [... event.listener(dms, 'ssDataChanged', @(h,evt) obj.pRequestUpdate([false true true]));... event.listener(dms, 'ssfBadDataChanged', @(h,evt) obj.pRequestUpdate([false true true]));... event.listener(dms, 'ssNamesChanged', @(h,evt) obj.pRequestUpdate([true false false]));... event.listener(dms, 'dmsDataTypeChanged', @obj.pdmsDataTypeChangedUpdate);... event.listener(dms, 'ssRecordsChanged', @(h,evt) obj.pRequestUpdate([false false true]));... event.listener(dms, 'ssTestsChanged', @(h,evt) obj.pRequestUpdate([false true false]));... event.listener(dms, 'SelectedTestsChanged', @obj.pSelectedTestsChangedUpdate);... ]; % listen for changes to selected outliers so the table can be % highlighted outlier_line = obj.MessageService.OutlierLine; OutlierListener = event.proplistener(outlier_line, outlier_line.findprop('OutlierIndices'),... 'PostSet', @obj.onMarkOutliers); obj.Listeners = [obj.Listeners(:) ; dmsListeners(:);OutlierListener]; end % pPostSetDataMessageService %---------------------------------------- function changed = pSelectColumns(obj) %PSELECTCOLUMNS select columns to display in table % CHANGED = PSELECTCOLUMNS(OBJ) displays a dialog for selecting which % columns to display. CHANGED is set to true if any display changes are % made. dlg = mbcgui.container.Dialog('Name','Columns To Display',... 'Size',[300, 400]); xregcenterfigure(dlg.Figure, [300, 400], ancestor(obj.Parent,'figure')); listctrl = mbcwidgets.List('Parent',dlg.Figure,... 'Editable',true,... 'ValueChangedCallback',@iSelectColumn,... 'SelectionMode','MultiRow'); listctrl.setColumnData({'Column Name'}); listctrl.setColumnWidths(250); listctrl.Peer.setDisplayChecks(true); names = get(obj.pGetCurrentViewData, 'Name'); if ~isempty(obj.ColumnNames) Ticked = ismember(names, obj.ColumnNames); else % select all columns by default Ticked = true(size(names)); end listctrl.setData( names(:) ) listctrl.Peer.setChecks( Ticked(:) ) check = uicontrol('Parent',dlg.Figure,... 'Style','pushbutton',... 'String','Check selected items',... 'Tag','CheckSelected',... 'Callback', @iCheckSelectedRows); uncheck = uicontrol('Parent',dlg.Figure,... 'Style','pushbutton',... 'Tag','UncheckSelected',... 'String','Uncheck selected items',... 'Callback', @iUncheckSelectedRows); dlg.Content = xreggridbaglayout(dlg.Figure,... 'dimension',[3 2],... 'rowsizes',[-1 25 5 ],... 'mergeblock',{[1 1],[1 2]},... 'gapx',2,'gapy',2,... 'border',[10 10 10 10],... 'elements',{listctrl,check,[],[],uncheck,[]}); % store controls in UserData for testing ud.CheckSelected = check; ud.UncheckSelected = uncheck; ud.Listview = listctrl; set(dlg.Figure,'UserData',ud); changed = 0; if strcmp(dlg.showDialog(),'OK'); if all(Ticked) % all selected obj.ColumnNames = []; else % store display names obj.ColumnNames = names(Ticked); end changed = 1; end delete(dlg); drawnow expose; function iCheckSelectedRows(~,~) %iCheckSelectedRows check all selected rows sel = listctrl.getSelectedRows; if ~isempty(sel) Ticked(sel) = true; listctrl.Peer.setChecks(Ticked) listctrl.selectRows(sel); % enable OK button enableButtons(dlg,'OK'); drawnow expose; end end % iCheck function iUncheckSelectedRows(~,~) %iUncheckSelectedRows uncheck all selected rows sel = listctrl.getSelectedRows; if ~isempty(sel) Ticked(sel) = false; listctrl.Peer.setChecks(Ticked) listctrl.selectRows(sel); if ~any(Ticked) % can't select no columns disableButtons(dlg,'OK'); end drawnow expose; end end % iUncheck function iSelectColumn(~,evt) %iSelectColumns select checkbox in table % toggle selected Ticked(evt.data.Rows) = ~Ticked(evt.data.Rows); % enable or disable OK button if required if any(Ticked) enableButtons(dlg,'OK'); elseif ~any(Ticked) % can't select no columns disableButtons(dlg,'OK'); end end end % pSelectColumns %---------------------------------------- function pSelectedTestsChangedUpdate(obj, ~,~) %PSELECTEDTESTSCHANGEDUPDATE Private method. Selects the relevant tests in the table. % PSELECTEDTESTSCHANGEDUPDATE(OBJ, EVENT) ts = obj.TStarts; tn = obj.TNums; if isempty(tn) return; end selected = obj.MessageService.SelectedTests; selected = tn(selected); if ~isempty(selected) ind = find(selected(1)==tn); if ~isempty(ind) row = ts(ind); obj.Table.selectRows(row); end end end % pSelectedTestsChangedUpdate %---------------------------------------- function pUpdateTable(obj) %PUPDATE Updates the contents of the table. % PUPDATETABLE(OBJ) updates the parts of the table that have previously % been requested as needing an update. updates = obj.UpdatesRequested; if ~isempty(obj.MessageService) data = obj.pGetCurrentViewData; if all(updates) || (updates(1) && (updates(2) || updates(3))) nR = size(data,1); [cn, locks] = i_getcolumndata(obj, data); [tnums, tstart] = i_getrowdata(obj, data); obj.Table.Peer.setData(nR, cn, locks, tstart, tnums); else if updates(1) [cn, locks] = i_getcolumndata(obj, data); obj.Table.Peer.setColumnData(cn, locks); end if updates(2) [tnums, tstart] = i_getrowdata(obj, data); obj.Table.Peer.setRowHeaderData(tstart, tnums); end if updates(3) nR = size(data,1); obj.Table.Peer.changeRowCount(nR); end end else obj.Table.Peer.setData(0, {}, [], [], []); end obj.Table.Editable = obj.AllowEdit; obj.Table.Peer.setShowRecords(obj.ShowRemovedData); obj.UpdatesRequested = [false false false]; end % pUpdateTable %---------------------------------------- function pdmsDataTypeChangedUpdate(obj,varargin) %PDMSDATATYPECHANGEDUPDATE Private method. Handles change in data type. % PDMSDATATYPECHANGEDUPDATE(OBJ); % Enables and disables the "Allow edit" button obj.pUpdateOptionsMenus; end % pdmsDataTypeChangedUpdate function onAllowEdit(obj,action,~) %onAllowEdit allow edit obj.AllowEdit = action.Selected; obj.pAllowEdit; end % i_AllowEdit %---------------------------------------- function onDuplicateRecords(obj,~,~) %onDuplicateRecords duplicate selected rows rows = obj.Table.getSelectedRows; if isempty(rows) % no selection return end % Get the sweepset currently on view, so that we can find the GUIDs of the selected rows ssf = obj.MessageService.SweepsetFilter; ssptr = dataptr(ssf); % underlying data ss = ssptr.info; rows = sort(double(rows)); for i=1:length(rows) rows(i) = rows(i) + i - 1; % number of rows already inserted before this one. ss = [ss(1:rows(i),:) ; double(ss(rows(i),:)) ; ss(rows(i)+1:size(ss, 1),:)]; end ssptr.info = ss; queueEvent(ssf, {'ssDataChanged' 'ssRecordsChanged'}); ssf = updateAll(ssf); obj.MessageService.flushEventQueue(ssf); obj.Table.selectRows(rows); end % i_DuplicateRecord %---------------------------------------- function onSelectColumns(obj,~,~) %onSelectColumns select columns to display callbacks changed = obj.pSelectColumns; if changed obj.pRequestUpdate([true, false, true]); end end % i_SelectColumns %---------------------------------------- function onUndoEdits(obj,~,~) %onUndoEdits undo edits callback pUndoEdit(obj); end % i_UndoEdit function onShowRemovedData(obj,action,~) %onShowRemovedData show removed records callback obj.ShowRemovedData = action.Selected; pShowRemovedData(obj) end function onMarkOutliers(obj,~,~) %onMarkOutliers outliers have changed if isgraphics(obj.Parent) ss = obj.pGetCurrentViewData; new_guids = obj.MessageService.OutlierLine.OutlierGuids; new_rows = getIndices( getGuids(ss) , new_guids ); new_rows(new_rows==0) = []; % remove any unmatched entries old_rows = obj.OutlierRows; obj.OutlierRows = new_rows; % store for next time add_rows = setdiff(new_rows,old_rows); remove_rows = setdiff(old_rows,new_rows); obj.Table.Peer.setOutlierAt([add_rows(:);remove_rows(:)]-1, ... [true(length(add_rows),1); false(length(remove_rows), 1)]); end end % onMarkOutliers function onEditTable(obj,~,evt) %onEditTable table edited callback % replace current table cursor with hourglass busy(obj.MessageService); updateColumnNames(obj) if ~isempty(obj.ColumnNames) column = obj.ColumnNames(evt.data.Columns); % use name instead of index else column = evt.data.Columns; end % Which sweepset are we viewing - to get the correct guids to indicate % where the change is occurring g = getGuids(obj.MessageService.SweepsetWithBadData); ssf = obj.MessageService.SweepsetFilter; ssf = modifyData(ssf,g(evt.data.Rows),column, evt.data.NewValue); obj.MessageService.flushEventQueue(ssf); % replace the original cursor idle(obj.MessageService); end function updateColumnNames(obj) %updateColumnNames update column names from the Java table dispColumns = obj.DisplayedColumnNames; allNames = get(obj.MessageService.Sweepset,'name'); if ~isempty(dispColumns) if isequal(allNames,dispColumns) obj.ColumnNames = []; else obj.ColumnNames = dispColumns; end end end end % possibly private or hidden end % classdef function isOut = i_getOutliers(obj,ss) % Check which data guids are in the GUIDs of the outlier line outliers = obj.MessageService.OutlierLine.OutlierGuids; if ~isempty(ss) isOut = ismember(getGuids(ss), outliers); else isOut = false(0,1); end end % i_getOutliers %------------------------------------ function i_SelectCallback(~, ~, obj) % Send ButtonDown from this view so that the framework makes it % the current view. notify(obj,'ButtonDown'); end % i_SelectCallback %------------------------------------- function hasevent = i_findevents(obj) eventsToCheck = {'ssDataChanged', ... 'ssfBadDataChanged', ... 'ssNamesChanged', ... 'ssRecordsChanged', ... 'ssTestsChanged'}; if ~isempty(obj.MessageService) hasevent = any(obj.MessageService.isEventPending(eventsToCheck)); else hasevent = false; end end % i_findevents %------------------------------------- function [colNames, locks] = i_getcolumndata(obj, data) allNames = get(data,'Name'); % updateColumnNames(obj); colNames = obj.ColumnNames; if ~isempty(colNames) % choose only column names which appear in the current data colNames = colNames( ismember(colNames,allNames) ); obj.ColumnNames = colNames; % store for next time end if isempty(colNames) % if no columns will appear, show everything colNames = allNames; obj.ColumnNames = []; end if obj.MessageService.isaSSF % lock variables and test variables so they are not editable ssf = obj.MessageService.SweepsetFilter; vars = get(ssf,'variables'); sweepvars = get(ssf,'sweepvariables'); locks = ismember( colNames, {vars.varName,sweepvars.varName} ); else locks = false(size(colNames)); end end % i_getcolumndata %------------------------------------- function [tNums, tStart] = i_getrowdata(obj, data) tStart = double(tstart(data)); tNums = double(testnum(data)); if obj.AllowEdit || obj.ShowRemovedData map = obj.MessageService.GoodToBadIndexMap; % select the visible subset of tests tStart = tStart(map); tNums = tNums(map); end obj.TStarts = tStart; obj.TNums = tNums; end % i_getrowdata