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