Java/Swing Components/Status Bar

Материал из Java эксперт
Версия от 18:01, 31 мая 2010; (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

A status bar is made of multiple zones

   
/**
 * L2FProd.ru Common Components 7.3 License.
 *
 * Copyright 2005-2007 L2FProd.ru
 *
 * Licensed 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.
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.rupoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import javax.swing.text.JTextComponent;
import javax.swing.text.View;
import javax.swing.text.html.HTMLDocument;
/**
 * StatusBar. <BR>A status bar is made of multiple zones. A zone can be any
 * JComponent.
 */
public class StatusBar extends JComponent {
  /**
   * The key used to identified the default zone
   */
  public final static String DEFAULT_ZONE = "default";
  private Hashtable idToZones;
  private Border zoneBorder;
  /**
   * Construct a new StatusBar
   *  
   */
  public StatusBar() {
    setLayout(LookAndFeelTweaks.createHorizontalPercentLayout());
    idToZones = new Hashtable();
    setZoneBorder(BorderFactory.createLineBorder(Color.lightGray));
  }
  public void setZoneBorder(Border border) {
    zoneBorder = border;
  }
  /**
   * Adds a new zone in the StatusBar
   * 
   * @param id
   * @param zone
   * @param constraints one of the constraint support by the
   *          {@link com.l2fprod.rumon.swing.PercentLayout}
   */
  public void addZone(String id, Component zone, String constraints) {
    // is there already a zone with this id?
    Component previousZone = getZone(id);
    if (previousZone != null) {
      remove(previousZone);
      idToZones.remove(id);
    }
    if (zone instanceof JComponent) {
      JComponent jc = (JComponent)zone;
      if (jc.getBorder() == null || jc.getBorder() instanceof UIResource) {
        if (jc instanceof JLabel) {
          jc.setBorder(
            new CompoundBorder(zoneBorder, new EmptyBorder(0, 2, 0, 2)));
          ((JLabel)jc).setText(" ");
        } else {
          jc.setBorder(zoneBorder);
        }
      }
    }
    add(zone, constraints);
    idToZones.put(id, zone);
  }
  public Component getZone(String id) {
    return (Component)idToZones.get(id);
  }
  /**
   * For example:
   * 
   * <code>
   *  setZones(new String[]{"A","B"},
   *           new JComponent[]{new JLabel(), new JLabel()},
   *           new String[]{"33%","*"});
   * </code>
   * 
   * would construct a new status bar with two zones (two JLabels)
   * named A and B, the first zone A will occupy 33 percents of the
   * overall size of the status bar and B the left space.
   * 
   * @param ids a value of type "String[]"
   * @param zones a value of type "JComponent[]"
   * @param constraints a value of type "String[]"
   */
  public void setZones(String[] ids, Component[] zones, String[] constraints) {
    removeAll();
    idToZones.clear();
    for (int i = 0, c = zones.length; i < c; i++) {
      addZone(ids[i], zones[i], constraints[i]);
    }
  }
}
/**
 * L2FProd.ru Common Components 7.3 License.
 *
 * Copyright 2005-2007 L2FProd.ru
 *
 * Licensed 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.
 */
/**
 * PercentLayout. <BR>Constraint based layout which allow the space to be
 * splitted using percentages. The following are allowed when adding components
 * to container:
 * <ul>
 * <li>container.add(component); <br>in this case, the component will be
 * sized to its preferred size
 * <li>container.add(component, "100"); <br>in this case, the component will
 * have a width (or height) of 100
 * <li>container.add(component, "25%"); <br>in this case, the component will
 * have a width (or height) of 25 % of the container width (or height) <br>
 * <li>container.add(component, "*"); <br>in this case, the component will
 * take the remaining space. if several components use the "*" constraint the
 * space will be divided among the components.
 * </ul>
 * 
 * @javabean.class
 *          name="PercentLayout"
 *          shortDescription="A layout supports constraints expressed in percent."
 */
 class PercentLayout implements LayoutManager2 {
  /**
   * Useful constant to layout the components horizontally (from top to
   * bottom).
   */
  public final static int HORIZONTAL = 0;
  /**
   * Useful constant to layout the components vertically (from left to right).
   */
  public final static int VERTICAL = 1;
  static class Constraint {
    protected Object value;
    private Constraint(Object value) {
      this.value = value;
    }
  }
  static class NumberConstraint extends Constraint {
    public NumberConstraint(int d) {
      this(new Integer(d));
    }
    public NumberConstraint(Integer d) {
      super(d);
    }
    public int intValue() {
      return ((Integer)value).intValue();
    }
  }
  static class PercentConstraint extends Constraint {
    public PercentConstraint(float d) {
      super(new Float(d));
    }
    public float floatValue() {
      return ((Float)value).floatValue();
    }
  }
  private final static Constraint REMAINING_SPACE = new Constraint("*");
  private final static Constraint PREFERRED_SIZE = new Constraint("");
  private int orientation;
  private int gap;
  private Hashtable m_ComponentToConstraint;
  /**
   * Creates a new HORIZONTAL PercentLayout with a gap of 0.
   */
  public PercentLayout() {
    this(HORIZONTAL, 0);
  }
  public PercentLayout(int orientation, int gap) {
    setOrientation(orientation);
    this.gap = gap;
    m_ComponentToConstraint = new Hashtable();
  }
  public void setGap(int gap) {
    this.gap = gap;   
  }
  
  /**
   * @javabean.property
   *          bound="true"
   *          preferred="true"
   */
  public int getGap() {
    return gap;
  }
  
  public void setOrientation(int orientation) {
    if (orientation != HORIZONTAL && orientation != VERTICAL) {
      throw new IllegalArgumentException("Orientation must be one of HORIZONTAL or VERTICAL");
    }
    this.orientation = orientation;
  }
  /**
   * @javabean.property
   *          bound="true"
   *          preferred="true"
   */
  public int getOrientation() {
    return orientation;
  }
  
  public Constraint getConstraint(Component component) {
    return (Constraint)m_ComponentToConstraint.get(component);
  }
  
  public void setConstraint(Component component, Object constraints) {
    if (constraints instanceof Constraint) {
      m_ComponentToConstraint.put(component, constraints);
    } else if (constraints instanceof Number) {
      setConstraint(
        component,
        new NumberConstraint(((Number)constraints).intValue()));
    } else if ("*".equals(constraints)) {
      setConstraint(component, REMAINING_SPACE);
    } else if ("".equals(constraints)) {
      setConstraint(component, PREFERRED_SIZE);
    } else if (constraints instanceof String) {
      String s = (String)constraints;
      if (s.endsWith("%")) {
        float value = Float.valueOf(s.substring(0, s.length() - 1))
          .floatValue() / 100;
        if (value > 1 || value < 0)
          throw new IllegalArgumentException("percent value must be >= 0 and <= 100");
        setConstraint(component, new PercentConstraint(value));
      } else {
        setConstraint(component, new NumberConstraint(Integer.valueOf(s)));
      }
    } else if (constraints == null) {
      // null constraint means preferred size
      setConstraint(component, PREFERRED_SIZE);
    } else {
      throw new IllegalArgumentException("Invalid Constraint");
    }    
  }
  
  public void addLayoutComponent(Component component, Object constraints) {
    setConstraint(component, constraints);    
  }
  /**
   * Returns the alignment along the x axis. This specifies how the component
   * would like to be aligned relative to other components. The value should be
   * a number between 0 and 1 where 0 represents alignment along the origin, 1
   * is aligned the furthest away from the origin, 0.5 is centered, etc.
   */
  public float getLayoutAlignmentX(Container target) {
    return 1.0f / 2.0f;
  }
  /**
   * Returns the alignment along the y axis. This specifies how the component
   * would like to be aligned relative to other components. The value should be
   * a number between 0 and 1 where 0 represents alignment along the origin, 1
   * is aligned the furthest away from the origin, 0.5 is centered, etc.
   */
  public float getLayoutAlignmentY(Container target) {
    return 1.0f / 2.0f;
  }
  /**
   * Invalidates the layout, indicating that if the layout manager has cached
   * information it should be discarded.
   */
  public void invalidateLayout(Container target) {
  }
  /**
   * Adds the specified component with the specified name to the layout.
   * 
   * @param name the component name
   * @param comp the component to be added
   */
  public void addLayoutComponent(String name, Component comp) {
  }
  /**
   * Removes the specified component from the layout.
   * 
   * @param comp the component ot be removed
   */
  public void removeLayoutComponent(Component comp) {
    m_ComponentToConstraint.remove(comp);
  }
  /**
   * Calculates the minimum size dimensions for the specified panel given the
   * components in the specified parent container.
   * 
   * @param parent the component to be laid out
   * @see #preferredLayoutSize
   */
  public Dimension minimumLayoutSize(Container parent) {
    return preferredLayoutSize(parent);
  }
  /**
   * Returns the maximum size of this component.
   * 
   * @see java.awt.ruponent#getMinimumSize()
   * @see java.awt.ruponent#getPreferredSize()
   * @see java.awt.LayoutManager
   */
  public Dimension maximumLayoutSize(Container parent) {
    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  }
  public Dimension preferredLayoutSize(Container parent) {
    Component[] components = parent.getComponents();
    Insets insets = parent.getInsets();
    int width = 0;
    int height = 0;
    Dimension componentPreferredSize;
    boolean firstVisibleComponent = true;
    for (int i = 0, c = components.length; i < c; i++) {
      if (components[i].isVisible()) {
        componentPreferredSize = components[i].getPreferredSize();
        if (orientation == HORIZONTAL) {
          height = Math.max(height, componentPreferredSize.height);
          width += componentPreferredSize.width;
          if (firstVisibleComponent) {
            firstVisibleComponent = false;
          } else {
            width += gap;
          }
        } else {
          height += componentPreferredSize.height;
          width = Math.max(width, componentPreferredSize.width);
          if (firstVisibleComponent) {
            firstVisibleComponent = false;
          } else {
            height += gap;
          }
        }
      }
    }
    return new Dimension(
      width + insets.right + insets.left,
      height + insets.top + insets.bottom);
  }
  public void layoutContainer(Container parent) {
    Insets insets = parent.getInsets();
    Dimension d = parent.getSize();
    // calculate the available sizes
    d.width = d.width - insets.left - insets.right;
    d.height = d.height - insets.top - insets.bottom;
    // pre-calculate the size of each components
    Component[] components = parent.getComponents();
    int[] sizes = new int[components.length];
    // calculate the available size
    int totalSize =
      (HORIZONTAL == orientation ? d.width : d.height)
        - (components.length - 1) * gap;
    int availableSize = totalSize;
    // PENDING(fred): the following code iterates 4 times on the component
    // array, need to find something more efficient!
       
    // give priority to components who want to use their preferred size or who
    // have a predefined size
    for (int i = 0, c = components.length; i < c; i++) {
      if (components[i].isVisible()) {
        Constraint constraint =
          (Constraint)m_ComponentToConstraint.get(components[i]);
        if (constraint == null || constraint == PREFERRED_SIZE) {
          sizes[i] =
            (HORIZONTAL == orientation
              ? components[i].getPreferredSize().width
              : components[i].getPreferredSize().height);
          availableSize -= sizes[i];
        } else if (constraint instanceof NumberConstraint) {
          sizes[i] = ((NumberConstraint)constraint).intValue();
          availableSize -= sizes[i];
        }
      }
    }
    
    // then work with the components who want a percentage of the remaining
    // space
    int remainingSize = availableSize;    
    for (int i = 0, c = components.length; i < c; i++) {
      if (components[i].isVisible()) {
        Constraint constraint =
          (Constraint)m_ComponentToConstraint.get(components[i]);
        if (constraint instanceof PercentConstraint) {
          sizes[i] = (int)(remainingSize * ((PercentConstraint)constraint)
            .floatValue());
          availableSize -= sizes[i];
        }
      }
    }
    
    // finally share the remaining space between the other components    
    ArrayList remaining = new ArrayList();
    for (int i = 0, c = components.length; i < c; i++) {
      if (components[i].isVisible()) {
        Constraint constraint =
          (Constraint)m_ComponentToConstraint.get(components[i]);
        if (constraint == REMAINING_SPACE) {
          remaining.add(new Integer(i));
          sizes[i] = 0;
        }
      }
    }
    if (remaining.size() > 0) {
      int rest = availableSize / remaining.size();
      for (Iterator iter = remaining.iterator(); iter.hasNext();) {
        sizes[((Integer)iter.next()).intValue()] = rest;
      }
    }
    // all calculations are done, apply the sizes
    int currentOffset = (HORIZONTAL == orientation ? insets.left : insets.top);
    for (int i = 0, c = components.length; i < c; i++) {
      if (components[i].isVisible()) {
        if (HORIZONTAL == orientation) {
          components[i].setBounds(
            currentOffset,
            insets.top,
            sizes[i],
            d.height);
        } else {
          components[i].setBounds(
            insets.left,
            currentOffset,
            d.width,
            sizes[i]);
        }
        currentOffset += gap + sizes[i];
      }
    }
  }
}
 /**
  * L2FProd.ru Common Components 7.3 License.
  *
  * Copyright 2005-2007 L2FProd.ru
  *
  * Licensed 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.
  */

 /**
  * LookAndFeelTweaks. <br>
  *  
  */
 class LookAndFeelTweaks {
   public final static Border PANEL_BORDER =
     BorderFactory.createEmptyBorder(3, 3, 3, 3);
   
   public final static Border WINDOW_BORDER =
     BorderFactory.createEmptyBorder(4, 10, 10, 10);
   public final static Border EMPTY_BORDER =
    BorderFactory.createEmptyBorder();
   
   public static void tweak() {
     Object listFont = UIManager.get("List.font");
     UIManager.put("Table.font", listFont);
     UIManager.put("ToolTip.font", listFont);
     UIManager.put("TextField.font", listFont);
     UIManager.put("FormattedTextField.font", listFont);
     UIManager.put("Viewport.background", "Table.background");
   }
   public static PercentLayout createVerticalPercentLayout() {
     return new PercentLayout(PercentLayout.VERTICAL, 8);
   }
   
   public static PercentLayout createHorizontalPercentLayout() {
     return new PercentLayout(PercentLayout.HORIZONTAL, 8);
   }
   
//   public static ButtonAreaLayout createButtonAreaLayout() {
//     return new ButtonAreaLayout(6);
//   }
   
   public static BorderLayout createBorderLayout() {
     return new BorderLayout(8, 8);
   }
   
   public static void setBorder(JComponent component) {
     if (component instanceof JPanel) {
       component.setBorder(PANEL_BORDER);
     }
   }
   public static void setBorderLayout(Container container) {
     container.setLayout(new BorderLayout(3, 3));
   }
   public static void makeBold(JComponent component) {
     component.setFont(component.getFont().deriveFont(Font.BOLD));
   }
   public static void makeMultilineLabel(JTextComponent area) {
     area.setFont(UIManager.getFont("Label.font"));
     area.setEditable(false);
     area.setOpaque(false);    
     if (area instanceof JTextArea) {
       ((JTextArea)area).setWrapStyleWord(true);
       ((JTextArea)area).setLineWrap(true);
     }
   }
   
   public static void htmlize(JComponent component) {
     htmlize(component, UIManager.getFont("Button.font"));
   }
   public static void htmlize(JComponent component, Font font) {
     String stylesheet =
       "body { margin-top: 0; margin-bottom: 0; margin-left: 0; margin-right: 0; font-family: "
         + font.getName()
         + "; font-size: "
         + font.getSize()
         + "pt; }"
         + "a, p, li { margin-top: 0; margin-bottom: 0; margin-left: 0; margin-right: 0; font-family: "
         + font.getName()
         + "; font-size: "
         + font.getSize()
         + "pt; }";
     try {
       HTMLDocument doc = null;
       if (component instanceof JEditorPane) {        
         if (((JEditorPane)component).getDocument() instanceof HTMLDocument) {
           doc = (HTMLDocument) ((JEditorPane)component).getDocument();
         }
       } else {
         View v =
           (View)component.getClientProperty(
             javax.swing.plaf.basic.BasicHTML.propertyKey);
         if (v != null && v.getDocument() instanceof HTMLDocument) {
           doc = (HTMLDocument)v.getDocument();
         }
       }
       if (doc != null) {
         doc.getStyleSheet().loadRules(
           new java.io.StringReader(stylesheet),
           null);
       } // end of if (doc != null)
     } catch (Exception e) {
       e.printStackTrace();
     }
   }
   public static Border addMargin(Border border) {
     return new CompoundBorder(border, PANEL_BORDER);
   }
 }





Paint your own status bar

    
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
class JStatusBar extends JPanel {
  public JStatusBar() {
    setLayout(new BorderLayout());
    setPreferredSize(new Dimension(10, 23));
    JPanel rightPanel = new JPanel(new BorderLayout());
    rightPanel.setOpaque(false);
    add(rightPanel, BorderLayout.EAST);
  }
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int y = 0;
    g.setColor(new Color(156, 154, 140));
    g.drawLine(0, y, getWidth(), y);
    y++;
    g.setColor(new Color(196, 194, 183));
    g.drawLine(0, y, getWidth(), y);
  }
}
public class Main {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(600, 200);
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new BorderLayout());
    JStatusBar statusBar = new JStatusBar();
    contentPane.add(statusBar, BorderLayout.SOUTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}





