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.Dimension;
    21  import java.awt.FlowLayout;
    22  import java.awt.GridBagConstraints;
    23  import java.awt.GridBagLayout;
    24  import java.awt.Insets;
    25  import java.text.NumberFormat;
    26
    27  import javax.swing.BorderFactory;
    28  import javax.swing.Icon;
    29  import javax.swing.ImageIcon;
    30  import javax.swing.JComponent;
    31  import javax.swing.JLabel;
    32  import javax.swing.JPanel;
    33  import javax.swing.SwingConstants;
    34  import javax.swing.SwingUtilities;
    35  import javax.swing.border.Border;
    36
    37  import org.apache.log4j.chainsaw.icons.ChainsawIcons;
    38  import org.apache.log4j.chainsaw.messages.MessageCenter;
    39
    40
    41  /**
    42   * A general purpose status bar for all Frame windows
    43   *
    44   * @author Paul Smith &lt;psmith@apache.org&gt;
    45   *
    46   */
    47  public class ChainsawStatusBar extends JPanel {
    48    private static final int DELAY_PERIOD = 5000;
    49    private static final String DEFAULT_MSG = "Welcome to Chainsaw v2!";
    50    private final JLabel statusMsg = new JLabel(DEFAULT_MSG);
    51    private final JLabel searchMatchLabel = new JLabel("", SwingConstants.CENTER);
    52    private final JLabel pausedLabel = new JLabel("", SwingConstants.CENTER);
    53    private final JLabel lineSelectionLabel = new JLabel("", SwingConstants.CENTER);
    54    private final JLabel eventCountLabel = new JLabel("", SwingConstants.CENTER);
    55    private final JLabel receivedEventLabel = new JLabel("", SwingConstants.CENTER);
    56    private final JLabel receivedConnectionlabel = new JLabel("", SwingConstants.CENTER);
    57    private volatile long lastReceivedConnection = System.currentTimeMillis();
    58    private final Thread connectionThread;
    59    private final Icon pausedIcon = new ImageIcon(ChainsawIcons.PAUSE);
    60    private final Icon netConnectIcon =
    61      new ImageIcon(ChainsawIcons.ANIM_NET_CONNECT);
    62    private final NumberFormat nf = NumberFormat.getNumberInstance();
    63    private final Border statusBarComponentBorder =
    64      BorderFactory.createLineBorder(statusMsg.getBackground().darker());
    65    private final LogUI logUI;
    66
    67      public ChainsawStatusBar(LogUI logUI) {
    68      setLayout(new GridBagLayout());
    69      this.logUI = logUI;
    70      nf.setMaximumFractionDigits(0);
    71      nf.setMinimumFractionDigits(0);
    72      nf.setGroupingUsed(false);
    73
    74      JPanel statusMsgPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));
    75
    76      statusMsgPanel.add(statusMsg);
    77      statusMsgPanel.setBorder(statusBarComponentBorder);
    78
    79      pausedLabel.setBorder(statusBarComponentBorder);
    80      pausedLabel.setMinimumSize(
    81        new Dimension(pausedIcon.getIconWidth(), pausedIcon.getIconHeight()));
    82
    83      pausedLabel.setToolTipText(
    84        "Shows whether the current Log panel is paused or not");
    85
    86      receivedEventLabel.setBorder(statusBarComponentBorder);
    87      receivedEventLabel.setToolTipText(
    88        "Indicates whether Chainsaw is receiving events, and how fast it is processing them");
    89      receivedEventLabel.setMinimumSize(
    90        new Dimension(
    91          receivedEventLabel.getFontMetrics(receivedEventLabel.getFont())
    92                            .stringWidth("99999999999.9/s") + 5,
    93          (int) receivedEventLabel.getPreferredSize().getHeight()));
    94
    95  	eventCountLabel.setBorder(statusBarComponentBorder);
    96  	eventCountLabel.setToolTipText("<# viewable events>:<# total events>");
    97  	eventCountLabel.setMinimumSize(
    98  	new Dimension(
    99  	eventCountLabel.getFontMetrics(eventCountLabel.getFont())
    100 						.stringWidth("Filtered/Total: 999999999999:999999999999") + 5,
    101 	  (int) eventCountLabel.getPreferredSize().getHeight()));
    102
    103     searchMatchLabel.setBorder(statusBarComponentBorder);
    104     searchMatchLabel.setToolTipText("<# viewable events>:<# total events>");
    105     searchMatchLabel.setMinimumSize(
    106     new Dimension(
    107     searchMatchLabel.getFontMetrics(eventCountLabel.getFont()).stringWidth("Find matches: 999999999999") + 5,
    108             (int) searchMatchLabel.getPreferredSize().getHeight()));
    109
    110     receivedConnectionlabel.setBorder(statusBarComponentBorder);
    111     receivedConnectionlabel.setToolTipText(
    112       "Indicates whether Chainsaw has received a remote connection");
    113     receivedConnectionlabel.setMinimumSize(
    114       new Dimension(
    115         netConnectIcon.getIconWidth() + 4,
    116         (int) receivedConnectionlabel.getPreferredSize().getHeight()));
    117
    118     lineSelectionLabel.setBorder(statusBarComponentBorder);
    119     lineSelectionLabel.setMinimumSize(
    120       new Dimension(
    121         lineSelectionLabel.getFontMetrics(lineSelectionLabel.getFont())
    122                           .stringWidth("999999999"),
    123         (int) lineSelectionLabel.getPreferredSize().getHeight()));
    124     lineSelectionLabel.setToolTipText(
    125       "The current line # selected");
    126
    127     JComponent[] toFix =
    128       new JComponent[] {
    129         searchMatchLabel, eventCountLabel,
    130         receivedConnectionlabel, lineSelectionLabel, receivedEventLabel,
    131         pausedLabel
    132       };
    133
    134     for (int i = 0; i < toFix.length; i++) {
    135       toFix[i].setPreferredSize(toFix[i].getMinimumSize());
    136       toFix[i].setMaximumSize(toFix[i].getMinimumSize());
    137     }
    138
    139     statusMsg.setMinimumSize(pausedLabel.getPreferredSize());
    140     statusMsg.setToolTipText("Shows messages from Chainsaw");
    141
    142     GridBagConstraints c = new GridBagConstraints();
    143     c.insets = new Insets(2, 2, 2, 2);
    144     c.weightx = 1.0;
    145     c.weighty = 1.0;
    146     c.ipadx = 2;
    147     c.ipady = 2;
    148     c.gridx = 0;
    149     c.gridy = 0;
    150     c.fill = GridBagConstraints.BOTH;
    151     c.anchor = GridBagConstraints.WEST;
    152
    153     add(statusMsgPanel, c);
    154
    155     c.weightx = 0.0;
    156     c.weighty = 0.0;
    157     c.gridx = 1;
    158     add(receivedConnectionlabel, c);
    159
    160 	c.weightx = 0.0;
    161 	c.weighty = 0.0;
    162 	c.gridx = 2;
    163 	add(lineSelectionLabel, c);
    164
    165     c.weightx = 0.0;
    166     c.weighty = 0.0;
    167     c.gridx = 3;
    168     add(searchMatchLabel, c);
    169
    170 	c.weightx = 0.0;
    171 	c.weighty = 0.0;
    172 	c.gridx = 4;
    173 	add(eventCountLabel, c);
    174
    175     c.weightx = 0.0;
    176     c.weighty = 0.0;
    177     c.gridx = 5;
    178     add(receivedEventLabel, c);
    179
    180     c.weightx = 0.0;
    181     c.weighty = 0.0;
    182     c.gridx = 6;
    183
    184     add(pausedLabel, c);
    185
    186     connectionThread =
    187       new Thread(
    188         new Runnable() {
    189           public void run() {
    190             while (true) {
    191               try {
    192                 Thread.sleep(DELAY_PERIOD);
    193               } catch (InterruptedException e) {
    194               }
    195
    196               Icon icon = null;
    197
    198               if (
    199                 (System.currentTimeMillis() - lastReceivedConnection) < DELAY_PERIOD) {
    200                 icon = netConnectIcon;
    201               }
    202
    203               final Icon theIcon = icon;
    204               SwingUtilities.invokeLater(
    205                 new Runnable() {
    206                   public void run() {
    207                     receivedConnectionlabel.setIcon(theIcon);
    208                   }
    209                 });
    210             }
    211           }
    212         });
    213     connectionThread.start();
    214   }
    215
    216   void setDataRate(final double dataRate) {
    217     SwingUtilities.invokeLater(
    218       new Runnable() {
    219         public void run() {
    220           receivedEventLabel.setText(nf.format(dataRate) + "/s");
    221         }
    222       });
    223   }
    224
    225   /**
    226    * Indicates a new connection has been established between
    227    * Chainsaw and some remote host
    228    * @param source
    229    */
    230   void remoteConnectionReceived(String source) {
    231     lastReceivedConnection = System.currentTimeMillis();
    232     MessageCenter.getInstance().getLogger().info("Connection received from " + source);
    233     connectionThread.interrupt();
    234
    235     //    TODO and maybe play a sound?
    236   }
    237
    238   /**
    239    * Called when the paused state of the LogPanel has been updated
    240    * @param isPaused
    241    * @param tabName
    242    */
    243   void setPaused(final boolean isPaused, String tabName) {
    244     if (tabName.equals(logUI.getActiveTabName())) {
    245       Runnable runnable =
    246         new Runnable() {
    247           public void run() {
    248               pausedLabel.setIcon(isPaused ? pausedIcon : null);
    249               pausedLabel.setToolTipText(
    250                 isPaused ? "This Log panel is currently paused"
    251                          : "This Log panel is not paused");
    252           }
    253       };
    254       SwingUtilities.invokeLater(runnable);
    255     }
    256   }
    257
    258   void setSelectedLine(
    259           final int selectedLine, final int lineCount, final int total, String tabName) {
    260     if (tabName.equals(logUI.getActiveTabName())) {
    261         SwingUtilities.invokeLater(
    262           new Runnable() {
    263             public void run() {
    264               lineSelectionLabel.setText(selectedLine+"");
    265               eventCountLabel.setText("Filtered/Total: " + lineCount + ":" + total);
    266             }
    267           });
    268     }
    269   }
    270
    271   void setSearchMatchCount(int searchMatchCount, String tabName) {
    272       if (tabName.equals(logUI.getActiveTabName())) {
    273           if (searchMatchCount == 0) {
    274             searchMatchLabel.setText("");
    275           } else {
    276             searchMatchLabel.setText("Find matches: " + searchMatchCount);
    277           }
    278       }
    279   }
    280
    281   void setNothingSelected() {
    282     SwingUtilities.invokeLater(
    283       new Runnable() {
    284         public void run() {
    285           lineSelectionLabel.setText("");
    286         }
    287       });
    288   }
    289
    290   void clear() {
    291     setMessage(DEFAULT_MSG);
    292     setNothingSelected();
    293     SwingUtilities.invokeLater(
    294       new Runnable() {
    295         public void run() {
    296           receivedEventLabel.setText("");
    297         }
    298       });
    299   }
    300
    301   public void setMessage(final String msg) {
    302     SwingUtilities.invokeLater(
    303       new Runnable() {
    304         public void run() {
    305           statusMsg.setText(" " + msg);
    306         }
    307       });
    308   }
    309 }