changeset 731:153988c559a8

New toolbar for header panel review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-October/003868.html reviewed-by: jerboaa
author Mario Torre <neugens.limasoftware@gmail.com>
date Wed, 24 Oct 2012 11:57:30 +0200
parents 8b73b939568c
children c0234110ca5f
files client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButton.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButtonUI.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionToggleButton.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HeaderPanel.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/LabelField.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SectionHeader.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButton.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButtonBorder.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ValueField.java client/swing/src/test/java/com/redhat/thermostat/client/swing/components/HeaderPanelTest.java common/core/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/locale/LocaleResources.java thread/client-common/src/main/resources/com/redhat/thermostat/thread/client/common/locale/strings.properties thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadView.java thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java
diffstat 15 files changed, 608 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButton.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButton.java	Wed Oct 24 11:57:30 2012 +0200
@@ -36,45 +36,87 @@
 
 package com.redhat.thermostat.client.swing.components;
 
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.lang.reflect.InvocationTargetException;
+
 import javax.swing.AbstractButton;
 import javax.swing.Icon;
 import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
 
 @SuppressWarnings("serial")
 public class ActionButton extends JButton implements ToolbarButton {
-
-    private AbstractButton realButton;
-    
+        
     public ActionButton(final Icon icon) {
-        super(icon);
-        
-        realButton = new JButton() {
-            @Override
-            public int getWidth() {
-                return icon.getIconWidth() + 5;
-            }
-            
-            @Override
-            public int getHeight() {
-                return icon.getIconHeight() + 4;
-            }
-        };
-        setUI(new ActionButtonUI(realButton));
-        
-        setSize(realButton.getWidth(), realButton.getHeight());
-        setContentAreaFilled(false);
-        
-        setPreferredSize(getSize());
-        setMinimumSize(getSize());
-        setMaximumSize(getSize());
-        
-        realButton.setModel(getModel());
-
-        setBorderPainted(false);
+        this(icon, "");
     }
     
+    public ActionButton(final Icon icon, String text) {
+        super(icon);
+                
+        setText(text);
+        
+        setUI(new ActionButtonUI());
+        setOpaque(false);
+        setContentAreaFilled(false);
+        setBorder(new ToolbarButtonBorder(this));
+    }
+        
     @Override
     public AbstractButton getToolbarButton() {
         return this;
     }
+    
+    @Override
+    public ToolbarButton copy() {
+        ActionButton copy = new ActionButton(getIcon(), getText());
+        copy.setName(getName());
+        copy.setToolTipText(getToolTipText());
+        return copy;
+    }
+    
+    public static void main(String[] args) throws InvocationTargetException, InterruptedException {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            
+            @Override
+            public void run() {
+               JFrame frame = new JFrame();
+               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+               
+               HeaderPanel header = new HeaderPanel();
+               header.setHeader("Test");
+               
+               Icon icon = new Icon() {
+                
+                @Override
+                public void paintIcon(Component c, Graphics g, int x, int y) {
+                    g.setColor(Color.CYAN);
+                    g.fillRect(x, y, 16, 16);
+
+                }
+                
+                @Override
+                public int getIconWidth() {
+                    // TODO Auto-generated method stub
+                    return 16;
+                }
+                
+                @Override
+                public int getIconHeight() {
+                    // TODO Auto-generated method stub
+                    return 16;
+                }
+            }; 
+               
+               header.addToolBarButton(new ActionButton(icon, "Fluff"));
+               
+               frame.getContentPane().add(header);
+               frame.setSize(500, 500);
+               frame.setVisible(true);
+            }
+        });
+    }      
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButtonUI.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButtonUI.java	Wed Oct 24 11:57:30 2012 +0200
@@ -36,7 +36,11 @@
 
 package com.redhat.thermostat.client.swing.components;
 
+import java.awt.FontMetrics;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
 import java.awt.image.BufferedImage;
 import java.awt.image.BufferedImageOp;
 import java.awt.image.ConvolveOp;
@@ -46,18 +50,16 @@
 import javax.swing.ButtonModel;
 import javax.swing.Icon;
 import javax.swing.JComponent;
-import javax.swing.border.Border;
 import javax.swing.plaf.metal.MetalButtonUI;
 