Single instance status bar

   
/*
 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 
 * - Redistribution in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials
 *   provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
 * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
 * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR
 * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
 * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 * 
 * You acknowledge that this software is not designed, licensed or
 * intended for use in the design, construction, operation or
 * maintenance of any nuclear facility.
 */

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
/**
 * Single instance status bar.
 * <p>
 * This class is also a MouseListener which listens to MOUSE_ENTERED
 * and MOUSE_EXITED events from Action derived components so that
 * the value of the Action.LONG_DESCRIPTION key is sent as a message
 * to the status bar. 
 * <p>
 * To enable this behavior, add the StatusBar
 * instance as a MouseListener to the component that was created from 
 * an Action.
 *
 * @version 1.6 01/15/03
 * @author  Mark Davidson
 */
public class StatusBar extends JPanel implements MouseListener {
  
    private JLabel label;
    private Dimension preferredSize;
    private static StatusBar INSTANCE;
  
    public StatusBar()  {
  this.setLayout(new FlowLayout(FlowLayout.LEFT));
  this.setBorder(BorderFactory.createEtchedBorder());
                               
  // Set a large blank label to set the preferred size.
  label = new JLabel("                                                                                        ");
  preferredSize = new Dimension(getWidth(label.getText()), 2 * getFontHeight());
      
  this.add(label);
    }

