KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > tracelog > ui > ShellMainLogViewer


1 package net.sourceforge.tracelog.ui;
2
3 import java.util.HashSet JavaDoc;
4 import java.util.List JavaDoc;
5
6 import net.sourceforge.tracelog.config.ConfigFile;
7 import net.sourceforge.tracelog.config.ConfigFileFactory;
8 import net.sourceforge.tracelog.config.LogFile;
9 import net.sourceforge.tracelog.config.UserConfig;
10 import net.sourceforge.tracelog.listeners.FileListener;
11 import net.sourceforge.tracelog.listeners.LogSizeHandler;
12 import net.sourceforge.tracelog.listeners.LogViewerHandler;
13 import net.sourceforge.tracelog.utils.Util;
14
15 import org.apache.log4j.Logger;
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.custom.StyledText;
18 import org.eclipse.swt.events.ModifyEvent;
19 import org.eclipse.swt.events.ModifyListener;
20 import org.eclipse.swt.events.SelectionAdapter;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.graphics.Font;
23 import org.eclipse.swt.graphics.Image;
24 import org.eclipse.swt.layout.GridData;
25 import org.eclipse.swt.layout.GridLayout;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Event;
29 import org.eclipse.swt.widgets.TabFolder;
30 import org.eclipse.swt.widgets.TabItem;
31 import org.eclipse.swt.widgets.ToolBar;
32 import org.eclipse.swt.widgets.ToolItem;
33
34 public class ShellMainLogViewer extends AbstractWidget {
35     private static Logger log = Logger.getLogger(ShellMainLogViewer.class);
36     public static final String JavaDoc LOG_VIEWER_DATA_KEY_SCROLL_LOCK = "scroll_lock";
37     private static final int DEFAULT_FONT_SIZE = 9;
38
39     private GridLayout buttonGridLayout;
40     private ConfigFile configFile;
41     private ConfigFileFactory configFileFactory;
42     private HashSet JavaDoc<Thread JavaDoc> daemonThreads;
43     private ModifyEvent event;
44
45     private List JavaDoc<LogFile> logFiles;
46     private int logFontSize;
47     private StyledText mainLogST;
48     private Event noDataEvent;
49     private TabFolder tabFolder;
50
51     private Image imageStop;
52     private Image imageStart;
53     private Image imageClearAll;
54
55     ShellMainLogViewer() {
56         super();
57         this.daemonThreads = new HashSet JavaDoc<Thread JavaDoc>();
58         this.mainLogST = null;
59         this.tabFolder = null;
60         this.configFileFactory = ConfigFileFactory.getInstance();
61
62         this.configFile = configFileFactory.getConfigFile();
63
64         // TODO logfile hack... to be fixed in next release
65
this.logFiles = configFile.getUserConfig().getLogGroups().get(0).getLogFiles();
66
67         this.logFontSize = DEFAULT_FONT_SIZE;
68         this.event = null;
69
70         this.imageStop = new Image(display, Util.getOwnResource(projectProperties.getIconStop()));
71         this.imageStart = new Image(display, Util.getOwnResource(projectProperties.getIconStart()));
72         this.imageClearAll = new Image(display, Util.getOwnResource(projectProperties.getIconClearAll()));
73
74         buttonGridLayout = new GridLayout(5, false);
75         buttonGridLayout.marginHeight = 0;
76         buttonGridLayout.marginWidth = 0;
77         buttonGridLayout.horizontalSpacing = 2;
78         buttonGridLayout.verticalSpacing = 0;
79
80         noDataEvent = new Event();
81         noDataEvent.data = LogViewerHandler.NO_DATA;
82     }
83
84     /**
85      * Returns the log viewer event.
86      *
87      * @return ModifyEvent object.
88      */

89     public ModifyEvent getEvent() {
90         return event;
91     }
92
93     /**
94      * Returns the log files.
95      *
96      * @return Log files.
97      */

98     public List JavaDoc<LogFile> getLogFiles() {
99         return logFiles;
100     }
101
102     /**
103      * Determines and returns the log viewer from the composite.
104      *
105      * @param composite
106      * Composite that contains the log viewer.
107      * @return Log viewer.
108      */

109     public StyledText getLogViewer(Composite composite) {
110         for (Control control : composite.getChildren()) {
111             if (control instanceof StyledText) {
112                 return (StyledText) control;
113             }
114         }
115         return null;
116     }
117
118     /**
119      * Redraws the tab items in the tab folder and restarts all log daemons.
120      */

121     public void redraw() {
122         removeTabItems();
123         destroyAllLogDaemons();
124         setupTabItems();
125         createAllLogDaemons();
126
127         mediator.handleEvent(ActionMediator.EVENT_UPDATE_LOG_SIZE_HANDLER);
128
129         parentShell.pack(true);
130         parentShell.setSize(640, 480);
131     }
132
133     /**
134      * Sets up the tab items in the tab folder and then starts all log daemons.
135      */

136     public void run() {
137         this.tabFolder = new TabFolder(parentShell, SWT.NONE);
138         tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
139
140         setupTabItems();
141         createAllLogDaemons();
142
143         mediator.handleEvent(ActionMediator.EVENT_UPDATE_LOG_SIZE_HANDLER);
144     }
145
146     /**
147      * Saves the log files.
148      *
149      * @param list
150      * Log files to be saved.
151      */

152     public void saveLogFiles(List JavaDoc<LogFile> list) {
153         logFiles = list;
154
155         UserConfig userConfig = configFile.getUserConfig();
156
157         // TODO log file hack... to be fixed in next release.
158
userConfig.getLogGroups().get(0).setLogFiles(logFiles);
159
160         configFile.saveUserConfig(userConfig);
161         // configFile.saveConfig(list);
162
}
163
164     /**
165      * Updates the log size handler for all log viewers based on the new purge
166      * strategy set by users.
167      *
168      * @param purgePercentage
169      * Total percentage to purge the log.
170      * @param logLineThreshold
171      * Max log line before purging kicks in.
172      */

173     public void updateLogSizeHandler(int purgePercentage, int logLineThreshold) {
174         for (int i = 0; i < tabFolder.getItemCount(); ++i) {
175             TabItem tabItem = tabFolder.getItem(i);
176
177             Composite composite = (Composite) tabItem.getControl();
178             StyledText logST = getLogViewer(composite);
179             logST.setData(new LogSizeHandler(logST, purgePercentage, logLineThreshold));
180         }
181     }
182
183     /**
184      * Creates log viewer composite that contains the viewer itself together
185      * with some action buttons.
186      *
187      * @param isMainLog
188      * Whether it is the main log or other logs.
189      * @return Newly created log viewer composite.
190      */

191     private Composite createLogViewerComposite(final boolean isMainLog) {
192         Composite composite = new Composite(tabFolder, SWT.NONE);
193         composite.setLayout(new GridLayout(2, false));
194
195         StyledText st = null;
196
197         // main log viewer
198
if (isMainLog) {
199             mainLogST = new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY);
200             st = mainLogST;
201         }
202         // other log viewer
203
else {
204             st = new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY);
205         }
206
207         st.setBackground(Util.COLOR_WHITE);
208         st.setLayoutData(new GridData(GridData.FILL_BOTH));
209         st.setFont(getLogFont());
210
211         // toolbar for organizing buttons
212
ToolBar toolbar = new ToolBar(composite, SWT.FLAT | SWT.VERTICAL);
213         toolbar.setLayout(buttonGridLayout);
214         toolbar.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
215
216         final ToolItem startStopTI = new ToolItem(toolbar, SWT.FLAT);
217         startStopTI.setImage(imageStop);
218         if (isMainLog) {
219             startStopTI.setToolTipText("Stop All Logs");
220         }
221         else {
222             startStopTI.setToolTipText("Stop Log");
223         }
224
225         ToolItem clearTI = new ToolItem(toolbar, SWT.FLAT);
226         clearTI.setImage(new Image(display, Util.getOwnResource(projectProperties.getIconClear())));
227         clearTI.setToolTipText("Clear Log");
228
229         // is main log, then show clear all logs icon
230
if (isMainLog) {
231             ToolItem clearAllTI = new ToolItem(toolbar, SWT.FLAT);
232             clearAllTI.setImage(imageClearAll);
233             clearAllTI.setToolTipText("Clear All Logs");
234
235             clearAllTI.addSelectionListener(new SelectionAdapter() {
236                 public void widgetSelected(SelectionEvent e) {
237                     clearAllLogViewers();
238                 }
239             });
240         }
241         // not main log, then show open file icon
242
else {
243             ToolItem openFileTI = new ToolItem(toolbar, SWT.FLAT);
244             openFileTI.setImage(new Image(display, Util.getOwnResource(projectProperties.getIconOpenFile())));
245             openFileTI.setToolTipText("Open Log File");
246
247             // open file button is clicked
248
openFileTI.addSelectionListener(new SelectionAdapter() {
249                 public void widgetSelected(SelectionEvent e) {
250                     handleOpenFile();
251                 }
252             });
253         }
254
255         ToolItem zoomInTI = new ToolItem(toolbar, SWT.FLAT);
256         zoomInTI.setImage(new Image(display, Util.getOwnResource(projectProperties.getIconZoomIn())));
257         zoomInTI.setToolTipText("Increase Font Size");
258
259         ToolItem zoomOutTI = new ToolItem(toolbar, SWT.FLAT);
260         zoomOutTI.setImage(new Image(display, Util.getOwnResource(projectProperties.getIconZoomOut())));
261         zoomOutTI.setToolTipText("Decrease Font Size");
262
263         final ToolItem scrollLockTI = new ToolItem(toolbar, SWT.CHECK);
264         scrollLockTI.setImage(new Image(display, Util.getOwnResource(projectProperties.getIconScrollLock())));
265         scrollLockTI.setToolTipText("Scroll Lock");
266
267         // start/stop listener
268
startStopTI.addSelectionListener(new SelectionAdapter() {
269             public void widgetSelected(SelectionEvent e) {
270                 handleStartStopLog(startStopTI, isMainLog);
271             }
272         });
273
274         // clear button is clicked
275
clearTI.addSelectionListener(new SelectionAdapter() {
276             public void widgetSelected(SelectionEvent e) {
277                 clearActiveLogViewer();
278             }
279         });
280
281         // increase font size
282
zoomInTI.addSelectionListener(new SelectionAdapter() {
283             public void widgetSelected(SelectionEvent e) {
284                 increaseLogFont();
285             }
286         });
287
288         // decrease font size
289
zoomOutTI.addSelectionListener(new SelectionAdapter() {
290             public void widgetSelected(SelectionEvent e) {
291                 decreaseLogFont();
292             }
293         });
294
295         // lock/unlock scroll
296
scrollLockTI.addSelectionListener(new SelectionAdapter() {
297             public void widgetSelected(SelectionEvent e) {
298                 handleLogScroll(scrollLockTI);
299             }
300         });
301
302         return composite;
303     }
304
305     private LogFile getActiveLogFile() {
306         // minus 1 is required because the first tab is main log
307
int selectedLogIndex = tabFolder.getSelectionIndex() - 1;
308         return logFiles.get(selectedLogIndex);
309     }
310
311     /**
312      * Determines the active tab to obtain which log to open, then opens the log
313      * file based on user's preferred default editor.
314      */

315     private void handleOpenFile() {
316         LogFile logFile = getActiveLogFile();
317
318         try {
319             Runtime.getRuntime().exec(new String JavaDoc[] {
320                     configFile.getUserConfig().getTextEditorPath(),
321                     logFile.getLogPath()
322             });
323         }
324         catch (Exception JavaDoc ex) {
325             log.error(ex);
326             ex.printStackTrace();
327         }
328     }
329
330     /**
331      * Handles start and stop log events.
332      *
333      * @param startStopTI
334      * Tool item.
335      * @param isMainLog
336      * Whether it is a main log or not.
337      */

338     private void handleStartStopLog(ToolItem startStopTI, boolean isMainLog) {
339         boolean toStop = startStopTI.getImage().equals(imageStop);
340
341         // stopping log
342
if (toStop) {
343             // for main log, stop all daemon threads
344
if (isMainLog) {
345                 destroyAllLogDaemons();
346
347                 for (TabItem tabItem : tabFolder.getItems()) {
348                     Composite composite = (Composite) tabItem.getControl();
349                     for (Control control : composite.getChildren()) {
350                         if (control instanceof ToolBar) {
351                             ToolBar toolbar = (ToolBar) control;
352
353                             for (ToolItem toolItem : toolbar.getItems()) {
354                                 if (toolItem.getImage().equals(imageStop)) {
355                                     toolItem.setImage(imageStart);
356                                     toolItem.setToolTipText("Start Log");
357                                 }
358                             }
359                         }
360                     }
361                 }
362
363                 startStopTI.setImage(imageStart);
364                 startStopTI.setToolTipText("Start All Logs");
365
366             }
367             // for other log, stop its daemon thread
368
else {
369                 destroySelectedLogDaemon();
370
371                 startStopTI.setImage(imageStart);
372                 startStopTI.setToolTipText("Start Log");
373             }
374         }
375         // starting log
376
else {
377             // for main log, start all daemon threads
378
if (isMainLog) {
379                 createAllLogDaemons();
380
381                 for (TabItem tabItem : tabFolder.getItems()) {
382                     Composite composite = (Composite) tabItem.getControl();
383                     for (Control control : composite.getChildren()) {
384                         if (control instanceof ToolBar) {
385                             ToolBar toolbar = (ToolBar) control;
386
387                             for (ToolItem toolItem : toolbar.getItems()) {
388                                 if (toolItem.getImage().equals(imageStart)) {
389                                     toolItem.setImage(imageStop);
390                                     toolItem.setToolTipText("Stop Log");
391                                 }
392                             }
393
394                         }
395                     }
396                 }
397
398                 startStopTI.setImage(imageStop);
399                 startStopTI.setToolTipText("Stop All Logs");
400             }
401             // for other log, start its daemon thread
402
else {
403                 createSelectedLogDaemon();
404
405                 startStopTI.setImage(imageStop);
406                 startStopTI.setToolTipText("Stop Log");
407             }
408         }
409     }
410
411     /**
412      * Handles whether to lock or unlock the scrolling log viewer.
413      *
414      * @param scrollLockTI
415      * Scroll lock tool item.
416      */

