All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.l2fprod.common.swing.PercentLayout Maven / Gradle / Ivy

Go to download

Orbit, a versatile image analysis software for biological image-based quantification

There is a newer version: 3.15
Show newest version
/**
 * $ $ License.
 *
 * Copyright $ 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.
 */
package com.l2fprod.common.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;

/**
 * PercentLayout. 
Constraint based layout which allow the space to be * splitted using percentages. The following are allowed when adding components * to container: *
    *
  • container.add(component);
    in this case, the component will be * sized to its preferred size *
  • container.add(component, "100");
    in this case, the component will * have a width (or height) of 100 *
  • container.add(component, "25%");
    in this case, the component will * have a width (or height) of 25 % of the container width (or height)
    *
  • container.add(component, "*");
    in this case, the component will * take the remaining space. if several components use the "*" constraint the * space will be divided among the components. *
* * @javabean.class * name="PercentLayout" * shortDescription="A layout supports constraints expressed in percent." */ public 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]; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy