|  | /* | 
|  | * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. | 
|  | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|  | * | 
|  | * This code is free software; you can redistribute it and/or modify it | 
|  | * under the terms of the GNU General Public License version 2 only, as | 
|  | * published by the Free Software Foundation.  Oracle designates this | 
|  | * particular file as subject to the "Classpath" exception as provided | 
|  | * by Oracle in the LICENSE file that accompanied this code. | 
|  | * | 
|  | * This code 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 | 
|  | * version 2 for more details (a copy is included in the LICENSE file that | 
|  | * accompanied this code). | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License version | 
|  | * 2 along with this work; if not, write to the Free Software Foundation, | 
|  | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|  | * | 
|  | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|  | * or visit www.oracle.com if you need additional information or have any | 
|  | * questions. | 
|  | */ | 
|  | package sun.swing; | 
|  |  | 
|  | import java.awt.Container; | 
|  | import java.awt.Insets; | 
|  | import javax.swing.*; | 
|  | import javax.swing.LayoutStyle.ComponentPlacement; | 
|  | import javax.swing.border.Border; | 
|  | import javax.swing.plaf.UIResource; | 
|  |  | 
|  | /** | 
|  | * An implementation of <code>LayoutStyle</code> that returns 6 for related | 
|  | * components, otherwise 12.  This class also provides helper methods for | 
|  | * subclasses. | 
|  | * | 
|  | */ | 
|  | public class DefaultLayoutStyle extends LayoutStyle { | 
|  | private static final DefaultLayoutStyle INSTANCE = | 
|  | new DefaultLayoutStyle(); | 
|  |  | 
|  | public static LayoutStyle getInstance() { | 
|  | return INSTANCE; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int getPreferredGap(JComponent component1, JComponent component2, | 
|  | ComponentPlacement type, int position, Container parent) { | 
|  | if (component1 == null || component2 == null || type == null) { | 
|  | throw new NullPointerException(); | 
|  | } | 
|  |  | 
|  | checkPosition(position); | 
|  |  | 
|  | if (type == ComponentPlacement.INDENT && | 
|  | (position == SwingConstants.EAST || | 
|  | position == SwingConstants.WEST)) { | 
|  | int indent = getIndent(component1, position); | 
|  | if (indent > 0) { | 
|  | return indent; | 
|  | } | 
|  | } | 
|  | return (type == ComponentPlacement.UNRELATED) ? 12 : 6; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int getContainerGap(JComponent component, int position, | 
|  | Container parent) { | 
|  | if (component == null) { | 
|  | throw new NullPointerException(); | 
|  | } | 
|  | checkPosition(position); | 
|  | return 6; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns true if the classes identify a JLabel and a non-JLabel | 
|  | * along the horizontal axis. | 
|  | */ | 
|  | protected boolean isLabelAndNonlabel(JComponent c1, JComponent c2, | 
|  | int position) { | 
|  | if (position == SwingConstants.EAST || | 
|  | position == SwingConstants.WEST) { | 
|  | boolean c1Label = (c1 instanceof JLabel); | 
|  | boolean c2Label = (c2 instanceof JLabel); | 
|  | return ((c1Label || c2Label) && (c1Label != c2Label)); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * For some look and feels check boxs and radio buttons typically | 
|  | * don't paint the border, yet they have padding for a border.  Look | 
|  | * and feel guidelines generally don't include this space.  Use | 
|  | * this method to subtract this space from the specified | 
|  | * components. | 
|  | * | 
|  | * @param source First component | 
|  | * @param target Second component | 
|  | * @param position Position doing layout along. | 
|  | * @param offset Ideal offset, not including border/margin | 
|  | * @return offset - border/margin around the component. | 
|  | */ | 
|  | protected int getButtonGap(JComponent source, JComponent target, | 
|  | int position, int offset) { | 
|  | offset -= getButtonGap(source, position); | 
|  | if (offset > 0) { | 
|  | offset -= getButtonGap(target, flipDirection(position)); | 
|  | } | 
|  | if (offset < 0) { | 
|  | return 0; | 
|  | } | 
|  | return offset; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * For some look and feels check boxs and radio buttons typically | 
|  | * don't paint the border, yet they have padding for a border.  Look | 
|  | * and feel guidelines generally don't include this space.  Use | 
|  | * this method to subtract this space from the specified | 
|  | * components. | 
|  | * | 
|  | * @param source Component | 
|  | * @param position Position doing layout along. | 
|  | * @param offset Ideal offset, not including border/margin | 
|  | * @return offset - border/margin around the component. | 
|  | */ | 
|  | protected int getButtonGap(JComponent source, int position, int offset) { | 
|  | offset -= getButtonGap(source, position); | 
|  | return Math.max(offset, 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * If <code>c</code> is a check box or radio button, and the border is | 
|  | * not painted this returns the inset along the specified axis. | 
|  | */ | 
|  | public int getButtonGap(JComponent c, int position) { | 
|  | String classID = c.getUIClassID(); | 
|  | if ((classID == "CheckBoxUI" || classID == "RadioButtonUI") && | 
|  | !((AbstractButton)c).isBorderPainted()) { | 
|  | Border border = c.getBorder(); | 
|  | if (border instanceof UIResource) { | 
|  | return getInset(c, position); | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | private void checkPosition(int position) { | 
|  | if (position != SwingConstants.NORTH && | 
|  | position != SwingConstants.SOUTH && | 
|  | position != SwingConstants.WEST && | 
|  | position != SwingConstants.EAST) { | 
|  | throw new IllegalArgumentException(); | 
|  | } | 
|  | } | 
|  |  | 
|  | protected int flipDirection(int position) { | 
|  | switch(position) { | 
|  | case SwingConstants.NORTH: | 
|  | return SwingConstants.SOUTH; | 
|  | case SwingConstants.SOUTH: | 
|  | return SwingConstants.NORTH; | 
|  | case SwingConstants.EAST: | 
|  | return SwingConstants.WEST; | 
|  | case SwingConstants.WEST: | 
|  | return SwingConstants.EAST; | 
|  | } | 
|  | assert false; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the amount to indent the specified component if it's | 
|  | * a JCheckBox or JRadioButton.  If the component is not a JCheckBox or | 
|  | * JRadioButton, 0 will be returned. | 
|  | */ | 
|  | protected int getIndent(JComponent c, int position) { | 
|  | String classID = c.getUIClassID(); | 
|  | if (classID == "CheckBoxUI" || classID == "RadioButtonUI") { | 
|  | AbstractButton button = (AbstractButton)c; | 
|  | Insets insets = c.getInsets(); | 
|  | Icon icon = getIcon(button); | 
|  | int gap = button.getIconTextGap(); | 
|  | if (isLeftAligned(button, position)) { | 
|  | return insets.left + icon.getIconWidth() + gap; | 
|  | } else if (isRightAligned(button, position)) { | 
|  | return insets.right + icon.getIconWidth() + gap; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | private Icon getIcon(AbstractButton button) { | 
|  | Icon icon = button.getIcon(); | 
|  | if (icon != null) { | 
|  | return icon; | 
|  | } | 
|  | String key = null; | 
|  | if (button instanceof JCheckBox) { | 
|  | key = "CheckBox.icon"; | 
|  | } else if (button instanceof JRadioButton) { | 
|  | key = "RadioButton.icon"; | 
|  | } | 
|  | if (key != null) { | 
|  | Object oIcon = UIManager.get(key); | 
|  | if (oIcon instanceof Icon) { | 
|  | return (Icon)oIcon; | 
|  | } | 
|  | } | 
|  | return null; | 
|  | } | 
|  |  | 
|  | private boolean isLeftAligned(AbstractButton button, int position) { | 
|  | if (position == SwingConstants.WEST) { | 
|  | boolean ltr = button.getComponentOrientation().isLeftToRight(); | 
|  | int hAlign = button.getHorizontalAlignment(); | 
|  | return ((ltr && (hAlign == SwingConstants.LEFT || | 
|  | hAlign == SwingConstants.LEADING)) || | 
|  | (!ltr && (hAlign == SwingConstants.TRAILING))); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | private boolean isRightAligned(AbstractButton button, int position) { | 
|  | if (position == SwingConstants.EAST) { | 
|  | boolean ltr = button.getComponentOrientation().isLeftToRight(); | 
|  | int hAlign = button.getHorizontalAlignment(); | 
|  | return ((ltr && (hAlign == SwingConstants.RIGHT || | 
|  | hAlign == SwingConstants.TRAILING)) || | 
|  | (!ltr && (hAlign == SwingConstants.LEADING))); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | private int getInset(JComponent c, int position) { | 
|  | return getInset(c.getInsets(), position); | 
|  | } | 
|  |  | 
|  | private int getInset(Insets insets, int position) { | 
|  | if (insets == null) { | 
|  | return 0; | 
|  | } | 
|  | switch(position) { | 
|  | case SwingConstants.NORTH: | 
|  | return insets.top; | 
|  | case SwingConstants.SOUTH: | 
|  | return insets.bottom; | 
|  | case SwingConstants.EAST: | 
|  | return insets.right; | 
|  | case SwingConstants.WEST: | 
|  | return insets.left; | 
|  | } | 
|  | assert false; | 
|  | return 0; | 
|  | } | 
|  | } |