417     private void handleLogScroll(ToolItem scrollLockTI) {
418         boolean toScrollLock = scrollLockTI.getSelection();
419
420         if (toScrollLock) {
421             scrollLockTI.setToolTipText("Scroll Unlock");
422         }
423         else {
424             scrollLockTI.setToolTipText("Scroll Lock");
425         }
426
427         getActiveLogViewer().setData(LOG_VIEWER_DATA_KEY_SCROLL_LOCK, toScrollLock);
428     }
429
430     /**
431      * Clears the content in the active log viewer.
432      */

433     private void clearActiveLogViewer() {
434         StyledText st = getActiveLogViewer();
435
436         st.setText("");
437
438         // prevents the tray icon from staying active
439
st.notifyListeners(SWT.Modify, noDataEvent);
440     }
441
442     private void clearAllLogViewers() {
443         for (TabItem tabItem : tabFolder.getItems()) {
444             StyledText styledText = getLogViewer((Composite) tabItem.getControl());
445             styledText.setText("");
446
447             // prevents the tray icon from staying active
448
styledText.notifyListeners(SWT.Modify, noDataEvent);
449         }
450     }
451
452     /**
453      * Decreases log font size.
454      */

455     private void decreaseLogFont() {
456         if (logFontSize > DEFAULT_FONT_SIZE) {
457             logFontSize--;
458             getActiveLogViewer().setFont(getLogFont());
459         }
460     }
461
462     /**
463      * Returns the active log viewer that is currently being viewed.
464      *
465      * @return Active log viewer.
466      */

