3745 lines · 140.5 KB · Java
RawDownload
     * has cached information it should be discarded.     *     * @param parent the {@code Container} hosting this LayoutManager     * @throws IllegalArgumentException if {@code parent} is not     *         the same {@code Container} that this was created with     */    public void invalidateLayout(Container parent) {        checkParent(parent);        // invalidateLayout is called from Container.invalidate, which        // does NOT grab the treelock.  All other methods do.  To make sure        // there aren't any possible threading problems we grab the tree lock        // here.        synchronized(parent.getTreeLock()) {            isValid = false;        }    }     private void prepare(int sizeType) {        boolean visChanged = false;        // Step 1: If not-valid, clear springs and update visibility.        if (!isValid) {            isValid = true;            horizontalGroup.setSize(HORIZONTAL, UNSET, UNSET);            verticalGroup.setSize(VERTICAL, UNSET, UNSET);            for (ComponentInfo ci : componentInfos.values()) {                if (ci.updateVisibility()) {                    visChanged = true;                }                ci.clearCachedSize();            }        }        // Step 2: Make sure components are bound to ComponentInfos        if (springsChanged) {            registerComponents(horizontalGroup, HORIZONTAL);            registerComponents(verticalGroup, VERTICAL);        }        // Step 3: Adjust the autopadding. This removes existing        // autopadding, then recalculates where it should go.        if (springsChanged || visChanged) {            checkComponents();            horizontalGroup.removeAutopadding();            verticalGroup.removeAutopadding();            if (getAutoCreateGaps()) {                insertAutopadding(true);            } else if (hasPreferredPaddingSprings ||                    getAutoCreateContainerGaps()) {                insertAutopadding(false);            }            springsChanged = false;        }        // Step 4: (for min/pref/max size calculations only) calculate the        // autopadding. This invokes for unsetting the calculated values, then        // recalculating them.        // If sizeType == SPECIFIC_SIZE, it indicates we're doing layout, this        // step will be done later on.        if (sizeType != SPECIFIC_SIZE && (getAutoCreateGaps() ||                getAutoCreateContainerGaps() || hasPreferredPaddingSprings)) {            calculateAutopadding(horizontalGroup, HORIZONTAL, sizeType, 0, 0);            calculateAutopadding(verticalGroup, VERTICAL, sizeType, 0, 0);        }    }     private void calculateAutopadding(Group group, int axis, int sizeType,            int origin, int size) {        group.unsetAutopadding();        switch(sizeType) {            case MIN_SIZE:                size = group.getMinimumSize(axis);                break;            case PREF_SIZE:                size = group.getPreferredSize(axis);                break;            case MAX_SIZE:                size = group.getMaximumSize(axis);                break;            default:                break;        }        group.setSize(axis, origin, size);        group.calculateAutopadding(axis);    }     private void checkComponents() {        for (ComponentInfo info : componentInfos.values()) {            if (info.horizontalSpring == null) {                throw new IllegalStateException(info.component +                        " is not attached to a horizontal group");            }            if (info.verticalSpring == null) {                throw new IllegalStateException(info.component +                        " is not attached to a vertical group");            }        }    }     private void registerComponents(Group group, int axis) {        List<Spring> springs = group.springs;        for (int counter = springs.size() - 1; counter >= 0; counter--) {            Spring spring = springs.get(counter);            if (spring instanceof ComponentSpring) {                ((ComponentSpring)spring).installIfNecessary(axis);            } else if (spring instanceof Group) {                registerComponents((Group)spring, axis);            }        }    }     private Dimension adjustSize(int width, int height) {        Insets insets = host.getInsets();        return new Dimension(width + insets.left + insets.right,                height + insets.top + insets.bottom);    }     private void checkParent(Container parent) {        if (parent != host) {            throw new IllegalArgumentException(                    "GroupLayout can only be used with one Container at a time");        }    }     /**     * Returns the {@code ComponentInfo} for the specified Component,     * creating one if necessary.     */    private ComponentInfo getComponentInfo(Component component) {        ComponentInfo info = componentInfos.get(component);        if (info == null) {            info = new ComponentInfo(component);            componentInfos.put(component, info);            if (component.getParent() != host) {                host.add(component);            }        }        return info;    }     /**     * Adjusts the autopadding springs for the horizontal and vertical     * groups.  If {@code insert} is {@code true} this will insert auto padding     * springs, otherwise this will only adjust the springs that     * comprise auto preferred padding springs.     */    private void insertAutopadding(boolean insert) {        horizontalGroup.insertAutopadding(HORIZONTAL,                new ArrayList<AutoPreferredGapSpring>(1),                new ArrayList<AutoPreferredGapSpring>(1),                new ArrayList<ComponentSpring>(1),                new ArrayList<ComponentSpring>(1), insert);        verticalGroup.insertAutopadding(VERTICAL,                new ArrayList<AutoPreferredGapSpring>(1),                new ArrayList<AutoPreferredGapSpring>(1),                new ArrayList<ComponentSpring>(1),                new ArrayList<ComponentSpring>(1), insert);    }     /**     * Returns {@code true} if the two Components have a common ParallelGroup     * ancestor along the particular axis.     */    private boolean areParallelSiblings(Component source, Component target,            int axis) {        ComponentInfo sourceInfo = getComponentInfo(source);        ComponentInfo targetInfo = getComponentInfo(target);        Spring sourceSpring;        Spring targetSpring;        if (axis == HORIZONTAL) {            sourceSpring = sourceInfo.horizontalSpring;            targetSpring = targetInfo.horizontalSpring;        } else {            sourceSpring = sourceInfo.verticalSpring;            targetSpring = targetInfo.verticalSpring;        }        Set<Spring> sourcePath = tmpParallelSet;        sourcePath.clear();        Spring spring = sourceSpring.getParent();        while (spring != null) {            sourcePath.add(spring);            spring = spring.getParent();        }        spring = targetSpring.getParent();        while (spring != null) {            if (sourcePath.contains(spring)) {                sourcePath.clear();                while (spring != null) {                    if (spring instanceof ParallelGroup) {                        return true;                    }                    spring = spring.getParent();                }                return false;            }            spring = spring.getParent();        }        sourcePath.clear();        return false;    }     private boolean isLeftToRight() {        return host.getComponentOrientation().isLeftToRight();    }     /**     * Returns a string representation of this {@code GroupLayout}.     * This method is intended to be used for debugging purposes,     * and the content and format of the returned string may vary     * between implementations.     *     * @return a string representation of this {@code GroupLayout}     **/    public String toString() {        if (springsChanged) {            registerComponents(horizontalGroup, HORIZONTAL);            registerComponents(verticalGroup, VERTICAL);        }        StringBuffer buffer = new StringBuffer();        buffer.append("HORIZONTAL\n");        createSpringDescription(buffer, horizontalGroup, "  ", HORIZONTAL);        buffer.append("\nVERTICAL\n");        createSpringDescription(buffer, verticalGroup, "  ", VERTICAL);        return buffer.toString();    }     private void createSpringDescription(StringBuffer buffer, Spring spring,            String indent, int axis) {        String origin = "";        String padding = "";        if (spring instanceof ComponentSpring) {            ComponentSpring cSpring = (ComponentSpring)spring;            origin = Integer.toString(cSpring.getOrigin()) + " ";            String name = cSpring.getComponent().getName();            if (name != null) {                origin = "name=" + name + ", ";            }        }        if (spring instanceof AutoPreferredGapSpring) {            AutoPreferredGapSpring paddingSpring =                    (AutoPreferredGapSpring)spring;            padding = ", userCreated=" + paddingSpring.getUserCreated() +                    ", matches=" + paddingSpring.getMatchDescription();        }        buffer.append(indent + spring.getClass().getName() + " " +                Integer.toHexString(spring.hashCode()) + " " +                origin +                ", size=" + spring.getSize() +                ", alignment=" + spring.getAlignment() +                " prefs=[" + spring.getMinimumSize(axis) +                " " + spring.getPreferredSize(axis) +                " " + spring.getMaximumSize(axis) +                padding + "]\n");        if (spring instanceof Group) {            List<Spring> springs = ((Group)spring).springs;            indent += "  ";            for (int counter = 0; counter < springs.size(); counter++) {                createSpringDescription(buffer, springs.get(counter), indent,                        axis);            }        }    }      /**     * Spring consists of a range: min, pref and max, a value some where in     * the middle of that, and a location. Spring caches the     * min/max/pref.  If the min/pref/max has internally changes, or needs     * to be updated you must invoke clear.     */    private abstract class Spring {        private int size;        private int min;        private int max;        private int pref;        private Spring parent;         private Alignment alignment;         Spring() {            min = pref = max = UNSET;        }         /**         * Calculates and returns the minimum size.         *         * @param axis the axis of layout; one of HORIZONTAL or VERTICAL         * @return the minimum size         */        abstract int calculateMinimumSize(int axis);         /**         * Calculates and returns the preferred size.         *         * @param axis the axis of layout; one of HORIZONTAL or VERTICAL         * @return the preferred size         */        abstract int calculatePreferredSize(int axis);         /**         * Calculates and returns the minimum size.         *         * @param axis the axis of layout; one of HORIZONTAL or VERTICAL         * @return the minimum size         */        abstract int calculateMaximumSize(int axis);         /**         * Sets the parent of this Spring.         */        void setParent(Spring parent) {            this.parent = parent;        }         /**         * Returns the parent of this spring.         */        Spring getParent() {            return parent;        }         // This is here purely as a conveniance for ParallelGroup to avoid        // having to track alignment separately.        void setAlignment(Alignment alignment) {            this.alignment = alignment;        }         /**         * Alignment for this Spring, this may be null.         */        Alignment getAlignment() {            return alignment;        }         /**         * Returns the minimum size.         */        final int getMinimumSize(int axis) {            if (min == UNSET) {                min = constrain(calculateMinimumSize(axis));            }            return min;        }         /**         * Returns the preferred size.         */        final int getPreferredSize(int axis) {            if (pref == UNSET) {                pref = constrain(calculatePreferredSize(axis));            }            return pref;        }         /**         * Returns the maximum size.         */        final int getMaximumSize(int axis) {            if (max == UNSET) {                max = constrain(calculateMaximumSize(axis));            }            return max;        }         /**         * Sets the value and location of the spring.  Subclasses         * will want to invoke super, then do any additional sizing.         *         * @param axis HORIZONTAL or VERTICAL         * @param origin of this Spring         * @param size of the Spring.  If size is UNSET, this invokes         *        clear.         */        void setSize(int axis, int origin, int size) {            this.size = size;            if (size == UNSET) {                unset();            }        }         /**         * Resets the cached min/max/pref.         */        void unset() {            size = min = pref = max = UNSET;        }         /**         * Returns the current size.         */        int getSize() {            return size;        }         int constrain(int value) {            return Math.min(value, Short.MAX_VALUE);        }         int getBaseline() {            return -1;        }         BaselineResizeBehavior getBaselineResizeBehavior() {            return BaselineResizeBehavior.OTHER;        }         final boolean isResizable(int axis) {            int min = getMinimumSize(axis);            int pref = getPreferredSize(axis);            return (min != pref || pref != getMaximumSize(axis));        }         /**         * Returns {@code true} if this spring will ALWAYS have a zero         * size. This should NOT check the current size, rather it's         * meant to quickly test if this Spring will always have a         * zero size.         *         * @param treatAutopaddingAsZeroSized if {@code true}, auto padding         *        springs should be treated as having a size of {@code 0}         * @return {@code true} if this spring will have a zero size,         *         {@code false} otherwise         */        abstract boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized);    }     /**     * {@code Group} provides the basis for the two types of     * operations supported by {@code GroupLayout}: laying out     * components one after another ({@link SequentialGroup SequentialGroup})     * or aligned ({@link ParallelGroup ParallelGroup}). {@code Group} and     * its subclasses have no public constructor; to create one use     * one of {@code createSequentialGroup} or     * {@code createParallelGroup}. Additionally, taking a {@code Group}     * created from one {@code GroupLayout} and using it with another     * will produce undefined results.     * <p>     * Various methods in {@code Group} and its subclasses allow you     * to explicitly specify the range. The arguments to these methods     * can take two forms, either a value greater than or equal to 0,     * or one of {@code DEFAULT_SIZE} or {@code PREFERRED_SIZE}. A     * value greater than or equal to {@code 0} indicates a specific     * size. {@code DEFAULT_SIZE} indicates the corresponding size     * from the component should be used.  For example, if {@code     * DEFAULT_SIZE} is passed as the minimum size argument, the     * minimum size is obtained from invoking {@code getMinimumSize}     * on the component. Likewise, {@code PREFERRED_SIZE} indicates     * the value from {@code getPreferredSize} should be used.     * The following example adds {@code myComponent} to {@code group}     * with specific values for the range. That is, the minimum is     * explicitly specified as 100, preferred as 200, and maximum as     * 300.     * <pre>     *   group.addComponent(myComponent, 100, 200, 300);     * </pre>     * The following example adds {@code myComponent} to {@code group} using     * a combination of the forms. The minimum size is forced to be the     * same as the preferred size, the preferred size is determined by     * using {@code myComponent.getPreferredSize} and the maximum is     * determined by invoking {@code getMaximumSize} on the component.     * <pre>     *   group.addComponent(myComponent, GroupLayout.PREFERRED_SIZE,     *             GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE);     * </pre>     * <p>     * Unless otherwise specified all the methods of {@code Group} and     * its subclasses that allow you to specify a range throw an     * {@code IllegalArgumentException} if passed an invalid range. An     * invalid range is one in which any of the values are &lt; 0 and     * not one of {@code PREFERRED_SIZE} or {@code DEFAULT_SIZE}, or     * the following is not met (for specific values): {@code min}     * &lt;= {@code pref} &lt;= {@code max}.     * <p>     * Similarly any methods that take a {@code Component} throw a     * {@code IllegalArgumentException} if passed {@code null} and any methods     * that take a {@code Group} throw an {@code NullPointerException} if     * passed {@code null}.     *     * @see #createSequentialGroup     * @see #createParallelGroup     * @since 1.6     */    public abstract class Group extends Spring {        // private int origin;        // private int size;        List<Spring> springs;         Group() {            springs = new ArrayList<Spring>();        }         /**         * Adds a {@code Group} to this {@code Group}.         *         * @param group the {@code Group} to add         * @return this {@code Group}         */        public Group addGroup(Group group) {            return addSpring(group);        }         /**         * Adds a {@code Component} to this {@code Group}.         *

Lines 1001–1500 of 3745. Previous lines