blob: cfc2fc3ccb33d78990455c019306f2c2fba91d8b [file] [log] [blame]
/*
* Copyright (c) 2002, 2006, 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 com.sun.java.swing.plaf.gtk;
import java.awt.Font;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.synth.*;
import com.sun.java.swing.plaf.gtk.GTKEngine.WidgetType;
/**
*
* @author Scott Violet
*/
class GTKStyleFactory extends SynthStyleFactory {
/**
* Saves all styles that have been accessed. In most common cases,
* the hash key is simply the WidgetType, but in more complex cases
* it will be a ComplexKey object that contains arguments to help
* differentiate similar styles.
*/
private final Map<Object, GTKStyle> stylesCache;
private Font defaultFont;
GTKStyleFactory() {
stylesCache = new HashMap<Object, GTKStyle>();
}
/**
* Returns the <code>GTKStyle</code> to use based on the
* <code>Region</code> id
*
* @param c this parameter isn't used, may be null.
* @param id of the region to get the style.
*/
public synchronized SynthStyle getStyle(JComponent c, Region id) {
WidgetType wt = GTKEngine.getWidgetType(c, id);
Object key = null;
if (id == Region.SCROLL_BAR) {
// The style/insets of a scrollbar can depend on a number of
// factors (see GTKStyle.getScrollBarInsets()) so use a
// complex key here.
if (c != null) {
JScrollBar sb = (JScrollBar)c;
boolean sp = (sb.getParent() instanceof JScrollPane);
boolean horiz = (sb.getOrientation() == JScrollBar.HORIZONTAL);
boolean ltr = sb.getComponentOrientation().isLeftToRight();
boolean focusable = sb.isFocusable();
key = new ComplexKey(wt, sp, horiz, ltr, focusable);
}
}
else if (id == Region.CHECK_BOX || id == Region.RADIO_BUTTON) {
// The style/insets of a checkbox or radiobutton can depend
// on the component orientation, so use a complex key here.
if (c != null) {
boolean ltr = c.getComponentOrientation().isLeftToRight();
key = new ComplexKey(wt, ltr);
}
}
else if (id == Region.BUTTON) {
// The style/insets of a button can depend on whether it is
// default capable or in a toolbar, so use a complex key here.
if (c != null) {
JButton btn = (JButton)c;
boolean toolButton = (btn.getParent() instanceof JToolBar);
boolean defaultCapable = btn.isDefaultCapable();
key = new ComplexKey(wt, toolButton, defaultCapable);
}
} else if (id == Region.MENU) {
if (c instanceof JMenu && ((JMenu) c).isTopLevelMenu() &&
UIManager.getBoolean("Menu.useMenuBarForTopLevelMenus")) {
wt = WidgetType.MENU_BAR;
}
}
if (key == null) {
// Otherwise, just use the WidgetType as the key.
key = wt;
}
GTKStyle result = stylesCache.get(key);
if (result == null) {
result = new GTKStyle(defaultFont, wt);
stylesCache.put(key, result);
}
return result;
}
void initStyles(Font defaultFont) {
this.defaultFont = defaultFont;
stylesCache.clear();
}
/**
* Represents a hash key used for fetching GTKStyle objects from the
* cache. In most cases only the WidgetType is used for lookup, but
* in some complex cases, other Object arguments can be specified
* via a ComplexKey to differentiate the various styles.
*/
private static class ComplexKey {
private final WidgetType wt;
private final Object[] args;
ComplexKey(WidgetType wt, Object... args) {
this.wt = wt;
this.args = args;
}
@Override
public int hashCode() {
int hash = wt.hashCode();
if (args != null) {
for (Object arg : args) {
hash = hash*29 + (arg == null ? 0 : arg.hashCode());
}
}
return hash;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ComplexKey)) {
return false;
}
ComplexKey that = (ComplexKey)o;
if (this.wt == that.wt) {
if (this.args == null && that.args == null) {
return true;
}
if (this.args != null && that.args != null &&
this.args.length == that.args.length)
{
for (int i = 0; i < this.args.length; i++) {
Object a1 = this.args[i];
Object a2 = that.args[i];
if (!(a1==null ? a2==null : a1.equals(a2))) {
return false;
}
}
return true;
}
}
return false;
}
@Override
public String toString() {
String str = "ComplexKey[wt=" + wt;
if (args != null) {
str += ",args=[";
for (int i = 0; i < args.length; i++) {
str += args[i];
if (i < args.length-1) str += ",";
}
str += "]";
}
str += "]";
return str;
}
}
}