View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.log4j.chainsaw;
19  
20  import java.awt.BorderLayout;
21  import java.awt.Component;
22  import java.awt.Dimension;
23  import java.awt.Insets;
24  import java.awt.event.ActionEvent;
25  import java.awt.event.ActionListener;
26  import java.awt.event.InputEvent;
27  import java.awt.event.KeyEvent;
28  import java.beans.PropertyChangeEvent;
29  import java.beans.PropertyChangeListener;
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.Iterator;
33  import java.util.List;
34  
35  import javax.swing.AbstractAction;
36  import javax.swing.Action;
37  import javax.swing.Box;
38  import javax.swing.ImageIcon;
39  import javax.swing.JButton;
40  import javax.swing.JCheckBoxMenuItem;
41  import javax.swing.JComponent;
42  import javax.swing.JDialog;
43  import javax.swing.JLabel;
44  import javax.swing.JMenu;
45  import javax.swing.JMenuBar;
46  import javax.swing.JMenuItem;
47  import javax.swing.JPanel;
48  import javax.swing.JRadioButtonMenuItem;
49  import javax.swing.JTextField;
50  import javax.swing.JToolBar;
51  import javax.swing.KeyStroke;
52  import javax.swing.SwingConstants;
53  import javax.swing.SwingUtilities;
54  import javax.swing.UIManager;
55  import javax.swing.event.ChangeEvent;
56  import javax.swing.event.ChangeListener;
57  
58  import org.apache.log4j.chainsaw.filter.FilterModel;
59  import org.apache.log4j.chainsaw.help.HelpManager;
60  import org.apache.log4j.chainsaw.icons.ChainsawIcons;
61  import org.apache.log4j.chainsaw.osx.OSXIntegration;
62  import org.apache.log4j.chainsaw.receivers.ReceiversHelper;
63  
64  
65  /***
66   * Encapsulates the full Toolbar, and menus and all the actions that can be performed from it.
67   * @author Paul Smith <psmith@apache.org>
68   * @author Scott Deboy <sdeboy@apache.org>
69   */
70  class ChainsawToolBarAndMenus implements ChangeListener {
71    private final SmallToggleButton showReceiversButton;
72    private final JTextField findField;
73    private final Action changeModelAction;
74    private final Action clearAction;
75    private final Action closeAction;
76    private final Action findNextAction;
77    private final Action findPreviousAction;
78    private final Action pauseAction;
79    private final Action showPreferencesAction;
80    private final Action showColorPanelAction;
81    private final Action showReceiversAction;
82    private final Action toggleLogTreeAction;
83    private final Action toggleScrollToBottomAction;
84    private final Action toggleDetailPaneAction;
85    private final Action toggleToolbarAction;
86    private final Action undockAction;
87    private final Action customExpressionPanelAction;
88    private final Collection lookAndFeelMenus = new ArrayList();
89    private final JCheckBoxMenuItem toggleShowReceiversCheck =
90      new JCheckBoxMenuItem();
91    private final JCheckBoxMenuItem toggleLogTreeMenuItem =
92      new JCheckBoxMenuItem();
93    private final JCheckBoxMenuItem toggleScrollToBottomMenuItem =
94      new JCheckBoxMenuItem();
95    private final JCheckBoxMenuItem toggleDetailMenuItem =
96      new JCheckBoxMenuItem();
97    private final JCheckBoxMenuItem toggleCyclicMenuItem =
98      new JCheckBoxMenuItem();
99    private final FileMenu fileMenu;
100   private final JCheckBoxMenuItem toggleStatusBarCheck =
101     new JCheckBoxMenuItem();
102   private final JMenu viewMenu = new JMenu("View");
103   private final JMenuBar menuBar;
104   private final JCheckBoxMenuItem menuItemClose = new JCheckBoxMenuItem();
105   private final JToolBar toolbar;
106   private LogUI logui;
107   private final SmallButton clearButton = new SmallButton();
108   private final SmallToggleButton detailPaneButton = new SmallToggleButton();
109   private final SmallToggleButton logTreePaneButton = new SmallToggleButton();
110   private final SmallToggleButton scrollToBottomButton = new SmallToggleButton();
111   private final SmallToggleButton pauseButton = new SmallToggleButton();
112   private final SmallToggleButton toggleCyclicButton = new SmallToggleButton();
113   private final Action[] logPanelSpecificActions;
114   private final JMenu activeTabMenu = new JMenu("Current tab");
115   private final JPanel findPanel;
116 
117   ChainsawToolBarAndMenus(final LogUI logui) {
118     this.logui = logui;
119     toolbar = new JToolBar(SwingConstants.HORIZONTAL);
120     menuBar = new JMenuBar();
121     fileMenu = new FileMenu(logui);
122     closeAction = createCloseHelpAction();
123     changeModelAction = createChangeModelAction();
124     findField = new JTextField();
125     findNextAction = getFindNextAction();
126     findPreviousAction = getFindPreviousAction();
127     customExpressionPanelAction = createCustomExpressionPanelAction();
128     showPreferencesAction = createShowPreferencesAction();
129     showColorPanelAction = createShowColorPanelAction();
130     toggleToolbarAction = createToggleToolbarAction();
131     toggleLogTreeAction = createToggleLogTreeAction();
132     toggleScrollToBottomAction = createScrollToBottomAction();
133     pauseAction = createPauseAction();
134     clearAction = createClearAction();
135     undockAction = createUndockAction();
136     showReceiversAction = createShowReceiversAction();
137     showReceiversButton = new SmallToggleButton(showReceiversAction);
138 
139     findPanel = new JPanel();
140 
141     Dimension findSize = new Dimension(170, 22);
142     Dimension findPanelSize = new Dimension(175, 30);
143     findPanel.setPreferredSize(findPanelSize);
144     findPanel.setMaximumSize(findPanelSize);
145     findPanel.setMinimumSize(findPanelSize);
146     findField.setPreferredSize(findSize);
147     findField.setMaximumSize(findSize);
148     findField.setMinimumSize(findSize);
149     findPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
150     findField.setAlignmentY(Component.CENTER_ALIGNMENT);
151     
152     toggleDetailPaneAction = createToggleDetailPaneAction();
153     createMenuBar();
154     createToolbar();
155 
156     logPanelSpecificActions =
157       new Action[] {
158         pauseAction, findNextAction, findPreviousAction, clearAction,
159         fileMenu.getFileSaveAction(), toggleDetailPaneAction,
160         showPreferencesAction, showColorPanelAction, undockAction,
161         toggleLogTreeAction, toggleScrollToBottomAction, changeModelAction,
162       };
163 
164     logui.getApplicationPreferenceModel().addPropertyChangeListener(
165       "statusBar",
166       new PropertyChangeListener() {
167         public void propertyChange(PropertyChangeEvent evt) {
168           boolean value = ((Boolean) evt.getNewValue()).booleanValue();
169           toggleStatusBarCheck.setSelected(value);
170         }
171       });
172 
173     logui.getApplicationPreferenceModel().addPropertyChangeListener(
174       "receivers",
175       new PropertyChangeListener() {
176         public void propertyChange(PropertyChangeEvent evt) {
177           boolean value = ((Boolean) evt.getNewValue()).booleanValue();
178           showReceiversButton.setSelected(value);
179           toggleShowReceiversCheck.setSelected(value);
180         }
181       });
182   }
183 
184   /***
185    * @return
186    */
187   private Action createChangeModelAction() {
188     Action action =
189       new AbstractAction("Use Cyclic", new ImageIcon(ChainsawIcons.REFRESH)) {
190         public void actionPerformed(ActionEvent arg0) {
191           LogPanel logPanel = logui.getCurrentLogPanel();
192           logPanel.toggleCyclic();
193           scanState();
194         }
195       };
196 
197     action.putValue(
198       Action.SHORT_DESCRIPTION, "Changes between Cyclic and Unlimited mode.");
199 
200     return action;
201   }
202 
203   /***
204   * @return
205   */
206   private Action createToggleLogTreeAction() {
207     Action action =
208       new AbstractAction("Toggle the Logger Tree Pane") {
209         public void actionPerformed(ActionEvent e) {
210           if (logui.getCurrentLogPanel() != null) {
211             logui.getCurrentLogPanel().toggleLogTreeVisible();
212           }
213         }
214       };
215 
216     action.putValue(Action.SHORT_DESCRIPTION, "Toggles the Logger Tree Pane");
217     action.putValue("enabled", Boolean.TRUE);
218     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_T));
219     action.putValue(
220       Action.ACCELERATOR_KEY,
221       KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK));
222     action.putValue(
223       Action.SMALL_ICON, new ImageIcon(ChainsawIcons.WINDOW_ICON));
224 
225     return action;
226   }
227 
228   /***
229    * @return
230    */
231    private Action createScrollToBottomAction() {
232      Action action =
233        new AbstractAction("Toggle Scroll to Bottom") {
234          public void actionPerformed(ActionEvent e) {
235            if (logui.getCurrentLogPanel() != null) {
236              logui.getCurrentLogPanel().toggleScrollToBottom();
237            }
238          }
239        };
240 
241      action.putValue(Action.SHORT_DESCRIPTION, "Toggles Scroll to Bottom");
242      action.putValue("enabled", Boolean.TRUE);
243      action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_B));
244      action.putValue(
245        Action.ACCELERATOR_KEY,
246        KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_MASK));
247      action.putValue(
248        Action.SMALL_ICON, new ImageIcon(ChainsawIcons.SCROLL_TO_BOTTOM));
249 
250      return action;
251    }
252 
253    /***
254    * DOCUMENT ME!
255    */
256   public void stateChange() {
257     scanState();
258   }
259 
260   /***
261    * DOCUMENT ME!
262    *
263    * @param e DOCUMENT ME!
264    */
265   public void stateChanged(ChangeEvent e) {
266     scanState();
267   }
268 
269   JMenuBar getMenubar() {
270     return menuBar;
271   }
272 
273   JToolBar getToolbar() {
274     return toolbar;
275   }
276 
277   private Action createClearAction() {
278     final Action action =
279       new AbstractAction("Clear") {
280         public void actionPerformed(ActionEvent e) {
281           LogPanel logPanel = logui.getCurrentLogPanel();
282 
283           if (logPanel == null) {
284             return;
285           }
286 
287           logPanel.clearEvents();
288         }
289       };
290 
291     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_C));
292     action.putValue(
293       Action.ACCELERATOR_KEY,
294       KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, InputEvent.CTRL_MASK));
295     action.putValue(
296       Action.SHORT_DESCRIPTION, "Removes all the events from the current view");
297     action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DELETE));
298 
299     return action;
300   }
301 
302   private Action createCloseHelpAction() {
303     final Action action =
304       new AbstractAction() {
305         public void actionPerformed(ActionEvent e) {
306           closeAction.putValue(Action.NAME, "Welcome tab");
307           logui.removeWelcomePanel();
308 
309           if (menuItemClose.isSelected()) {
310             logui.addWelcomePanel();
311           } else {
312           }
313         }
314       };
315 
316     action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F1"));
317 
318     //    action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.ALT_MASK));
319     action.putValue(Action.SHORT_DESCRIPTION, "Toggles the Welcome tab");
320     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_C));
321     action.putValue(Action.NAME, "Welcome tab");
322 
323     return action;
324   }
325 
326   private void createMenuBar() {
327     JMenuItem menuItemUseRightMouse =
328       new JMenuItem(
329         "Other options available via panel's right mouse button popup menu");
330     menuItemUseRightMouse.setEnabled(false);
331 
332     viewMenu.setMnemonic('V');
333 
334     final JCheckBoxMenuItem showToolbarCheck =
335       new JCheckBoxMenuItem(toggleToolbarAction);
336     showToolbarCheck.setSelected(
337       logui.getApplicationPreferenceModel().isToolbar());
338 
339     logui.getApplicationPreferenceModel().addPropertyChangeListener(
340       "toolbar",
341       new PropertyChangeListener() {
342         public void propertyChange(PropertyChangeEvent evt) {
343           boolean value = ((Boolean) evt.getNewValue()).booleanValue();
344           showToolbarCheck.setSelected(value);
345         }
346       });
347 
348     menuItemClose.setAction(closeAction);
349 
350     JCheckBoxMenuItem pause = new JCheckBoxMenuItem(pauseAction);
351     JMenuItem menuPrefs = new JMenuItem(showPreferencesAction);
352     menuPrefs.setText(
353       showPreferencesAction.getValue(Action.SHORT_DESCRIPTION).toString());
354 
355     JMenuItem menuCustomExpressionPanel =
356       new JMenuItem(customExpressionPanelAction);
357     menuCustomExpressionPanel.setText(
358       customExpressionPanelAction.getValue(Action.SHORT_DESCRIPTION).toString());
359 
360     JMenuItem menuShowColor = new JMenuItem(showColorPanelAction);
361     menuShowColor.setText(
362       showColorPanelAction.getValue(Action.SHORT_DESCRIPTION).toString());
363 
364     JMenuItem menuUndock = new JMenuItem(undockAction);
365 
366     JMenuItem showAppPrefs =
367       new JMenuItem("Show Application-wide Preferences...");
368 
369     showAppPrefs.addActionListener(
370       new ActionListener() {
371         public void actionPerformed(ActionEvent e) {
372           logui.showApplicationPreferences();
373         }
374       });
375 
376     toggleDetailMenuItem.setAction(toggleDetailPaneAction);
377     toggleDetailMenuItem.setSelected(true);
378 
379     toggleCyclicMenuItem.setAction(changeModelAction);
380 
381     toggleCyclicMenuItem.setSelected(true);
382 
383     toggleLogTreeMenuItem.setAction(toggleLogTreeAction);
384     toggleLogTreeMenuItem.setSelected(true);
385 
386     toggleScrollToBottomMenuItem.setAction(toggleScrollToBottomAction);
387 
388     final Action toggleStatusBarAction =
389       new AbstractAction("Show Status bar") {
390         public void actionPerformed(ActionEvent arg0) {
391           logui.getApplicationPreferenceModel().setStatusBar(
392             toggleStatusBarCheck.isSelected());
393         }
394       };
395 
396     toggleStatusBarAction.putValue(
397       Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_B));
398     toggleStatusBarCheck.setAction(toggleStatusBarAction);
399     toggleStatusBarCheck.setSelected(
400       logui.getApplicationPreferenceModel().isStatusBar());
401 
402     activeTabMenu.add(pause);
403     activeTabMenu.add(toggleCyclicMenuItem);
404     activeTabMenu.addSeparator();
405     activeTabMenu.add(toggleDetailMenuItem);
406     activeTabMenu.add(toggleLogTreeMenuItem);
407     activeTabMenu.addSeparator();
408     activeTabMenu.add(menuUndock);
409     activeTabMenu.add(menuShowColor);
410     activeTabMenu.add(menuPrefs);
411 
412     activeTabMenu.addSeparator();
413     activeTabMenu.add(new JMenuItem(clearAction));
414     activeTabMenu.addSeparator();
415     activeTabMenu.add(toggleScrollToBottomMenuItem);
416     activeTabMenu.add(menuItemUseRightMouse);
417 
418     viewMenu.add(showToolbarCheck);
419     viewMenu.add(toggleStatusBarCheck);
420     viewMenu.add(toggleShowReceiversCheck);
421     viewMenu.add(menuItemClose);
422     viewMenu.addSeparator();
423     viewMenu.add(menuCustomExpressionPanel);
424 
425     if (!OSXIntegration.IS_OSX) {
426         viewMenu.addSeparator();
427         viewMenu.add(showAppPrefs);
428     }
429 
430     JMenu helpMenu = new JMenu("Help");
431     helpMenu.setMnemonic('H');
432 
433     JMenuItem about = new JMenuItem("About Chainsaw v2...");
434     about.setMnemonic('A');
435     about.addActionListener(
436       new ActionListener() {
437         public void actionPerformed(ActionEvent e) {
438           logui.showAboutBox();
439         }
440       });
441 
442     Action startTutorial =
443       new AbstractAction("Tutorial...", new ImageIcon(ChainsawIcons.HELP)) {
444         public void actionPerformed(ActionEvent e) {
445           logui.setupTutorial();
446         }
447       };
448 
449     startTutorial.putValue(
450       Action.SHORT_DESCRIPTION, "Starts the tutorial process");
451     helpMenu.add(startTutorial);
452 
453     List knownReceivers =
454       ReceiversHelper.getInstance().getKnownReceiverClasses();
455     JMenu receiverHelp = new JMenu("Receiver JavaDoc");
456 
457     for (Iterator iter = knownReceivers.iterator(); iter.hasNext();) {
458       final Class clazz = (Class) iter.next();
459       receiverHelp.add(
460         new AbstractAction(clazz.getName()) {
461           public void actionPerformed(ActionEvent arg0) {
462             HelpManager.getInstance().showHelpForClass(clazz);
463           }
464         });
465     }
466 
467     helpMenu.add(receiverHelp);
468 
469     helpMenu.addSeparator();
470     helpMenu.add(CommonActions.getInstance().getShowReleaseNotes());
471     helpMenu.add(about);
472 
473     menuBar.add(fileMenu);
474     menuBar.add(viewMenu);
475     menuBar.add(activeTabMenu);
476     menuBar.add(helpMenu);
477   }
478 
479   private Action createPauseAction() {
480     final Action action =
481       new AbstractAction("Pause") {
482         public void actionPerformed(ActionEvent evt) {
483           LogPanel logPanel = logui.getCurrentLogPanel();
484 
485           if (logPanel == null) {
486             return;
487           }
488 
489           logPanel.setPaused(!logPanel.isPaused());
490           scanState();
491         }
492       };
493 
494     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_P));
495     action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F12"));
496     action.putValue(
497       Action.SHORT_DESCRIPTION,
498       "Causes incoming events for this tab to be discarded");
499     action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.PAUSE));
500 
501     return action;
502   }
503 
504   private Action createShowPreferencesAction() {
505     Action showPreferences =
506       new AbstractAction("", ChainsawIcons.ICON_PREFERENCES) {
507         public void actionPerformed(ActionEvent arg0) {
508           LogPanel logPanel = logui.getCurrentLogPanel();
509 
510           if (logPanel != null) {
511             logPanel.showPreferences();
512           }
513         }
514       };
515 
516     showPreferences.putValue(
517       Action.SHORT_DESCRIPTION, "LogPanel Preferences...");
518 
519     // TODO think of good mnemonics and HotKey for this action
520     return showPreferences;
521   }
522 
523   private Action createCustomExpressionPanelAction() {
524     final JDialog dialog = new JDialog(logui, "Define tab", true);
525     dialog.getContentPane().add(getCustomExpressionPanel());
526     dialog.pack();
527 
528     Action createExpressionPanel =
529       new AbstractAction("", ChainsawIcons.ICON_HELP) {
530         public void actionPerformed(ActionEvent arg0) {
531           dialog.setVisible(true);
532         }
533       };
534 
535     createExpressionPanel.putValue(
536       Action.SHORT_DESCRIPTION, "Create custom expression LogPanel...");
537 
538     // TODO think of good mnemonics and HotKey for this action
539     return createExpressionPanel;
540   }
541 
542   private Action createShowColorPanelAction() {
543     Action showColorPanel =
544       new AbstractAction("", ChainsawIcons.ICON_PREFERENCES) {
545         public void actionPerformed(ActionEvent arg0) {
546           LogPanel logPanel = logui.getCurrentLogPanel();
547 
548           if (logPanel != null) {
549             logPanel.showColorPreferences();
550           }
551         }
552       };
553 
554     showColorPanel.putValue(
555       Action.SHORT_DESCRIPTION, "LogPanel Color Filter...");
556 
557     // TODO think of good mnemonics and HotKey for this action
558     return showColorPanel;
559   }
560 
561   /***
562    * @return
563    */
564   private Action createShowReceiversAction() {
565     final Action action =
566       new AbstractAction("Show Receivers") {
567         public void actionPerformed(ActionEvent arg0) {
568           logui.getApplicationPreferenceModel().setReceivers(
569             !logui.getApplicationPreferenceModel().isReceivers());
570         }
571       };
572 
573     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_E));
574     action.putValue(
575       Action.SHORT_DESCRIPTION,
576       "Shows the currently configured Log4j Receivers");
577     action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F6"));
578     action.putValue(
579       Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ANIM_NET_CONNECT));
580     toggleShowReceiversCheck.setAction(action);
581 
582     return action;
583   }
584 
585   private Action createToggleDetailPaneAction() {
586     Action action =
587       new AbstractAction("Show Detail Pane") {
588         public void actionPerformed(ActionEvent evt) {
589           LogPanel logPanel = logui.getCurrentLogPanel();
590 
591           if (logPanel == null) {
592             return;
593           }
594 
595           logPanel.toggleDetailVisible();
596         }
597       };
598 
599     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
600     action.putValue(
601       Action.ACCELERATOR_KEY,
602       KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK));
603     action.putValue(Action.SHORT_DESCRIPTION, "Hides/Shows the Detail Pane");
604     action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.INFO));
605 
606     return action;
607   }
608 
609   private Action createToggleToolbarAction() {
610     /***
611      * -== Begin of Show/Hide toolbar action
612      */
613     final Action action =
614       new AbstractAction("Show Toolbar") {
615         public void actionPerformed(ActionEvent e) {
616           logui.getApplicationPreferenceModel().setToolbar(
617             !logui.getApplicationPreferenceModel().isToolbar());
618         }
619       };
620 
621     action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_T));
622 
623     return action;
624   }
625 
626   private void createToolbar() {
627     Insets buttonMargins = new Insets(1, 1, 1, 1);
628 
629     FileMenu menu = (FileMenu) menuBar.getMenu(0);
630 
631     JButton fileOpenButton = new SmallButton(menu.getLog4JFileOpenAction());
632     fileOpenButton.setMargin(buttonMargins);
633 
634     JButton fileSaveButton = new SmallButton(menu.getFileSaveAction());
635     fileSaveButton.setMargin(buttonMargins);
636 
637     fileOpenButton.setText("");
638     fileSaveButton.setText("");
639 
640     toolbar.add(fileOpenButton);
641     toolbar.add(fileSaveButton);
642     toolbar.addSeparator();
643 
644     pauseButton.setAction(pauseAction);
645     pauseButton.setText("");
646 
647     //		pauseButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F12"),pauseAction.getValue(Action.NAME) );
648     pauseButton.getActionMap().put(
649       pauseAction.getValue(Action.NAME), pauseAction);
650 
651     toggleCyclicButton.setAction(changeModelAction);
652     toggleCyclicButton.setText(null);
653 
654     detailPaneButton.setAction(toggleDetailPaneAction);
655     detailPaneButton.setText(null);
656     detailPaneButton.getActionMap().put(
657       toggleDetailPaneAction.getValue(Action.NAME), toggleDetailPaneAction);
658     detailPaneButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
659       KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK),
660       toggleDetailPaneAction.getValue(Action.NAME));
661 
662     logTreePaneButton.setAction(toggleLogTreeAction);
663     logTreePaneButton.getActionMap().put(
664       toggleLogTreeAction.getValue(Action.NAME), toggleLogTreeAction);
665     logTreePaneButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
666       KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK),
667       toggleLogTreeAction.getValue(Action.NAME));
668     logTreePaneButton.setText(null);
669 
670     scrollToBottomButton.setAction(toggleScrollToBottomAction);
671     scrollToBottomButton.getActionMap().put(
672       toggleScrollToBottomAction.getValue(Action.NAME), toggleScrollToBottomAction);
673     scrollToBottomButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
674       KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_MASK),
675       toggleScrollToBottomAction.getValue(Action.NAME));
676     scrollToBottomButton.setText(null);
677 
678     SmallButton prefsButton = new SmallButton(showPreferencesAction);
679     SmallButton undockButton = new SmallButton(undockAction);
680     undockButton.setText("");
681 
682     toolbar.add(undockButton);
683     toolbar.add(pauseButton);
684     toolbar.add(toggleCyclicButton);
685     toolbar.addSeparator();
686     toolbar.add(detailPaneButton);
687     toolbar.add(logTreePaneButton);
688     toolbar.add(scrollToBottomButton);
689     toolbar.add(prefsButton);
690     toolbar.addSeparator();
691 
692     toolbar.add(clearButton);
693     clearButton.setAction(clearAction);
694     clearButton.setText("");
695     toolbar.addSeparator();
696 
697     JButton findNextButton = new SmallButton(findNextAction);
698     findNextButton.setText("");
699     findNextButton.getActionMap().put(
700       findNextAction.getValue(Action.NAME), findNextAction);
701     findNextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
702       (KeyStroke) findNextAction.getValue(Action.ACCELERATOR_KEY),
703       findNextAction.getValue(Action.NAME));
704 
705     JButton findPreviousButton = new SmallButton(findPreviousAction);
706     findPreviousButton.setText("");
707     findPreviousButton.getActionMap().put(
708       findPreviousAction.getValue(Action.NAME), findPreviousAction);
709     findPreviousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
710       (KeyStroke) findPreviousAction.getValue(Action.ACCELERATOR_KEY),
711       findPreviousAction.getValue(Action.NAME));
712 
713     findPanel.add(findField);
714 
715     toolbar.add(findPanel);
716     toolbar.add(findNextButton);
717     toolbar.add(findPreviousButton);
718 
719     toolbar.addSeparator();
720 
721     showReceiversButton.setText(null);
722     toolbar.add(showReceiversButton);
723 
724     toolbar.add(Box.createHorizontalGlue());
725 
726     toolbar.setMargin(buttonMargins);
727     toolbar.setFloatable(false);
728   }
729 
730   private Action createUndockAction() {
731     Action action =
732       new AbstractAction("Undock", ChainsawIcons.ICON_UNDOCK) {
733         public void actionPerformed(ActionEvent arg0) {
734           LogPanel logPanel = logui.getCurrentLogPanel();
735 
736           if (logPanel != null) {
737             logPanel.undock();
738           }
739         }
740       };
741 
742     action.putValue(
743       Action.SHORT_DESCRIPTION,
744       "Undocks the current Log panel into it's own window");
745 
746     //	TODO think of some mnemonics and HotKeys for this action
747     return action;
748   }
749 
750   private void scanState() {
751     toggleStatusBarCheck.setSelected(logui.isStatusBarVisible());
752     toggleShowReceiversCheck.setSelected(
753       logui.getApplicationPreferenceModel().isReceivers());
754 
755     logTreePaneButton.setSelected(logui.isLogTreePanelVisible());
756     LogPanel panel = logui.getCurrentLogPanel();
757     if (panel != null) {
758     	scrollToBottomButton.setSelected(panel.isScrollToBottom());
759     } else {
760     	scrollToBottomButton.setSelected(false);
761     }
762     showReceiversButton.setSelected(
763       logui.getApplicationPreferenceModel().isReceivers());
764     menuItemClose.setSelected(logui.getTabbedPane().containsWelcomePanel());
765 
766     /***
767      * We get the currently selected LogPanel, and if null, deactivate some
768      * actions
769      */
770     LogPanel logPanel = logui.getCurrentLogPanel();
771 
772     boolean activateLogPanelActions = true;
773 
774     if (logPanel == null) {
775       activateLogPanelActions = false;
776       findField.setEnabled(false);
777       findPanel.removeAll();
778       findPanel.add(findField);
779       activeTabMenu.setEnabled(false);
780       closeAction.setEnabled(true);
781       detailPaneButton.setSelected(false);
782       toggleCyclicButton.setSelected(false);
783     } else {
784       activeTabMenu.setEnabled(true);
785       fileMenu.getFileSaveAction().setEnabled(true);
786       findPanel.removeAll();
787       findPanel.add(logPanel.getFindTextField());
788 
789       pauseButton.getModel().setSelected(logPanel.isPaused());
790       toggleCyclicButton.setSelected(logPanel.isCyclic());
791       logui.getStatusBar().setPaused(logPanel.isPaused());
792       toggleCyclicMenuItem.setSelected(logPanel.isCyclic());
793       detailPaneButton.getModel().setSelected(logPanel.isDetailVisible());
794       toggleLogTreeMenuItem.setSelected(logPanel.isLogTreeVisible());
795       toggleScrollToBottomMenuItem.setSelected(logPanel.isScrollToBottom());
796     }
797 
798     findPanel.invalidate();
799     findPanel.revalidate();
800     findPanel.repaint();
801 
802     for (int i = 0; i < logPanelSpecificActions.length; i++) {
803       logPanelSpecificActions[i].setEnabled(activateLogPanelActions);
804     }
805 
806     String currentLookAndFeelName = UIManager.getLookAndFeel().getName();
807 
808     for (Iterator iter = lookAndFeelMenus.iterator(); iter.hasNext();) {
809       JRadioButtonMenuItem element = (JRadioButtonMenuItem) iter.next();
810 
811       if (element.getText().equals(currentLookAndFeelName)) {
812         element.setSelected(true);
813       } else {
814         element.setSelected(false);
815       }
816     }
817   }
818 
819   private Action getFindNextAction() {
820     final Action action =
821       new AbstractAction("Find next") {
822         public void actionPerformed(ActionEvent e) {
823           LogPanel p = logui.getCurrentLogPanel();
824 
825           if (p != null) {
826             p.findNext();
827           }
828         }
829       };
830 
831     //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
832     action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F3"));
833     action.putValue(
834       Action.SHORT_DESCRIPTION,
835       "Find the next occurrence of the rule from the current row");
836     action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DOWN));
837 
838     return action;
839   }
840 
841   private Action getFindPreviousAction() {
842     final Action action =
843       new AbstractAction("Find previous") {
844         public void actionPerformed(ActionEvent e) {
845           LogPanel p = logui.getCurrentLogPanel();
846 
847           if (p != null) {
848             p.findPrevious();
849           }
850         }
851       };
852 
853     //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
854     action.putValue(
855       Action.ACCELERATOR_KEY,
856       KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_MASK));
857     action.putValue(
858       Action.SHORT_DESCRIPTION,
859       "Find the previous occurrence of the rule from the current row");
860     action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UP));
861 
862     return action;
863   }
864 
865   private JPanel getCustomExpressionPanel() {
866     final JPanel panel = new JPanel(new BorderLayout());
867     panel.add(
868       new JLabel("Enter expression for new tab:  "), BorderLayout.NORTH);
869 
870     final JTextField textField = new JTextField();
871     textField.addKeyListener(
872       new ExpressionRuleContext(new FilterModel(), textField));
873     panel.add(textField, BorderLayout.CENTER);
874 
875     JButton ok = new JButton("OK");
876     JButton close = new JButton("Close");
877     JPanel lowerPanel = new JPanel();
878     lowerPanel.add(ok);
879     lowerPanel.add(Box.createHorizontalStrut(7));
880     lowerPanel.add(close);
881     panel.add(lowerPanel, BorderLayout.SOUTH);
882 
883     ok.addActionListener(
884       new AbstractAction() {
885         public void actionPerformed(ActionEvent evt) {
886           logui.createCustomExpressionLogPanel(textField.getText());
887           SwingUtilities.getAncestorOfClass(JDialog.class, panel).setVisible(
888             false);
889         }
890       });
891 
892     close.addActionListener(
893       new AbstractAction() {
894         public void actionPerformed(ActionEvent evt) {
895           SwingUtilities.getAncestorOfClass(JDialog.class, panel).setVisible(
896             false);
897         }
898       });
899 
900     //String expression = JOptionPane.showInputDialog(logui, "Enter expression", "Create custom expression LogPanel", JOptionPane.PLAIN_MESSAGE);
901     return panel;
902   }
903 }