    /**
     * Return the instance of the StatusBar. If this has not been explicity
     * set then it will be created.
     *
     * @return the StatusBar instance.
     * @see #setInstance
     */
    public static StatusBar getInstance() {
  if (INSTANCE == null) {
      INSTANCE = new StatusBar();
  }
        return INSTANCE;
    }
    /**
     * Sets the StatusBar instance.
     */
    public static void setInstance(StatusBar status) {
  INSTANCE = status;
    }
    /**
     * Returns the string width
     * @param s the string
     * @return the string width
     */
    protected int getWidth(String s) {
  FontMetrics fm = this.getFontMetrics(this.getFont());
  if (fm == null) {
      return 0;
  }
  return fm.stringWidth(s);
    }
    /**
     * Returns the height of a line of text
     * @return the height of a line of text
     */
    protected int getFontHeight() {
  FontMetrics fm = this.getFontMetrics(this.getFont());
  if (fm == null) {
      return 0;
  }
  return fm.getHeight();
    }
    /**
     * Returns the perferred size
     * @return the preferred size
     */
    public Dimension getPreferredSize() {
  return preferredSize;
    }
    /**
     * Sets non-transient status bar message
     * @param message the message to display on the status bar
     */
    public void setMessage(String message) {
  label.setText(message);
    }    
    //
    // MouseListener methods 
    //
    public void mouseClicked(MouseEvent evt) {}
    public void mousePressed(MouseEvent evt) {}
    public void mouseReleased(MouseEvent evt) {}
    public void mouseExited(MouseEvent evt) {
  setMessage("");
    }
    /**
     * Takes the LONG_DESCRIPTION of the Action based components
     * and sends them to the Status bar
     */
    public void mouseEntered(MouseEvent evt) {
  if (evt.getSource() instanceof AbstractButton)  {
      AbstractButton button = (AbstractButton)evt.getSource();
      Action action = button.getAction();
      if (action != null)  {
    String message = (String)action.getValue(Action.LONG_DESCRIPTION);
    setMessage(message);
      }
  }
    }
    /**
     * Helper method to recursively register all MenuElements with 
     * a mouse listener.
     */
    public void registerMouseListener(MenuElement[] elements) {
  for (int i = 0; i < elements.length; i++) {
      if (elements[i] instanceof JMenuItem) {
    ((JMenuItem)elements[i]).addMouseListener(this);
      }
      registerMouseListener(elements[i].getSubElements());
  }
    }
    /**
     * Helper method to register all components with a mouse listener.
     */
    public void registerMouseListener(Component[] components) {
  for (int i = 0; i < components.length; i++) {
      if (components[i] instanceof AbstractButton) {
    ((AbstractButton)components[i]).addMouseListener(this);
      }
  }
    }
} // end class StatusBar





Statusbar component

   
/*
 * Copyright (C) 2001-2003 Colin Bell
 * colbell@users.sourceforge.net
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
import java.awt.*;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
/**
 * This is a statusbar component with a text control for messages.
 *
 * @author 
 */
public class StatusBar extends JPanel
{
  /**
   * Message to display if there is no msg to display. Defaults to a
   * blank string.
   */
  private String _msgWhenEmpty = " ";
  /** Label showing the message in the statusbar. */
  private final JLabel _textLbl = new JLabel();
   private final JProgressBar _progressBar = new JProgressBar();
   private final JPanel _pnlLabelOrProgress = new JPanel();
   /** Constraints used to add new controls to this statusbar. */
  private final GridBagConstraints _gbc = new GridBagConstraints();
  private Font _font;
  /**
   * Default ctor.
   */
  public StatusBar()
  {
    super(new GridBagLayout());
    createGUI();
  }
  /**
   * Set the font for controls in this statusbar.
   *
   * @param font  The font to use.
   *
   * @throws  IllegalArgumentException
   *      Thrown if <TT>null</TT> <TT>Font</TT> passed.
   */
  public synchronized void setFont(Font font)
  {
    if (font == null)
    {
      throw new IllegalArgumentException("Font == null");
    }
    super.setFont(font);
    _font = font;
    updateSubcomponentsFont(this);
  }
  /**
   * Set the text to display in the message label.
   *
   * @param text  Text to display in the message label.
   */
  public synchronized void setText(String text)
  {
    String myText = null;
    if (text != null)
    {
      myText = text.trim();
    }
    if (myText != null && myText.length() > 0)
    {
      _textLbl.setText(myText);
    }
    else
    {
      clearText();
    }
  }
    /**
     * Returns the text label"s current value 
     * @return
     */
    public synchronized String getText() {
        return _textLbl.getText();
    }
    
  public synchronized void clearText()
  {
    _textLbl.setText(_msgWhenEmpty);
  }
  public synchronized void setTextWhenEmpty(String value)
  {
    final boolean wasEmpty = _textLbl.getText().equals(_msgWhenEmpty);
    if (value != null && value.length() > 0)
    {
      _msgWhenEmpty = value;
    }
    else
    {
      _msgWhenEmpty = " ";
    }
    if (wasEmpty)
    {
      clearText();
    }
  }
  public synchronized void addJComponent(JComponent comp)
  {
    if (comp == null)
    {
      throw new IllegalArgumentException("JComponent == null");
    }
    comp.setBorder(createComponentBorder());
    if (_font != null)
    {
      comp.setFont(_font);
      updateSubcomponentsFont(comp);
    }
    super.add(comp, _gbc);
  }
  public static Border createComponentBorder()
  {
    return BorderFactory.createCompoundBorder(
      BorderFactory.createBevelBorder(BevelBorder.LOWERED),
      BorderFactory.createEmptyBorder(0, 4, 0, 4));
  }
  private void createGUI()
  {
    clearText();
      Dimension progSize = _progressBar.getPreferredSize();
      progSize.height = _textLbl.getPreferredSize().height;
      _progressBar.setPreferredSize(progSize);
      _progressBar.setStringPainted(true);
      _pnlLabelOrProgress.setLayout(new GridLayout(1,1));
      _pnlLabelOrProgress.add(_textLbl);
      // The message area is on the right of the statusbar and takes
    // up all available space.
    _gbc.anchor = GridBagConstraints.WEST;
    _gbc.weightx = 1.0;
    _gbc.fill = GridBagConstraints.HORIZONTAL;
    _gbc.gridy = 0;
    _gbc.gridx = 0;
    addJComponent(_pnlLabelOrProgress);
    // Any other components are on the right.
    _gbc.weightx = 0.0;
    _gbc.anchor = GridBagConstraints.CENTER;
    _gbc.gridx = GridBagConstraints.RELATIVE;
  }
  private void updateSubcomponentsFont(Container cont)
  {
    Component[] comps = cont.getComponents();
    for (int i = 0; i < comps.length; ++i)
    {
      comps[i].setFont(_font);
      if (comps[i] instanceof Container)
      {
        updateSubcomponentsFont((Container)comps[i]);
      }
    }
  }
   public void setStatusBarProgress(String msg, int minimum, int maximum, int value)
   {
      if(false == _pnlLabelOrProgress.getComponent(0) instanceof JProgressBar)
      {
         _pnlLabelOrProgress.remove(0);
         _pnlLabelOrProgress.add(_progressBar);
         validate();
      }
      _progressBar.setMinimum(minimum);
      _progressBar.setMaximum(maximum);
      _progressBar.setValue(value);
      if(null != msg)
      {
         _progressBar.setString(msg);
      }
      else
      {
         _progressBar.setString("");
      }
   }
   public void setStatusBarProgressFinished()
   {
      if(_pnlLabelOrProgress.getComponent(0) instanceof JProgressBar)
      {
         _pnlLabelOrProgress.remove(0);
         _pnlLabelOrProgress.add(_textLbl);
         validate();
         repaint();
      }
   }
}





