/*
* Copyright (C) 2005-2006 Sun Microsystems, Inc. All rights reserved. Use is
* subject to license terms.
*/
package org.jdesktop.layout;
import java.awt.Container;
import javax.swing.ButtonModel;
import javax.swing.DefaultButtonModel;
import javax.swing.JComponent;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTheme;
import java.lang.reflect.*;
/**
* An implementation of <code>LayoutStyle</code> for the java look and feel.
* This information comes from the
* <a href="http://java.sun.com/products/jlf/ed2/book/HIG.Visual2.html">
* The Java Look and Feel Design Guidelines</a>.
*
* @version $Revision: 1.1 $
*/
class MetalLayoutStyle extends LayoutStyle {
/**
* Whether or not we're using ocean, the default metal theme in 1.5.
*/
private boolean isOcean;
public MetalLayoutStyle() {
isOcean = false;
try {
Method method = MetalLookAndFeel.class.
getMethod("getCurrentTheme", (Class[])null);
isOcean = ((MetalTheme)method.invoke(null, (Object[])null)).
getName() == "Ocean";
} catch (NoSuchMethodException nsme) {
} catch (IllegalAccessException iae) {
} catch (IllegalArgumentException iae2) {
} catch (InvocationTargetException ite) {
}
}
// NOTE: The JLF makes reference to a number of guidelines in terms of
// 6 pixels - 1 pixel. The rationale is because steel buttons have
// a heavy border followed by a light border, and so that if you pad
// by 6 pixels it'll look like 7. Using 5 pixels than produces an effect
// of 6 pixels. With Ocean things are different, the only component
// that you want this behavior to happen with is checkboxs.
public int getPreferredGap(JComponent source, JComponent target,
int type, int position, Container parent) {
// Invoke super to check arguments.
super.getPreferredGap(source, target, type, position, parent);
if (type == INDENT) {
if (position == SwingConstants.EAST || position == SwingConstants.WEST) {
int gap = getButtonChildIndent(source, position);
if (gap != 0) {
return gap;
}
return 12;
}
// Treat vertical INDENT as RELATED
type = RELATED;
}
String sourceCID = source.getUIClassID();
String targetCID = target.getUIClassID();
int offset;
if (type == RELATED) {
if (sourceCID == "ToggleButtonUI" &&
targetCID == "ToggleButtonUI") {
ButtonModel sourceModel = ((JToggleButton)source).getModel();
ButtonModel targetModel = ((JToggleButton)target).getModel();
if ((sourceModel instanceof DefaultButtonModel) &&
(targetModel instanceof DefaultButtonModel) &&
(((DefaultButtonModel)sourceModel).getGroup() ==
((DefaultButtonModel)targetModel).getGroup()) &&
((DefaultButtonModel)sourceModel).getGroup() != null) {
// When toggle buttons are exclusive (that is, they form a
// radio button set), separate them with 2 pixels. This
// rule applies whether the toggle buttons appear in a
// toolbar or elsewhere in the interface.
// Note: this number does not appear to include any borders
// and so is not adjusted by the border of the toggle
// button
return 2;
}
// When toggle buttons are independent (like checkboxes)
// and used outside a toolbar, separate them with 5
// pixels.
if (isOcean) {
return 6;
}
return 5;
}
offset = 6;
}
else {
offset = 12;
}
if ((position == SwingConstants.EAST ||
position == SwingConstants.WEST) &&
((sourceCID == "LabelUI" && targetCID != "LabelUI") ||
(sourceCID != "LabelUI" && targetCID == "LabelUI"))) {
// Insert 12 pixels between the trailing edge of a
// label and any associated components. Insert 12
// pixels between the trailing edge of a label and the
// component it describes when labels are
// right-aligned. When labels are left-aligned, insert
// 12 pixels between the trailing edge of the longest
// label and its associated component
return getCBRBPadding(source, target, position, offset + 6);
}
return getCBRBPadding(source, target, position, offset);
}
int getCBRBPadding(JComponent source, JComponent target, int position,
int offset) {
offset = super.getCBRBPadding(source, target, position, offset);
if (offset > 0) {
int buttonAdjustment = getButtonAdjustment(source, position);
if (buttonAdjustment == 0) {
buttonAdjustment = getButtonAdjustment(target,
flipDirection(position));
}
offset -= buttonAdjustment;
}
if (offset < 0) {
return 0;
}
return offset;
}
private int getButtonAdjustment(JComponent source, int edge) {
String uid = source.getUIClassID();
if (uid == "ButtonUI" || uid == "ToggleButtonUI") {
if (!isOcean && (edge == SwingConstants.EAST ||
edge == SwingConstants.SOUTH)) {
return 1;
}
}
else if (edge == SwingConstants.SOUTH) {
if (uid == "RadioButtonUI" || (!isOcean && uid == "CheckBoxUI")) {
return 1;
}
}
return 0;
}
public int getContainerGap(JComponent component, int position,
Container parent) {
super.getContainerGap(component, position, parent);
// Here's the rules we should be honoring:
//
// Include 11 pixels between the bottom and right
// borders of a dialog box and its command
// buttons. (To the eye, the 11-pixel spacing appears
// to be 12 pixels because the white borders on the
// lower and right edges of the button components are
// not visually significant.)
// NOTE: this last text was designed with Steel in mind, not Ocean.
//
// Insert 12 pixels between the edges of the panel and the
// titled border. Insert 11 pixels between the top of the
// title and the component above the titled border. Insert 12
// pixels between the bottom of the title and the top of the
// first label in the panel. Insert 11 pixels between
// component groups and between the bottom of the last
// component and the lower border.
return getCBRBPadding(component, position, 12 -
getButtonAdjustment(component, position));
}
}