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 <psmith@apache.org>
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 pausedLabel = new JLabel("", SwingConstants.CENTER);
52    private final JLabel lineSelectionLabel = new JLabel("", SwingConstants.CENTER);
53    private final JLabel eventCountLabel = new JLabel("", SwingConstants.CENTER);
54    private final JLabel receivedEventLabel = new JLabel("0.0", SwingConstants.CENTER);
55    private final JLabel receivedConnectionlabel = new JLabel("", SwingConstants.CENTER);
56    private volatile long lastReceivedConnection = System.currentTimeMillis();
57    private final Thread connectionThread;
58    private final Icon pausedIcon = new ImageIcon(ChainsawIcons.PAUSE);
59    private final Icon netConnectIcon =
60      new ImageIcon(ChainsawIcons.ANIM_NET_CONNECT);
61    private final NumberFormat nf = NumberFormat.getNumberInstance();
62    private final Border statusBarComponentBorder =
63      BorderFactory.createLineBorder(statusMsg.getBackground().darker());
64  
65    public ChainsawStatusBar() {
66      setLayout(new GridBagLayout());
67  
68      nf.setMaximumFractionDigits(1);
69      nf.setMinimumFractionDigits(1);
70      nf.setGroupingUsed(false);
71  
72      JPanel statusMsgPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));
73      
74      statusMsgPanel.add(statusMsg);
75      statusMsgPanel.setBorder(statusBarComponentBorder);
76      
77      pausedLabel.setBorder(statusBarComponentBorder);
78      pausedLabel.setMinimumSize(
79        new Dimension(pausedIcon.getIconWidth(), pausedIcon.getIconHeight()));
80  
81      pausedLabel.setToolTipText(
82        "Shows whether the current Log panel is paused or not");
83  
84      receivedEventLabel.setBorder(statusBarComponentBorder);
85      receivedEventLabel.setToolTipText(
86        "Indicates whether Chainsaw is receiving events, and how fast it is processing them");
87      receivedEventLabel.setMinimumSize(
88        new Dimension(
89          receivedEventLabel.getFontMetrics(receivedEventLabel.getFont())
90                            .stringWidth("9999.9/s") + 5,
91          (int) receivedEventLabel.getPreferredSize().getHeight()));
92  
93  	eventCountLabel.setBorder(statusBarComponentBorder);
94  	eventCountLabel.setToolTipText("<# viewable events>:<# total events>");
95  	eventCountLabel.setMinimumSize(
96  	new Dimension(
97  	eventCountLabel.getFontMetrics(eventCountLabel.getFont())
98  						.stringWidth("99999:99999") + 5,
99  	  (int) eventCountLabel.getPreferredSize().getHeight()));
100 	  
101     receivedConnectionlabel.setBorder(statusBarComponentBorder);
102     receivedConnectionlabel.setToolTipText(
103       "Indicates whether Chainsaw has received a remote connection");
104     receivedConnectionlabel.setMinimumSize(
105       new Dimension(
106         netConnectIcon.getIconWidth() + 4,
107         (int) receivedConnectionlabel.getPreferredSize().getHeight()));
108 
109     lineSelectionLabel.setBorder(statusBarComponentBorder);
110     lineSelectionLabel.setMinimumSize(
111       new Dimension(
112         lineSelectionLabel.getFontMetrics(lineSelectionLabel.getFont())
113                           .stringWidth("999999"),
114         (int) lineSelectionLabel.getPreferredSize().getHeight()));
115     lineSelectionLabel.setToolTipText(
116       "The current line # selected");
117 
118     JComponent[] toFix =
119       new JComponent[] {
120 		eventCountLabel,
121         receivedConnectionlabel, lineSelectionLabel, receivedEventLabel,
122         pausedLabel
123       };
124 
125     for (int i = 0; i < toFix.length; i++) {
126       toFix[i].setPreferredSize(toFix[i].getMinimumSize());
127       toFix[i].setMaximumSize(toFix[i].getMinimumSize());
128     }
129 
130     statusMsg.setMinimumSize(pausedLabel.getPreferredSize());
131     statusMsg.setToolTipText("Shows messages from Chainsaw");
132 
133     GridBagConstraints c = new GridBagConstraints();
134     c.insets = new Insets(2, 2, 2, 2);
135     c.weightx = 1.0;
136     c.weighty = 1.0;
137     c.ipadx = 2;
138     c.ipady = 2;
139     c.gridx = 0;
140     c.gridy = 0;
141     c.fill = GridBagConstraints.BOTH;
142     c.anchor = GridBagConstraints.WEST;
143 
144     add(statusMsgPanel, c);
145 
146     c.weightx = 0.0;
147     c.weighty = 0.0;
148     c.gridx = 1;
149     add(receivedConnectionlabel, c);
150 
151 	c.weightx = 0.0;
152 	c.weighty = 0.0;
153 	c.gridx = 2;
154 	add(lineSelectionLabel, c);
155 	
156 	c.weightx = 0.0;
157 	c.weighty = 0.0;
158 	c.gridx = 3;
159 	add(eventCountLabel, c);
160 
161     c.weightx = 0.0;
162     c.weighty = 0.0;
163     c.gridx = 4;
164     add(receivedEventLabel, c);
165 
166     c.weightx = 0.0;
167     c.weighty = 0.0;
168     c.gridx = 5;
169 
170     add(pausedLabel, c);
171 
172     connectionThread =
173       new Thread(
174         new Runnable() {
175           public void run() {
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                 new Runnable() {
192                   public void run() {
193                     receivedConnectionlabel.setIcon(theIcon);
194                   }
195                 });
196             }
197           }
198         });
199     connectionThread.start();
200   }
201 
202   void setDataRate(final double dataRate) {
203     SwingUtilities.invokeLater(
204       new Runnable() {
205         public void run() {
206           receivedEventLabel.setText(nf.format(dataRate) + "/s");
207         }
208       });
209   }
210 
211   /***
212    * Indicates a new connection has been established between
213    * Chainsaw and some remote host
214    * @param source
215    */
216   void remoteConnectionReceived(String source) {
217     lastReceivedConnection = System.currentTimeMillis();
218     MessageCenter.getInstance().getLogger().info("Connection received from " + source);
219     connectionThread.interrupt();
220 
221     //    TODO and maybe play a sound?
222   }
223 
224   /***
225    * Called when the paused state of the LogPanel has been updated
226    * @param isPaused
227    */
228   void setPaused(final boolean isPaused) {
229     Runnable runnable =
230       new Runnable() {
231         public void run() {
232           pausedLabel.setIcon(isPaused ? pausedIcon : null);
233           pausedLabel.setToolTipText(
234             isPaused ? "This Log panel is currently paused"
235                      : "This Log panel is not paused");
236         }
237       };
238 
239     SwingUtilities.invokeLater(runnable);
240   }
241 
242   void setSelectedLine(
243     final int selectedLine, final int lineCount, final int total) {
244     SwingUtilities.invokeLater(
245       new Runnable() {
246         public void run() {
247           lineSelectionLabel.setText(
248             selectedLine+"");
249 			eventCountLabel.setText(lineCount + ":" + total);
250         }
251       });
252   }
253 
254   void setNothingSelected() {
255     SwingUtilities.invokeLater(
256       new Runnable() {
257         public void run() {
258           lineSelectionLabel.setText("");
259         }
260       });
261   }
262 
263   void clear() {
264     setMessage(DEFAULT_MSG);
265     setNothingSelected();
266     SwingUtilities.invokeLater(
267       new Runnable() {
268         public void run() {
269           receivedEventLabel.setText("");
270         }
271       });
272   }
273 
274   public void setMessage(final String msg) {
275     SwingUtilities.invokeLater(
276       new Runnable() {
277         public void run() {
278           statusMsg.setText(" " + msg);
279         }
280       });
281   }
282 }