Status Bar Demo

    
       
/*
Swing Hacks Tips and Tools for Killer GUIs
By Joshua Marinacci, Chris Adamson
First Edition June 2005  
Series: Hacks
ISBN: 0-596-00907-0
Pages: 542
website: http://www.oreilly.ru/catalog/swinghks/
*/
       
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.SystemColor;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
public class StatusBarSimulator {
  public static void main(String[] args) {
    try {
      UIManager.setLookAndFeel(new WindowsLookAndFeel());
    } catch (Exception e) {
    }
    JFrame frame = new JFrame();
    frame.setBounds(200, 200, 600, 200);
    frame.setTitle("Status bar simulator");
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new BorderLayout());
    StatusBar statusBar = new StatusBar();
    contentPane.add(statusBar, BorderLayout.SOUTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}
class StatusBar extends JPanel {
  public StatusBar() {
    setLayout(new BorderLayout());
    setPreferredSize(new Dimension(10, 23));
    JPanel rightPanel = new JPanel(new BorderLayout());
    rightPanel.add(new JLabel(new AngledLinesWindowsCornerIcon()), BorderLayout.SOUTH);
    rightPanel.setOpaque(false);
    add(rightPanel, BorderLayout.EAST);
    setBackground(SystemColor.control);
  }
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int y = 0;
    g.setColor(new Color(156, 154, 140));
    g.drawLine(0, y, getWidth(), y);
    y++;
    g.setColor(new Color(196, 194, 183));
    g.drawLine(0, y, getWidth(), y);
    y++;
    g.setColor(new Color(218, 215, 201));
    g.drawLine(0, y, getWidth(), y);
    y++;
    g.setColor(new Color(233, 231, 217));
    g.drawLine(0, y, getWidth(), y);
    y = getHeight() - 3;
    g.setColor(new Color(233, 232, 218));
    g.drawLine(0, y, getWidth(), y);
    y++;
    g.setColor(new Color(233, 231, 216));
    g.drawLine(0, y, getWidth(), y);
    y = getHeight() - 1;
    g.setColor(new Color(221, 221, 220));
    g.drawLine(0, y, getWidth(), y);
  }
}
class AngledLinesWindowsCornerIcon implements Icon {
  private static final Color WHITE_LINE_COLOR = new Color(255, 255, 255);
  private static final Color GRAY_LINE_COLOR = new Color(172, 168, 153);
  private static final int WIDTH = 13;
  private static final int HEIGHT = 13;
  public int getIconHeight() {
    return WIDTH;
  }
  public int getIconWidth() {
    return HEIGHT;
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    g.setColor(WHITE_LINE_COLOR);
    g.drawLine(0, 12, 12, 0);
    g.drawLine(5, 12, 12, 5);
    g.drawLine(10, 12, 12, 10);
    g.setColor(GRAY_LINE_COLOR);
    g.drawLine(1, 12, 12, 1);
    g.drawLine(2, 12, 12, 2);
    g.drawLine(3, 12, 12, 3);
    g.drawLine(6, 12, 12, 6);
    g.drawLine(7, 12, 12, 7);
    g.drawLine(8, 12, 12, 8);
    g.drawLine(11, 12, 12, 11);
    g.drawLine(12, 12, 12, 12);
  }
}