001: /*
002: * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.swing;
026:
027: import java.awt.Container;
028: import java.awt.Insets;
029: import javax.swing.*;
030: import javax.swing.LayoutStyle.ComponentPlacement;
031: import javax.swing.border.Border;
032: import javax.swing.plaf.UIResource;
033:
034: /**
035: * An implementation of <code>LayoutStyle</code> that returns 6 for related
036: * components, otherwise 12. This class also provides helper methods for
037: * subclasses.
038: *
039: * @version 1.8, 05/05/07
040: */
041: public class DefaultLayoutStyle extends LayoutStyle {
042: private static final DefaultLayoutStyle INSTANCE = new DefaultLayoutStyle();
043:
044: public static LayoutStyle getInstance() {
045: return INSTANCE;
046: }
047:
048: @Override
049: public int getPreferredGap(JComponent component1,
050: JComponent component2, ComponentPlacement type,
051: int position, Container parent) {
052:
053: if (component1 == null || component2 == null || type == null) {
054: throw new NullPointerException();
055: }
056: if (type == ComponentPlacement.INDENT
057: && (position == SwingConstants.EAST || position == SwingConstants.WEST)) {
058: int indent = getIndent(component1, position);
059: if (indent > 0) {
060: return indent;
061: }
062: }
063: return (type == ComponentPlacement.UNRELATED) ? 12 : 6;
064: }
065:
066: @Override
067: public int getContainerGap(JComponent component, int position,
068: Container parent) {
069: if (component == null) {
070: throw new NullPointerException();
071: }
072: checkPosition(position);
073: return 6;
074: }
075:
076: /**
077: * Returns true if the classes identify a JLabel and a non-JLabel
078: * along the horizontal axis.
079: */
080: protected boolean isLabelAndNonlabel(JComponent c1, JComponent c2,
081: int position) {
082: if (position == SwingConstants.EAST
083: || position == SwingConstants.WEST) {
084: boolean c1Label = (c1 instanceof JLabel);
085: boolean c2Label = (c2 instanceof JLabel);
086: return ((c1Label || c2Label) && (c1Label != c2Label));
087: }
088: return false;
089: }
090:
091: /**
092: * For some look and feels check boxs and radio buttons typically
093: * don't paint the border, yet they have padding for a border. Look
094: * and feel guidelines generally don't include this space. Use
095: * this method to subtract this space from the specified
096: * components.
097: *
098: * @param source First component
099: * @param target Second component
100: * @param position Position doing layout along.
101: * @param offset Ideal offset, not including border/margin
102: * @return offset - border/margin around the component.
103: */
104: protected int getButtonGap(JComponent source, JComponent target,
105: int position, int offset) {
106: offset -= getButtonGap(source, position);
107: if (offset > 0) {
108: offset -= getButtonGap(target, flipDirection(position));
109: }
110: if (offset < 0) {
111: return 0;
112: }
113: return offset;
114: }
115:
116: /**
117: * For some look and feels check boxs and radio buttons typically
118: * don't paint the border, yet they have padding for a border. Look
119: * and feel guidelines generally don't include this space. Use
120: * this method to subtract this space from the specified
121: * components.
122: *
123: * @param source Component
124: * @param position Position doing layout along.
125: * @param offset Ideal offset, not including border/margin
126: * @return offset - border/margin around the component.
127: */
128: protected int getButtonGap(JComponent source, int position,
129: int offset) {
130: offset -= getButtonGap(source, position);
131: return Math.max(offset, 0);
132: }
133:
134: /**
135: * If <code>c</code> is a check box or radio button, and the border is
136: * not painted this returns the inset along the specified axis.
137: */
138: public int getButtonGap(JComponent c, int position) {
139: String classID = c.getUIClassID();
140: if ((classID == "CheckBoxUI" || classID == "RadioButtonUI")
141: && !((AbstractButton) c).isBorderPainted()) {
142: Border border = c.getBorder();
143: if (border instanceof UIResource) {
144: return getInset(c, position);
145: }
146: }
147: return 0;
148: }
149:
150: private void checkPosition(int position) {
151: if (position != SwingConstants.NORTH
152: && position != SwingConstants.SOUTH
153: && position != SwingConstants.WEST
154: && position != SwingConstants.EAST) {
155: throw new IllegalArgumentException();
156: }
157: }
158:
159: protected int flipDirection(int position) {
160: switch (position) {
161: case SwingConstants.NORTH:
162: return SwingConstants.SOUTH;
163: case SwingConstants.SOUTH:
164: return SwingConstants.NORTH;
165: case SwingConstants.EAST:
166: return SwingConstants.WEST;
167: case SwingConstants.WEST:
168: return SwingConstants.EAST;
169: }
170: assert false;
171: return 0;
172: }
173:
174: /**
175: * Returns the amount to indent the specified component if it's
176: * a JCheckBox or JRadioButton. If the component is not a JCheckBox or
177: * JRadioButton, 0 will be returned.
178: */
179: protected int getIndent(JComponent c, int position) {
180: String classID = c.getUIClassID();
181: if (classID == "CheckBoxUI" || classID == "RadioButtonUI") {
182: AbstractButton button = (AbstractButton) c;
183: Insets insets = c.getInsets();
184: Icon icon = getIcon(button);
185: int gap = button.getIconTextGap();
186: if (isLeftAligned(button, position)) {
187: return insets.left + icon.getIconWidth() + gap;
188: } else if (isRightAligned(button, position)) {
189: return insets.right + icon.getIconWidth() + gap;
190: }
191: }
192: return 0;
193: }
194:
195: private Icon getIcon(AbstractButton button) {
196: Icon icon = button.getIcon();
197: if (icon != null) {
198: return icon;
199: }
200: String key = null;
201: if (button instanceof JCheckBox) {
202: key = "CheckBox.icon";
203: } else if (button instanceof JRadioButton) {
204: key = "RadioButton.icon";
205: }
206: if (key != null) {
207: Object oIcon = UIManager.get(key);
208: if (oIcon instanceof Icon) {
209: return (Icon) oIcon;
210: }
211: }
212: return null;
213: }
214:
215: private boolean isLeftAligned(AbstractButton button, int position) {
216: if (position == SwingConstants.WEST) {
217: boolean ltr = button.getComponentOrientation()
218: .isLeftToRight();
219: int hAlign = button.getHorizontalAlignment();
220: return ((ltr && (hAlign == SwingConstants.LEFT || hAlign == SwingConstants.LEADING)) || (!ltr && (hAlign == SwingConstants.TRAILING)));
221: }
222: return false;
223: }
224:
225: private boolean isRightAligned(AbstractButton button, int position) {
226: if (position == SwingConstants.EAST) {
227: boolean ltr = button.getComponentOrientation()
228: .isLeftToRight();
229: int hAlign = button.getHorizontalAlignment();
230: return ((ltr && (hAlign == SwingConstants.RIGHT || hAlign == SwingConstants.TRAILING)) || (!ltr && (hAlign == SwingConstants.LEADING)));
231: }
232: return false;
233: }
234:
235: private int getInset(JComponent c, int position) {
236: return getInset(c.getInsets(), position);
237: }
238:
239: private int getInset(Insets insets, int position) {
240: if (insets == null) {
241: return 0;
242: }
243: switch (position) {
244: case SwingConstants.NORTH:
245: return insets.top;
246: case SwingConstants.SOUTH:
247: return insets.bottom;
248: case SwingConstants.EAST:
249: return insets.right;
250: case SwingConstants.WEST:
251: return insets.left;
252: }
253: assert false;
254: return 0;
255: }
256: }
|