467     private StyledText getActiveLogViewer() {
468         TabItem tabItem = tabFolder.getItem(tabFolder.getSelectionIndex());
469         Composite composite = (Composite) tabItem.getControl();
470
471         return getLogViewer(composite);
472     }
473
474     /**
475      * Creates and return new font object.
476      *
477      * @return Font object.
478      */

479     private Font getLogFont() {
480         return new Font(display, "Courier New", logFontSize, SWT.NORMAL);
481     }
482
483     /**
484      * Increases log font size.
485      */

486     private void increaseLogFont() {
487         if (logFontSize < 19) {
488             logFontSize++;
489             getActiveLogViewer().setFont(getLogFont());
490         }
491     }
492
493     /**
494      * Removes all tab items from the tab folder.
495      */

496     private void removeTabItems() {
497         TabItem[] tabItems = tabFolder.getItems();
498         for (int i = 0; i < tabItems.length; ++i) {
499             tabItems[i].dispose();
500         }
501     }
502
503     /**
504      * Sets up all tab items in the tab folder.
505      */

506     private void setupTabItems() {
507
508         // setting up main tab
509
TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
510
511         Composite composite = createLogViewerComposite(true);
512
513         mainLogST.addModifyListener(new ModifyListener() {
514             public void modifyText(ModifyEvent e) {
515                 event = e;
516                 mediator.handleEvent(ActionMediator.EVENT_UPDATE_TRAY_ICON);
517             }
518         });
519
520         tabItem.setControl(composite);
521         tabItem.setText(projectProperties.getMainTabItemName());
522
523         // setting up other tabs based on the log configuration
524
for (int i = 0; i < logFiles.size(); ++i) {
525             String JavaDoc tabItemName = logFiles.get(i).getLogName();
526
527             composite = createLogViewerComposite(false);
528
529             tabItem = new TabItem(tabFolder, SWT.NONE);
530             tabItem.setControl(composite);
531             tabItem.setText(tabItemName);
532         }
533
534         tabFolder.pack();
535     }
536
537     /**
538      * Creates all log daemons and store them in a thread collection for easy
539      * reference.
540      */

