| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.log4j.chainsaw; |
| |
| import java.awt.Dimension; |
| import java.awt.FlowLayout; |
| import java.awt.GridBagConstraints; |
| import java.awt.GridBagLayout; |
| import java.awt.Insets; |
| import java.text.NumberFormat; |
| |
| import javax.swing.BorderFactory; |
| import javax.swing.Icon; |
| import javax.swing.ImageIcon; |
| import javax.swing.JComponent; |
| import javax.swing.JLabel; |
| import javax.swing.JPanel; |
| import javax.swing.SwingConstants; |
| import javax.swing.SwingUtilities; |
| import javax.swing.border.Border; |
| |
| import org.apache.log4j.chainsaw.icons.ChainsawIcons; |
| import org.apache.log4j.chainsaw.messages.MessageCenter; |
| |
| |
| /** |
| * A general purpose status bar for all Frame windows |
| * |
| * @author Paul Smith <psmith@apache.org> |
| * |
| */ |
| public class ChainsawStatusBar extends JPanel { |
| private static final int DELAY_PERIOD = 5000; |
| private static final String DEFAULT_MSG = "Welcome to Chainsaw v2!"; |
| private final JLabel statusMsg = new JLabel(DEFAULT_MSG); |
| private final JLabel searchMatchLabel = new JLabel("", SwingConstants.CENTER); |
| private final JLabel pausedLabel = new JLabel("", SwingConstants.CENTER); |
| private final JLabel lineSelectionLabel = new JLabel("", SwingConstants.CENTER); |
| private final JLabel eventCountLabel = new JLabel("", SwingConstants.CENTER); |
| private final JLabel receivedEventLabel = new JLabel("", SwingConstants.CENTER); |
| private final JLabel receivedConnectionlabel = new JLabel("", SwingConstants.CENTER); |
| private volatile long lastReceivedConnection = System.currentTimeMillis(); |
| private final Thread connectionThread; |
| private final Icon pausedIcon = new ImageIcon(ChainsawIcons.PAUSE); |
| private final Icon netConnectIcon = |
| new ImageIcon(ChainsawIcons.ANIM_NET_CONNECT); |
| private final NumberFormat nf = NumberFormat.getNumberInstance(); |
| private final Border statusBarComponentBorder = |
| BorderFactory.createLineBorder(statusMsg.getBackground().darker()); |
| private final LogUI logUI; |
| |
| public ChainsawStatusBar(LogUI logUI) { |
| setLayout(new GridBagLayout()); |
| this.logUI = logUI; |
| nf.setMaximumFractionDigits(0); |
| nf.setMinimumFractionDigits(0); |
| nf.setGroupingUsed(false); |
| |
| JPanel statusMsgPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2)); |
| |
| statusMsgPanel.add(statusMsg); |
| statusMsgPanel.setBorder(statusBarComponentBorder); |
| |
| pausedLabel.setBorder(statusBarComponentBorder); |
| pausedLabel.setMinimumSize( |
| new Dimension(pausedIcon.getIconWidth(), pausedIcon.getIconHeight())); |
| |
| pausedLabel.setToolTipText( |
| "Shows whether the current Log panel is paused or not"); |
| |
| receivedEventLabel.setBorder(statusBarComponentBorder); |
| receivedEventLabel.setToolTipText( |
| "Indicates whether Chainsaw is receiving events, and how fast it is processing them"); |
| receivedEventLabel.setMinimumSize( |
| new Dimension( |
| receivedEventLabel.getFontMetrics(receivedEventLabel.getFont()) |
| .stringWidth("99999999999.9/s") + 5, |
| (int) receivedEventLabel.getPreferredSize().getHeight())); |
| |
| eventCountLabel.setBorder(statusBarComponentBorder); |
| eventCountLabel.setToolTipText("<# viewable events>:<# total events>"); |
| eventCountLabel.setMinimumSize( |
| new Dimension( |
| eventCountLabel.getFontMetrics(eventCountLabel.getFont()) |
| .stringWidth("Filtered/Total: 999999999999:999999999999") + 5, |
| (int) eventCountLabel.getPreferredSize().getHeight())); |
| |
| searchMatchLabel.setBorder(statusBarComponentBorder); |
| searchMatchLabel.setToolTipText("<# viewable events>:<# total events>"); |
| searchMatchLabel.setMinimumSize( |
| new Dimension( |
| searchMatchLabel.getFontMetrics(eventCountLabel.getFont()).stringWidth("Find matches: 999999999999") + 5, |
| (int) searchMatchLabel.getPreferredSize().getHeight())); |
| |
| receivedConnectionlabel.setBorder(statusBarComponentBorder); |
| receivedConnectionlabel.setToolTipText( |
| "Indicates whether Chainsaw has received a remote connection"); |
| receivedConnectionlabel.setMinimumSize( |
| new Dimension( |
| netConnectIcon.getIconWidth() + 4, |
| (int) receivedConnectionlabel.getPreferredSize().getHeight())); |
| |
| lineSelectionLabel.setBorder(statusBarComponentBorder); |
| lineSelectionLabel.setMinimumSize( |
| new Dimension( |
| lineSelectionLabel.getFontMetrics(lineSelectionLabel.getFont()) |
| .stringWidth("999999999"), |
| (int) lineSelectionLabel.getPreferredSize().getHeight())); |
| lineSelectionLabel.setToolTipText( |
| "The current line # selected"); |
| |
| JComponent[] toFix = |
| new JComponent[] { |
| searchMatchLabel, eventCountLabel, |
| receivedConnectionlabel, lineSelectionLabel, receivedEventLabel, |
| pausedLabel |
| }; |
| |
| for (JComponent aToFix : toFix) { |
| aToFix.setPreferredSize(aToFix.getMinimumSize()); |
| aToFix.setMaximumSize(aToFix.getMinimumSize()); |
| } |
| |
| statusMsg.setMinimumSize(pausedLabel.getPreferredSize()); |
| statusMsg.setToolTipText("Shows messages from Chainsaw"); |
| |
| GridBagConstraints c = new GridBagConstraints(); |
| c.insets = new Insets(2, 2, 2, 2); |
| c.weightx = 1.0; |
| c.weighty = 1.0; |
| c.ipadx = 2; |
| c.ipady = 2; |
| c.gridx = 0; |
| c.gridy = 0; |
| c.fill = GridBagConstraints.BOTH; |
| c.anchor = GridBagConstraints.WEST; |
| |
| add(statusMsgPanel, c); |
| |
| c.weightx = 0.0; |
| c.weighty = 0.0; |
| c.gridx = 1; |
| add(receivedConnectionlabel, c); |
| |
| c.weightx = 0.0; |
| c.weighty = 0.0; |
| c.gridx = 2; |
| add(lineSelectionLabel, c); |
| |
| c.weightx = 0.0; |
| c.weighty = 0.0; |
| c.gridx = 3; |
| add(searchMatchLabel, c); |
| |
| c.weightx = 0.0; |
| c.weighty = 0.0; |
| c.gridx = 4; |
| add(eventCountLabel, c); |
| |
| c.weightx = 0.0; |
| c.weighty = 0.0; |
| c.gridx = 5; |
| add(receivedEventLabel, c); |
| |
| c.weightx = 0.0; |
| c.weighty = 0.0; |
| c.gridx = 6; |
| |
| add(pausedLabel, c); |
| |
| connectionThread = |
| new Thread( |
| () -> { |
| while (true) { |
| try { |
| Thread.sleep(DELAY_PERIOD); |
| } catch (InterruptedException e) { |
| } |
| |
| Icon icon = null; |
| |
| if ( |
| (System.currentTimeMillis() - lastReceivedConnection) < DELAY_PERIOD) { |
| icon = netConnectIcon; |
| } |
| |
| final Icon theIcon = icon; |
| SwingUtilities.invokeLater( |
| () -> receivedConnectionlabel.setIcon(theIcon)); |
| } |
| }); |
| connectionThread.start(); |
| } |
| |
| void setDataRate(final double dataRate) { |
| SwingUtilities.invokeLater( |
| () -> receivedEventLabel.setText(nf.format(dataRate) + "/s")); |
| } |
| |
| /** |
| * Indicates a new connection has been established between |
| * Chainsaw and some remote host |
| * @param source |
| */ |
| void remoteConnectionReceived(String source) { |
| lastReceivedConnection = System.currentTimeMillis(); |
| MessageCenter.getInstance().getLogger().info("Connection received from " + source); |
| connectionThread.interrupt(); |
| |
| // TODO and maybe play a sound? |
| } |
| |
| /** |
| * Called when the paused state of the LogPanel has been updated |
| * @param isPaused |
| * @param tabName |
| */ |
| void setPaused(final boolean isPaused, String tabName) { |
| if (tabName.equals(logUI.getActiveTabName())) { |
| Runnable runnable = |
| () -> { |
| pausedLabel.setIcon(isPaused ? pausedIcon : null); |
| pausedLabel.setToolTipText( |
| isPaused ? "This Log panel is currently paused" |
| : "This Log panel is not paused"); |
| }; |
| SwingUtilities.invokeLater(runnable); |
| } |
| } |
| |
| void setSelectedLine( |
| final int selectedLine, final int lineCount, final int total, String tabName) { |
| if (tabName.equals(logUI.getActiveTabName())) { |
| SwingUtilities.invokeLater( |
| () -> { |
| lineSelectionLabel.setText(selectedLine+""); |
| eventCountLabel.setText("Filtered/Total: " + lineCount + ":" + total); |
| }); |
| } |
| } |
| |
| void setSearchMatchCount(int searchMatchCount, String tabName) { |
| if (tabName.equals(logUI.getActiveTabName())) { |
| if (searchMatchCount == 0) { |
| searchMatchLabel.setText(""); |
| } else { |
| searchMatchLabel.setText("Find matches: " + searchMatchCount); |
| } |
| } |
| } |
| |
| void setNothingSelected() { |
| SwingUtilities.invokeLater( |
| () -> lineSelectionLabel.setText("")); |
| } |
| |
| void clear() { |
| setMessage(DEFAULT_MSG); |
| setNothingSelected(); |
| SwingUtilities.invokeLater( |
| () -> receivedEventLabel.setText("")); |
| } |
| |
| public void setMessage(final String msg) { |
| SwingUtilities.invokeLater( |
| () -> statusMsg.setText(" " + msg)); |
| } |
| } |