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