+import com.redhat.thermostat.client.ui.Palette;
+
 class ActionButtonUI extends MetalButtonUI {
 
     private BufferedImage sourceIcon;
     private BufferedImage rollOverIcon;
-    private AbstractButton realButton;
     
-    ActionButtonUI(AbstractButton button) {
-        this.realButton = button;
-    }
+    ActionButtonUI() {}
     
     private BufferedImage getBrighterImage(BufferedImage source) {
         float[] kernel = new float[] { 0, 0, 0, 0, 1.2f, 0, 0, 0, 0 };
@@ -67,20 +69,20 @@
         return brighterOp.filter(source, new BufferedImage(source.getWidth(),
                 source.getHeight(), source.getType()));
     }
-
+    
     @Override
-    public void paint(Graphics g, JComponent c) {
-
+    protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect,
+                              Rectangle textRect, Rectangle iconRect)
+    {
+        // nothing to do
+    }
+    
+    @Override
+    protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) {
+        
         AbstractButton button = (AbstractButton) c;
         ButtonModel model = button.getModel();
-        if (model.isPressed() || model.isArmed() || model.isSelected()) {
-            realButton.paint(g);
-        } else if (model.isRollover()) {
-            Border border = realButton.getBorder();
-            border.paintBorder(realButton, g, 0, 0, realButton.getWidth(),
-                    realButton.getHeight());
-        }
-        // paint the icon, always to the center
+        
         Icon icon = button.getIcon();
         int w = icon.getIconWidth();
         int h = icon.getIconHeight();
@@ -95,14 +97,49 @@
         if (rollOverIcon == null) {
             rollOverIcon = getBrighterImage(sourceIcon);
         }
+        
+        int x = 3;
+        int y = button.getHeight() / 2 - h / 2;
 
-        int x = realButton.getWidth() / 2 - w / 2;
-        int y = realButton.getHeight() / 2 - h / 2;
-
+        String text = button.getText();
+        if (text == null || text.equals("")) {
+            x = button.getWidth() / 2 - w / 2;
+        }
+        
         if (model.isRollover()) {
             g.drawImage(rollOverIcon, x, y, null);
         } else {
             g.drawImage(sourceIcon, x, y, null);
         }
     }
+    
+    @Override
+    protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
+        GraphicsUtils graphicsUtils = GraphicsUtils.getInstance();
+        Graphics2D graphics = graphicsUtils.createAAGraphics(g);
+        FontMetrics metrics = b.getFontMetrics(b.getFont());
+        graphicsUtils.drawStringWithShadow(b, graphics, text, b.getForeground(), textRect.x,
+                                           textRect.y + metrics.getAscent());
+    }
+
+    @Override
+    public void paint(Graphics g, JComponent c) {
+
+        AbstractButton button = (AbstractButton) c;
+        ButtonModel model = button.getModel();
+
+        if (model.isRollover() || model.isPressed() || model.isSelected()) {
+            GraphicsUtils graphicsUtils = GraphicsUtils.getInstance();
+            Graphics2D graphics = graphicsUtils.createAAGraphics(g);
+
+            graphicsUtils.setGradientPaint(graphics, 0, button.getHeight(), button.getBackground(), Palette.WHITE.getColor());
+            
+            Shape shape = graphicsUtils.getRoundShape(button.getWidth() - 1, button.getHeight() - 1);
+            graphics.fill(shape);
+            
+            graphics.dispose();
+        }
+        
+        super.paint(g, c);
+    }
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionToggleButton.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionToggleButton.java	Wed Oct 24 11:57:30 2012 +0200
@@ -36,44 +36,87 @@
 
 package com.redhat.thermostat.client.swing.components;
 
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.lang.reflect.InvocationTargetException;
+
 import javax.swing.AbstractButton;
 import javax.swing.Icon;
+import javax.swing.JFrame;
 import javax.swing.JToggleButton;
+import javax.swing.SwingUtilities;
 
 @SuppressWarnings("serial")
 public class ActionToggleButton extends JToggleButton implements ToolbarButton {
-    private AbstractButton realButton;
-    
-    public ActionToggleButton(final Icon icon) {
-        super(icon);
         
-        realButton = new JToggleButton() {
-            @Override
-            public int getWidth() {
-                return icon.getIconWidth() + 4;
-            }
-            
-            @Override
-            public int getHeight() {
-                return icon.getIconHeight() + 4;
-            }
-        };
-        setUI(new ActionButtonUI(realButton));
+    public ActionToggleButton(final Icon icon) {
+        this(icon, "");
+    }
+    
+    public ActionToggleButton(final Icon icon, String text) {
+        super(icon);
+                
+        setText(text);
         
-        setSize(realButton.getWidth(), realButton.getHeight());
+        setUI(new ActionButtonUI());
+        setOpaque(false);
         setContentAreaFilled(false);
-        
-        setPreferredSize(getSize());
-        setMinimumSize(getSize());
-        setMaximumSize(getSize());
-        
-        realButton.setModel(getModel());
-
-        setBorderPainted(false);
+        setBorder(new ToolbarButtonBorder(this));
     }
     
     @Override
     public AbstractButton getToolbarButton() {
         return this;
-    }    
+    }
+    
+    @Override
+    public ToolbarButton copy() {
+        ActionToggleButton copy = new ActionToggleButton(getIcon(), getText());
+        copy.setSelected(isSelected());
+        copy.setName(getName());
+        copy.setToolTipText(getToolTipText());
+        return copy;
+    }
+    
+    public static void main(String[] args) throws InvocationTargetException, InterruptedException {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            
+            @Override
+            public void run() {
+               JFrame frame = new JFrame();
+               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+               
+               HeaderPanel header = new HeaderPanel();
+               header.setHeader("Test");
+               
+               Icon icon = new Icon() {
+                   @Override
+                   public void paintIcon(Component c, Graphics g, int x, int y) {
+                       g.setColor(Color.CYAN);
+                       g.fillRect(x, y, 16, 16);
+                   }
+                
+                   @Override
+                   public int getIconWidth() {
+                       return 16;
+                   }
+                
+                   @Override
+                   public int getIconHeight() {
+                       return 16;
+                   }
+               }; 
+               
+               ActionToggleButton button = new ActionToggleButton(icon);
+               header.addToolBarButton(button);
+               
+               button.setText("fluff");
+               
+               frame.getContentPane().add(header);
+               frame.setSize(500, 500);
+               frame.setVisible(true);
+            }
+        });
+    }     
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HeaderPanel.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HeaderPanel.java	Wed Oct 24 11:57:30 2012 +0200
@@ -40,13 +40,27 @@
 import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.prefs.PreferenceChangeEvent;
+import java.util.prefs.PreferenceChangeListener;
+import java.util.prefs.Preferences;
 
+import javax.swing.AbstractButton;
 import javax.swing.BoxLayout;
 import javax.swing.JComponent;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
+import javax.swing.JMenuItem;
 import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
 import javax.swing.SwingUtilities;
 
 /**
@@ -54,6 +68,10 @@
  */
 @SuppressWarnings("serial")
 public class HeaderPanel extends JPanel {
+        
+    public static final String SHOW_TEXT = "SHOW_TEXT";
+    
+    private boolean showText;
     
     private String header;
     
@@ -62,11 +80,23 @@
     private JPanel headerPanel;
     private JPanel controlPanel;
     
+    private List<ToolbarButton> buttons;
+
+    private Preferences prefs;
+    
     public HeaderPanel() {
         this("");
     }
     
     public HeaderPanel(String header) {
+        this(Preferences.userRoot().node(HeaderPanel.class.getName()), "");
+    }
+    
+    public HeaderPanel(Preferences prefs, String header) {
+        
+        buttons = new ArrayList<ToolbarButton>();
+        
+        this.prefs = prefs;
         
         this.header = header;
         
@@ -74,6 +104,7 @@
 
         headerLabel = new ShadowLabel(header, new EmptyIcon(5, 5));
         headerPanel = new GradientPanel(Color.WHITE, getBackground());
+        headerPanel.setName("clickableArea");
         headerPanel.setPreferredSize(new Dimension(HeaderPanel.this.getWidth(), 40));
         
         headerPanel.setLayout(new BorderLayout(0, 0));
@@ -90,8 +121,45 @@
         contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.X_AXIS));
         
         add(contentPanel, BorderLayout.CENTER);
