Updated the order of imports in the source files of simulator plugins.
[platform/upstream/iotivity.git] / service / simulator / java / eclipse-plugin / ServiceProviderPlugin / src / oic / simulator / serviceprovider / view / LogView.java
1 /*
2  * Copyright 2015 Samsung Electronics All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package oic.simulator.serviceprovider.view;
18
19 import org.eclipse.jface.action.Action;
20 import org.eclipse.jface.action.IAction;
21 import org.eclipse.jface.action.IContributionItem;
22 import org.eclipse.jface.action.IMenuManager;
23 import org.eclipse.jface.action.IToolBarManager;
24 import org.eclipse.jface.action.MenuManager;
25 import org.eclipse.jface.action.Separator;
26 import org.eclipse.jface.dialogs.MessageDialog;
27 import org.eclipse.jface.resource.ImageDescriptor;
28 import org.eclipse.jface.viewers.DoubleClickEvent;
29 import org.eclipse.jface.viewers.IDoubleClickListener;
30 import org.eclipse.jface.viewers.ISelectionChangedListener;
31 import org.eclipse.jface.viewers.IStructuredSelection;
32 import org.eclipse.jface.viewers.SelectionChangedEvent;
33 import org.eclipse.jface.viewers.StructuredSelection;
34 import org.eclipse.jface.viewers.TreeViewer;
35 import org.eclipse.jface.viewers.Viewer;
36 import org.eclipse.jface.viewers.ViewerComparator;
37 import org.eclipse.jface.window.Window;
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.events.KeyEvent;
40 import org.eclipse.swt.events.KeyListener;
41 import org.eclipse.swt.events.SelectionAdapter;
42 import org.eclipse.swt.events.SelectionEvent;
43 import org.eclipse.swt.layout.GridData;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Display;
46 import org.eclipse.swt.widgets.FileDialog;
47 import org.eclipse.swt.widgets.Text;
48 import org.eclipse.swt.widgets.Tree;
49 import org.eclipse.swt.widgets.TreeColumn;
50 import org.eclipse.swt.widgets.TreeItem;
51 import org.eclipse.ui.IActionBars;
52 import org.eclipse.ui.IWorkbenchActionConstants;
53 import org.eclipse.ui.IWorkbenchPage;
54 import org.eclipse.ui.dialogs.FilteredTree;
55 import org.eclipse.ui.dialogs.PatternFilter;
56 import org.eclipse.ui.part.ViewPart;
57
58 import java.io.BufferedWriter;
59 import java.io.FileWriter;
60 import java.io.IOException;
61 import java.text.DateFormat;
62 import java.text.SimpleDateFormat;
63 import java.util.HashMap;
64 import java.util.List;
65
66 import org.oic.simulator.ILogger.Level;
67
68 import oic.simulator.logger.LogContentProvider;
69 import oic.simulator.logger.LogEntry;
70 import oic.simulator.logger.LogLabelProvider;
71 import oic.simulator.serviceprovider.Activator;
72 import oic.simulator.serviceprovider.listener.ILogListener;
73 import oic.simulator.serviceprovider.manager.LogManager;
74 import oic.simulator.serviceprovider.utils.Constants;
75 import oic.simulator.serviceprovider.view.dialogs.FilterDialog;
76 import oic.simulator.serviceprovider.view.dialogs.LogDetailsDialog;
77
78 /**
79  * This class manages and shows the log view in the perspective.
80  */
81 public class LogView extends ViewPart {
82
83     public static final String        VIEW_ID              = "oic.simulator.serviceprovider.view.log";
84
85     private LogManager                logManager;
86     private ILogListener              logListener;
87
88     private LogContentProvider        treeContentProvider;
89
90     private FilteredTree              tree;
91     private TreeColumn                severityColumn;
92     private TreeColumn                dateColumn;
93     private TreeColumn                messageColumn;
94
95     private IAction                   exportLogAction;
96     private IAction                   clearLogAction;
97     private IAction                   deleteLogAction;
98     private IAction                   scrollLockAction;
99     private IAction                   logDetailsAction;
100     private IAction                   filterAction;
101     private IAction                   activateViewAction;
102     private IAction                   showTextFilter;
103     private IContributionItem         groupByAction;
104
105     private HashMap<Integer, Boolean> shownSeverities      = new HashMap<Integer, Boolean>();
106
107     private boolean                   activateOnChange     = false;
108
109     private boolean                   hideTextFilter       = false;
110
111     private boolean                   scrollLockDisabled;
112
113     public static final int           ORDER_BY_TIME        = 0;
114     public static final int           ORDER_BY_SEVERITY    = 1;
115     public static final int           ORDER_BY_MESSAGE     = 2;
116
117     int                               sortCandidate        = ORDER_BY_TIME;
118
119     SortAction                        sortByTimeAction     = new SortAction(
120                                                                    "Order by Time",
121                                                                    ORDER_BY_TIME);
122     SortAction                        sortBySeverityAction = new SortAction(
123                                                                    "Order by Severity",
124                                                                    ORDER_BY_SEVERITY);
125     SortAction                        sortByMessageAction  = new SortAction(
126                                                                    "Order by Message",
127                                                                    ORDER_BY_MESSAGE);
128
129     private ViewerComparator          dateComparator;
130     private ViewerComparator          severityComparator;
131     private ViewerComparator          messageComparator;
132
133     private TreeColumn                sortColumn           = null;
134     private static int                DOWN                 = 1;
135     private static int                UP                   = -1;
136     private int                       sortDirection        = DOWN;
137
138     public LogView() {
139
140         logListener = new ILogListener() {
141
142             @Override
143             public void logChanged(final List<LogEntry> entry) {
144                 Display.getDefault().asyncExec(new Runnable() {
145
146                     @Override
147                     public void run() {
148                         TreeViewer viewer = tree.getViewer();
149                         if (viewer.getControl().isDisposed()) {
150                             return;
151                         }
152                         viewer.setInput(entry);
153                         updateTree(false);
154                     }
155                 });
156             }
157
158             @Override
159             public void logAdded(final LogEntry added) {
160                 Display.getDefault().asyncExec(new Runnable() {
161
162                     @Override
163                     public void run() {
164                         TreeViewer viewer = tree.getViewer();
165                         if (viewer.getControl().isDisposed()) {
166                             return;
167                         }
168                         LogContentProvider provider = (LogContentProvider) viewer
169                                 .getContentProvider();
170                         provider.addLog(added);
171                         tree.getViewer().add(viewer.getInput(), added);
172                         @SuppressWarnings("unchecked")
173                         List<LogEntry> input = (List<LogEntry>) viewer
174                                 .getInput();
175                         if (input.size() > Constants.LOG_SIZE) {
176                             viewer.remove(viewer.getInput(), 0);
177                         }
178                         updateTree(true);
179                     }
180                 });
181             }
182
183             private void updateTree(boolean needscroll) {
184                 if (activateOnChange) {
185                     IWorkbenchPage page = Activator.getDefault().getWorkbench()
186                             .getActiveWorkbenchWindow().getActivePage();
187                     if (page != null) {
188                         page.bringToTop(LogView.this);
189                     }
190                 }
191                 if (scrollLockDisabled && needscroll) {
192                     Tree tree2 = tree.getViewer().getTree();
193                     if (tree2.getItemCount() > 0) {
194                         TreeItem item = tree2.getItem(tree2.getItemCount() - 1);
195                         tree2.setTopItem(item);
196                         deleteLogAction.setEnabled(true);
197                     }
198                 }
199             }
200         };
201
202         logManager = Activator.getDefault().getLogManager();
203
204         // Initially state of scroll lock
205         scrollLockDisabled = true;
206     }
207
208     @Override
209     public void createPartControl(Composite parent) {
210         PatternFilter filter = new PatternFilter() {
211
212             DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
213
214             @Override
215             protected boolean isLeafMatch(Viewer viewer, Object element) {
216                 if (element instanceof LogEntry) {
217                     LogEntry logEntry = (LogEntry) element;
218                     String severity = LogManager.getSeverityName(logEntry
219                             .getSeverity());
220                     String date = dateFormat.format(logEntry.getDate());
221                     String message = logEntry.getMessage();
222                     return wordMatches(severity) || wordMatches(date)
223                             || wordMatches(message);
224                 }
225                 return false;
226             }
227         };
228         filter.setIncludeLeadingWildcard(true);
229         tree = new FilteredTree(parent, SWT.SINGLE | SWT.H_SCROLL
230                 | SWT.V_SCROLL | SWT.FULL_SELECTION, filter, true);
231
232         setupFilteredTree();
233
234         createColumnComparators();
235
236         createActions();
237
238         setDefaultShownSeverities();
239
240         IActionBars actionBars = getViewSite().getActionBars();
241         IToolBarManager toolBarManager = actionBars.getToolBarManager();
242         toolBarManager.add(exportLogAction);
243         toolBarManager.add(clearLogAction);
244         toolBarManager.add(deleteLogAction);
245         toolBarManager.add(scrollLockAction);
246         toolBarManager
247                 .add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
248
249         IMenuManager mgr = actionBars.getMenuManager();
250         mgr.add(groupByAction);
251         mgr.add(new Separator());
252         mgr.add(filterAction);
253         mgr.add(new Separator());
254         mgr.add(activateViewAction);
255         mgr.add(showTextFilter);
256
257         addManagerListeners();
258
259         if (sortCandidate == ORDER_BY_TIME) {
260             sortByTimeAction.run();
261         } else if (sortCandidate == ORDER_BY_SEVERITY) {
262             sortBySeverityAction.run();
263         } else { // order_selected == ORDER_BY_NONE
264             sortByMessageAction.run();
265         }
266
267     }
268
269     private void setupFilteredTree() {
270         tree.setLayoutData(new GridData(GridData.FILL_BOTH));
271         final Tree innerTree = tree.getViewer().getTree();
272         innerTree.setLinesVisible(true);
273
274         severityColumn = new TreeColumn(innerTree, SWT.LEFT);
275         severityColumn.setText("Severity");
276         severityColumn.setWidth(110);
277         severityColumn.addSelectionListener(new SelectionAdapter() {
278
279             @Override
280             public void widgetSelected(SelectionEvent e) {
281                 sortBySeverityAction.run();
282             }
283         });
284         dateColumn = new TreeColumn(innerTree, SWT.LEFT);
285         dateColumn.setText("Time");
286         dateColumn.setWidth(110);
287         dateColumn.addSelectionListener(new SelectionAdapter() {
288
289             @Override
290             public void widgetSelected(SelectionEvent e) {
291                 sortByTimeAction.run();
292             }
293         });
294         messageColumn = new TreeColumn(innerTree, SWT.LEFT);
295         messageColumn.setText("Message");
296         messageColumn.setWidth(180);
297         messageColumn.addSelectionListener(new SelectionAdapter() {
298             @Override
299             public void widgetSelected(SelectionEvent e) {
300                 sortByMessageAction.run();
301             }
302         });
303
304         innerTree.setHeaderVisible(true);
305
306         treeContentProvider = new LogContentProvider();
307
308         tree.getViewer().setContentProvider(treeContentProvider);
309         tree.getViewer().setLabelProvider(new LogLabelProvider());
310
311         tree.getViewer().setInput(logManager.getLogEntries());
312
313         tree.getViewer().addSelectionChangedListener(
314                 new ISelectionChangedListener() {
315
316                     @Override
317                     public void selectionChanged(SelectionChangedEvent event) {
318                         deleteLogAction.setEnabled(!tree.getViewer()
319                                 .getSelection().isEmpty());
320                         logDetailsAction.setEnabled(!tree.getViewer()
321                                 .getSelection().isEmpty());
322                     }
323                 });
324
325         tree.getViewer().getTree().addKeyListener(new KeyListener() {
326
327             @Override
328             public void keyReleased(KeyEvent e) {
329             }
330
331             @Override
332             public void keyPressed(KeyEvent e) {
333                 if (e.character == (char) 127) { // If delete key is pressed
334                     if (deleteLogAction.isEnabled()) {
335                         deleteLogAction.run();
336                     }
337                 }
338             }
339         });
340
341         tree.getViewer().addDoubleClickListener(new IDoubleClickListener() {
342
343             @Override
344             public void doubleClick(DoubleClickEvent event) {
345                 logDetailsAction.run();
346             }
347         });
348     }
349
350     private void createColumnComparators() {
351         dateComparator = new ViewerComparator() {
352
353             @Override
354             public int compare(Viewer viewer, Object e1, Object e2) {
355                 LogEntry l1 = (LogEntry) e1;
356                 LogEntry l2 = (LogEntry) e2;
357                 return l1.getDate().compareTo(l2.getDate()) * sortDirection;
358             }
359         };
360
361         severityComparator = new ViewerComparator() {
362
363             @Override
364             public int compare(Viewer viewer, Object e1, Object e2) {
365                 LogEntry l1 = (LogEntry) e1;
366                 LogEntry l2 = (LogEntry) e2;
367                 if (l1.getSeverity() < l2.getSeverity()) {
368                     return -1 * sortDirection;
369                 }
370                 if (l1.getSeverity() > l2.getSeverity()) {
371                     return 1 * sortDirection;
372                 }
373                 return 0;
374             }
375         };
376
377         messageComparator = new ViewerComparator() {
378
379             @Override
380             public int compare(Viewer viewer, Object e1, Object e2) {
381                 LogEntry l1 = (LogEntry) e1;
382                 LogEntry l2 = (LogEntry) e2;
383                 return l1.getMessage().compareTo(l2.getMessage())
384                         * sortDirection;
385             }
386         };
387
388     }
389
390     private void setDefaultShownSeverities() {
391         shownSeverities.put(Level.INFO.ordinal(), true);
392         shownSeverities.put(Level.DEBUG.ordinal(), true);
393         shownSeverities.put(Level.WARNING.ordinal(), true);
394         shownSeverities.put(Level.ERROR.ordinal(), true);
395     }
396
397     private void addManagerListeners() {
398         logManager.addLogListener(logListener);
399         logManager.applyFilter(shownSeverities);
400     }
401
402     private void createActions() {
403         exportLogAction = createExportLogAction();
404         clearLogAction = createClearLogAction();
405         deleteLogAction = createDeleteLogAction();
406         scrollLockAction = createScrollLockAction();
407         logDetailsAction = createLogDetailsAction();
408
409         filterAction = createFilterAction();
410         activateViewAction = createActivateViewAction();
411         showTextFilter = createShowTextFilter();
412         groupByAction = createGroupByAction();
413     }
414
415     private IAction createExportLogAction() {
416         Action action = new Action("Export log") {
417             @Override
418             public void run() {
419                 FileDialog fd = new FileDialog(Display.getDefault()
420                         .getActiveShell(), SWT.SAVE);
421                 fd.setOverwrite(true);
422                 fd.setFileName("OIC_Simulator_ServerLog.log");
423                 fd.setFilterExtensions(Constants.SAVE_LOG_FILTER_EXTENSIONS);
424                 String name = fd.open();
425                 List<LogEntry> logEntries = logManager.getLogEntries();
426                 StringBuilder sb = new StringBuilder();
427                 for (LogEntry entry : logEntries) {
428                     sb.append(entry.toString());
429                 }
430                 String data = sb.toString();
431                 BufferedWriter out = null;
432                 try {
433                     out = new BufferedWriter(new FileWriter(name));
434                     out.write(data);
435                 } catch (IOException e) {
436                     e.printStackTrace();
437                     MessageDialog.openError(
438                             Display.getDefault().getActiveShell(),
439                             "Export error",
440                             "Could not export log. IO exception: "
441                                     + e.getMessage());
442                 } finally {
443                     try {
444                         if (null != out) {
445                             out.close();
446                         }
447                     } catch (IOException e) {
448                         System.out.println("Error occurred during close.");
449                     }
450                 }
451             }
452         };
453         action.setToolTipText("Export log");
454
455         action.setImageDescriptor(ImageDescriptor.createFromFile(
456                 this.getClass(), "/icons/export_log_e.gif"));
457         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
458                 this.getClass(), "/icons/export_log_d.gif"));
459         action.setEnabled(true);
460
461         return action;
462     }
463
464     private IAction createClearLogAction() {
465         Action action = new Action("Clear log") {
466
467             @Override
468             public void run() {
469                 logManager.clearLog();
470             }
471         };
472         action.setToolTipText("Clear log");
473
474         action.setImageDescriptor(ImageDescriptor.createFromFile(
475                 this.getClass(), "/icons/clear_e.gif"));
476         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
477                 this.getClass(), "/icons/clear_d.gif"));
478         action.setEnabled(true);
479         return action;
480     }
481
482     private IAction createDeleteLogAction() {
483         Action action = new Action("Delete log entry") {
484
485             @Override
486             @SuppressWarnings("unchecked")
487             public void run() {
488                 IStructuredSelection selection = (IStructuredSelection) tree
489                         .getViewer().getSelection();
490                 List<LogEntry> entries = (List<LogEntry>) tree.getViewer()
491                         .getInput();
492                 LogEntry selectedEntry = (LogEntry) selection.getFirstElement();
493                 if (null != selectedEntry) {
494                     LogEntry toBeShownEntry = null;
495                     for (LogEntry entry : entries) {
496                         if (entry.equals(selectedEntry)) {
497                             int size = entries.size();
498                             int index = entries.indexOf(selectedEntry);
499                             if (index + 1 < size) {
500                                 toBeShownEntry = entries.get(index + 1);
501                             } else if (index > 0) {
502                                 toBeShownEntry = entries.get(index - 1);
503                             }
504                             break;
505                         }
506                     }
507                     logManager.removeEntry(selectedEntry);
508                     if (null != toBeShownEntry) {
509                         tree.getViewer().setSelection(
510                                 new StructuredSelection(toBeShownEntry));
511                     }
512                 }
513             }
514         };
515         action.setToolTipText("Delete log entry");
516         action.setImageDescriptor(ImageDescriptor.createFromFile(
517                 this.getClass(), "/icons/delete_e.gif"));
518         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
519                 this.getClass(), "/icons/delete_d.gif"));
520         action.setEnabled(false);
521         return action;
522     }
523
524     private IAction createScrollLockAction() {
525         Action action = new Action("Scroll lock") {
526
527             @Override
528             public void run() {
529                 scrollLockDisabled = !this.isChecked();
530             };
531
532             @Override
533             public int getStyle() {
534                 return IAction.AS_CHECK_BOX;
535             }
536         };
537         action.setToolTipText("Scroll lock");
538         action.setImageDescriptor(ImageDescriptor.createFromFile(
539                 this.getClass(), "/icons/lock_e.gif"));
540         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
541                 this.getClass(), "/icons/lock_d.gif"));
542         action.setEnabled(true);
543         return action;
544     }
545
546     private IAction createLogDetailsAction() {
547         Action action = new Action("Details...") {
548
549             @Override
550             public void run() {
551                 Display.getDefault().asyncExec(new Runnable() {
552
553                     @Override
554                     public void run() {
555                         LogEntry x = (LogEntry) ((IStructuredSelection) tree
556                                 .getViewer().getSelection()).getFirstElement();
557
558                         new LogDetailsDialog(Display.getDefault()
559                                 .getActiveShell(), LogManager.getSeverityName(x
560                                 .getSeverity()), LogManager.getSeverityIcon(x
561                                 .getSeverity()), x.getDate(), x.getMessage())
562                                 .open();
563                     }
564                 });
565             }
566         };
567         action.setToolTipText("Details...");
568         action.setImageDescriptor(ImageDescriptor.createFromFile(
569                 this.getClass(), "/icons/log_details_e.gif"));
570         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
571                 this.getClass(), "/icons/log_details_e.gif"));
572         action.setEnabled(false);
573         return action;
574     }
575
576     private IAction createFilterAction() {
577         Action action = new Action("Filters ...") {
578
579             @Override
580             public void run() {
581                 FilterDialog fd = new FilterDialog(Display.getDefault()
582                         .getActiveShell(), shownSeverities);
583                 if (fd.open() == Window.OK) {
584                     logManager.applyFilter(shownSeverities);
585                 }
586                 tree.getViewer().refresh();
587             }
588         };
589         action.setToolTipText("Filters ...");
590
591         action.setImageDescriptor(ImageDescriptor.createFromFile(
592                 this.getClass(), "/icons/filter_e.gif"));
593         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
594                 this.getClass(), "/icons/filter_d.gif"));
595         action.setEnabled(true);
596         return action;
597     }
598
599     private IAction createActivateViewAction() {
600         Action action = new Action("Activate view on new events",
601                 IAction.AS_CHECK_BOX) {
602
603             @Override
604             public void run() {
605                 activateOnChange = this.isChecked();
606             }
607         };
608         action.setChecked(activateOnChange);
609         action.setToolTipText("Activate view on new events");
610
611         action.setImageDescriptor(ImageDescriptor.createFromFile(
612                 this.getClass(), "/icons/prop_e.gif"));
613         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
614                 this.getClass(), "/icons/prop_d.gif"));
615         action.setEnabled(true);
616         return action;
617     }
618
619     private IAction createShowTextFilter() {
620         Action action = new Action("Show text filter", IAction.AS_CHECK_BOX) {
621
622             @Override
623             public void run() {
624                 Text filterControl = tree.getFilterControl();
625                 Composite filterComposite = filterControl.getParent();
626                 GridData gd = (GridData) filterComposite.getLayoutData();
627                 boolean visible = isChecked();
628                 gd.exclude = !visible;
629                 filterComposite.setVisible(visible);
630                 filterControl.setText("");
631                 if (visible) {
632                     filterControl.selectAll();
633                     setFocus();
634                 }
635                 tree.layout(false);
636                 hideTextFilter = !visible;
637             }
638         };
639         action.setToolTipText("Show text filter");
640
641         action.setImageDescriptor(ImageDescriptor.createFromFile(
642                 this.getClass(), "/icons/tree_mode_e.gif"));
643         action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
644                 this.getClass(), "/icons/tree_mode_d.gif"));
645         action.setEnabled(true);
646         action.setChecked(!hideTextFilter);
647         if (hideTextFilter) {
648             action.run();
649         }
650         return action;
651     }
652
653     private IContributionItem createGroupByAction() {
654         IMenuManager manager = new MenuManager("Order by");
655         manager.add(sortByTimeAction);
656         manager.add(sortBySeverityAction);
657         manager.add(sortByMessageAction);
658         return manager;
659     }
660
661     class SortAction extends Action {
662
663         private final int sortBy;
664
665         public SortAction(String text, int sortBy) {
666             super(text, IAction.AS_RADIO_BUTTON);
667             this.sortBy = sortBy;
668
669             if (sortCandidate == sortBy) {
670                 setChecked(true);
671             }
672         }
673
674         @Override
675         public void run() {
676             sortBySeverityAction.setChecked(false);
677             sortByTimeAction.setChecked(false);
678             sortCandidate = sortBy;
679             setChecked(true);
680
681             ViewerComparator comparator;
682             TreeColumn column;
683             if (sortBy == ORDER_BY_SEVERITY) {
684                 comparator = severityComparator;
685                 column = severityColumn;
686             } else if (sortBy == ORDER_BY_TIME) {
687                 comparator = dateComparator;
688                 column = dateColumn;
689             } else { // Order by message
690                 comparator = messageComparator;
691                 column = messageColumn;
692             }
693             TreeViewer viewer = tree.getViewer();
694             viewer.setComparator(comparator);
695             viewer.getTree().setSortColumn(column);
696             if (column.equals(sortColumn)) { // reverse sorting order
697                 sortDirection = viewer.getTree().getSortDirection() == SWT.UP ? DOWN
698                         : UP;
699                 viewer.getTree().setSortDirection(
700                         sortDirection == UP ? SWT.UP : SWT.DOWN);
701                 viewer.refresh();
702             } else { // set this column as the one to sort by
703                 sortDirection = DOWN;
704                 viewer.getTree().setSortDirection(SWT.DOWN);
705             }
706             sortColumn = column;
707             refresh();
708         }
709     }
710
711     private void refresh() {
712         tree.getViewer().refresh();
713     }
714
715     @Override
716     public void setFocus() {
717         tree.setFocus();
718     }
719
720     @Override
721     public void dispose() {
722         logManager.removeLogListener(logListener);
723         super.dispose();
724     }
725 }