541     private void createAllLogDaemons() {
542         // some daemon still exists, then kill them all first before recreating
543
// them. This may happen when user stops all logs, then starts single
544
// log first before attempting to start all logs. If the additional
545
// daemons are not removed, then there will be more than one daemon
546
// listening to the same log file in one log viewer, which in the sense
547
// doesn't accomplish anything useful.
548
if (!daemonThreads.isEmpty()) {
549             destroyAllLogDaemons();
550         }
551
552         for (int i = 0; i < logFiles.size(); ++i) {
553             LogFile logFile = logFiles.get(i);
554             TabItem tabItem = tabFolder.getItem(i + 1);
555
556             createLogDaemonThread(logFile, tabItem);
557         }
558     }
559
560     /**
561      * Interrupts all log daemons and clear them from the thread collection.
562      */

563     private void destroyAllLogDaemons() {
564         for (Thread JavaDoc daemonThread : daemonThreads) {
565             daemonThread.interrupt();
566         }
567
568         daemonThreads.clear();
569     }
570
571     /**
572      * Interrupts the selected log viewer's daemon thread.
573      */

574     private void destroySelectedLogDaemon() {
575         LogFile logFile = getActiveLogFile();
576
577         Thread JavaDoc daemonThread = getDaemonByName(logFile.getId());
578
579         if (daemonThread != null) {
580             daemonThread.interrupt();
581
582             daemonThreads.remove(daemonThread);
583         }
584     }
585
586     /**
587      * Creates the selected log viewer's daemon thread.
588      */

589     private void createSelectedLogDaemon() {
590         int selectedTabIndex = tabFolder.getSelectionIndex();
591         LogFile logFile = logFiles.get(selectedTabIndex - 1);
592         TabItem tabItem = tabFolder.getItem(selectedTabIndex);
593
594         createLogDaemonThread(logFile, tabItem);
595     }
596
597     /**
598      * Creates a log daemon thread and start it.
599      *
600      * @param logFile
601      * Log bean object.
602      * @param tabItem
603      * Tab item.
604      */

605     private void createLogDaemonThread(LogFile logFile, TabItem tabItem) {
606         Composite composite = (Composite) tabItem.getControl();
607         StyledText logST = getLogViewer(composite);
608         LogViewerHandler logRepository = new LogViewerHandler(logFile, mainLogST, logST);
609         FileListener listener = new FileListener(logRepository, logFile.getLogPath());
610
611         Thread JavaDoc thread = new Thread JavaDoc(listener, logFile.getId());
612         thread.setDaemon(true);
613         thread.start();
614
615         daemonThreads.add(thread);
616     }
617
618     /**
619      * Returns the daemon thread by name.
620      *
621      * @param name
622      * Daemon thread name.
623      * @return Daemon thread if found, otherwise null.
624      */

625     private Thread JavaDoc getDaemonByName(String JavaDoc name) {
626
627         for (Thread JavaDoc daemonThread : daemonThreads) {
628             if (daemonThread.getName().equals(name)) {
629                 return daemonThread;
630             }
631         }
632
633         return null;
634     }
635 }
636
Popular Tags