+        registerPreferences();
+        showText = prefs.getBoolean(HeaderPanel.class.getName(), false);
+        
+        headerPanel.addMouseListener(new PreferencesPopupListener());
     }
    
+    public boolean isShowToolbarText() {
+        return showText;
+    }
+    
+    private void registerPreferences() {
+        prefs.addPreferenceChangeListener(new PreferenceChangeListener() {
+            @Override
+            public void preferenceChange(PreferenceChangeEvent evt) {
+                
+                String key = evt.getKey();
+                boolean _value = false;
+                if (key.equalsIgnoreCase(HeaderPanel.class.getName())) {
+                    _value = prefs.getBoolean(HeaderPanel.class.getName(), false);
+                }
+                final boolean value = _value;
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        boolean oldShowText = showText;
+                        showText = value;
+                        controlPanel.removeAll();
+                        for (ToolbarButton button : buttons) {
+                            addToolBarButton_noClient(button);
+                        }
+                        revalidate();
+                        
+                        firePropertyChange(SHOW_TEXT, oldShowText, showText);
+                    }
+                });
+            }
+        });
+    }
+    
     public String getHeader() {
         return header;
     }
@@ -108,8 +176,75 @@
         repaint();
     }
 
+    private void addToolBarButton_noClient(final ToolbarButton button) {
+        AbstractButton theButton = button.getToolbarButton();
+        if (!showText) {
+            final AbstractButton proxy = button.copy().getToolbarButton();
+            proxy.setText("");
+            proxy.addActionListener(new ActionListener() {
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    button.getToolbarButton().setSelected(proxy.isSelected());                   
+                }
+            });
+            // need this so that if one of those properties change on the real button
+            // we can reflect it on the proxy
+            button.getToolbarButton().addPropertyChangeListener(new PropertyChangeListener() {
+                @Override
+                public void propertyChange(PropertyChangeEvent evt) {
+                    AbstractButton theButton = button.getToolbarButton();
+                    proxy.setName(theButton.getName());
+                    proxy.setToolTipText(theButton.getToolTipText());                
+                }
+            });
+            theButton = proxy;
+        }
+        controlPanel.add(theButton);
+    }
+    
     public void addToolBarButton(ToolbarButton button) {
-        controlPanel.add(button.getToolbarButton());
+        buttons.add(button);
+        addToolBarButton_noClient(button);
+    }
+    
+    class PreferencesPopup extends JPopupMenu {
+        JMenuItem preferencesMenu;
+        public PreferencesPopup(){
+            // TODO: localize
+            String text = "Show button text";
+            if (showText) {
+                text = "Hide button text";
+            }
+            preferencesMenu = new JMenuItem(text);
+            preferencesMenu.addActionListener(new ActionListener() {
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    prefs.putBoolean(HeaderPanel.class.getName(), !showText);
+                }
+            });
+            add(preferencesMenu);
+        }
+    }
+
+    class PreferencesPopupListener extends MouseAdapter {
+        public void mousePressed(MouseEvent e){
+            if (e.isPopupTrigger()) {
+                popupPreferences(e);
+            }
+        }
+
+        public void mouseReleased(MouseEvent e){
+            if (e.isPopupTrigger()) {
+                popupPreferences(e);
+            }
+        }
+
+        private void popupPreferences(MouseEvent e){
+            if (buttons.size() > 0) {
+                PreferencesPopup menu = new PreferencesPopup();
+                menu.show(e.getComponent(), e.getX(), e.getY());
+            }
+        }
     }
     
     public static void main(String[] args) throws InvocationTargetException, InterruptedException {
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/LabelField.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/LabelField.java	Wed Oct 24 11:57:30 2012 +0200
@@ -39,6 +39,7 @@
 import javax.swing.JLabel;
 import javax.swing.SwingConstants;
 
+@SuppressWarnings("serial")
 public class LabelField extends JLabel {
 
     public LabelField(String text) {
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SectionHeader.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SectionHeader.java	Wed Oct 24 11:57:30 2012 +0200
@@ -39,7 +39,7 @@
 import javax.swing.JLabel;
 import javax.swing.SwingConstants;
 
-
+@SuppressWarnings("serial")
 public class SectionHeader extends JLabel {
 
     public SectionHeader(String text) {
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButton.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButton.java	Wed Oct 24 11:57:30 2012 +0200
@@ -40,4 +40,5 @@
 
 public interface ToolbarButton {
     AbstractButton getToolbarButton();
+    ToolbarButton copy();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButtonBorder.java	Wed Oct 24 11:57:30 2012 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.swing.components;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.io.Serializable;
+
+import javax.swing.AbstractButton;
+import javax.swing.ButtonModel;
+import javax.swing.plaf.UIResource;
+
+import com.redhat.thermostat.client.ui.Palette;
+
+@SuppressWarnings("serial")
+public class ToolbarButtonBorder extends DebugBorder implements UIResource, Serializable {
+
+    public ToolbarButtonBorder(ToolbarButton button) {
+        // TODO Auto-generated constructor stub
+    }
+    
+    @Override
+    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+        
+        AbstractButton button = (AbstractButton) c;
+        ButtonModel model = button.getModel();
+        
+        Color colour = Palette.GRAY.getColor();
+        if (model.isPressed()) {
+            colour = Palette.PALE_GRAY.getColor();
+        } else if (model.isRollover()) {
+            colour = Palette.DARK_GRAY.getColor();
+        }
+        
+        if (model.isRollover() || model.isPressed() || model.isSelected()) {
+            GraphicsUtils graphicsUtils = GraphicsUtils.getInstance();
+            Graphics2D graphics = graphicsUtils.createAAGraphics(g);            
+
+            Shape shape = graphicsUtils.getRoundShape(width - 1, height - 1);
+
+            graphics.setColor(colour);
+            graphics.translate(x, y);
+            graphics.draw(shape);
+
+            graphics.dispose();
+        }
+    }
+}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ValueField.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ValueField.java	Wed Oct 24 11:57:30 2012 +0200
@@ -43,6 +43,7 @@
  * A custom swing component meant for showing values. Use it like you would use
  * any other JTextComponent.
  */
+@SuppressWarnings("serial")
 public class ValueField extends JEditorPane {
 
     public ValueField(String text) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/HeaderPanelTest.java	Wed Oct 24 11:57:30 2012 +0200
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.swing.components;
+
+import java.awt.Dimension;
+import java.util.Random;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+
+import javax.swing.Icon;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiTask;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JPanelFixture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+@RunWith(CacioFESTRunner.class)
+public class HeaderPanelTest {
+
+    private JFrame frame;
+    private FrameFixture frameFixture;
+    private HeaderPanel header;
+    
+    private Icon someIcon1;
+    private Icon someIcon2;
+    private Icon someIcon3;
+
+    private Preferences prefs;
+    
+    @BeforeClass
+    public static void setUpOnce() {
+        FailOnThreadViolationRepaintManager.install();
+    }
+    
+    @Before
+    public void setUp() {
+        
+        Random random = new Random(); 
+        prefs = Preferences.userRoot().node(HeaderPanelTest.class.getName() + "." + random.nextInt());
+        
+        GuiActionRunner.execute(new GuiTask() {
+            @Override
+            protected void executeInEDT() throws Throwable {
+                frame = new JFrame();
+                
+                header = new HeaderPanel(prefs, "Test Panel");
+                header.setName("headerPanel");
+                
+                JPanel content = new JPanel();
+                content.setName("contentPanel");
+                
+                header.setContent(content);
+                
+                someIcon1 = new EmptyIcon(16, 16);
+                someIcon2 = new EmptyIcon(16, 16);
+                someIcon3 = new EmptyIcon(16, 16);
+                
+                ActionButton button1 = new ActionButton(someIcon1, "button1");
+                button1.setName("button1");
+                
+                ActionButton button2 = new ActionButton(someIcon2, "button2");
+                button2.setName("button2");
+                
+                ActionToggleButton toggle1 = new ActionToggleButton(someIcon3, "toggle1");
+                toggle1.setName("toggle1");
+
+                header.addToolBarButton(button1);
+                header.addToolBarButton(button2);
+                header.addToolBarButton(toggle1);
+                
+                frame.getContentPane().add(header);
+                
+                frame.setMinimumSize(new Dimension(800, 300));
+            }
+        });
+        frameFixture = new FrameFixture(frame);
+    }
+    
+    @After
+    public void tearDown() throws BackingStoreException {
+        frameFixture.cleanUp();
+        frameFixture = null;
+        prefs.removeNode();
+    }
+    
+    @Test
+    public void testContentPaneAdded() {
+        frameFixture.show();
+        
+        JPanelFixture contentPanel = frameFixture.panel("contentPanel");
+        contentPanel.requireVisible();
+    }
+    
+    @Test
+    public void testContentAdded() {
+        frameFixture.show();
+        
+        JPanelFixture contentPanel = frameFixture.panel("contentPanel");
+        contentPanel.requireVisible();
+        
+        frameFixture.button("button1").requireVisible();
+        frameFixture.button("button2").requireVisible();
+        frameFixture.toggleButton("toggle1").requireVisible();
+    }
+    
+    @Test
+    public void testshowtoolbarText() throws InterruptedException {
+        frameFixture.show();
+        
+        JPanelFixture headerPanel = frameFixture.panel("clickableArea");
+        headerPanel.requireVisible();
+        
+        assertFalse(header.isShowToolbarText());
+
+        frameFixture.button("button1").requireText("");
+
+        headerPanel.showPopupMenu().click();
+
+        assertTrue(header.isShowToolbarText());
+
+        frameFixture.button("button1").requireVisible();
+        frameFixture.button("button2").requireVisible();
+        frameFixture.toggleButton("toggle1").requireVisible();
+        
+        frameFixture.button("button1").requireText("button1");
+        
+        headerPanel.showPopupMenu().click();
+        
+        assertFalse(header.isShowToolbarText());
+
+        frameFixture.button("button1").requireText("");
+
+        frameFixture.button("button1").requireVisible();
+        frameFixture.button("button2").requireVisible();
+        frameFixture.toggleButton("toggle1").requireVisible();
+    }
+}
--- a/common/core/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java	Wed Oct 24 11:57:30 2012 +0200
@@ -41,7 +41,6 @@
 
 import com.redhat.thermostat.utils.keyring.Credentials;
 import com.redhat.thermostat.utils.keyring.Keyring;
-import com.redhat.thermostat.utils.keyring.KeyringProvider;
 
 public class ClientPreferences {
 
--- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/locale/LocaleResources.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/locale/LocaleResources.java	Wed Oct 24 11:57:30 2012 +0200
@@ -53,6 +53,7 @@
     
     START_RECORDING,
     STOP_RECORDING,
+    THREAD_MONITOR_SWITCH,
     
     VM_CAPABILITIES,
     TABLE,
--- a/thread/client-common/src/main/resources/com/redhat/thermostat/thread/client/common/locale/strings.properties	Wed Oct 24 11:11:06 2012 +0200
+++ b/thread/client-common/src/main/resources/com/redhat/thermostat/thread/client/common/locale/strings.properties	Wed Oct 24 11:57:30 2012 +0200
@@ -13,6 +13,8 @@
     
 START_RECORDING = Start Recording
 STOP_RECORDING = Stop Recording
+THREAD_MONITOR_SWITCH = Monitor Thread
+
 VM_CAPABILITIES = VM Capabilities
 TABLE = Table
 DETAILS = Details
--- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadView.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadView.java	Wed Oct 24 11:57:30 2012 +0200
@@ -111,6 +111,7 @@
         
         timelinePanel = new ThreadAliveDaemonTimelinePanel();
         panel.getToggleButton().setToolTipText(t.localize(LocaleResources.START_RECORDING));
+        panel.getToggleButton().setText(t.localize(LocaleResources.THREAD_MONITOR_SWITCH));
         panel.getToggleButton().addItemListener(new ItemListener()
         {
             @Override
--- a/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java	Wed Oct 24 11:11:06 2012 +0200
+++ b/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java	Wed Oct 24 11:57:30 2012 +0200
@@ -57,7 +57,6 @@
 import org.fest.swing.edt.GuiActionRunner;
 import org.fest.swing.edt.GuiTask;
 import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JLabelFixture;
 import org.fest.swing.fixture.JToggleButtonFixture;
 import org.junit.After;
 import org.junit.AfterClass;