• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package autotest.tko;
2 
3 import autotest.common.JsonRpcCallback;
4 import autotest.common.JsonRpcProxy;
5 import autotest.common.Utils;
6 import autotest.common.CustomHistory.HistoryToken;
7 import autotest.common.spreadsheet.Spreadsheet;
8 import autotest.common.spreadsheet.SpreadsheetSelectionManager;
9 import autotest.common.spreadsheet.Spreadsheet.CellInfo;
10 import autotest.common.spreadsheet.Spreadsheet.SpreadsheetListener;
11 import autotest.common.ui.ContextMenu;
12 import autotest.common.ui.NotifyManager;
13 import autotest.common.ui.TableActionsPanel;
14 import autotest.common.ui.TableActionsPanel.TableActionsWithExportCsvListener;
15 import autotest.common.ui.TableSelectionPanel.SelectionPanelListener;
16 import autotest.tko.CommonPanel.CommonPanelListener;
17 import autotest.tko.TableView.TableSwitchListener;
18 import autotest.tko.TableView.TableViewConfig;
19 import autotest.tko.TkoSpreadsheetUtils.DrilldownType;
20 
21 import com.google.gwt.event.dom.client.ClickEvent;
22 import com.google.gwt.event.dom.client.ClickHandler;
23 import com.google.gwt.event.logical.shared.ResizeEvent;
24 import com.google.gwt.event.logical.shared.ResizeHandler;
25 import com.google.gwt.event.logical.shared.ValueChangeEvent;
26 import com.google.gwt.event.logical.shared.ValueChangeHandler;
27 import com.google.gwt.json.client.JSONArray;
28 import com.google.gwt.json.client.JSONObject;
29 import com.google.gwt.json.client.JSONString;
30 import com.google.gwt.json.client.JSONValue;
31 import com.google.gwt.user.client.Command;
32 import com.google.gwt.user.client.Event;
33 import com.google.gwt.user.client.History;
34 import com.google.gwt.user.client.Window;
35 import com.google.gwt.user.client.ui.Anchor;
36 import com.google.gwt.user.client.ui.Button;
37 import com.google.gwt.user.client.ui.CheckBox;
38 import com.google.gwt.user.client.ui.HTML;
39 import com.google.gwt.user.client.ui.MenuBar;
40 import com.google.gwt.user.client.ui.Panel;
41 import com.google.gwt.user.client.ui.SimplePanel;
42 import com.google.gwt.user.client.ui.VerticalPanel;
43 
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Map;
47 
48 public class SpreadsheetView extends ConditionTabView
49                              implements SpreadsheetListener, TableActionsWithExportCsvListener,
50                                         CommonPanelListener, SelectionPanelListener {
51     private static final String HISTORY_ONLY_LATEST = "show_only_latest";
52     public static final String DEFAULT_ROW = "kernel";
53     public static final String DEFAULT_COLUMN = "platform";
54     public static final String DEFAULT_DRILLDOWN = "job_tag";
55 
56     private static final String HISTORY_SHOW_INCOMPLETE = "show_incomplete";
57     private static final String HISTORY_COLUMN = "column";
58     private static final String HISTORY_ROW = "row";
59     private static final String HISTORY_CONTENT = "content";
60 
61     private static JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
62     private static JsonRpcProxy afeRpcProxy = JsonRpcProxy.getProxy(JsonRpcProxy.AFE_BASE_URL);
63     private TableSwitchListener listener;
64     protected Map<String,String[]> drilldownMap = new HashMap<String,String[]>();
65     private HeaderFieldCollection headerFields = commonPanel.getHeaderFields();
66 
67     private SpreadsheetHeaderSelect rowSelect = new SpreadsheetHeaderSelect(headerFields);
68     private SpreadsheetHeaderSelectorView rowSelectDisplay = new SpreadsheetHeaderSelectorView();
69     private SpreadsheetHeaderSelect columnSelect = new SpreadsheetHeaderSelect(headerFields);
70     private SpreadsheetHeaderSelectorView columnSelectDisplay = new SpreadsheetHeaderSelectorView();
71     private ContentSelect contentSelect = new ContentSelect(headerFields);
72     private CheckBox showIncomplete = new CheckBox("Show incomplete tests");
73     private CheckBox showOnlyLatest = new CheckBox("Show only latest test per cell");
74     private Button queryButton = new Button("Query");
75     private TestGroupDataSource normalDataSource = TestGroupDataSource.getStatusCountDataSource();
76     private TestGroupDataSource latestDataSource = TestGroupDataSource.getLatestTestsDataSource();
77     private Spreadsheet spreadsheet = new Spreadsheet();
78     private SpreadsheetDataProcessor spreadsheetProcessor =
79         new SpreadsheetDataProcessor(spreadsheet);
80     private SpreadsheetSelectionManager selectionManager =
81         new SpreadsheetSelectionManager(spreadsheet, null);
82     private TableActionsPanel actionsPanel = new TableActionsPanel(false);
83     private Panel jobCompletionPanel = new SimplePanel();
84     private boolean currentShowIncomplete, currentShowOnlyLatest;
85     private boolean notYetQueried = true;
86 
SpreadsheetView(TableSwitchListener listener)87     public SpreadsheetView(TableSwitchListener listener) {
88         this.listener = listener;
89         commonPanel.addListener(this);
90         rowSelect.bindDisplay(rowSelectDisplay);
91         columnSelect.bindDisplay(columnSelectDisplay);
92     }
93 
94     @Override
getElementId()95     public String getElementId() {
96         return "spreadsheet_view";
97     }
98 
99     @Override
initialize()100     public void initialize() {
101         super.initialize();
102 
103         setHeaderSelectField(rowSelect, DEFAULT_ROW);
104         setHeaderSelectField(columnSelect, DEFAULT_COLUMN);
105 
106         actionsPanel.setActionsWithCsvListener(this);
107         actionsPanel.setSelectionListener(this);
108         actionsPanel.setVisible(false);
109 
110         contentSelect.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
111             public void onValueChange(ValueChangeEvent<Boolean> event) {
112                 if (event.getValue()) {
113                     showOnlyLatest.setValue(true);
114                     showOnlyLatest.setEnabled(false);
115                 } else {
116                     showOnlyLatest.setEnabled(true);
117                 }
118             }
119         });
120 
121         updateViewFromState();
122 
123         queryButton.addClickHandler(new ClickHandler() {
124             public void onClick(ClickEvent event) {
125                 doQueryWithCommonPanelCheck();
126                 updateHistory();
127             }
128         });
129 
130         spreadsheet.setVisible(false);
131         spreadsheet.setListener(this);
132 
133         Anchor swapLink = new Anchor("swap");
134         swapLink.addClickHandler(new ClickHandler() {
135             public void onClick(ClickEvent event) {
136                 SpreadsheetHeaderSelect.State rowState = rowSelect.getStateFromView();
137                 rowSelect.loadFromState(columnSelect.getStateFromView());
138                 columnSelect.loadFromState(rowState);
139             }
140         });
141 
142         Panel filterOptions = new VerticalPanel();
143         filterOptions.add(showIncomplete);
144         filterOptions.add(showOnlyLatest);
145 
146         addWidget(filterOptions, "ss_filter_options");
147         addWidget(rowSelectDisplay, "ss_row_select");
148         addWidget(columnSelectDisplay, "ss_column_select");
149         addWidget(contentSelect, "ss_additional_content");
150         addWidget(swapLink, "ss_swap");
151         addWidget(queryButton, "ss_query_controls");
152         addWidget(actionsPanel, "ss_actions");
153         addWidget(spreadsheet, "ss_spreadsheet");
154         addWidget(jobCompletionPanel, "ss_job_completion");
155 
156         Window.addResizeHandler(new ResizeHandler() {
157             public void onResize(ResizeEvent event) {
158                 if(spreadsheet.isVisible()) {
159                     spreadsheet.fillWindow(true);
160                 }
161             }
162         });
163 
164         setupDrilldownMap();
165     }
166 
setHeaderSelectField(SpreadsheetHeaderSelect headerSelect, String defaultField)167     private void setHeaderSelectField(SpreadsheetHeaderSelect headerSelect,
168                                       String defaultField) {
169         headerSelect.setSelectedItem(headerFields.getFieldBySqlName(defaultField));
170     }
171 
getWholeTableTestSet()172     protected TestSet getWholeTableTestSet() {
173         boolean isSingleTest = spreadsheetProcessor.getNumTotalTests() == 1;
174         if (isSingleTest) {
175             return getTestSet(spreadsheetProcessor.getLastCellInfo());
176         }
177 
178         if (currentShowOnlyLatest) {
179             List<Integer> testIndices = spreadsheet.getAllTestIndices();
180             String filter = "test_idx IN (" + Utils.joinStrings(",", testIndices) + ")";
181             ConditionTestSet tests = new ConditionTestSet();
182             tests.addCondition(filter);
183             return tests;
184         }
185 
186         return new ConditionTestSet(getFullConditionArgs());
187     }
188 
setupDrilldownMap()189     protected void setupDrilldownMap() {
190         drilldownMap.put("platform", new String[] {"hostname", "test_name"});
191         drilldownMap.put("hostname", new String[] {"job_tag", "status"});
192 
193         drilldownMap.put("kernel", new String[] {"test_name", "status"});
194         drilldownMap.put("test_name", new String[] {"subdir", "job_name", "job_tag"});
195 
196         drilldownMap.put("status", new String[] {"reason", "job_tag"});
197 
198         drilldownMap.put("job_owner", new String[] {"job_name", "job_tag"});
199 
200         drilldownMap.put("test_finished_time", new String[] {"status", "job_tag"});
201         drilldownMap.put("DATE(test_finished_time)",
202                          new String[] {"test_finished_time", "job_tag"});
203 
204         drilldownMap.put("job_tag", new String[] {"subdir"});
205     }
206 
setSelectedHeader(HeaderSelect list, List<HeaderField> fields)207     protected void setSelectedHeader(HeaderSelect list, List<HeaderField> fields) {
208         list.setSelectedItems(fields);
209     }
210 
211     @Override
refresh()212     public void refresh() {
213         notYetQueried = false;
214         actionsPanel.setVisible(true);
215         spreadsheet.setVisible(false);
216         selectionManager.clearSelection();
217         spreadsheet.clear();
218         setJobCompletionHtml("&nbsp");
219 
220         final JSONObject condition = getFullConditionArgs();
221 
222         contentSelect.addToCondition(condition);
223 
224         setLoading(true);
225         if (currentShowOnlyLatest) {
226             spreadsheetProcessor.setDataSource(latestDataSource);
227         } else {
228             spreadsheetProcessor.setDataSource(normalDataSource);
229         }
230         spreadsheetProcessor.setHeaders(rowSelect.getSelectedItems(),
231                                         columnSelect.getSelectedItems(),
232                                         getQueryParameters());
233         spreadsheetProcessor.refresh(condition, new Command() {
234             public void execute() {
235                 condition.put("extra_info", null);
236 
237                 if (isJobFilteringCondition(condition)) {
238                     showCompletionPercentage(condition);
239                 } else {
240                     setLoading(false);
241                 }
242             }
243         });
244     }
245 
getQueryParameters()246     private JSONObject getQueryParameters() {
247         JSONObject parameters = new JSONObject();
248         rowSelect.addQueryParameters(parameters);
249         columnSelect.addQueryParameters(parameters);
250         return parameters;
251     }
252 
getFullConditionArgs()253     private JSONObject getFullConditionArgs() {
254         JSONObject args = commonPanel.getConditionArgs();
255         String condition = TkoUtils.getSqlCondition(args);
256         if (!condition.equals("")) {
257             condition = "(" + condition + ") AND ";
258         }
259         condition += "status != 'TEST_NA'";
260         if (!currentShowIncomplete) {
261             condition += " AND status != 'RUNNING'";
262         }
263         args.put("extra_where", new JSONString(condition));
264         return args;
265     }
266 
updateStateFromView()267     private void updateStateFromView() {
268         rowSelect.updateStateFromView();
269         columnSelect.updateStateFromView();
270         currentShowIncomplete = showIncomplete.getValue();
271         currentShowOnlyLatest = showOnlyLatest.getValue();
272         commonPanel.updateStateFromView();
273     }
274 
275     @Override
doQuery()276     public void doQuery() {
277         List<HeaderField> rows = rowSelect.getSelectedItems();
278         List<HeaderField> columns = columnSelect.getSelectedItems();
279         if (rows.isEmpty() || columns.isEmpty()) {
280             NotifyManager.getInstance().showError("You must select row and column fields");
281             return;
282         }
283 
284         updateStateFromView();
285         refresh();
286     }
287 
showCompletionPercentage(JSONObject condition)288     private void showCompletionPercentage(JSONObject condition) {
289         rpcProxy.rpcCall("get_job_ids", condition, new JsonRpcCallback() {
290             @Override
291             public void onSuccess(JSONValue result) {
292                 finishShowCompletionPercentage(result.isArray());
293                 setLoading(false);
294             }
295 
296             @Override
297             public void onError(JSONObject errorObject) {
298                 super.onError(errorObject);
299                 setLoading(false);
300             }
301         });
302     }
303 
finishShowCompletionPercentage(JSONArray jobIds)304     private void finishShowCompletionPercentage(JSONArray jobIds) {
305         final int jobCount = jobIds.size();
306         if (jobCount == 0) {
307             return;
308         }
309 
310         JSONObject args = new JSONObject();
311         args.put("job__id__in", jobIds);
312         afeRpcProxy.rpcCall("get_hqe_percentage_complete", args, new JsonRpcCallback() {
313             @Override
314             public void onSuccess(JSONValue result) {
315                 int percentage = (int) (result.isNumber().doubleValue() * 100);
316                 StringBuilder message = new StringBuilder("Matching ");
317                 if (jobCount == 1) {
318                     message.append("job is ");
319                 } else {
320                     message.append("jobs are ");
321                 }
322                 message.append(percentage);
323                 message.append("% complete");
324                 setJobCompletionHtml(message.toString());
325             }
326         });
327     }
328 
setJobCompletionHtml(String html)329     private void setJobCompletionHtml(String html) {
330         jobCompletionPanel.clear();
331         jobCompletionPanel.add(new HTML(html));
332     }
333 
isJobFilteringCondition(JSONObject condition)334     private boolean isJobFilteringCondition(JSONObject condition) {
335         return TkoUtils.getSqlCondition(condition).indexOf("job_tag") != -1;
336     }
337 
338     @Override
onCellClicked(CellInfo cellInfo, boolean isRightClick)339     public void onCellClicked(CellInfo cellInfo, boolean isRightClick) {
340         Event event = Event.getCurrentEvent();
341         TestSet testSet = getTestSet(cellInfo);
342         DrilldownType drilldownType = TkoSpreadsheetUtils.getDrilldownType(cellInfo);
343         if (isRightClick) {
344             if (!selectionManager.isEmpty()) {
345                 testSet = getTestSet(selectionManager.getSelectedCells());
346                 drilldownType = DrilldownType.DRILLDOWN_BOTH;
347             }
348             ContextMenu menu = getContextMenu(testSet, drilldownType);
349             menu.showAtWindow(event.getClientX(), event.getClientY());
350             return;
351         }
352 
353         if (isSelectEvent(event)) {
354             selectionManager.toggleSelected(cellInfo);
355             return;
356         }
357 
358         HistoryToken historyToken;
359         if (testSet.isSingleTest()) {
360             historyToken = listener.getSelectTestHistoryToken(testSet.getTestIndex());
361         } else {
362             historyToken = getDrilldownHistoryToken(testSet,
363                                                     getDefaultDrilldownRow(drilldownType),
364                                                     getDefaultDrilldownColumn(drilldownType));
365         }
366         openHistoryToken(historyToken);
367     }
368 
getTestSet(CellInfo cellInfo)369     private TestSet getTestSet(CellInfo cellInfo) {
370         return TkoSpreadsheetUtils.getTestSet(cellInfo, getFullConditionArgs(),
371                 rowSelect.getSelectedItems(), columnSelect.getSelectedItems());
372     }
373 
getTestSet(List<CellInfo> cells)374     private TestSet getTestSet(List<CellInfo> cells) {
375         CompositeTestSet tests = new CompositeTestSet();
376         for (CellInfo cell : cells) {
377             tests.add(getTestSet(cell));
378         }
379         return tests;
380     }
381 
getDrilldownHistoryToken(TestSet tests, String newRowField, String newColumnField)382     private HistoryToken getDrilldownHistoryToken(TestSet tests, String newRowField,
383                                                   String newColumnField) {
384         saveHistoryState();
385         commonPanel.refineCondition(tests);
386         rowSelect.setSelectedItem(headerFields.getFieldBySqlName(newRowField));
387         columnSelect.setSelectedItem(headerFields.getFieldBySqlName(newColumnField));
388         HistoryToken historyArguments = getHistoryArguments();
389         restoreHistoryState();
390         return historyArguments;
391     }
392 
doDrilldown(TestSet tests, String newRowField, String newColumnField)393     private void doDrilldown(TestSet tests, String newRowField, String newColumnField) {
394         History.newItem(getDrilldownHistoryToken(tests, newRowField, newColumnField).toString());
395     }
396 
getDefaultDrilldownRow(DrilldownType type)397     private String getDefaultDrilldownRow(DrilldownType type) {
398         return getDrilldownRows(type)[0];
399     }
400 
getDefaultDrilldownColumn(DrilldownType type)401     private String getDefaultDrilldownColumn(DrilldownType type) {
402         return getDrilldownColumns(type)[0];
403     }
404 
getContextMenu(final TestSet tests, DrilldownType drilldownType)405     private ContextMenu getContextMenu(final TestSet tests, DrilldownType drilldownType) {
406         TestContextMenu menu = new TestContextMenu(tests, listener);
407 
408         if (!menu.addViewDetailsIfSingleTest()) {
409             MenuBar drilldownMenu = menu.addSubMenuItem("Drill down");
410             fillDrilldownMenu(tests, drilldownType, drilldownMenu);
411         }
412 
413         menu.addItem("View in table", new Command() {
414             public void execute() {
415                 switchToTable(tests, false);
416             }
417         });
418         menu.addItem("Triage failures", new Command() {
419             public void execute() {
420                 switchToTable(tests, true);
421             }
422         });
423 
424         menu.addLabelItems();
425         return menu;
426     }
427 
fillDrilldownMenu(final TestSet tests, DrilldownType drilldownType, MenuBar menu)428     private void fillDrilldownMenu(final TestSet tests, DrilldownType drilldownType, MenuBar menu) {
429         for (final String rowField : getDrilldownRows(drilldownType)) {
430             for (final String columnField : getDrilldownColumns(drilldownType)) {
431                 if (rowField.equals(columnField)) {
432                     continue;
433                 }
434                 menu.addItem(rowField + " vs. " + columnField, new Command() {
435                     public void execute() {
436                         doDrilldown(tests, rowField, columnField);
437                     }
438                 });
439             }
440         }
441     }
442 
getDrilldownFields(List<HeaderField> fields, DrilldownType type, DrilldownType otherType)443     private String[] getDrilldownFields(List<HeaderField> fields, DrilldownType type,
444                                         DrilldownType otherType) {
445         HeaderField lastField = fields.get(fields.size() - 1);
446         String lastFieldName = lastField.getSqlName();
447         if (type == otherType) {
448             return new String[] {lastFieldName};
449         } else {
450             if (lastField instanceof MachineLabelField) {
451                 // treat machine label fields like platform, for the purpose of default drilldown
452                 lastFieldName = "platform";
453             }
454             if (drilldownMap.containsKey(lastFieldName)) {
455                 return drilldownMap.get(lastFieldName);
456             }
457             return new String[] {DEFAULT_DRILLDOWN};
458         }
459     }
460 
getDrilldownRows(DrilldownType type)461     private String[] getDrilldownRows(DrilldownType type) {
462         return getDrilldownFields(rowSelect.getSelectedItems(), type,
463                                   DrilldownType.DRILLDOWN_COLUMN);
464     }
465 
getDrilldownColumns(DrilldownType type)466     private String[] getDrilldownColumns(DrilldownType type) {
467         return getDrilldownFields(columnSelect.getSelectedItems(), type,
468                                   DrilldownType.DRILLDOWN_ROW);
469     }
470 
updateViewFromState()471     private void updateViewFromState() {
472         rowSelect.updateViewFromState();
473         columnSelect.updateViewFromState();
474         showIncomplete.setValue(currentShowIncomplete);
475         showOnlyLatest.setValue(currentShowOnlyLatest);
476         commonPanel.updateViewFromState();
477     }
478 
479     @Override
getHistoryArguments()480     public HistoryToken getHistoryArguments() {
481         HistoryToken arguments = super.getHistoryArguments();
482         if (!notYetQueried) {
483             rowSelect.addHistoryArguments(arguments, HISTORY_ROW);
484             columnSelect.addHistoryArguments(arguments, HISTORY_COLUMN);
485             contentSelect.addHistoryArguments(arguments, HISTORY_CONTENT);
486             arguments.put(HISTORY_SHOW_INCOMPLETE, Boolean.toString(currentShowIncomplete));
487             arguments.put(HISTORY_ONLY_LATEST, Boolean.toString(showOnlyLatest.getValue()));
488             commonPanel.addHistoryArguments(arguments);
489         }
490         return arguments;
491     }
492 
493     @Override
handleHistoryArguments(Map<String, String> arguments)494     public void handleHistoryArguments(Map<String, String> arguments) {
495         super.handleHistoryArguments(arguments);
496         commonPanel.handleHistoryArguments(arguments);
497         rowSelect.handleHistoryArguments(arguments, HISTORY_ROW);
498         columnSelect.handleHistoryArguments(arguments, HISTORY_COLUMN);
499         contentSelect.handleHistoryArguments(arguments, HISTORY_CONTENT);
500 
501         currentShowIncomplete = Boolean.valueOf(arguments.get(HISTORY_SHOW_INCOMPLETE));
502         currentShowOnlyLatest = Boolean.valueOf(arguments.get(HISTORY_ONLY_LATEST));
503         updateViewFromState();
504     }
505 
506     @Override
fillDefaultHistoryValues(Map<String, String> arguments)507     protected void fillDefaultHistoryValues(Map<String, String> arguments) {
508         Utils.setDefaultValue(arguments, HISTORY_ROW, DEFAULT_ROW);
509         Utils.setDefaultValue(arguments, HISTORY_COLUMN, DEFAULT_COLUMN);
510         Utils.setDefaultValue(arguments,
511                               HISTORY_ROW + SpreadsheetHeaderSelect.HISTORY_FIXED_VALUES, "");
512         Utils.setDefaultValue(arguments,
513                               HISTORY_COLUMN + SpreadsheetHeaderSelect.HISTORY_FIXED_VALUES, "");
514         Utils.setDefaultValue(arguments, HISTORY_SHOW_INCOMPLETE, Boolean.toString(false));
515         Utils.setDefaultValue(arguments, HISTORY_ONLY_LATEST, Boolean.toString(false));
516     }
517 
switchToTable(final TestSet tests, boolean isTriageView)518     private void switchToTable(final TestSet tests, boolean isTriageView) {
519         commonPanel.refineCondition(tests);
520         TableViewConfig config;
521         if (isTriageView) {
522             config = TableViewConfig.TRIAGE;
523             refineConditionForTriage();
524         } else {
525             config = TableViewConfig.DEFAULT;
526         }
527         listener.onSwitchToTable(config);
528     }
529 
refineConditionForTriage()530     private void refineConditionForTriage() {
531         commonPanel.refineCondition("status != 'GOOD'");
532     }
533 
getActionMenu()534     public ContextMenu getActionMenu() {
535         TestSet tests;
536         if (selectionManager.isEmpty()) {
537             tests = getWholeTableTestSet();
538         } else {
539             tests = getTestSet(selectionManager.getSelectedCells());
540         }
541         return getContextMenu(tests, DrilldownType.DRILLDOWN_BOTH);
542     }
543 
onExportCsv()544     public void onExportCsv() {
545         JSONObject params = new JSONObject();
546         contentSelect.addToCondition(params);
547         TkoUtils.doCsvRequest(spreadsheetProcessor.getDataSource(),
548                               spreadsheetProcessor.getCurrentQuery(), params);
549     }
550 
onSelectAll(boolean ignored)551     public void onSelectAll(boolean ignored) {
552         selectionManager.selectAll();
553     }
554 
onSelectNone()555     public void onSelectNone() {
556         selectionManager.clearSelection();
557     }
558 
559     @Override
hasFirstQueryOccurred()560     protected boolean hasFirstQueryOccurred() {
561         return !notYetQueried;
562     }
563 
setLoading(boolean loading)564     private void setLoading(boolean loading) {
565         queryButton.setEnabled(!loading);
566         NotifyManager.getInstance().setLoading(loading);
567     }
568 
569     @Override
onSetControlsVisible(boolean visible)570     public void onSetControlsVisible(boolean visible) {
571         TkoUtils.setElementVisible("ss_all_controls", visible);
572         if (isTabVisible()) {
573             spreadsheet.fillWindow(true);
574         }
575     }
576 
577     @Override
onFieldsChanged()578     public void onFieldsChanged() {
579         rowSelect.refreshFields();
580         columnSelect.refreshFields();
581         contentSelect.refreshFields();
582     }
583 }
584