Mega Code Archive

 
Categories / Java / Swing Components
 

A status bar is made of multiple zones

/**  * L2FProd.com Common Components 7.3 License.  *  * Copyright 2005-2007 L2FProd.com  *  * 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.Component; 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.CompoundBorder; 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.common.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.com Common Components 7.3 License.  *  * Copyright 2005-2007 L2FProd.com  *  * 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.Component#getMinimumSize()    * @see java.awt.Component#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.com Common Components 7.3 License.   *   * Copyright 2005-2007 L2FProd.com   *   * 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);    }  }