// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program 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 for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: MacLookAndFeel.java,v 1.5 2007/05/14 15:16:32 spyromus Exp $
//
package com.salas.bb.utils.uif.laf;
import ch.randelshofer.quaqua.QuaquaComboBoxUI;
import ch.randelshofer.quaqua.QuaquaManager;
import ch.randelshofer.quaqua.VisualMargin;
import ch.randelshofer.quaqua.util.Images;
import com.salas.bb.utils.i18n.Strings;
import javax.swing.*;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.IconUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.ColorUIResource;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.net.URL;
/**
* Tweaked mac look and feel.
*/
public class MacLookAndFeel extends LAFProxy
{
private UIDefaults lafDefaults;
/**
* Creates look and feel.
*/
public MacLookAndFeel()
{
String lafClassName = "apple.laf.AquaLookAndFeel";
try
{
Class lafClass = Class.forName(lafClassName);
setLookAndFeel((LookAndFeel)lafClass.newInstance());
} catch (ClassNotFoundException e)
{
throw new IllegalStateException(MessageFormat.format(
Strings.error("failed.to.find.standard.aqua.laf"),
new Object[] { lafClassName }));
} catch (InstantiationException e)
{
throw new IllegalStateException(MessageFormat.format(
Strings.error("failed.to.create.instance.of.aqua.laf"),
new Object[] { lafClassName }));
} catch (IllegalAccessException e)
{
throw new IllegalStateException(MessageFormat.format(
Strings.error("failed.to.access.aqua.laf.class"),
new Object[] { lafClassName }));
}
}
/**
* UIManager.setLookAndFeel calls this method before the first call (and typically the only
* call) to getDefaults(). Subclasses should do any one-time setup they need here, rather than
* in a static initializer, because look and feel class objects may be loaded just to discover
* that isSupportedLookAndFeel() returns false.
*
* @see #uninitialize
* @see javax.swing.UIManager#setLookAndFeel
*/
public void initialize()
{
AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
laf.initialize();
lafDefaults = laf.getDefaults();
initResourceBundle(lafDefaults);
initClassDefaults(lafDefaults);
initComponentDefaults(lafDefaults);
return null;
}
});
}
/**
* Initializes component UI default class names.
*
* @param table defaults table.
*/
protected void initClassDefaults(UIDefaults table)
{
String quaquaPrefix = "ch.randelshofer.quaqua.Quaqua";
String quaquaPantherPrefix = "ch.randelshofer.quaqua.panther.QuaquaPanther";
Object[] objects = new Object[]
{
"PopupMenuSeparatorUI", MacPopupMenuSeparatorUI.class.getName(),
"ComboBoxUI", QuaquaComboBoxUI.class.getName(),
// for JFileChooser
"BrowserUI", quaquaPrefix + "BrowserUI",
"FileChooserUI", quaquaPantherPrefix + "FileChooserUI",
};
table.putDefaults(objects);
}
/**
* Initializes component defaults.
*
* @param table defaults table.
*/
protected void initComponentDefaults(UIDefaults table)
{
// Set visual margin.
int[] values = QuaquaManager.getProperty("Quaqua.visualMargin", new int[] { 3, 3, 3, 3});
InsetsUIResource visualMargin = new InsetsUIResource(values[0], values[1], values[2], values[3]);
// Opaqueness
boolean opaque = QuaquaManager.getProperty("Quaqua.opaque", "false").equals("true");
String commonDir = "/ch/randelshofer/quaqua/images/";
Icon[] browserIcons = makeIcons(commonDir+"Browser.disclosureIcons.png", 4, true);
Font smallSystemFont = SMALL_SYSTEM_FONT;
Object[] objects = new Object[]
{
"PopupMenu.border", new UIDefaults.ProxyLazyValue(MacMenuBorder.class.getName()),
"Separator.background", Color.decode("#f4f4f4"),
"Separator.foreground", Color.decode("#dadada"),
"ComboBox.border", new VisualMargin(2,2,2,2),
"ComboBox.dropDownIcon", makeButtonStateIcon(commonDir + "ComboBox.dropDownIcons.png", 6),
"ComboBox.opaque", opaque,
"ComboBox.popupIcon", makeButtonStateIcon(commonDir + "ComboBox.popupIcons.png", 6),
"ComboBox.smallPopupIcon", makeButtonStateIcon(commonDir + "ComboBox.small.popupIcons.png", 6),
"ComboBox.smallDropDownIcon", makeButtonStateIcon(commonDir + "ComboBox.small.dropDownIcons.png", 6),
// The values for this margin are ignored. We dynamically compute a margin
// for the various button styles that we support, if we encounter a
// a margin that is an instanceof a UIResource.
"ComboBoxButton.margin", new InsetsUIResource(0,0,0,0),
// The visual margin is used to allow each component having room
// for a cast shadow and a focus ring, and still supporting a
// consistent visual arrangement of all components aligned to their
// visualy perceived lines.
"Component.visualMargin", visualMargin,
// for JFileChooser
"Browser.expandedIcon", browserIcons[0],
"Browser.expandingIcon", browserIcons[1],
"Browser.selectedExpandedIcon", browserIcons[2],
"Browser.selectedExpandingIcon", browserIcons[3],
"Browser.selectionBackground", new ColorUIResource(56,117,215),
"Browser.selectionForeground", new ColorUIResource(255,255,255),
"Browser.inactiveSelectionBackground", new ColorUIResource(208,208,208),
"Browser.inactiveSelectionForeground", new ColorUIResource(0,0,0),
"FileChooser.homeFolderIcon", LookAndFeel.makeIcon(getClass(), commonDir+"FileChooser.homeFolderIcon.png"),
"FileView.computerIcon", LookAndFeel.makeIcon(getClass(), commonDir+"FileView.computerIcon.png"),
"FileChooser.previewLabelForeground", new ColorUIResource(0x000000),
"FileChooser.previewValueForeground", new ColorUIResource(0x000000),
"FileChooser.previewLabelFont", smallSystemFont,
"FileChooser.previewValueFont", smallSystemFont,
"FileChooser.splitPaneDividerSize", new Integer(6),
"FileChooser.previewLabelInsets",new InsetsUIResource(0,0,0,4),
"FileChooser.cellTipOrigin", new Point(18, 1),
};
table.putDefaults(objects);
}
protected static Object makeButtonStateIcon(String location, int states)
{
return new UIDefaults.ProxyLazyValue(
"ch.randelshofer.quaqua.QuaquaIconFactory",
"createButtonStateIcon",
new Object[] { location, states }
);
}
/**
* Returns our tweaked defaults.
*
* @return defaults.
*/
public UIDefaults getDefaults()
{
return lafDefaults;
}
// New stuff for JFileChooser
protected void initResourceBundle(UIDefaults table)
{
table.addResourceBundle("ch.randelshofer.quaqua.Labels");
}
protected URL getResource(String location) {
URL url = getClass().getResource(location);
if (url == null) {
throw new InternalError("image resource missing: "+location);
}
return url;
}
protected Image createImage(String location) {
return Toolkit.getDefaultToolkit().createImage(getResource(location));
}
protected Icon[] makeIcons(String location, int count, boolean horizontal) {
Icon[] icons = new Icon[count];
BufferedImage[] images = Images.split(
createImage(location),
count, horizontal
);
for (int i=0; i < count; i++) {
icons[i] = new IconUIResource(new ImageIcon(images[i]));
}
return icons;
}
/**
* The small system font (Lucida Grande Regular 11 pt) is used for
* informative text in alerts. It is also the default font for column
* headings in lists, for help tags, and for small controls. You can also
* use it to provide additional information about settings in various
* windows, such as the QuickTime pane in System Preferences.
*/
protected static final FontUIResource SMALL_SYSTEM_FONT =
new FontUIResource("Lucida Grande", Font.PLAIN, 11);
}