diff --git a/README b/README index d774ab80b70466958efc3ae02347b54eb84fc1b5..e3cc63ec993be85b2eb12e21d38d3e1a16f007f4 100644 --- a/README +++ b/README @@ -9,25 +9,35 @@ Simple Build Instructions: http://java.sun.com/javase/downloads/index.jsp Set the environment variable ALT_BOOTDIR to the location of this JDK 6. - 2. Download and install the Binary Plugs for the most recent JDK7 from + 2. Download and install the JIBX libraries, version 1.1.5 from + http://sourceforge.net/project/showfiles.php?group_id=69358&package_id=68290 + You'll need the following four JAR files: + bcel.jar + jibx-bind.jar + jibx-run.jar + xpp3.jar + Set the environment variable ALT_JIBX_LIBS_PATH to the location of + these JAR files. + + 3. Download and install the Binary Plugs for the most recent JDK7 from http://download.java.net/openjdk/jdk7/ Set the environment variable ALT_BINARY_PLUGS_PATH to the location of these binary plugs. - 3. Either download and install the latest JDK7 from + 4. Either download and install the latest JDK7 from http://download.java.net/openjdk/jdk7/, or build your own complete OpenJDK7 by using the top level Makefile in the OpenJDK Mercurial forest. Set the environment variable ALT_JDK_IMPORT_PATH to the location of this latest JDK7 or OpenJDK7 build. - 4. Check the sanity of doing a build with the current machine: + 5. Check the sanity of doing a build with the current machine: cd make && gnumake sanity See README-builds.html if you run into problems. - 5. Do a partial build of the jdk: + 6. Do a partial build of the jdk: cd make && gnumake all - 6. Construct the images: + 7. Construct the images: cd make && gnumake images The resulting JDK image should be found in build/*/j2sdk-image diff --git a/make/common/Sanity.gmk b/make/common/Sanity.gmk index 3388be0403fbb6fc9878d4e9af2545edf4830362..eb4f00eb89953fc4449ecdaf229705e98c713bee 100644 --- a/make/common/Sanity.gmk +++ b/make/common/Sanity.gmk @@ -92,7 +92,8 @@ sanity-all:: sanity-base \ sane-ld_run_path \ sane-alt_bootdir \ sane-bootdir \ - sane-alsa-headers + sane-alsa-headers \ + sane-jibx ifdef OPENJDK sanity-all:: sane-freetype diff --git a/make/common/shared/Defs.gmk b/make/common/shared/Defs.gmk index 5da4a29047e20de6af1a8777bb30b59efaad98fc..dc62f1ee5a47409882446c95e670e8199d3a8be4 100644 --- a/make/common/shared/Defs.gmk +++ b/make/common/shared/Defs.gmk @@ -515,6 +515,15 @@ endif # NOTE: ISA_DIR is usually empty, on Solaris it might be /sparcv9 or /amd64 BINDIR = $(OUTPUTDIR)/bin$(ISA_DIR) +# JIBX_LIBS_PATH: path to JIBX libraries, needed for NimbusLookAndFeel +ifdef ALT_JIBX_LIBS_PATH + JIBX_LIBS_PATH:=$(call FullPath,$(ALT_JIBX_LIBS_PATH)) + JIBX_LIBS_PATH:=$(call AltCheckSpaces,JIBX_LIBS_PATH) + JIBX_LIBS_PATH:=$(call AltCheckValue,JIBX_LIBS_PATH) +else + JIBX_LIBS_PATH=$(JDK_DEVTOOLS_DIR)/share/jibx/lib +endif + # MOZILLA_HEADERS_PATH: path to mozilla header files for plugin ifdef ALT_MOZILLA_HEADERS_PATH MOZILLA_HEADERS_PATH :=$(call FullPath,$(ALT_MOZILLA_HEADERS_PATH)) @@ -529,7 +538,7 @@ ifneq ($(PLATFORM), windows) JDK_CUPS_HEADERS_PATH=$(JDK_DEVTOOLS_DIR)/share/cups/include ifdef ALT_CUPS_HEADERS_PATH CUPS_HEADERS_PATH:=$(call FullPath,$(ALT_CUPS_HEADERS_PATH)) - CUP_HEADERS_PATH:=$(call AltCheckValue,CUPS_HEADERS_PATH) + CUPS_HEADERS_PATH:=$(call AltCheckValue,CUPS_HEADERS_PATH) else CUPS_HEADERS_PATH:= \ $(shell if [ -d "$(JDK_CUPS_HEADERS_PATH)" ]; then \ diff --git a/make/common/shared/Sanity-Settings.gmk b/make/common/shared/Sanity-Settings.gmk index b64e3b52a136a931d3230425feebadcd5fad802b..283598e394db424f6cac63f832dddac05129209e 100644 --- a/make/common/shared/Sanity-Settings.gmk +++ b/make/common/shared/Sanity-Settings.gmk @@ -233,6 +233,7 @@ ifeq ($(PLATFORM),windows) endif endif ALL_SETTINGS+=$(call addAltSetting,CACERTS_FILE) +ALL_SETTINGS+=$(call addAltSetting,JIBX_LIBS_PATH) ifndef OPENJDK ALL_SETTINGS+=$(call addAltSetting,MOZILLA_HEADERS_PATH) endif diff --git a/make/common/shared/Sanity.gmk b/make/common/shared/Sanity.gmk index 180e52196a999ee3f366ed96723285ca6d380268..84d5e2201a0b18e42108858f671c704b491a27d3 100644 --- a/make/common/shared/Sanity.gmk +++ b/make/common/shared/Sanity.gmk @@ -213,6 +213,7 @@ include $(JDK_MAKE_SHARED_DIR)/Sanity-Settings.gmk sane-link \ sane-cacerts \ sane-alsa-headers \ + sane-jibx \ sane-ant_version \ sane-zip_version \ sane-unzip_version \ @@ -1497,6 +1498,18 @@ ifeq ($(PLATFORM), solaris) endif +###################################################### +# JIBX_LIBS_PATH must be valid +###################################################### +sane-jibx: + @if [ ! -r $(subst \,/,$(JIBX_LIBS_PATH))/jibx-run.jar ]; then \ + $(ECHO) "ERROR: You do not have access to valid JIBX library files. \n" \ + " Please check your access to \n" \ + " $(subst \,/,$(JIBX_LIBS_PATH))/jibx-run.jar \n" \ + " and/or check your value of ALT_JDK_DEVTOOLS_DIR, ALT_JIBX_LIBS_PATH \n" \ + "" >> $(ERROR_FILE) ; \ + fi + ###################################################### # MOZILLA_HEADERS_PATH must be valid ###################################################### diff --git a/make/javax/swing/plaf/Makefile b/make/javax/swing/plaf/Makefile index f8e5e0c150a30d77d1097864f399da675273d7c8..aea88f2f7ff11aef3bb2785a085d11d6de192713 100644 --- a/make/javax/swing/plaf/Makefile +++ b/make/javax/swing/plaf/Makefile @@ -34,9 +34,14 @@ include $(BUILDDIR)/common/Defs.gmk # include FILES.gmk AUTO_FILES_JAVA_DIRS = javax/swing/plaf sun/swing com/sun/java/swing/plaf +SUBDIRS = nimbus + +# Nimbus is handled in its own directory +AUTO_JAVA_PRUNE = nimbus + ifeq ($(PLATFORM), windows) # Don't build GTK L&F on Windows - AUTO_JAVA_PRUNE = gtk + AUTO_JAVA_PRUNE += gtk endif MISC_FILES = $(MISC_SWING_FILES) @@ -68,8 +73,10 @@ endif # Process LOGO_ICONS and Motif Icons first. # build: $(LOGO_ICONS) $(MISC_SWING_FILES_MOTIF_GIF) $(MISC_SWING_FILES_MOTIF_PNG) other_files + $(SUBDIRS-loop) -clean:: classes.clean +clean clobber:: + $(SUBDIRS-loop) # # Include diff --git a/make/javax/swing/plaf/nimbus/Makefile b/make/javax/swing/plaf/nimbus/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ed59f137e5379b64d7e73d3a8a5c1ff271fa086d --- /dev/null +++ b/make/javax/swing/plaf/nimbus/Makefile @@ -0,0 +1,60 @@ +# +# Copyright 1998-2007 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +BUILDDIR = ../../../.. +PACKAGE = javax.swing.plaf.nimbus +PRODUCT = com +SWING_SRC = $(SHARE_SRC)/classes/javax/swing +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +NIMBUS_PKG = javax/swing/plaf/nimbus +NIMBUS_COMPAT_PKG = com/sun/java/swing/plaf/nimbus +NIMBUS_GENSRC_DIR = $(GENSRCDIR)/$(NIMBUS_PKG) +NIMBUS_SKIN_FILE = $(SHARE_SRC)/classes/$(NIMBUS_PKG)/skin.laf +NIMBUS_GENERATOR_JAR = $(BUILDTOOLJARDIR)/nimbus_generator.jar + +AUTO_FILES_JAVA_DIRS = $(NIMBUS_PKG) $(NIMBUS_COMPAT_PKG) + + +# +# Rules +# +CLASSES_INIT = $(NIMBUS_GENSRC_DIR) + +include $(BUILDDIR)/common/Classes.gmk + +$(NIMBUS_GENSRC_DIR): $(NIMBUS_SKIN_FILE) $(NIMBUS_GENERATOR_JAR) + @$(ECHO) "Generating Nimbus source files:" + $(BOOT_JAVA_CMD) -jar $(NIMBUS_GENERATOR_JAR) \ + -skinFile $(NIMBUS_SKIN_FILE) \ + -buildDir $(GENSRCDIR) -srcDir $(GENSRCDIR) \ + -packagePrefix $(PACKAGE) -lafName Nimbus + @$(ECHO) "Finished generating Nimbus source files" + +clean clobber:: + $(RM) -r $(NIMBUS_GENSRC_DIR) diff --git a/make/tools/Makefile b/make/tools/Makefile index 3803fbc6edabb494e7b7318384985815ac39ec7d..a927209f3304a497b8ac72da965d1b8ba7c6ffb2 100644 --- a/make/tools/Makefile +++ b/make/tools/Makefile @@ -51,6 +51,7 @@ SUBDIRS = \ makeclasslist \ strip_properties \ spp \ + swing-nimbus \ CharsetMapping all build clean clobber:: diff --git a/make/tools/swing-nimbus/Makefile b/make/tools/swing-nimbus/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..36df571c5f5be4c8f7a283ecdc8af1d905dee0fa --- /dev/null +++ b/make/tools/swing-nimbus/Makefile @@ -0,0 +1,91 @@ +# +# Copyright 1998-2005 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building the Nimbus generator +# + +BUILDDIR = ../.. +PACKAGE = org.jdesktop.synthdesigner.generator +PRODUCT = tools +PROGRAM = nimbus_generator +include $(BUILDDIR)/common/Defs.gmk + +BUILDTOOL_SOURCE_ROOT = classes +BUILDTOOL_MAIN = $(PKGDIR)/Generator.java + +# +# Files +# + +MAIN_CLASS_FILE = $(BUILDTOOLCLASSDIR)/$(BUILDTOOL_MAIN:%.java=%.class) +SOURCE_FILES = $(shell $(FIND) $(BUILDTOOL_SOURCE_ROOT) -name '*.java' -print) + +TEMPLATE_FILES = $(SHARE_SRC)/classes/javax/swing/plaf/nimbus/Defaults.template \ + $(SHARE_SRC)/classes/javax/swing/plaf/nimbus/PainterImpl.template \ + $(SHARE_SRC)/classes/javax/swing/plaf/nimbus/StateImpl.template +TEMPLATE_DEST = $(BUILDTOOLCLASSDIR)/org/jdesktop/synthdesigner/generator/resources + +JIBX_FILES = $(BUILDTOOL_SOURCE_ROOT)/org/jdesktop/swingx/designer/Designer.jibx.xml \ + $(BUILDTOOL_SOURCE_ROOT)/org/jdesktop/synthdesigner/synthmodel/SynthModel.jibx.xml +JIBX_LIBS_CP = $(JIBX_LIBS_PATH)/bcel.jar$(CLASSPATH_SEPARATOR)$(JIBX_LIBS_PATH)/xpp3.jar$(CLASSPATH_SEPARATOR)$(JIBX_LIBS_PATH)/jibx-bind.jar$(CLASSPATH_SEPARATOR)$(JIBX_LIBS_PATH)/jibx-run.jar +JIBX_LIBS_LIST = $(subst $(CLASSPATH_SEPARATOR), ,$(JIBX_LIBS_CP)) + + +# +# Rules +# + +include $(BUILDDIR)/common/BuildToolJar.gmk + +$(MAIN_CLASS_FILE): $(SOURCE_FILES) $(JIBX_LIBS_LIST) + @$(MKDIR) -p $(BUILDTOOLCLASSDIR) + $(BOOT_JAVAC_CMD) -classpath "$(JIBX_LIBS_CP)" \ + -d $(BUILDTOOLCLASSDIR) -sourcepath $(BUILDTOOL_SOURCE_ROOT) \ + $(SOURCE_FILES) + +$(TEMPLATE_DEST): $(TEMPLATE_FILES) + $(MKDIR) -p $(TEMPLATE_DEST) + $(RM) $(TEMPLATE_DEST)/*.template + $(CP) $(TEMPLATE_FILES) $(TEMPLATE_DEST) + +$(BUILDTOOL_MANIFEST_FILE): $(MAIN_CLASS_FILE) + $(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@ + $(ECHO) "Class-Path: $(JIBX_LIBS_LIST:$(JIBX_LIBS_PATH)/%=%)" >> $@ + $(CP) $(JIBX_LIBS_LIST) $(BUILDTOOLJARDIR) + +$(BUILDTOOL_JAR_FILE): $(MAIN_CLASS_FILE) $(TEMPLATE_DEST) \ + $(JIBX_FILES) $(BUILDTOOL_MANIFEST_FILE) + @$(prep-target) + $(BOOT_JAVA_CMD) \ + -classpath "$(JIBX_LIBS_CP)$(CLASSPATH_SEPARATOR)$(BUILDTOOLCLASSDIR)" \ + org.jibx.binding.Compile $(JIBX_FILES) + $(BOOT_JAR_CMD) cfm $@ $(BUILDTOOL_MANIFEST_FILE) \ + -C $(BUILDTOOLCLASSDIR) org \ + $(BOOT_JAR_JFLAGS) || $(RM) $@ + @$(java-vm-cleanup) + +clean clobber:: + $(RM) -r $(TEMPLATE_DEST) diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/beans/AbstractBean.java b/make/tools/swing-nimbus/classes/org/jdesktop/beans/AbstractBean.java new file mode 100644 index 0000000000000000000000000000000000000000..91325319b1ac01edaa86954e5f4cb56e92e1ee23 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/beans/AbstractBean.java @@ -0,0 +1,475 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.beans; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; + +/** + *

A convenience class from which to extend all non-visual AbstractBeans. It + * manages the PropertyChange notification system, making it relatively trivial + * to add support for property change events in getters/setters.

+ * + *

A non-visual java bean is a Java class that conforms to the AbstractBean + * patterns to allow visual manipulation of the bean's properties and event + * handlers at design-time.

+ * + *

Here is a simple example bean that contains one property, foo, and the + * proper pattern for implementing property change notification: + *


+ *  public class ABean extends AbstractBean {
+ *    private String foo;
+ *
+ *    public void setFoo(String newFoo) {
+ *      String old = getFoo();
+ *      this.foo = newFoo;
+ *      firePropertyChange("foo", old, getFoo());
+ *    }
+ *
+ *    public String getFoo() {
+ *      return foo;
+ *    }
+ *  }
+ * 

+ * + *

You will notice that "getFoo()" is used in the setFoo method rather than + * accessing "foo" directly for the gets. This is done intentionally so that if + * a subclass overrides getFoo() to return, for instance, a constant value the + * property change notification system will continue to work properly.

+ * + *

The firePropertyChange method takes into account the old value and the new + * value. Only if the two differ will it fire a property change event. So you can + * be assured from the above code fragment that a property change event will only + * occur if old is indeed different from getFoo()

+ * + *

AbstractBean also supports {@link VetoablePropertyChange} events. + * These events are similar to PropertyChange events, except a special + * exception can be used to veto changing the property. For example, perhaps the + * property is changing from "fred" to "red", but a listener deems that "red" is + * unexceptable. In this case, the listener can fire a veto exception and the property must + * remain "fred". For example: + *


+ *  public class ABean extends AbstractBean {
+ *    private String foo;
+ *
+ *    public void setFoo(String newFoo) throws PropertyVetoException {
+ *      String old = getFoo();
+ *      this.foo = newFoo;
+ *      fireVetoableChange("foo", old, getFoo());
+ *    }
+ *
+ *    public String getFoo() {
+ *      return foo;
+ *    }
+ *  }
+ *
+ *  public class Tester {
+ *    public static void main(String... args) {
+ *      try {
+ *        ABean a = new ABean();
+ *        a.setFoo("fred");
+ *        a.addVetoableChangeListener(new VetoableChangeListener() {
+ *          public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
+ *            if ("red".equals(evt.getNewValue()) {
+ *              throw new PropertyVetoException("Cannot be red!", evt);
+ *            }
+ *          }
+ *        }
+ *        a.setFoo("red");
+ *      } catch (Exception e) {
+ *        e.printStackTrace(); // this will be executed
+ *      }
+ *    }
+ *  }
+ * 

+ * + * @status REVIEWED + * @author rbair + */ +public abstract class AbstractBean { + /** + * Helper class that manages all the property change notification machinery. + * PropertyChangeSupport cannot be extended directly because it requires + * a bean in the constructor, and the "this" argument is not valid until + * after super construction. Hence, delegation instead of extension + */ + private transient PropertyChangeSupport pcs; + + /** + * Helper class that manages all the veto property change notification machinery. + */ + private transient VetoableChangeSupport vcs; + + /** Creates a new instance of AbstractBean */ + protected AbstractBean() { + pcs = new PropertyChangeSupport(this); + vcs = new VetoableChangeSupport(this); + } + + /** + * Creates a new instance of AbstractBean, using the supplied PropertyChangeSupport and + * VetoableChangeSupport delegates. Neither of these may be null. + */ + protected AbstractBean(PropertyChangeSupport pcs, VetoableChangeSupport vcs) { + if (pcs == null) { + throw new NullPointerException("PropertyChangeSupport must not be null"); + } + if (vcs == null) { + throw new NullPointerException("VetoableChangeSupport must not be null"); + } + + this.pcs = pcs; + this.vcs = vcs; + } + + /** + * Add a PropertyChangeListener to the listener list. + * The listener is registered for all properties. + * The same listener object may be added more than once, and will be called + * as many times as it is added. + * If listener is null, no exception is thrown and no action + * is taken. + * + * @param listener The PropertyChangeListener to be added + */ + public final void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + /** + * Remove a PropertyChangeListener from the listener list. + * This removes a PropertyChangeListener that was registered + * for all properties. + * If listener was added more than once to the same event + * source, it will be notified one less time after being removed. + * If listener is null, or was never added, no exception is + * thrown and no action is taken. + * + * @param listener The PropertyChangeListener to be removed + */ + public final void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + /** + * Returns an array of all the listeners that were added to the + * PropertyChangeSupport object with addPropertyChangeListener(). + *

+ * If some listeners have been added with a named property, then + * the returned array will be a mixture of PropertyChangeListeners + * and PropertyChangeListenerProxys. If the calling + * method is interested in distinguishing the listeners then it must + * test each element to see if it's a + * PropertyChangeListenerProxy, perform the cast, and examine + * the parameter. + * + *

+     * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
+     * for (int i = 0; i < listeners.length; i++) {
+     *   if (listeners[i] instanceof PropertyChangeListenerProxy) {
+     *     PropertyChangeListenerProxy proxy =
+     *                    (PropertyChangeListenerProxy)listeners[i];
+     *     if (proxy.getPropertyName().equals("foo")) {
+     *       // proxy is a PropertyChangeListener which was associated
+     *       // with the property named "foo"
+     *     }
+     *   }
+     * }
+     *
+ * + * @see java.beans.PropertyChangeListenerProxy + * @return all of the PropertyChangeListeners added or an + * empty array if no listeners have been added + */ + public final PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + /** + * Add a PropertyChangeListener for a specific property. The listener + * will be invoked only when a call on firePropertyChange names that + * specific property. + * The same listener object may be added more than once. For each + * property, the listener will be invoked the number of times it was added + * for that property. + * If propertyName or listener is null, no + * exception is thrown and no action is taken. + * + * @param propertyName The name of the property to listen on. + * @param listener The PropertyChangeListener to be added + */ + public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + /** + * Remove a PropertyChangeListener for a specific property. + * If listener was added more than once to the same event + * source for the specified property, it will be notified one less time + * after being removed. + * If propertyName is null, no exception is thrown and no + * action is taken. + * If listener is null, or was never added for the specified + * property, no exception is thrown and no action is taken. + * + * @param propertyName The name of the property that was listened on. + * @param listener The PropertyChangeListener to be removed + */ + public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + /** + * Returns an array of all the listeners which have been associated + * with the named property. + * + * @param propertyName The name of the property being listened to + * @return all of the PropertyChangeListeners associated with + * the named property. If no such listeners have been added, + * or if propertyName is null, an empty array is + * returned. + */ + public final PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + /** + * Report a bound property update to any registered listeners. + * No event is fired if old and new are equal and non-null. + * + *

+ * This is merely a convenience wrapper around the more general + * firePropertyChange method that takes {@code + * PropertyChangeEvent} value. + * + * @param propertyName The programmatic name of the property + * that was changed. + * @param oldValue The old value of the property. + * @param newValue The new value of the property. + */ + protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Fire an existing PropertyChangeEvent to any registered listeners. + * No event is fired if the given event's old and new values are + * equal and non-null. + * @param evt The PropertyChangeEvent object. + */ + protected final void firePropertyChange(PropertyChangeEvent evt) { + pcs.firePropertyChange(evt); + } + + + /** + * Report a bound indexed property update to any registered + * listeners. + *

+ * No event is fired if old and new values are equal + * and non-null. + * + *

+ * This is merely a convenience wrapper around the more general + * firePropertyChange method that takes {@code PropertyChangeEvent} value. + * + * @param propertyName The programmatic name of the property that + * was changed. + * @param index index of the property element that was changed. + * @param oldValue The old value of the property. + * @param newValue The new value of the property. + */ + protected final void fireIndexedPropertyChange(String propertyName, + int index, Object oldValue, Object newValue) { + pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); + } + + /** + * Check if there are any listeners for a specific property, including + * those registered on all properties. If propertyName + * is null, only check for listeners registered on all properties. + * + * @param propertyName the property name. + * @return true if there are one or more listeners for the given property + */ + protected final boolean hasPropertyChangeListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + /** + * Check if there are any listeners for a specific property, including + * those registered on all properties. If propertyName + * is null, only check for listeners registered on all properties. + * + * @param propertyName the property name. + * @return true if there are one or more listeners for the given property + */ + protected final boolean hasVetoableChangeListeners(String propertyName) { + return vcs.hasListeners(propertyName); + } + + /** + * Add a VetoableListener to the listener list. + * The listener is registered for all properties. + * The same listener object may be added more than once, and will be called + * as many times as it is added. + * If listener is null, no exception is thrown and no action + * is taken. + * + * @param listener The VetoableChangeListener to be added + */ + + public final void addVetoableChangeListener(VetoableChangeListener listener) { + vcs.addVetoableChangeListener(listener); + } + + /** + * Remove a VetoableChangeListener from the listener list. + * This removes a VetoableChangeListener that was registered + * for all properties. + * If listener was added more than once to the same event + * source, it will be notified one less time after being removed. + * If listener is null, or was never added, no exception is + * thrown and no action is taken. + * + * @param listener The VetoableChangeListener to be removed + */ + public final void removeVetoableChangeListener(VetoableChangeListener listener) { + vcs.removeVetoableChangeListener(listener); + } + + /** + * Returns the list of VetoableChangeListeners. If named vetoable change listeners + * were added, then VetoableChangeListenerProxy wrappers will returned + *

+ * @return List of VetoableChangeListeners and VetoableChangeListenerProxys + * if named property change listeners were added. + */ + public final VetoableChangeListener[] getVetoableChangeListeners(){ + return vcs.getVetoableChangeListeners(); + } + + /** + * Add a VetoableChangeListener for a specific property. The listener + * will be invoked only when a call on fireVetoableChange names that + * specific property. + * The same listener object may be added more than once. For each + * property, the listener will be invoked the number of times it was added + * for that property. + * If propertyName or listener is null, no + * exception is thrown and no action is taken. + * + * @param propertyName The name of the property to listen on. + * @param listener The VetoableChangeListener to be added + */ + + public final void addVetoableChangeListener(String propertyName, + VetoableChangeListener listener) { + vcs.addVetoableChangeListener(propertyName, listener); + } + + /** + * Remove a VetoableChangeListener for a specific property. + * If listener was added more than once to the same event + * source for the specified property, it will be notified one less time + * after being removed. + * If propertyName is null, no exception is thrown and no + * action is taken. + * If listener is null, or was never added for the specified + * property, no exception is thrown and no action is taken. + * + * @param propertyName The name of the property that was listened on. + * @param listener The VetoableChangeListener to be removed + */ + + public final void removeVetoableChangeListener(String propertyName, + VetoableChangeListener listener) { + vcs.removeVetoableChangeListener(propertyName, listener); + } + + /** + * Returns an array of all the listeners which have been associated + * with the named property. + * + * @param propertyName The name of the property being listened to + * @return all the VetoableChangeListeners associated with + * the named property. If no such listeners have been added, + * or if propertyName is null, an empty array is + * returned. + */ + public final VetoableChangeListener[] getVetoableChangeListeners(String propertyName) { + return vcs.getVetoableChangeListeners(propertyName); + } + + /** + * Report a vetoable property update to any registered listeners. If + * anyone vetos the change, then fire a new event reverting everyone to + * the old value and then rethrow the PropertyVetoException. + *

+ * No event is fired if old and new are equal and non-null. + * + * @param propertyName The programmatic name of the property + * that is about to change.. + * @param oldValue The old value of the property. + * @param newValue The new value of the property. + * @exception PropertyVetoException if the recipient wishes the property + * change to be rolled back. + */ + protected final void fireVetoableChange(String propertyName, + Object oldValue, Object newValue) + throws PropertyVetoException { + vcs.fireVetoableChange(propertyName, oldValue, newValue); + } + + /** + * Fire a vetoable property update to any registered listeners. If + * anyone vetos the change, then fire a new event reverting everyone to + * the old value and then rethrow the PropertyVetoException. + *

+ * No event is fired if old and new are equal and non-null. + * + * @param evt The PropertyChangeEvent to be fired. + * @exception PropertyVetoException if the recipient wishes the property + * change to be rolled back. + */ + protected final void fireVetoableChange(PropertyChangeEvent evt) + throws PropertyVetoException { + vcs.fireVetoableChange(evt); + } + + /** + * @inheritDoc + */ + public Object clone() throws CloneNotSupportedException { + AbstractBean result = (AbstractBean) super.clone(); + result.pcs = new PropertyChangeSupport(result); + result.vcs = new VetoableChangeSupport(result); + return result; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BezierControlPoint.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BezierControlPoint.java new file mode 100644 index 0000000000000000000000000000000000000000..be2bc4efbd9ca675436b1a3d1313ff24a665ecfb --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BezierControlPoint.java @@ -0,0 +1,265 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import java.awt.BasicStroke; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * BezierControlPoint + * + * @author Created by Jasper Potts (May 29, 2007) + */ +public class BezierControlPoint extends ControlPoint { + private HandleControlPoint cp1 = new HandleControlPoint(); + private HandleControlPoint cp2 = new HandleControlPoint(); + private transient boolean makingChange = false; + private transient PropertyChangeListener cpListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { +// if (!makingChange) { +// makingChange = true; +// if (evt.getSource() == cp1) { +// double angle = Math.tan((cp1.getY() - getY())/(cp1.getX() - getX())); +// double cp2len = Math.sqrt( +// Math.pow(cp2.getX() - getX(),2) + +// Math.pow(cp2.getY() - getY(),2) +// ); +// double offsetX = cp2len * Math.sin(angle); +// double offsetY = cp2len * Math.cos(angle); +// cp2.setPosition(getX() - offsetX, getY() - offsetY); +// } else { +// double angle = Math.tan((cp2.getY() - getY())/(cp2.getX() - getX())); +// double cp1len = Math.sqrt( +// Math.pow(cp1.getX() - getX(),2) + +// Math.pow(cp1.getY() - getY(),2) +// ); +// double offsetX = cp1len * Math.sin(angle); +// double offsetY = cp1len * Math.cos(angle); +// cp1.setPosition(getX() - offsetX, getY() - offsetY); +// } +//// if (evt.getSource() == cp1) { +//// double offsetX = cp1.getX() - getX(); +//// double offsetY = cp1.getY() - getY(); +//// cp2.setPosition(getX() - offsetX, getY() - offsetY); +//// } else { +//// double offsetX = cp2.getX() - getX(); +//// double offsetY = cp2.getY() - getY(); +//// cp1.setPosition(getX() - offsetX, getY() - offsetY); +//// } +// makingChange = false; +// firePropertyChange("cp1", null, cp1); +// firePropertyChange("cp2", null, cp1); +// } + firePropertyChange("shape",null,getShape()); + } + }; + + public BezierControlPoint() { + cp1.addPropertyChangeListener(cpListener); + cp2.addPropertyChangeListener(cpListener); + } + + public BezierControlPoint(double x, double y) { + super(x, y); + cp1.addPropertyChangeListener(cpListener); + cp2.addPropertyChangeListener(cpListener); + cp1.setPosition(x, y); + cp2.setPosition(x, y); + } + + public boolean isSharpCorner() { + return + (cp1.getX() == x.getValue()) && + (cp1.getY() == y.getValue()) && + (cp2.getX() == x.getValue()) && + (cp2.getY() == y.getValue()); + } + + public void flip(int width, int height){ + makingChange = true; + if (width > 0){ + x.setValue(width - x.getValue()); + cp1.x.setValue(width - cp1.x.getValue()); + cp2.x.setValue(width - cp2.x.getValue()); + } + if (height > 0){ + y.setValue(height - y.getValue()); + cp1.y.setValue(height - cp1.y.getValue()); + cp2.y.setValue(height - cp2.y.getValue()); + } + makingChange = false; + } + + public void convertToSharpCorner() { + cp1.setPosition(x.getValue(), y.getValue()); + cp2.setPosition(x.getValue(), y.getValue()); + } + + public List getControlPoints() { + if (isSharpCorner()) { + return Collections.emptyList(); + } else { + List points = new ArrayList(); + points.add(cp1); + points.add(cp2); + return points; + } + } + + public HandleControlPoint getCp1() { + return cp1; + } + + public HandleControlPoint getCp2() { + return cp2; + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + g2.setStroke(new BasicStroke((float) pixelSize)); + // paint control line + g2.setColor(GraphicsHelper.BEZIER_CONTROL_LINE); + g2.draw(new Line2D.Double(cp1.getX(), cp1.getY(), getX(), getY())); + g2.draw(new Line2D.Double(getX(), getY(), cp2.getX(), cp2.getY())); + // paint this control point + Shape s; + if (isSharpCorner()) { + double size = pixelSize * 4d; + GeneralPath path = new GeneralPath(); + path.moveTo(getX() - size, getY()); + path.lineTo(getX(), getY() + size); + path.lineTo(getX() + size, getY()); + path.lineTo(getX(), getY() - size); + path.closePath(); + s = path; + } else { + double size = pixelSize * 3d; + s = new Ellipse2D.Double(getX() - size, getY() - size, + size * 2, size * 2); + } + g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_FILL); + g2.fill(s); + g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_LINE); + g2.draw(s); + // paint child control points + if (!isSharpCorner()) { + cp1.paintControls(g2, pixelSize, true); + cp2.paintControls(g2, pixelSize, true); + } + } + + + public void move(double moveX, double moveY, boolean snapPixels) { + makingChange = true; + super.move(moveX, moveY, snapPixels); + cp1.move(moveX, moveY, snapPixels); + cp2.move(moveX, moveY, snapPixels); + makingChange = false; + } + + public double getCp1X() { + return cp1.getX(); + } + + public void setCp1X(double v) { + cp1.setX(v); + } + + public double getCp1Y() { + return cp1.getY(); + } + + public void setCp1Y(double v) { + cp1.setY(v); + } + + public double getCp2X() { + return cp2.getX(); + } + + public void setCp2X(double v) { + cp2.setX(v); + } + + public double getCp2Y() { + return cp2.getY(); + } + + public void setCp2Y(double v) { + cp2.setY(v); + } + + // ================================================================================================================= + // Bezier handle control point + + public class HandleControlPoint extends ControlPoint { + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + if (!isSharp()){ + double size = pixelSize * 3d; + Shape s = new Ellipse2D.Double(getX() - size, getY() - size, + size * 2, size * 2); + g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_FILL); + g2.fill(s); + g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_LINE); + g2.draw(s); + g2.draw(new Rectangle2D.Double(getX() - (pixelSize / 2), getY() - (pixelSize / 2), pixelSize, pixelSize)); + } + } + + public boolean isHit(Point2D p, double pixelSize) { + return !isSharp() && super.isHit(p, pixelSize); + } + + /** + * Is the line controled by this handle in or out of the parent BezierControlPoint sharp. + * + * @return true If this is the exact same point as the parent BezierControlPoint. + */ + public boolean isSharp(){ + return x.getValue() == BezierControlPoint.this.x.getValue() && + y.getValue() == BezierControlPoint.this.y.getValue(); + } + + public void convertToSharp(){ + setPosition(BezierControlPoint.this.x.getValue(),BezierControlPoint.this.y.getValue()); + } + + public BezierControlPoint getParentControlPoint(){ + return BezierControlPoint.this; + } + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BlendingMode.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BlendingMode.java new file mode 100644 index 0000000000000000000000000000000000000000..ade7d08c39e652bad7d238e2b1cf6a4554b0fea9 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BlendingMode.java @@ -0,0 +1,100 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + + +/** + * BlendingMode - Enum of composite blending modes, setup to match photoshop as closely as possible + * + * @author Created by Jasper Potts (May 31, 2007) + */ +public enum BlendingMode { + NORMAL, + // DISSOLVE, missing + // ----------------------------- + DARKEN, + MULTIPLY, + COLOR_BURN, + LINEAR_BURN, // (SUBTRACT) + // ----------------------------- + LIGHTEN, + SCREEN, + COLOR_DODGE, + LINEAR_DODGE, // (ADD) + // ----------------------------- + OVERLAY, + SOFT_LIGHT, + HARD_LIGHT, + VIVID_LIGHT, // (HEAT) is close + LINEAR_LIGHT, // (GLOW) is close + //PIN_LIGHT, missing + //HARD_MIX, missing + // ----------------------------- + DIFFERENCE, + EXCLUSION, + // ----------------------------- + HUE, // nowhere close + SATURATION, + COLOR, + LUMINOSITY, // close but not exact + //LIGHTER_COLOR, missing + //DARKER_COLOR, missing + ; + + + // ================================================================================================================= + // Helper methods for creating Blending Mode Combo Box + + public static final Object[] BLENDING_MODES = new Object[]{ + BlendingMode.NORMAL, + // DISSOLVE, missing + "-", + BlendingMode.DARKEN, + BlendingMode.MULTIPLY, + BlendingMode.COLOR_BURN, + BlendingMode.LINEAR_BURN, // (SUBTRACT) + "-", + BlendingMode.LIGHTEN, + BlendingMode.SCREEN, + BlendingMode.COLOR_DODGE, + BlendingMode.LINEAR_DODGE, // (ADD) + "-", + BlendingMode.OVERLAY, + BlendingMode.SOFT_LIGHT, + BlendingMode.HARD_LIGHT, + BlendingMode.VIVID_LIGHT, // (HEAT) is close + BlendingMode.LINEAR_LIGHT, // (GLOW) is close + //PIN_LIGHT, missing + //HARD_MIX, missing + "-", + BlendingMode.DIFFERENCE, + BlendingMode.EXCLUSION, + "-", + BlendingMode.HUE, // nowhere close + BlendingMode.SATURATION, + BlendingMode.COLOR, + BlendingMode.LUMINOSITY, // close but not exact + }; +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Canvas.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Canvas.java new file mode 100644 index 0000000000000000000000000000000000000000..43f9cc621792a025eab9be8e31714bb2ce18b011 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Canvas.java @@ -0,0 +1,308 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.utils.HasResources; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +import javax.swing.UIDefaults; +import java.awt.AlphaComposite; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * ComponentRegion + * + * @author Created by Jasper Potts (May 22, 2007) + */ +public class Canvas extends AbstractBean implements LayerContainer, HasUIDefaults, HasResources { + private Dimension size; + /** list of all layers in the canvas, the first layer is painted on top */ + private List layers; + private int nextLayerNameIndex = 1; + private BufferedImage buffer; + private boolean isValid = false; + private Insets stretchingInsets = null; + private Layer workingLayer = null; + private PropertyChangeListener layersPropertyChangeListener; + private UIDefaults canvasUIDefaults = null; + private transient File resourcesDir; + private transient File imagesDir; + private transient File templatesDir; + + // ================================================================================================================= + // Constructor + + /** Private constructor for JIBX */ + protected Canvas() { + layersPropertyChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + isValid = false; + // pass on layer change + int index = layers.indexOf((Layer) evt.getSource()); + if (index != -1) { + firePropertyChange("layers[" + index + "]." + evt.getPropertyName(), evt.getOldValue(), + evt.getNewValue()); + } + } + }; + } + + public Canvas(int width, int height) { + this(); + stretchingInsets = new Insets(1, 1, 1, 1); + layers = new ArrayList(); + setSize(new Dimension(width, height)); + addLayer(new Layer()); + } + + // ================================================================================================================= + // JIBX Methods + + /** + * Called by JIBX before all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + private void preSet(IUnmarshallingContext context) { + canvasUIDefaults = (UIDefaults) context.getUserContext(); + } + + // ================================================================================================================= + // Bean Methods + + /** + * Get the UIDefaults for this canvas. The UIDefaults is used to store default pallet of colors, fonts etc. + * + * @return Canvas UIDefaults + */ + public UIDefaults getUiDefaults() { + return canvasUIDefaults; + } + + /** + * Set the UIDefaults for this canvas. The UIDefaults is used to store default pallet of colors, fonts etc. + * + * @param canvasUIDefaults Canvas UIDefaults + */ + public void setUiDefaults(UIDefaults canvasUIDefaults) { + this.canvasUIDefaults = canvasUIDefaults; + } + + /** + * Get the current working layer, is is the layer that new shapes will be drawn into + * + * @return The current working layer, may be null if there is no working layer + */ + public Layer getWorkingLayer() { + return workingLayer; + } + + /** + * Set the current working layer, is is the layer that new shapes will be drawn into + * + * @param workingLayer the new working layer, must be a child of this canvas + */ + public void setWorkingLayer(Layer workingLayer) { + Layer old = getWorkingLayer(); + this.workingLayer = workingLayer; + firePropertyChange("workingLayer", old, getWorkingLayer()); + } + + public int getNextLayerNameIndex() { + return nextLayerNameIndex++; + } + + public Dimension getSize() { + return size; + } + + public void setSize(Dimension size) { + Dimension old = getSize(); + this.size = size; + buffer = new BufferedImage(this.size.width, this.size.height, BufferedImage.TYPE_INT_ARGB); + isValid = false; + firePropertyChange("size", old, getSize()); + } + + + public Insets getStretchingInsets() { + return stretchingInsets; + } + + public void setStretchingInsets(Insets stretchingInsets) { + Insets old = getStretchingInsets(); + this.stretchingInsets = stretchingInsets; + firePropertyChange("stretchingInsets", old, getStretchingInsets()); + } + + public BufferedImage getRenderedImage() { + if (!isValid) { + Graphics2D g2 = buffer.createGraphics(); + // clear + g2.setComposite(AlphaComposite.Clear); + g2.fillRect(0, 0, buffer.getWidth(), buffer.getHeight()); + // paint + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setComposite(AlphaComposite.SrcOver); + for (int i = layers.size() - 1; i >= 0; i--) { + layers.get(i).paint(g2, 1); + } + g2.dispose(); + } + return buffer; + } + + /** + * @return true if this Canvas has not been edited. + *

+ * TODO Currently this is not a bound property, but should be. That is, when the Canvas becomes edited + * (usually due to the Layer having a shape added to it), then a property change event should be fired. + */ + public boolean isBlank() { + return layers.size() == 0 || (layers.size() == 1 && layers.get(0).isEmpty()); + } + + public File getResourcesDir() { + return resourcesDir; + } + + public void setResourcesDir(File resourcesDir) { + File old = getResourcesDir(); + this.resourcesDir = resourcesDir; + firePropertyChange("resourcesDir", old, getResourcesDir()); + } + + public File getImagesDir() { + return imagesDir; + } + + public void setImagesDir(File imagesDir) { + File old = getImagesDir(); + this.imagesDir = imagesDir; + firePropertyChange("imagesDir", old, getImagesDir()); + } + + public File getTemplatesDir() { + return templatesDir; + } + + public void setTemplatesDir(File templatesDir) { + File old = getTemplatesDir(); + this.templatesDir = templatesDir; + firePropertyChange("templatesDir", old, getTemplatesDir()); + } + + // ================================================================================================================= + // LayerContainer Methods + + public LayerContainer getParent() { + // we are root so null + return null; + } + + public void addLayerToBottom(Layer layer) { + layers.add(layer); + layer.setParent(this); + layer.addPropertyChangeListener(layersPropertyChangeListener); + // no single layer changes so fire all changed event + firePropertyChange("layers", null, layers); + } + + public void addLayer(int i, Layer layer) { + layers.add(i, layer); + layer.setParent(this); + layer.addPropertyChangeListener(layersPropertyChangeListener); + // no single layer changes so fire all changed event + firePropertyChange("layers", null, layers); + } + + public void addLayer(Layer layer) { + layers.add(0, layer); + layer.setParent(this); + layer.addPropertyChangeListener(layersPropertyChangeListener); + // no single layer changes so fire all changed event + firePropertyChange("layers", null, layers); + } + + public Layer getLayer(int index) { + return layers.get(index); + } + + public int getLayerCount() { + return layers.size(); + } + + public Iterator getLayerIterator() { + return Collections.unmodifiableList(layers).iterator(); + } + + public Collection getLayers() { + return Collections.unmodifiableList(layers); + } + + public int indexOfLayer(Layer layer) { + return layers.indexOf(layer); + } + + public void removeLayer(Layer layer) { + int index = layers.indexOf(layer); + if (index != -1) { + layers.remove(layer); + layer.removePropertyChangeListener(layersPropertyChangeListener); + fireIndexedPropertyChange("layers", index, layer, null); + } + } + + public Dimension getRootSize() { + return getSize(); + } + + // ================================================================================================================= + // JIBX Helper Methods + + /** Called by JIBX after "layers" has been filled so we can set parents and listeners */ + private void setupLayers() { + for (Layer layer : layers) { + layer.setParent(this); + layer.addPropertyChangeListener(layersPropertyChangeListener); + } + // no single layer changes so fire all changed event + firePropertyChange("layers", null, layers); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/ControlPoint.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/ControlPoint.java new file mode 100644 index 0000000000000000000000000000000000000000..b4d231c5ca9cd3275658b6488c1785036b239ceb --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/ControlPoint.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Collections; +import java.util.List; + +/** + * ControlPoint + * + * @author Created by Jasper Potts (May 24, 2007) + */ +public class ControlPoint extends SimpleShape { + protected Color fillColor; + protected Color lineColor; + protected DoubleBean x, y; + + public ControlPoint() { + this(new DoubleBean(), new DoubleBean()); + } + + public ControlPoint(Color fillColor, Color lineColor) { + this(new DoubleBean(), new DoubleBean(), fillColor, lineColor); + } + + public ControlPoint(double x, double y) { + this(new DoubleBean(x), new DoubleBean(y)); + } + + public ControlPoint(DoubleBean x, DoubleBean y) { + this(x, y, GraphicsHelper.CONTROL_POINT_FILL, GraphicsHelper.CONTROL_POINT_LINE); + } + + public ControlPoint(DoubleBean x, DoubleBean y, Color fillColor, Color lineColor) { + this.x = x; + this.y = y; + this.fillColor = fillColor; + this.lineColor = lineColor; + x.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("position", + new Point2D.Double((Double) evt.getOldValue(), getY()), + getPosition()); + } + }); + y.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("position", + new Point2D.Double(getX(), (Double) evt.getOldValue()), + getPosition()); + } + }); + } + + public double getX() { + return x.getValue(); + } + + public double getY() { + return y.getValue(); + } + + public void setX(double x) { + this.x.setValue(x); + } + + public void setY(double y) { + this.y.setValue(y); + } + + public void setPosition(Point2D position) { + x.setValue(position.getX()); + y.setValue(position.getY()); + } + + public void setPosition(double x, double y) { + setPosition(new Point2D.Double(x, y)); + } + + public Point2D getPosition() { + return new Point2D.Double(getX(), getY()); + } + + public Rectangle2D getBounds(double pixelSize) { + double size = pixelSize * 4d; + return new Rectangle2D.Double(getX() - size, getY() - size, + size * 2, size * 2); + } + + public boolean isHit(Point2D p, double pixelSize) { + return getBounds(pixelSize).contains(p); + } + + + public Shape getShape() { + return getBounds(0); + } + + public void paint(Graphics2D g2, double pixelSize) { + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + g2.setStroke(new BasicStroke((float) pixelSize)); + Shape s = getBounds(pixelSize); + g2.setColor(fillColor); + g2.fill(s); + g2.setColor(lineColor); + g2.draw(s); + } + + public List getControlPoints() { + return Collections.emptyList(); + } + + + public void move(double moveX, double moveY, boolean snapPixels) { + if (snapPixels) { + setPosition( + Math.round(x.getValue() + moveX), + Math.round(y.getValue() + moveY)); + } else { + setPosition(x.getValue() + moveX, y.getValue() + moveY); + } + } + + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Designer.jibx.xml b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Designer.jibx.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f80bcf40989481b45ac56a9a1289f7523d45f8f --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Designer.jibx.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/DoubleBean.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/DoubleBean.java new file mode 100644 index 0000000000000000000000000000000000000000..7297b809bfeb30e4c37c9b55d88df451bef806c5 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/DoubleBean.java @@ -0,0 +1,69 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import org.jdesktop.beans.AbstractBean; + +/** + * DoubleBean - Simple bean for a observable double value + * + * @author Created by Jasper Potts (May 25, 2007) + */ +public class DoubleBean extends AbstractBean { + private double value = 0; + + public DoubleBean() {} + + public DoubleBean(double value) { + this.value = value; + } + + public double getValue() { + return value; + } + + public void setValue(double value) { + double old = this.value; + this.value = value; + firePropertyChange("value", old, this.value); + } + + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DoubleBean that = (DoubleBean) o; + + if (Double.compare(that.value, value) != 0) return false; + + return true; + } + + public int hashCode() { + long temp = value != +0.0d ? Double.doubleToLongBits(value) : 0L; + return (int) (temp ^ (temp >>> 32)); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/EllipseShape.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/EllipseShape.java new file mode 100644 index 0000000000000000000000000000000000000000..e0d12371697166ee8a45fa4cb362dd70a4da69f3 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/EllipseShape.java @@ -0,0 +1,189 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +/** + * EllipseShape + * + * @author Created by Jasper Potts (May 22, 2007) + */ +public class EllipseShape extends PaintedShape { + + private DoubleBean x1 = new DoubleBean(); + private DoubleBean x2 = new DoubleBean(); + private DoubleBean y1 = new DoubleBean(); + private DoubleBean y2 = new DoubleBean(); + private ControlPoint tl = new ControlPoint(x1, y1); + private ControlPoint tr = new ControlPoint(x2, y1); + private ControlPoint bl = new ControlPoint(x1, y2); + private ControlPoint br = new ControlPoint(x2, y2); + + // ================================================================================================================= + // Constructors + + /** private noargs constructor for JIBX */ + private EllipseShape() { + this(null); + } + + public EllipseShape(UIDefaults canvasUiDefaults) { + super(canvasUiDefaults); + PropertyChangeListener listener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("bounds", null, getBounds(0)); + } + }; + x1.addPropertyChangeListener(listener); + y1.addPropertyChangeListener(listener); + x2.addPropertyChangeListener(listener); + y2.addPropertyChangeListener(listener); + } + + public EllipseShape(double x, double y, double w, double h) { + this(); + x1.setValue(x); + y1.setValue(y); + x2.setValue(x + w); + y2.setValue(y + h); + } + + public Rectangle2D getBounds(double pixelSize) { + double left = Math.min(x1.getValue(), x2.getValue()); + double right = Math.max(x1.getValue(), x2.getValue()); + double top = Math.min(y1.getValue(), y2.getValue()); + double bottom = Math.max(y1.getValue(), y2.getValue()); + return new Rectangle2D.Double(left, top, right - left, bottom - top); + } + + public Ellipse2D getShape() { + double left = Math.min(x1.getValue(), x2.getValue()); + double right = Math.max(x1.getValue(), x2.getValue()); + double top = Math.min(y1.getValue(), y2.getValue()); + double bottom = Math.max(y1.getValue(), y2.getValue()); + return new Ellipse2D.Double(left, top, right - left, bottom - top); + } + + public boolean isHit(Point2D p, double pixelSize) { + return getBounds(pixelSize).contains(p); + } + + public void paint(Graphics2D g2, double pixelSize) { + g2.setPaint(getPaint()); + g2.fill(getShape()); + } + + public void setFrame(double x1, double y1, double x2, double y2) { + this.x1.setValue(x1); + this.y1.setValue(y1); + this.x2.setValue(x2); + this.y2.setValue(y2); + } + + @Override + public String toString() { + Rectangle2D bounds = getBounds(0); + return "ELLIPSE { x=" + bounds.getX() + ", y=" + bounds.getY() + ", w=" + bounds.getWidth() + ", h=" + bounds.getHeight() + " }"; + } + + public List getControlPoints() { + List points = new ArrayList(); + points.addAll(super.getControlPoints()); + points.add(tl); + points.add(tr); + points.add(bl); + points.add(br); + return points; + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + if (paintControlLines) { + g2.setStroke(new BasicStroke((float) pixelSize)); + g2.setColor(GraphicsHelper.CONTROL_LINE); + g2.draw(getShape()); + } + tl.paintControls(g2, pixelSize, true); + tr.paintControls(g2, pixelSize, true); + bl.paintControls(g2, pixelSize, true); + br.paintControls(g2, pixelSize, true); +// super.paintControls(g2, pixelSize, paintControlLines); + } + + public void move(double moveX, double moveY, boolean snapPixels) { + if (snapPixels) { + x1.setValue(Math.round(x1.getValue() + moveX)); + x2.setValue(Math.round(x2.getValue() + moveX)); + y1.setValue(Math.round(y1.getValue() + moveY)); + y2.setValue(Math.round(y2.getValue() + moveY)); + } else { + x1.setValue(x1.getValue() + moveX); + x2.setValue(x2.getValue() + moveX); + y1.setValue(y1.getValue() + moveY); + y2.setValue(y2.getValue() + moveY); + } + } + + public double getX1() { + return x1.getValue(); + } + + public void setX1(double x1) { + this.x1.setValue(x1); + } + + public double getX2() { + return x2.getValue(); + } + + public void setX2(double x2) { + this.x2.setValue(x2); + } + + public double getY1() { + return y1.getValue(); + } + + public void setY1(double y1) { + this.y1.setValue(y1); + } + + public double getY2() { + return y2.getValue(); + } + + public void setY2(double y2) { + this.y2.setValue(y2); + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/GraphicsHelper.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/GraphicsHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..519c42e94e50052a060ed205cb5112f993890d3f --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/GraphicsHelper.java @@ -0,0 +1,45 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import java.awt.Color; + +/** + * GraphicsHelper + * + * @author Created by Jasper Potts (May 29, 2007) + */ +public class GraphicsHelper { + public static final Color FILL_LINE = Color.BLUE; + public static final Color FILL_CP_LINE = Color.BLUE; + public static final Color FILL_CP_FILL = Color.WHITE; + public static final Color CONTROL_LINE = Color.RED; + public static final Color CONTROL_POINT_LINE = Color.RED; + public static final Color CONTROL_POINT_FILL = Color.WHITE; + public static final Color BEZIER_CONTROL_POINT_LINE = CONTROL_POINT_LINE; + public static final Color BEZIER_CONTROL_POINT_FILL = CONTROL_POINT_FILL; + public static final Color BEZIER_CONTROL_LINE = Color.DARK_GRAY; + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Layer.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Layer.java new file mode 100644 index 0000000000000000000000000000000000000000..3b112ae93fb1302a96149dddd1fd6659f36115bc --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Layer.java @@ -0,0 +1,443 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import org.jdesktop.swingx.designer.effects.Effect; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Layer + * + * @author Created by Jasper Potts (May 22, 2007) + */ +public class Layer extends SimpleShape implements Iterable, LayerContainer { + public static enum LayerType { + standard, template + } + + private String name; + protected LayerType type = LayerType.standard; + /** List of shapes in this layer, first shape is painted on top */ + private List shapes = new ArrayList(); + private List effects = new ArrayList(); + private double opacity = 1; + private double fillOpacity = 1; + private BlendingMode blendingMode = BlendingMode.NORMAL; + private boolean locked = false; + private boolean visible = true; + private PropertyChangeListener shapeChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + int index = shapes.indexOf((SimpleShape) evt.getSource()); + firePropertyChange("shapes[" + index + "]." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + private PropertyChangeListener effectChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + int index = effects.indexOf((Effect) evt.getSource()); + System.out.println( + "Layer.propertyChange EFFECT PROPERTY CHANGED " + evt.getSource() + " -- " + evt.getPropertyName()); + firePropertyChange("effects[" + index + "]." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + private BufferedImage buffer = null; + // ================================================================================================================= + // Constructors + + public Layer() { + } + + public Layer(String name) { + this(); + this.name = name; + } + + /** Called by JIBX after populating this layer so we can add listeners to children */ + protected void postInit() { + for (SimpleShape shape : shapes) { + shape.addPropertyChangeListener(shapeChangeListener); + shape.setParent(this); + } + for (Effect effect : effects) { + effect.addPropertyChangeListener(effectChangeListener); + } + } + + // ================================================================================================================= + // Bean Methods + + public LayerType getType() { + return type; + } + + public boolean isLocked() { + return locked; + } + + public void setLocked(boolean locked) { + boolean old = isLocked(); + this.locked = locked; + firePropertyChange("locked", old, isLocked()); + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + boolean old = isVisible(); + this.visible = visible; + firePropertyChange("visible", old, isVisible()); + } + + public String getName() { + return name; + } + + public void setName(String name) { + String old = getName(); + this.name = name; + firePropertyChange("name", old, getName()); + } + + public void setParent(LayerContainer parent) { + super.setParent(parent); + // generate a name if null + if (name == null) { + Canvas c = null; + LayerContainer p = parent; + while (true) { + if (p instanceof Canvas) { + c = (Canvas) p; + break; + } else if (p == null) { + break; + } + p = p.getParent(); + } + if (c != null) { + setName("Layer " + c.getNextLayerNameIndex()); + } + } + } + + /** + * Add shape to top of layer so it paints above all other shapes + * + * @param shape The shape to add + */ + public void add(SimpleShape shape) { + shapes.add(0, shape); + shape.setParent(this); + shape.addPropertyChangeListener(shapeChangeListener); + fireIndexedPropertyChange("shapes", 0, null, shape); + } + + public void remove(SimpleShape shape) { + int index = shapes.indexOf(shape); + if (index != -1) { + shapes.remove(shape); + shape.setParent(null); + fireIndexedPropertyChange("shapes", index, shape, null); + } + } + + /** + * Returns an unmodifianle iterator over a set of elements of type SimpleShape. + * + * @return an Iterator. + */ + public Iterator iterator() { + return Collections.unmodifiableList(shapes).iterator(); + } + + + public List getEffects() { + return Collections.unmodifiableList(effects); + } + + public void addEffect(Effect effect) { + int index = effects.size(); + effects.add(effect); + effect.addPropertyChangeListener(effectChangeListener); + fireIndexedPropertyChange("effects", index, null, effects); + } + + public void removeEffect(Effect effect) { + int index = effects.indexOf(effect); + if (index != -1) { + effects.remove(effect); + effect.removePropertyChangeListener(effectChangeListener); + fireIndexedPropertyChange("effects", index, effect, null); + } + } + + public double getOpacity() { + return opacity; + } + + public void setOpacity(double opacity) { + if (opacity < 0 || opacity > 1) return; + double old = getOpacity(); + this.opacity = opacity; + firePropertyChange("opacity", old, getOpacity()); + } + + public double getFillOpacity() { + return fillOpacity; + } + + public void setFillOpacity(double fillOpacity) { + if (fillOpacity < 0 || fillOpacity > 1) return; + double old = getFillOpacity(); + this.fillOpacity = fillOpacity; + firePropertyChange("fillOpacity", old, getFillOpacity()); + } + + public BlendingMode getBlendingMode() { + return blendingMode; + } + + public void setBlendingMode(BlendingMode blendingMode) { + BlendingMode old = getBlendingMode(); + this.blendingMode = blendingMode; + firePropertyChange("blendingMode", old, getBlendingMode()); + } + + // ================================================================================================================= + // Layer Methods + + /** + * Get the parent canvas that contains this layer + * + * @return Parant canvas, or null if the layer is not in a canvas + */ + public Canvas getCanvas() { + LayerContainer lc = this; + while (lc != null) { + if (lc instanceof Canvas) return (Canvas) lc; + lc = lc.getParent(); + } + return null; + } + + public List getShapes() { + return new ArrayList(shapes); + } + + public List getIntersectingShapes(Point2D p, double pixelSize) { + if (isLocked() || !isVisible()) return Collections.emptyList(); + List intersectingShapes = new ArrayList(); + for (SimpleShape shape : shapes) { + if (shape instanceof Layer) { + intersectingShapes.addAll(((Layer) shape).getIntersectingShapes(p, pixelSize)); + } else { + if (shape.isHit(p, pixelSize)) intersectingShapes.add(shape); + } + } + return intersectingShapes; + } + + public List getIntersectingShapes(Rectangle2D rect, double pixelSize) { + if (isLocked() || !isVisible()) return Collections.emptyList(); + List intersectingShapes = new ArrayList(); + for (SimpleShape shape : shapes) { + if (shape instanceof Layer) { + intersectingShapes.addAll(((Layer) shape).getIntersectingShapes(rect, pixelSize)); + } else { + if (shape.intersects(rect, pixelSize)) intersectingShapes.add(shape); + } + } + return intersectingShapes; + + } + + public boolean isEmpty() { + return shapes.isEmpty(); + } + + // ================================================================================================================= + // SimpleShape Methods + + public Rectangle2D getBounds(double pixelSize) { + Rectangle2D.Double rect = new Rectangle2D.Double(); + for (SimpleShape shape : shapes) { + rect.add(shape.getBounds(pixelSize)); + } + return rect; + } + + + public Shape getShape() { + return getBounds(0); + } + + public boolean isHit(Point2D p, double pixelSize) { + if (isLocked() || !isVisible()) return false; + for (SimpleShape shape : shapes) { + if (shape.isHit(p, pixelSize)) return true; + } + return false; + } + + public boolean intersects(Rectangle2D rect, double pixelSize) { + if (isLocked() || !isVisible()) return false; + for (SimpleShape shape : shapes) { + if (shape.intersects(rect, pixelSize)) return true; + } + return false; + } + + public List getControlPoints() { + return Collections.emptyList(); + } + + public void paint(Graphics2D g2, double pixelSize) { + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + + } + + public String toString() { + return getName(); + } + + // ================================================================================================================= + // LayerContainer Methods + + public void addLayer(int i, Layer layer) { + // get existing layer at index i + Layer existingLayer = getLayer(i); + if (existingLayer == null) { + addLayer(layer); + } else { + int index = indexOfLayer(existingLayer); + shapes.add(index, layer); + layer.setParent(this); + layer.addPropertyChangeListener(shapeChangeListener); + fireIndexedPropertyChange("layers", index, null, layer); + } + } + + public void addLayer(Layer layer) { + shapes.add(layer); + layer.setParent(this); + layer.addPropertyChangeListener(shapeChangeListener); + int index = indexOfLayer(layer); + fireIndexedPropertyChange("layers", index, null, layer); + } + + public Layer getLayer(int index) { + int i = -1; + for (SimpleShape shape : shapes) { + if (shape instanceof Layer) i++; + if (i == index) return (Layer) shape; + } + return null; + } + + public int getLayerCount() { + int count = 0; + for (SimpleShape shape : shapes) { + if (shape instanceof Layer) count++; + } + return count; + } + + + public Collection getLayers() { + List layers = new ArrayList(); + for (SimpleShape shape : shapes) { + if (shape instanceof Layer) layers.add((Layer) shape); + } + return Collections.unmodifiableList(layers); + } + + public Iterator getLayerIterator() { + return new Iterator() { + private int index = 0; + + public boolean hasNext() { + for (int i = index; i < shapes.size(); i++) { + if (shapes.get(i) instanceof Layer) { + return true; + } + } + return false; + } + + public Layer next() { + for (; index < shapes.size(); index++) { + if (shapes.get(index) instanceof Layer) { + Layer nextLayer = (Layer) shapes.get(index); + index++; // increment index so we don't find the same one again + return nextLayer; + } + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public int indexOfLayer(Layer layer) { + int i = -1; + for (SimpleShape s : shapes) { + if (s instanceof Layer) i++; + if (s == layer) return i; + } + return -1; + } + + public void removeLayer(Layer layer) { + int index = indexOfLayer(layer); + if (index != -1) { + shapes.remove(layer); + layer.removePropertyChangeListener(shapeChangeListener); + fireIndexedPropertyChange("layers", index, layer, null); + } + } + + + public Dimension getRootSize() { + return getParent().getRootSize(); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/LayerContainer.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/LayerContainer.java new file mode 100644 index 0000000000000000000000000000000000000000..b5af519cc39da8a9b9549699e977192f7038c089 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/LayerContainer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import java.awt.Dimension; +import java.beans.PropertyChangeListener; +import java.util.Collection; +import java.util.Iterator; + +/** + * LayerContainer + * + * @author Created by Jasper Potts (May 31, 2007) + */ +public interface LayerContainer { + public void addPropertyChangeListener(PropertyChangeListener listener); + + public void removePropertyChangeListener(PropertyChangeListener listener); + + public LayerContainer getParent(); + + public void addLayer(Layer layer); + + public void addLayer(int i, Layer layer); + + public void removeLayer(Layer layer); + + public int getLayerCount(); + + public Layer getLayer(int index); + + public int indexOfLayer(Layer layer); + + public Iterator getLayerIterator(); + + public Collection getLayers(); + + /** + * Get the size in pixels of the root of the layer tree, this is usualy a canvas + * + * @return The size of the whole layer tree + */ + public Dimension getRootSize(); + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PaintedShape.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PaintedShape.java new file mode 100644 index 0000000000000000000000000000000000000000..2d6d3cbf5996dd085674588da8784cf5b0cd8965 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PaintedShape.java @@ -0,0 +1,289 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import org.jdesktop.swingx.designer.paint.Matte; +import org.jdesktop.swingx.designer.paint.PaintModel; + +import javax.swing.UIDefaults; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; +import java.awt.Paint; +import java.awt.RadialGradientPaint; +import java.awt.Shape; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * PaintedShape + * + * @author Created by Jasper Potts (May 22, 2007) + */ +public abstract class PaintedShape extends SimpleShape { + + private PaintModel paint; + // control points for paint control types + private DoubleBean px1 = new DoubleBean(0.25); + private DoubleBean px2 = new DoubleBean(0.75); + private DoubleBean py1 = new DoubleBean(0); + private DoubleBean py2 = new DoubleBean(1); + private ControlPoint ptl = new PaintControlPoint(px1, py1); + private ControlPoint ptr = new PaintControlPoint(px2, py1); + private ControlPoint pbl = new PaintControlPoint(px1, py2); + private ControlPoint pbr = new PaintControlPoint(px2, py2); + private PropertyChangeListener paintListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("paint." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + + protected PaintedShape() { + px1.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("x1", evt.getOldValue(), evt.getNewValue()); + } + }); + py1.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("y1", evt.getOldValue(), evt.getNewValue()); + } + }); + px2.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("x2", evt.getOldValue(), evt.getNewValue()); + } + }); + py2.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("y2", evt.getOldValue(), evt.getNewValue()); + } + }); + } + + protected PaintedShape(UIDefaults canvasUiDefaults) { + this(); + setPaintModel(new Matte(Color.ORANGE, canvasUiDefaults)); + } + + public PaintModel getPaintModel() { + return paint; + } + + public void setPaintModel(PaintModel paint) { + PaintModel old = getPaintModel(); + if (old != null) old.removePropertyChangeListener(paintListener); + this.paint = paint; + this.paint.addPropertyChangeListener(paintListener); + firePropertyChange("paintModel", old, getPaintModel()); + } + + public Paint getPaint() { + Paint p = getPaintModel().getPaint(); + if (p instanceof Color) { + return p; + } + //resize p as necessary to fit the bounds of this PaintedShape + Rectangle2D bounds = getBounds(0); + if (p instanceof LinearGradientPaint) { + LinearGradientPaint lgp = (LinearGradientPaint) p; + return new LinearGradientPaint( + convertLocalPoint(ptl.getPosition(), bounds), + convertLocalPoint(pbr.getPosition(), bounds), + lgp.getFractions(), + lgp.getColors()); + } else if (p instanceof RadialGradientPaint) { + RadialGradientPaint rgp = (RadialGradientPaint) p; + Point2D outer = convertLocalPoint(ptl.getPosition(), bounds); + Point2D center = convertLocalPoint(pbr.getPosition(), bounds); + double deltaX = Math.abs(center.getX() - outer.getX()); + double deltaY = Math.abs(center.getY() - outer.getY()); + float radius = (float) Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)); + return new RadialGradientPaint( + center, + radius, + rgp.getFractions(), + rgp.getColors()); + } else { + return p; + } + } + + public List getControlPoints() { + switch (paint.getPaintControlType()) { + case control_line: + return Arrays.asList(ptl, pbr); + case control_rect: + return Arrays.asList(ptl, ptr, pbl, pbr); + default: + return Collections.emptyList(); + } + } + + public void paintFillControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + switch (paint.getPaintControlType()) { + case control_line: + Point2D p1 = convertLocalPoint(ptl.getPosition(), PaintedShape.this.getBounds(0)); + Point2D p2 = convertLocalPoint(pbr.getPosition(), PaintedShape.this.getBounds(0)); + g2.setStroke(new BasicStroke((float) pixelSize)); + g2.setColor(GraphicsHelper.FILL_LINE); + g2.draw(new Line2D.Double(p1.getX(), p1.getY(), p2.getX(), p2.getY())); + ptl.paintControls(g2, pixelSize, true); + pbr.paintControls(g2, pixelSize, true); + break; + case control_rect: + g2.setStroke(new BasicStroke((float) pixelSize)); + g2.setColor(GraphicsHelper.FILL_LINE); + g2.draw(new Rectangle2D.Double( + px1.getValue(), + py1.getValue(), + px2.getValue() - px1.getValue(), + py2.getValue() - py1.getValue())); + ptl.paintControls(g2, pixelSize, true); + ptr.paintControls(g2, pixelSize, true); + pbl.paintControls(g2, pixelSize, true); + pbr.paintControls(g2, pixelSize, true); + break; + } + } + + public void move(double moveX, double moveY, boolean snapPixels) { + for (ControlPoint controlPoint : getControlPoints()) { + if (!(controlPoint instanceof PaintControlPoint)) controlPoint.move(moveX, moveY, snapPixels); + } + } + + public double getPaintX1() { + return px1.getValue(); + } + + public void setPaintX1(double x1) { + this.px1.setValue(x1); + } + + public double getPaintX2() { + return px2.getValue(); + } + + public void setPaintX2(double x2) { + this.px2.setValue(x2); + } + + public double getPaintY1() { + return py1.getValue(); + } + + public void setPaintY1(double y1) { + this.py1.setValue(y1); + } + + public double getPaintY2() { + return py2.getValue(); + } + + public void setPaintY2(double y2) { + this.py2.setValue(y2); + } + + // ================================================================================================================= + // Private helper methods + + private Point2D convertLocalPoint(Point2D point, Rectangle2D bounds) { + point.setLocation( + bounds.getX() + (point.getX() * bounds.getWidth()), + bounds.getY() + (point.getY() * bounds.getHeight()) + ); + return point; + } + + private Point2D convertScreenPoint(Point2D point, Rectangle2D bounds) { + return new Point2D.Double( + (point.getX() - bounds.getX()) / bounds.getWidth(), + (point.getY() - bounds.getY()) / bounds.getHeight() + ); + } + + // ================================================================================================================= + // Gradient ControlPoint + + /** + * A Special ControlPoint thats internal values are in coordinates relative to the shapes bounds. With 0,0 being the + * top left of the shape and 1.0X == shape width and 1.0Y == shapes height. + */ + public class PaintControlPoint extends ControlPoint { + public PaintControlPoint() { + super(GraphicsHelper.FILL_CP_FILL, GraphicsHelper.FILL_CP_LINE); + } + + public PaintControlPoint(DoubleBean x, DoubleBean y) { + super(x, y, GraphicsHelper.FILL_CP_FILL, GraphicsHelper.FILL_CP_LINE); + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + Point2D p = convertLocalPoint(getPosition(), PaintedShape.this.getBounds(0)); + g2.setStroke(new BasicStroke((float) pixelSize)); + double size = pixelSize * 4d; + Shape s = new Ellipse2D.Double(p.getX() - size, p.getY() - size, + size * 2, size * 2); + g2.setPaint(new GradientPaint( + (float) p.getX(), (float) (p.getY() - size), Color.CYAN, + (float) p.getX(), (float) (p.getY() + size), Color.WHITE + )); + g2.fill(s); + g2.setColor(GraphicsHelper.FILL_CP_LINE); + g2.draw(s); + } + + public void move(double moveX, double moveY, boolean snapPixels) { + Rectangle2D bounds = PaintedShape.this.getBounds(0); + moveX = moveX / bounds.getWidth(); + moveY = moveY / bounds.getHeight(); + if (snapPixels) { + // snap to neareast 0.5 + double newX = Math.round((x.getValue() + moveX) * 2d) / 2d; + double newY = Math.round((y.getValue() + moveY) * 2d) / 2d; + setPosition(newX, newY); + } else { + setPosition(x.getValue() + moveX, y.getValue() + moveY); + } + } + + public Rectangle2D getBounds(double pixelSize) { + Point2D p = convertLocalPoint(getPosition(), PaintedShape.this.getBounds(0)); + double size = pixelSize * 4d; + return new Rectangle2D.Double(p.getX() - size, p.getY() - size, + size * 2, size * 2); + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PathShape.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PathShape.java new file mode 100644 index 0000000000000000000000000000000000000000..969972643636b4e4f41301b1692a89cd8c82056c --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PathShape.java @@ -0,0 +1,194 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +/** + * PathShape + * + * @author Created by Jasper Potts (May 29, 2007) + */ +public class PathShape extends PaintedShape { + + private Shape cachedShape = null; + private List controlPoints = new ArrayList(); + private PropertyChangeListener cpListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + rebuildShape(); + } + }; + + // ================================================================================================================= + // Constructors + + /** private noargs constructor for JIBX */ + private PathShape() { + this(null); + } + + public PathShape(UIDefaults canvasUiDefaults) { + super(canvasUiDefaults); + } + + public BezierControlPoint addPoint(double x, double y) { + BezierControlPoint cp = new BezierControlPoint(x, y); + controlPoints.add(cp); + cp.addPropertyChangeListener(cpListener); + // update shape + rebuildShape(); + // return new control point + return cp; + } + + public Shape getShape() { + if (cachedShape == null) { + rebuildShape(); + } + return cachedShape; + } + + private void rebuildShape() { + GeneralPath path = new GeneralPath(); + BezierControlPoint first, last; + first = last = controlPoints.get(0); + path.moveTo((float) first.getX(), (float) first.getY()); + for (int i = 0; i < controlPoints.size(); i++) { + BezierControlPoint controlPoint = controlPoints.get(i); + if (last.getCp2().isSharp() && controlPoint.getCp1().isSharp()) { + path.lineTo(controlPoint.getX(), controlPoint.getY()); + } else { + path.curveTo( + (float) last.getCp2().getX(), (float) last.getCp2().getY(), + (float) controlPoint.getCp1().getX(), (float) controlPoint.getCp1().getY(), + (float) controlPoint.getX(), (float) controlPoint.getY() + ); + } + last = controlPoint; + } + // close path + if (last.getCp2().isSharp() && first.getCp1().isSharp()) { + path.lineTo(first.getX(), first.getY()); + } else { + path.curveTo( + (float) last.getCp2().getX(), (float) last.getCp2().getY(), + (float) first.getCp1().getX(), (float) first.getCp1().getY(), + (float) first.getX(), (float) first.getY() + ); + } + path.closePath(); + // fire change + cachedShape = path; + firePropertyChange("shape", null, cachedShape); + } + + @Override + public String toString() { + String p = "PATH {\n"; + BezierControlPoint first, last; + first = last = controlPoints.get(0); + p += " path.moveTo(" + first.getX() + "," + first.getY() + ");"; + for (int i = 0; i < controlPoints.size(); i++) { + BezierControlPoint controlPoint = controlPoints.get(i); + p += " path.curveTo(" + + (float) last.getCp2().getX() + "," + (float) last.getCp2().getY() + "," + + (float) controlPoint.getCp1().getX() + "," + (float) controlPoint.getCp1().getY() + "," + + (float) controlPoint.getX() + "," + (float) controlPoint.getY() + + ");\n"; + last = controlPoint; + } + // close path + p += " path.curveTo(" + + (float) last.getCp2().getX() + "," + (float) last.getCp2().getY() + "," + + (float) first.getCp1().getX() + "," + (float) first.getCp1().getY() + "," + + (float) first.getX() + "," + (float) first.getY() + + ");\n"; + p += "}\n"; + return p; + } + + // ================================================================================================================= + // Shape Methods + + public Rectangle2D getBounds(double pixelSize) { + return getShape().getBounds2D(); + } + + public List getControlPoints() { + List pts = new ArrayList(); + for (BezierControlPoint controlPoint : controlPoints) { + pts.add(controlPoint); + } + for (ControlPoint controlPoint : super.getControlPoints()) { + pts.add(controlPoint); + } + return pts; + } + + public void setControlPoints(List controlPoints) { + List old = this.controlPoints; + for (BezierControlPoint cp : old) { + cp.removePropertyChangeListener(cpListener); + } + this.controlPoints = controlPoints; + for (BezierControlPoint cp : this.controlPoints) { + cp.addPropertyChangeListener(cpListener); + } + // update shape + rebuildShape(); + } + + public boolean isHit(Point2D p, double pixelSize) { + return getShape().contains(p); + } + + public void paint(Graphics2D g2, double pixelSize) { + g2.setPaint(getPaint()); + g2.fill(getShape()); + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + if (paintControlLines) { + g2.setStroke(new BasicStroke((float) pixelSize)); + g2.setColor(GraphicsHelper.CONTROL_LINE); + g2.draw(getShape()); + } + for (BezierControlPoint controlPoint : controlPoints) { + if (!controlPoint.isSharpCorner()) controlPoint.paintControls(g2, pixelSize, true); + } + } + + public List getBezierControlPoints() { + return controlPoints; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/RectangleShape.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/RectangleShape.java new file mode 100644 index 0000000000000000000000000000000000000000..d93ef3f1ef5849749c9b816a98179dc5a0cf78d6 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/RectangleShape.java @@ -0,0 +1,266 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +/** + * RectangleShape + * + * @author Created by Jasper Potts (May 22, 2007) + */ +public class RectangleShape extends PaintedShape { + + private DoubleBean x1 = new DoubleBean(); + private DoubleBean x2 = new DoubleBean(); + private DoubleBean y1 = new DoubleBean(); + private DoubleBean y2 = new DoubleBean(); + private ControlPoint tl = new ControlPoint(x1, y1); + private ControlPoint tr = new ControlPoint(x2, y1); + private ControlPoint bl = new ControlPoint(x1, y2); + private ControlPoint br = new ControlPoint(x2, y2); + private DoubleBean roundingX = new DoubleBean() { + public void setValue(double value) { + // contrain y = y1 and x is between x1+1 and (x2-x1)/2 + boolean x1isLess = x1.getValue() < x2.getValue(); + double min = x1isLess ? x1.getValue() + 1 : x1.getValue() - 1; + double max = x1isLess ? x1.getValue() + ((x2.getValue() - x1.getValue()) / 2) : + x2.getValue() + ((x1.getValue() - x2.getValue()) / 2); + double newX = value; + if (newX < min) newX = min; + if (newX > max) newX = max; + super.setValue(newX); + } + }; + private ControlPoint rounding = new ControlPoint(roundingX, y1) { + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + double size = pixelSize * 3d; + Shape s = new Ellipse2D.Double(getX() - size, getY() - size, + size * 2, size * 2); + g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_FILL); + g2.fill(s); + g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_LINE); + g2.draw(s); + } + + public void setPosition(Point2D position) { + // only alow X to change + x.setValue(position.getX()); + } + + }; + + // ================================================================================================================= + // Constructors + + /** private noargs constructor for JIBX */ + private RectangleShape() { + this(null); + } + + public RectangleShape(UIDefaults canvasUiDefaults) { + super(canvasUiDefaults); + x1.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + // keep rounding point in sync + roundingX.setValue(roundingX.getValue() + + ((Double) evt.getNewValue() - (Double) evt.getOldValue())); + firePropertyChange("bounds", null, getBounds(0)); + } + }); + x2.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + // keep rounding point in sync + double distanceFromX1 = Math.abs(roundingX.getValue() - x1.getValue()); + roundingX.setValue( + (x1.getValue() < x2.getValue()) ? x1.getValue() + distanceFromX1 : + x1.getValue() - distanceFromX1 + ); + firePropertyChange("bounds", null, getBounds(0)); + } + }); + PropertyChangeListener listener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("bounds", null, getBounds(0)); + } + }; + y1.addPropertyChangeListener(listener); + y2.addPropertyChangeListener(listener); + rounding.addPropertyChangeListener(listener); + } + + public RectangleShape(double x, double y, double w, double h) { + this(); + x1.setValue(x); + y1.setValue(y); + x2.setValue(x + w); + y2.setValue(y + h); + } + + public Shape getShape() { + double rounding = getRounding(); + double left = Math.min(x1.getValue(), x2.getValue()); + double right = Math.max(x1.getValue(), x2.getValue()); + double top = Math.min(y1.getValue(), y2.getValue()); + double bottom = Math.max(y1.getValue(), y2.getValue()); + if (rounding > 0) { + return new RoundRectangle2D.Double( + left, top, right - left, bottom - top, rounding, rounding + ); + } else { + return new Rectangle2D.Double(left, top, right - left, bottom - top); + } + } + + public double getRounding() { + double rounding = Math.abs(roundingX.getValue() - x1.getValue()) * 2; + return rounding > 2 ? rounding : 0; + } + + public void setRounding(double rounding) { + if (rounding > 0 && rounding < 2) rounding = 0; + roundingX.setValue((rounding / 2d) + x1.getValue()); + } + + public boolean isRounded() { + return getRounding() > 0; + } + + public double getX1() { + return x1.getValue(); + } + + public void setX1(double x1) { + this.x1.setValue(x1); + } + + public double getX2() { + return x2.getValue(); + } + + public void setX2(double x2) { + this.x2.setValue(x2); + } + + public double getY1() { + return y1.getValue(); + } + + public void setY1(double y1) { + this.y1.setValue(y1); + } + + public double getY2() { + return y2.getValue(); + } + + public void setY2(double y2) { + this.y2.setValue(y2); + } + + // ================================================================================================================= + // SimpleShape Methods + + public Rectangle2D getBounds(double pixelSize) { + double left = Math.min(x1.getValue(), x2.getValue()); + double right = Math.max(x1.getValue(), x2.getValue()); + double top = Math.min(y1.getValue(), y2.getValue()); + double bottom = Math.max(y1.getValue(), y2.getValue()); + return new Rectangle2D.Double(left, top, right - left, bottom - top); + } + + public boolean isHit(Point2D p, double pixelSize) { + return getShape().contains(p); + } + + public void paint(Graphics2D g2, double pixelSize) { + g2.setPaint(getPaint()); + g2.fill(getShape()); + } + + public void setFrame(double x1, double y1, double x2, double y2) { + this.x1.setValue(x1); + this.y1.setValue(y1); + this.x2.setValue(x2); + this.y2.setValue(y2); + } + + @Override + public String toString() { + Rectangle2D bounds = getBounds(0); + if (isRounded()) { + return "ROUND RECT { x=" + bounds.getX() + ", y=" + bounds.getY() + ", w=" + bounds.getWidth() + ", h=" + bounds.getHeight() + ", rounding=" + getRounding() + " }"; + } else { + return "ROUND RECT { x=" + bounds.getX() + ", y=" + bounds.getY() + ", w=" + bounds.getWidth() + ", h=" + bounds.getHeight() + " }"; + } + } + + public List getControlPoints() { + List points = new ArrayList(); + points.addAll(super.getControlPoints()); + points.add(tl); + points.add(tr); + points.add(bl); + points.add(br); + points.add(rounding); + return points; + } + + public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) { + if (paintControlLines) { + g2.setStroke(new BasicStroke((float) pixelSize)); + g2.setColor(GraphicsHelper.CONTROL_LINE); + g2.draw(getShape()); + } + tl.paintControls(g2, pixelSize, true); + tr.paintControls(g2, pixelSize, true); + bl.paintControls(g2, pixelSize, true); + br.paintControls(g2, pixelSize, true); + rounding.paintControls(g2, pixelSize, true); + } + + public void move(double moveX, double moveY, boolean snapPixels) { + if (snapPixels) { + x1.setValue(Math.round(x1.getValue() + moveX)); + x2.setValue(Math.round(x2.getValue() + moveX)); + y1.setValue(Math.round(y1.getValue() + moveY)); + y2.setValue(Math.round(y2.getValue() + moveY)); + } else { + x1.setValue(x1.getValue() + moveX); + x2.setValue(x2.getValue() + moveX); + y1.setValue(y1.getValue() + moveY); + y2.setValue(y2.getValue() + moveY); + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/SimpleShape.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/SimpleShape.java new file mode 100644 index 0000000000000000000000000000000000000000..c001c0f42b1f3649e8c7a263b2669d952b61095a --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/SimpleShape.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import org.jdesktop.beans.AbstractBean; + +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.List; + +/** + * SimpleShape + * + * @author Created by Jasper Potts (May 22, 2007) + */ +public abstract class SimpleShape extends AbstractBean { + + protected AffineTransform transform = new AffineTransform(); + protected LayerContainer parent = null; + + public void applyTransform(AffineTransform t) { + transform.concatenate(t); + } + + public abstract Rectangle2D getBounds(double pixelSize); + + public abstract void paint(Graphics2D g2, double pixelSize); + + public abstract boolean isHit(Point2D p, double pixelSize); + + public boolean intersects(Rectangle2D rect, double pixelSize) { + return getBounds(pixelSize).intersects(rect); + } + + public abstract List getControlPoints(); + + public abstract void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines); + + public void move(double moveX, double moveY, boolean snapPixels) { + for (ControlPoint controlPoint : getControlPoints()) { + controlPoint.move(moveX, moveY, snapPixels); + } + } + + public LayerContainer getParent() { + return parent; + } + + public void setParent(LayerContainer parent) { + LayerContainer old = getParent(); + this.parent = parent; + firePropertyChange("parent", old, getParent()); + } + + public abstract Shape getShape(); +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/TemplateLayer.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/TemplateLayer.java new file mode 100644 index 0000000000000000000000000000000000000000..d0e51c29ed9433c4a1776734cf542d36cf77c221 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/TemplateLayer.java @@ -0,0 +1,142 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer; + +import org.jdesktop.swingx.designer.effects.Effect; + +import javax.imageio.ImageIO; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.lang.ref.SoftReference; + +/** + * TemplateLayer + * + * @author Created by Jasper Potts (Jul 2, 2007) + */ +public class TemplateLayer extends Layer { + + private String fileName; + private transient SoftReference imgRef = null; + + public TemplateLayer() { + type = LayerType.template; + } + + public TemplateLayer(String fileName, BufferedImage templateImage) { + super("Template"); + this.fileName = fileName; + type = LayerType.template; + if (templateImage != null) { + imgRef = new SoftReference(templateImage); + } + } + + // ================================================================================================================= + // Methods + + public String getName() { + return super.getName(); + } + + /** + * template layers are always locked + * + * @return true + */ + public boolean isLocked() { + return true; + } + + public void add(SimpleShape shape) { + throw new IllegalStateException("Template layers can't contain shapes"); + } + + public void addEffect(Effect effect) { + throw new IllegalStateException("Template layers can't contain effects"); + } + + public void addLayer(int i, Layer layer) { + throw new IllegalStateException("Template layers can't contain sub layers"); + } + + public void addLayer(Layer layer) { + throw new IllegalStateException("Template layers can't contain sub layers"); + } + + public void paint(Graphics2D g2, double pixelSize) { + if (isVisible()) { + BufferedImage img = getTemplateImage(); + if (img != null) g2.drawImage(img, 0, 0, null); + } + } + + + public Image getBuffer(GraphicsConfiguration graphicsConfiguration) { + return getTemplateImage(); + } + + public BufferedImage getTemplateImage() { + BufferedImage img = null; + if (imgRef == null || (img = imgRef.get()) == null) { + + // can not access canvas + final File templateImgFile = new File(getCanvas().getTemplatesDir(), fileName); + System.out.println("templateImgFile = " + templateImgFile.getAbsolutePath()); + System.out.println("templateImgFile.exists = " + templateImgFile.exists()); + try { + img = ImageIO.read(templateImgFile); + imgRef = new SoftReference(img); + } catch (IOException e) { + e.printStackTrace(); + // create error image + img = new BufferedImage(getCanvas().getSize().width, getCanvas().getSize().height, + BufferedImage.TYPE_INT_RGB); + Graphics2D g2 = img.createGraphics(); + g2.setColor(Color.RED); + g2.fillRect(0, 0, img.getWidth(), img.getHeight()); + g2.setColor(Color.WHITE); + g2.setFont(g2.getFont().deriveFont(8f)); + FontMetrics fontMetrics = g2.getFontMetrics(); + Rectangle2D stringBounds = fontMetrics.getStringBounds("Missing Image", g2); + int offsetX = (int) ((img.getWidth() - stringBounds.getWidth()) / 2d); + int offsetY = (int) (((img.getHeight() - stringBounds.getHeight()) / 2d) - stringBounds.getY()); + g2.drawString("Missing Image", offsetX, offsetY); + g2.dispose(); + imgRef = new SoftReference(img); + } + } + return img; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/DropShadowEffect.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/DropShadowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..ae95ea50ce367d879b83191c21760502ab8674d1 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/DropShadowEffect.java @@ -0,0 +1,137 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import org.jdesktop.swingx.designer.paint.Matte; + +import javax.swing.UIDefaults; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.util.Arrays; + +/** + * DropShadowEffect + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +public class DropShadowEffect extends ShadowEffect { + + protected DropShadowEffect() {} + + ; + + public DropShadowEffect(UIDefaults uiDefaults) { + color = new Matte(Color.BLACK, uiDefaults); + } + + // ================================================================================================================= + // Effect Methods + + /** + * Get the display name for this effect + * + * @return The user displayable name + */ + public String getDisplayName() { + return "Drop Shadow"; + } + + /** + * Get the type of this effect, one of UNDER,BLENDED,OVER. UNDER means the result of apply effect should be painted + * under the src image. BLENDED means the result of apply sffect contains a modified src image so just it should be + * painted. OVER means the result of apply effect should be painted over the src image. + * + * @return The effect type + */ + public EffectType getEffectType() { + return EffectType.UNDER; + } + + /** + * Apply the effect to the src image generating the result . The result image may or may not contain the source + * image depending on what the effect type is. + * + * @param src The source image for applying the effect to + * @param dst The dstination image to paint effect result into. If this is null then a new image will be created + * @param w The width of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @param h The height of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @return The result of appl + */ + public BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h) { + // calculate offset + double trangleAngle = Math.toRadians(angle - 90); + int offsetX = (int) (Math.sin(trangleAngle) * distance); + int offsetY = (int) (Math.cos(trangleAngle) * distance); + // clac expanded size + int tmpOffX = offsetX + size; + int tmpOffY = offsetY + size; + int tmpW = w + offsetX + size + size; + int tmpH = h + offsetY + size + size; + // create tmp buffers + int[] lineBuf = getTmpIntArray(w); + byte[] tmpBuf1 = getTmpByteArray1(tmpW * tmpH); + Arrays.fill(tmpBuf1, (byte) 0x00); + byte[] tmpBuf2 = getTmpByteArray2(tmpW * tmpH); + // extract src image alpha channel and inverse and offset + Raster srcRaster = src.getRaster(); + for (int y = 0; y < h; y++) { + int dy = (y + tmpOffY); + int offset = dy * tmpW; + srcRaster.getDataElements(0, y, w, 1, lineBuf); + for (int x = 0; x < w; x++) { + int dx = x + tmpOffX; + tmpBuf1[offset + dx] = (byte) ((lineBuf[x] & 0xFF000000) >>> 24); + } + } + // blur + float[] kernel = EffectUtils.createGaussianKernel(size); + EffectUtils.blur(tmpBuf1, tmpBuf2, tmpW, tmpH, kernel, size); // horizontal pass + EffectUtils.blur(tmpBuf2, tmpBuf1, tmpH, tmpW, kernel, size);// vertical pass + //rescale + float spread = Math.min(1 / (1 - (0.01f * this.spread)), 255); + for (int i = 0; i < tmpBuf1.length; i++) { + int val = (int) (((int) tmpBuf1[i] & 0xFF) * spread); + tmpBuf1[i] = (val > 255) ? (byte) 0xFF : (byte) val; + } + // create color image with shadow color and greyscale image as alpha + if (dst == null) dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + WritableRaster shadowRaster = dst.getRaster(); + int red = color.getRed(), green = color.getGreen(), blue = color.getBlue(); + for (int y = 0; y < h; y++) { + int srcY = y + tmpOffY; + int shadowOffset = (srcY - offsetY) * tmpW; + for (int x = 0; x < w; x++) { + int srcX = x + tmpOffX; + lineBuf[x] = tmpBuf1[shadowOffset + (srcX - offsetX)] << 24 | red << 16 | green << 8 | blue; + } + shadowRaster.setDataElements(0, y, w, 1, lineBuf); + } + return dst; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/Effect.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/Effect.java new file mode 100644 index 0000000000000000000000000000000000000000..7b8b697caaf5393968f2bd886683d9826864eef1 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/Effect.java @@ -0,0 +1,153 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.BlendingMode; + +import java.awt.image.BufferedImage; +import java.lang.ref.SoftReference; + +/** + * Effect + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +public abstract class Effect extends AbstractBean { + protected boolean visible = true; + + public enum EffectType { + UNDER, BLENDED, OVER + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + boolean old = isVisible(); + this.visible = visible; + firePropertyChange("visible", old, isVisible()); + } + + public String toString() { + return getDisplayName(); + } + + // ================================================================================================================= + // Abstract Methods + + /** + * Get the display name for this effect + * + * @return The user displayable name + */ + public abstract String getDisplayName(); + + /** + * Get the type of this effect, one of UNDER,BLENDED,OVER. UNDER means the result of apply effect should be painted + * under the src image. BLENDED means the result of apply sffect contains a modified src image so just it should be + * painted. OVER means the result of apply effect should be painted over the src image. + * + * @return The effect type + */ + public abstract EffectType getEffectType(); + + /** + * Get the blending mode to use to paint the result effected image if the EffectType is UNDER or OVER. + * + * @return The blending mode for the effect + */ + public abstract BlendingMode getBlendingMode(); + + /** + * Get the opacity to use to paint the result effected image if the EffectType is UNDER or OVER. + * + * @return The opactity for the effect, 0.0f -> 1.0f + */ + public abstract float getOpacity(); + + /** + * Apply the effect to the src image generating the result . The result image may or may not contain the source + * image depending on what the effect type is. + * + * @param src The source image for applying the effect to + * @param dst The dstination image to paint effect result into. If this is null then a new image will be created + * @param w The width of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @param h The height of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @return The result of appl + */ + public abstract BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h); + + // ================================================================================================================= + // Static data cache + + private static SoftReference tmpIntArray = null; + private static SoftReference tmpByteArray1 = null; + private static SoftReference tmpByteArray2 = null; + private static SoftReference tmpByteArray3 = null; + + protected static int[] getTmpIntArray(int size) { + int[] tmp; + if (tmpIntArray == null || (tmp = tmpIntArray.get()) == null || tmp.length < size) { + // create new array + tmp = new int[size]; + tmpIntArray = new SoftReference(tmp); + } + return tmp; + } + + protected static byte[] getTmpByteArray1(int size) { + byte[] tmp; + if (tmpByteArray1 == null || (tmp = tmpByteArray1.get()) == null || tmp.length < size) { + // create new array + tmp = new byte[size]; + tmpByteArray1 = new SoftReference(tmp); + } + return tmp; + } + + protected static byte[] getTmpByteArray2(int size) { + byte[] tmp; + if (tmpByteArray2 == null || (tmp = tmpByteArray2.get()) == null || tmp.length < size) { + // create new array + tmp = new byte[size]; + tmpByteArray2 = new SoftReference(tmp); + } + return tmp; + } + + protected static byte[] getTmpByteArray3(int size) { + byte[] tmp; + if (tmpByteArray3 == null || (tmp = tmpByteArray3.get()) == null || tmp.length < size) { + // create new array + tmp = new byte[size]; + tmpByteArray3 = new SoftReference(tmp); + } + return tmp; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtils.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..9a6876b5a5a041b9a7804ef2421c2c6978961f5a --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtils.java @@ -0,0 +1,99 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + + +/** + * EffectUtils + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +public class EffectUtils { + + /** + *

Blurs the source pixels into the destination pixels. The force of the blur is specified by the radius which + * must be greater than 0.

The source and destination pixels arrays are expected to be in the BYTE_GREY + * format.

After this method is executed, dstPixels contains a transposed and filtered copy of + * srcPixels.

+ * + * @param srcPixels the source pixels + * @param dstPixels the destination pixels + * @param width the width of the source picture + * @param height the height of the source picture + * @param kernel the kernel of the blur effect + * @param radius the radius of the blur effect + */ + public static void blur(byte[] srcPixels, byte[] dstPixels, + int width, int height, + float[] kernel, int radius) { + float p; + int cp; + for (int y = 0; y < height; y++) { + int index = y; + int offset = y * width; + for (int x = 0; x < width; x++) { + p = 0.0f; + for (int i = -radius; i <= radius; i++) { + int subOffset = x + i; + if (subOffset < 0 || subOffset >= width) { + subOffset = (x + width) % width; + } + int pixel = srcPixels[offset + subOffset] & 0xFF; + float blurFactor = kernel[radius + i]; + p += blurFactor * pixel; + } + cp = (int) (p + 0.5f); + dstPixels[index] = (byte) (cp > 255 ? 255 : cp); + index += height; + } + } + } + + public static float[] createGaussianKernel(int radius) { + if (radius < 1) { + throw new IllegalArgumentException("Radius must be >= 1"); + } + + float[] data = new float[radius * 2 + 1]; + + float sigma = radius / 3.0f; + float twoSigmaSquare = 2.0f * sigma * sigma; + float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI); + float total = 0.0f; + + for (int i = -radius; i <= radius; i++) { + float distance = i * i; + int index = i + radius; + data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot; + total += data[index]; + } + + for (int i = 0; i < data.length; i++) { + data[i] /= total; + } + + return data; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtilsTemp.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtilsTemp.java new file mode 100644 index 0000000000000000000000000000000000000000..17bfd333f9bcd56dff8485aa6a69f31ede44442f --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtilsTemp.java @@ -0,0 +1,82 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import java.awt.Composite; +import java.awt.CompositeContext; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +/** + * EffectUtilsTemp - effect utils methods that are not being used for now but we might want later + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +public class EffectUtilsTemp { + + /** + * Extract the alpha channel of a image into new greyscale buffered image + * + * @param src Must but INT_ARGB buffered image + * @return new TYPE_BYTE_GRAY image of just the alpha channel + */ + public static BufferedImage extractAlpha(BufferedImage src) { + int w = src.getWidth(); + int h = src.getHeight(); + // extract image alpha channel as greyscale image + final BufferedImage greyImg = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY); + Graphics2D g2 = greyImg.createGraphics(); + g2.setComposite(new Composite() { + public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, + RenderingHints hints) { + return new CompositeContext() { + public void dispose() {} + + public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { + int width = Math.min(src.getWidth(), dstIn.getWidth()); + int height = Math.min(src.getHeight(), dstIn.getHeight()); + int[] srcPixels = new int[width]; + byte[] dstPixels = new byte[width]; + for (int y = 0; y < height; y++) { + src.getDataElements(0, y, width, 1, srcPixels); + for (int x = 0; x < width; x++) { + dstPixels[x] = (byte) ((srcPixels[x] & 0xFF000000) >>> 24); + } + dstOut.setDataElements(0, y, width, 1, dstPixels); + } + } + }; + } + }); + g2.drawImage(src, 0, 0, null); + g2.dispose(); + return greyImg; + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerGlowEffect.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerGlowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..ea0b2d153597e873477b1975fd383b2a6d0d8a19 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerGlowEffect.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import org.jdesktop.swingx.designer.paint.Matte; + +import javax.swing.UIDefaults; +import java.awt.Color; + +/** + * InnerGlowEffect + * + * @author Created by Jasper Potts (Jun 21, 2007) + */ +public class InnerGlowEffect extends InnerShadowEffect { + + protected InnerGlowEffect() { + distance = 0; + } + + public InnerGlowEffect(UIDefaults uiDefaults) { + color = new Matte(new Color(255, 255, 211), uiDefaults); + } + + /** + * Get the display name for this effect + * + * @return The user displayable name + */ + public String getDisplayName() { + return "Inner Glow"; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerShadowEffect.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerShadowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..502c4a0537ef80e2b5b0a21f287ff3fb0c9c77e3 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerShadowEffect.java @@ -0,0 +1,142 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import org.jdesktop.swingx.designer.paint.Matte; + +import javax.swing.UIDefaults; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.util.Arrays; + +/** + * InnerShadowEffect + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +public class InnerShadowEffect extends ShadowEffect { + + protected InnerShadowEffect() {} + + ; + + public InnerShadowEffect(UIDefaults uiDefaults) { + color = new Matte(Color.BLACK, uiDefaults); + } + + // ================================================================================================================= + // Effect Methods + + /** + * Get the display name for this effect + * + * @return The user displayable name + */ + public String getDisplayName() { + return "Inner Shadow"; + } + + /** + * Get the type of this effect, one of UNDER,BLENDED,OVER. UNDER means the result of apply effect should be painted + * under the src image. BLENDED means the result of apply sffect contains a modified src image so just it should be + * painted. OVER means the result of apply effect should be painted over the src image. + * + * @return The effect type + */ + public Effect.EffectType getEffectType() { + return Effect.EffectType.OVER; + } + + /** + * Apply the effect to the src image generating the result . The result image may or may not contain the source + * image depending on what the effect type is. + * + * @param src The source image for applying the effect to + * @param dst The dstination image to paint effect result into. If this is null then a new image will be created + * @param w The width of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @param h The height of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @return The result of appl + */ + public BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h) { + // calculate offset + double trangleAngle = Math.toRadians(angle - 90); + int offsetX = (int) (Math.sin(trangleAngle) * distance); + int offsetY = (int) (Math.cos(trangleAngle) * distance); + // clac expanded size + int tmpOffX = offsetX + size; + int tmpOffY = offsetY + size; + int tmpW = w + offsetX + size + size; + int tmpH = h + offsetY + size + size; + // create tmp buffers + int[] lineBuf = getTmpIntArray(w); + byte[] srcAlphaBuf = getTmpByteArray1(tmpW * tmpH); + Arrays.fill(srcAlphaBuf, (byte) 0xFF); + byte[] tmpBuf1 = getTmpByteArray2(tmpW * tmpH); + byte[] tmpBuf2 = getTmpByteArray3(tmpW * tmpH); + // extract src image alpha channel and inverse and offset + Raster srcRaster = src.getRaster(); + for (int y = 0; y < h; y++) { + int dy = (y + tmpOffY); + int offset = dy * tmpW; + srcRaster.getDataElements(0, y, w, 1, lineBuf); + for (int x = 0; x < w; x++) { + int dx = x + tmpOffX; + srcAlphaBuf[offset + dx] = (byte) ((255 - ((lineBuf[x] & 0xFF000000) >>> 24)) & 0xFF); + } + } + // blur + float[] kernel = EffectUtils.createGaussianKernel(size * 2); + EffectUtils.blur(srcAlphaBuf, tmpBuf2, tmpW, tmpH, kernel, size * 2); // horizontal pass + EffectUtils.blur(tmpBuf2, tmpBuf1, tmpH, tmpW, kernel, size * 2);// vertical pass + //rescale + float spread = Math.min(1 / (1 - (0.01f * this.spread)), 255); + for (int i = 0; i < tmpBuf1.length; i++) { + int val = (int) (((int) tmpBuf1[i] & 0xFF) * spread); + tmpBuf1[i] = (val > 255) ? (byte) 0xFF : (byte) val; + } + // create color image with shadow color and greyscale image as alpha + if (dst == null) dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + WritableRaster shadowRaster = dst.getRaster(); + int red = color.getRed(), green = color.getGreen(), blue = color.getBlue(); + for (int y = 0; y < h; y++) { + int srcY = y + tmpOffY; + int offset = srcY * tmpW; + int shadowOffset = (srcY - offsetY) * tmpW; + for (int x = 0; x < w; x++) { + int srcX = x + tmpOffX; + int origianlAlphaVal = 255 - ((int) srcAlphaBuf[offset + srcX] & 0xFF); + int shadowVal = (int) tmpBuf1[shadowOffset + (srcX - offsetX)] & 0xFF; + int alphaVal = Math.min(origianlAlphaVal, shadowVal); + lineBuf[x] = ((byte) alphaVal & 0xFF) << 24 | red << 16 | green << 8 | blue; + } + shadowRaster.setDataElements(0, y, w, 1, lineBuf); + } + return dst; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/OuterGlowEffect.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/OuterGlowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..c431ed747eaa3eac19e86c9490fc7f245d0d59ed --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/OuterGlowEffect.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import org.jdesktop.swingx.designer.paint.Matte; + +import javax.swing.UIDefaults; +import java.awt.Color; + +/** + * OuterGlowEffect + * + * @author Created by Jasper Potts (Jun 21, 2007) + */ +public class OuterGlowEffect extends DropShadowEffect { + + protected OuterGlowEffect() { + distance = 0; + } + + public OuterGlowEffect(UIDefaults uiDefaults) { + color = new Matte(new Color(255, 255, 211), uiDefaults); + } + + /** + * Get the display name for this effect + * + * @return The user displayable name + */ + public String getDisplayName() { + return "Outer Glow"; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/ShadowEffect.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/ShadowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..39620d5491191f354271195ccd30a306c3766fd1 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/ShadowEffect.java @@ -0,0 +1,132 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.effects; + +import org.jdesktop.swingx.designer.BlendingMode; +import org.jdesktop.swingx.designer.paint.Matte; + +import javax.swing.UIDefaults; +import java.awt.Color; + +/** + * ShadowEffect - base class with all the standard properties for shadow effects + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +public abstract class ShadowEffect extends Effect { + protected Matte color; + protected BlendingMode blendingMode = BlendingMode.NORMAL; + /** Opacity a float 0-1 for percentage */ + protected float opacity = 0.75f; + /** Angle in degrees between 0-360 */ + protected int angle = 135; + /** Distance in pixels */ + protected int distance = 5; + /** The shadow spread between 0-100 % */ + protected int spread = 0; + /** Size in pixels */ + protected int size = 5; + + protected ShadowEffect() {} + + ; + + public ShadowEffect(UIDefaults uiDefaults) { + color = new Matte(Color.BLACK, uiDefaults); + } + + // ================================================================================================================= + // Bean methods + + public Matte getColor() { + return color; + } + + public void setColor(Matte color) { + Matte old = getColor(); + this.color = color; + firePropertyChange("color", old, getColor()); + } + + public BlendingMode getBlendingMode() { + return blendingMode; + } + + public void setBlendingMode(BlendingMode blendingMode) { + BlendingMode old = getBlendingMode(); + this.blendingMode = blendingMode; + firePropertyChange("blendingMode", old, getBlendingMode()); + } + + public float getOpacity() { + return opacity; + } + + public void setOpacity(float opacity) { + float old = getOpacity(); + this.opacity = opacity; + firePropertyChange("opacity", old, getOpacity()); + } + + public int getAngle() { + return angle; + } + + public void setAngle(int angle) { + int old = getAngle(); + this.angle = angle; + firePropertyChange("angle", old, getAngle()); + } + + public int getDistance() { + return distance; + } + + public void setDistance(int distance) { + int old = getDistance(); + this.distance = distance; + firePropertyChange("distance", old, getDistance()); + } + + public int getSpread() { + return spread; + } + + public void setSpread(int spread) { + int old = getSpread(); + this.spread = spread; + firePropertyChange("spread", old, getSpread()); + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + int old = getSize(); + this.size = size; + firePropertyChange("size", old, getSize()); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/font/Typeface.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/font/Typeface.java new file mode 100644 index 0000000000000000000000000000000000000000..89d4675f3745e60652584943731abdaafff54b8c --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/font/Typeface.java @@ -0,0 +1,484 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.font; + +import java.awt.Font; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.UIDefaults; +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +/** + * I don't think the name is technically correct (ie: a typeface is not a font), + * but I wanted something besides "font" so, here it is. + * + * This is a mutable font, much like Matte is a mutable color. Also like Matte, + * Typeface can be derived. + * + * @author rbair + */ +public class Typeface extends AbstractBean { + //specifies whether to derive bold, or italic. + //Default means, get my value from my parent. + //Off means, leave bold/italic off. + //On means, make bold/italic on. + public enum DeriveStyle { Default, Off, On } + + private String uiDefaultParentName; + /** This is a local UIDefaults that contains all the UIDefaults in the Model. */ + private transient UIDefaults uiDefaults = new UIDefaults(); + private PropertyChangeListener uiDefaultsChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + if (uiDefaultParentName != null && uiDefaultParentName.equals(evt.getPropertyName())) { + updateFontFromOffsets(); + } + } + }; + + /** + * The name of the font. If uiDefaultParentName is specified, then this name + * will be set to be equal to the name of the parent font. + */ + private String name; + /** + * The size of the font. If uiDefaultParentName is set, then this value is + * updated to reflect the size of the parent font * the sizeOffset. + */ + private int size; + + //this field is not publically accessible. Rather, it is updated based on + //"bold" and "italic" as necessary. + private int style = Font.PLAIN; + private DeriveStyle bold = DeriveStyle.Default; + private DeriveStyle italic = DeriveStyle.Default; + + /** + * The size offset. Only used if uiDefaultParentName is specified. This offset + * will be multiplied with the parent font's size to determine the size of this + * typeface. The offset is specified as a percentage, either positive or negative. + * + * The reason a percentage was used, was so that things would look correctly + * when scaled, such as with high DPI situations. + */ + private float sizeOffset; + + /** + * Create a new Typeface. Note that, without specifying the uiDefaults, + * you cannot have font derivation. Thus, this constructor should never + * be called, except for the XML binding stuff. + */ + public Typeface() { } + + /** + * Creates a new Typeface. + * + * @param f The font from which to get the font name, size, and style to use + * to initialize this typeface. Note that this font is not used as a parent + * font for derivation purposes. Rather, it is used as a source from which to + * copy initial settings. + * + * @param uiDefaults The uiDefaults to use for font derivation purposes. + * When the uiDefaultParentName is specified, then this Typeface will inspect + * the given UIDefaults for that parent font. Note that the UIDefaults + * should be populated with a font, and not with a typeface. + */ + public Typeface(Font f, UIDefaults uiDefaults) { + if (f != null) { + this.name = f.getName(); + this.size = f.getSize(); + this.style = f.getStyle(); + } + setUiDefaults(uiDefaults); + } + + // ================================================================================================================= + // JIBX Methods + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + protected void postSet(IUnmarshallingContext context) { + // walk up till we get synth model + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof HasUIDefaults) { + UIDefaults uiDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults(); + if (uiDefaults != null) { + setUiDefaults(uiDefaults); + break; + } + } + } + } + + // ================================================================================================================= + // Typeface methods + + /** + * Is the Typeface an absolute Font not derived from a parent ui default + * + * @return true if this is a absolute not uidefault derived font + */ + public boolean isAbsolute() { + return uiDefaultParentName == null; + } + + /** + * Set all properties of this Typeface to be the same as src and fire all the change events + * + * @param src the Typeface to copy properties from + */ + public void copy(Typeface src) { + // keep old values + Font oldFont = getFont(); + String oldParentName = uiDefaultParentName; + String oldName = name; + int oldSize = size; + float oldSizeOffset = sizeOffset; + DeriveStyle oldBold = bold, oldItalic = italic; + + style = src.style; + + //Note, I don't just call the setters here, because I want to make + //sure the "font" PCE is only fired once, at the end. + name = src.name; + firePropertyChange("name", oldName, name); + size = src.size; + firePropertyChange("size", oldSize, size); + bold = src.bold; + firePropertyChange("bold", oldBold, bold); + italic = src.italic; + firePropertyChange("italic", oldItalic, italic); + sizeOffset = src.sizeOffset; + firePropertyChange("sizeOffset", oldSizeOffset, sizeOffset); + uiDefaultParentName = src.uiDefaultParentName; + firePropertyChange("uiDefaultParentName", oldParentName, uiDefaultParentName); + setUiDefaults(src.uiDefaults); + firePropertyChange("font", oldFont, getFont()); + } + + // ================================================================================================================= + // Bean Methods + + /** + * Get the local UIDefaults that contains all the UIDefaults in the Model. + * + * @return The UIDefaults for the model that contains this Typeface, can be null if this Typeface is not part of a bigger + * model + */ + public UIDefaults getUiDefaults() { + return uiDefaults; + } + + /** + * Set the local UIDefaults that contains all the UIDefaults in the Model. + * + * @param uiDefaults The UIDefaults for the model that contains this Typeface, can be null if this Typeface is not part of + * a bigger model + */ + public void setUiDefaults(UIDefaults uiDefaults) { + if (uiDefaults != this.uiDefaults) { + UIDefaults old = getUiDefaults(); + if (old != null) old.removePropertyChangeListener(uiDefaultsChangeListener); + this.uiDefaults = uiDefaults; + if (uiDefaults != null) this.uiDefaults.addPropertyChangeListener(uiDefaultsChangeListener); + firePropertyChange("uiDefaults", old, getUiDefaults()); + } + } + + /** + * Get the name if the uidefault font that is the parent that this Typeface is derived from. If null then this is a + * absolute font. + * + * @return Parent font ui default name + */ + public String getUiDefaultParentName() { + return uiDefaultParentName; + } + + /** + * Set the name if the uidefault font that is the parent that this Typeface is derived from. If null then this is a + * absolute font. + * + * @param uiDefaultParentName Parent font ui default name + */ + public void setUiDefaultParentName(String uiDefaultParentName) { + String old = getUiDefaultParentName(); + this.uiDefaultParentName = uiDefaultParentName; + firePropertyChange("uiDefaultParentName", old, getUiDefaultParentName()); + if (isAbsolute()) { + // reset offsets + float oldSizeOffset = sizeOffset; + sizeOffset = 0; + firePropertyChange("sizeOffset", oldSizeOffset, sizeOffset); + } else { + updateFontFromOffsets(); + } + } + + /** + * @return Gets the name of the font + */ + public final String getName() { + return name; + } + + /** + * Sets the name of the font. This method call only works if + * isAbsolute returns true. Otherwise, it is ignored. + * @param name the name of the font + */ + public void setName(String name) { + if (isAbsolute()) { + String old = this.name; + Font oldF = getFont(); + this.name = name; + firePropertyChange("name", old, this.name); + firePropertyChange("font", oldF, getFont()); + } + } + + /** + * @return gets the size of the font. + */ + public final int getSize() { + return size; + } + + /** + *

Sets the size of the font. THis method call will work whether + * isAbsolute returns true or false. If this is an absolute + * typeface, then the size is set directly. Otherwise, if this is a + * derived typeface, then the sizeOffset will be updated to reflect the + * proper offset based on this size, and the size of the parent font.

+ * + *

For example, if the parent font's size was 12, and the sizeOffset was + * -2 (thus yielding as size on this typeface of 10), and you call setSize + * passing in "14" as the size, then the sizeOffset will be updated to be + * equal to "2".

+ * + * @param size the new size for this typeface. + */ + public void setSize(int size) { + int old = this.size; + Font oldF = getFont(); + this.size = size; + firePropertyChange("size", old, this.size); + firePropertyChange("font", oldF, getFont()); + updateOffsetsFromFont(); + } + + /** + * @return the size offset + */ + public final float getSizeOffset() { + return sizeOffset; + } + + /** + * Sets the percentage by which the size of this font should be different + * from its parent font. This property is kept in synch with the size property. + * + * @param sizeOffset the size offset. May be any float. The value "1" means, + * 100%. -1 means "-100%". 2 means "200%", and so on. + */ + public void setSizeOffset(float sizeOffset) { + float old = this.sizeOffset; + Font oldF = getFont(); + this.sizeOffset = sizeOffset; + firePropertyChange("sizeOffset", old, this.sizeOffset); + firePropertyChange("font", oldF, getFont()); + updateFontFromOffsets(); + } + + public DeriveStyle getBold() { + return bold; + } + + public void setBold(DeriveStyle bold) { + DeriveStyle old = this.bold; + this.bold = bold == null ? DeriveStyle.Default : bold; + firePropertyChange("bold", old, this.bold); + updateFontFromOffsets(); + } + + public DeriveStyle getItalic() { + return italic; + } + + public void setItalic(DeriveStyle italic) { + DeriveStyle old = this.italic; + this.italic = italic == null ? DeriveStyle.Default : italic; + firePropertyChange("italic", old, this.italic); + updateFontFromOffsets(); + } + + /** + * @return whether or not the font represented by this typeface is supported + * on this operating system platform. + */ + public boolean isFontSupported() { + return true;//Font.getFont(name) != null; + } + + /** + * @return Gets the font associated with this Typeface. If font derivation is + * being used, then the Font returned is the result of that derivation. + */ + public Font getFont() { + return new Font(name, style, size); + } + + /** + * Sets the font from which this Typeface should extract the font name, style, + * and size. If font derivation is being used, then the font name will be ignored, + * the style will be used (and always override the parent font), and the size + * will be set and the sizeOffset updated appropriately. + * + * @param f the Font + */ + public void setFont(Font f) { + Font oldFont = getFont(); + String oldName = name; + int oldSize = size; + DeriveStyle oldBold = bold, oldItalic = italic; + name = f.getName(); + size = f.getSize(); + style = f.getStyle(); + updateOffsetsFromFont(); + firePropertyChange("name", oldName, name); + firePropertyChange("size", oldSize, size); + firePropertyChange("bold", oldBold, bold); + firePropertyChange("italic", oldItalic, italic); + firePropertyChange("font", oldFont, getFont()); + } + + /** + * @inheritDoc + * + * @return A formatted string representing this Typeface. This String should + * not be considered public API, as it may change in a future release. + */ + @Override public String toString() { + Font f = getFont(); + String strStyle; + if (f.isBold()) { + strStyle = f.isItalic() ? "bolditalic" : "bold"; + } else { + strStyle = f.isItalic() ? "italic" : "plain"; + } + + if (isAbsolute()) { + return Typeface.class.getName() + "[name=" + name + ", size=" + size + ", style=" + strStyle + "]"; + } else { + return Typeface.class.getName() + "[base=" + uiDefaultParentName + + ", name=" + name + ", size=" + size + "(offset " + sizeOffset + ")" + + ", style=" + strStyle + "]"; + } + } + + @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Typeface typeface = (Typeface) o; + if (!typeface.name.equals(name)) return false; + if (size != typeface.size) return false; + if (bold != typeface.bold) return false; + if (italic != typeface.italic) return false; + if (sizeOffset != typeface.sizeOffset) return false; + if (uiDefaultParentName != null ? !uiDefaultParentName.equals(typeface.uiDefaultParentName) : + typeface.uiDefaultParentName != null) return false; + return true; + } + + @Override public int hashCode() { + int result; + result = name.hashCode(); + result = 31 * result + size; + result = 31 * result + bold.ordinal(); + result = 31 * result + italic.ordinal(); + result = 31 * result + (int)(sizeOffset*100); + result = 31 * result + (uiDefaultParentName != null ? uiDefaultParentName.hashCode() : 0); + return result; + } + + @Override public Typeface clone() { + Typeface clone = new Typeface(); + clone.name = name; + clone.size = size; + clone.style = style; + clone.bold = bold; + clone.italic = italic; + clone.sizeOffset = sizeOffset; + clone.uiDefaultParentName = uiDefaultParentName; + clone.setUiDefaults(uiDefaults); + return clone; + } + + // ================================================================================================================= + // Private Helper Methods + + private void updateOffsetsFromFont() { + if (!isAbsolute()) { + float oldSizeOffset = sizeOffset; + Font parentFont = uiDefaults.getFont(uiDefaultParentName); + if (parentFont != null) { + float s = size; + float p = parentFont.getSize(); + sizeOffset = (s/p) - 1f; + firePropertyChange("sizeOffset", oldSizeOffset, sizeOffset); + } + } + } + + private void updateFontFromOffsets() { + if (!isAbsolute()) { + Font oldFont = getFont(); + // get parent font data + Font parentFont = uiDefaults.getFont(uiDefaultParentName); + if (parentFont != null) { + String oldName = name; + int oldSize = size; + + name = parentFont.getName(); + size = Math.round(parentFont.getSize() * (1f + sizeOffset)); + + boolean isBold = (bold == DeriveStyle.Default && parentFont.isBold()) || bold == DeriveStyle.On; + boolean isItalic = (italic == DeriveStyle.Default && parentFont.isItalic()) || italic == DeriveStyle.On; + style = Font.PLAIN; + if (isBold) style = style | Font.BOLD; + if (isItalic) style = style | Font.ITALIC; + + // update fire events + firePropertyChange("name", oldName, name); + firePropertyChange("size", oldSize, size); + firePropertyChange("font", oldFont, getFont()); + } + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/CanvasMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/CanvasMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..6c201fd0feece936056c5b4f90294dcb957f408c --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/CanvasMapper.java @@ -0,0 +1,123 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.jibxhelpers; + +import org.jdesktop.swingx.designer.Canvas; +import org.jdesktop.swingx.designer.utils.HasPath; +import org.jdesktop.swingx.designer.utils.HasResources; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.BindingDirectory; +import org.jibx.runtime.IBindingFactory; +import org.jibx.runtime.IMarshallable; +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + +import javax.swing.UIDefaults; +import java.io.File; + +/** + * CanvasMapper + * + * @author Created by Jasper Potts (Jun 12, 2007) + */ +public class CanvasMapper implements IMarshaller, IUnmarshaller { + private static final String ELEMENT_NAME = "canvas"; + private IBindingFactory bindingFactory; + + + public CanvasMapper() { + try { + bindingFactory = BindingDirectory.getFactory(Canvas.class); + } catch (JiBXException e) { + e.printStackTrace(); + } + } + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(null, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof Canvas)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + // version found, create marshaller for the associated binding +// IBindingFactory bindingFactory = BindingDirectory.getFactory(object.getClass()); + MarshallingContext context = (MarshallingContext) bindingFactory.createMarshallingContext(); + // configure marshaller for writing document + context.setXmlWriter(iMarshallingContext.getXmlWriter()); + // output object as document + ((IMarshallable) object).marshal(context); + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(null, ELEMENT_NAME)) { + ctx.throwStartTagNameError(null, ELEMENT_NAME); + } + +// IBindingFactory bindingFactory = BindingDirectory.getFactory(Canvas.class); + UnmarshallingContext uctx = (UnmarshallingContext) bindingFactory.createUnmarshallingContext(); + uctx.setFromContext(ctx); + // get the uiDefaults from SynthModel and set them as user context + UIDefaults uiDefaults = ((HasUIDefaults) ctx.getStackObject(ctx.getStackDepth() - 1)).getUiDefaults(); + uctx.setUserContext(uiDefaults); + // get has resources + HasResources hasResources = (HasResources) ctx.getStackObject(ctx.getStackDepth() - 1); + // get path + HasPath hasPath = null; + for (int i = 0; i < ctx.getStackDepth(); i++) { + if (ctx.getStackObject(i) instanceof HasPath) { + hasPath = (HasPath) ctx.getStackObject(i); + break; + } + } + // Unmarshal the Canvas + Canvas canvas = (Canvas) uctx.unmarshalElement(); + // set canvas's ui defaults + canvas.setUiDefaults(uiDefaults); + // get canvas path + String canvasPath = hasPath.getPath(); + // calc and set resources + canvas.setResourcesDir(new File(hasResources.getResourcesDir(), canvasPath)); + canvas.setTemplatesDir(new File(hasResources.getTemplatesDir(), canvasPath)); + canvas.setImagesDir(new File(hasResources.getImagesDir(), canvasPath)); + // return canvas + return canvas; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/ColorMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/ColorMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..81cc738506f1adc481adc7e8dd65ce0302162a29 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/ColorMapper.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.jibxhelpers; + +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + +import java.awt.Color; + +/** + * ColorMapper + * + * @author Created by Jasper Potts (Jun 8, 2007) + */ +public class ColorMapper implements IMarshaller, IUnmarshaller { + private static final String ELEMENT_NAME = "color"; + private static final String RED_NAME = "red"; + private static final String GREEN_NAME = "green"; + private static final String BLUE_NAME = "blue"; + private static final String ALPHA_NAME = "alpha"; + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(null, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof Color)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + Color color = (Color) object; + ctx.startTagAttributes(0, ELEMENT_NAME). + attribute(0, RED_NAME, color.getRed()). + attribute(0, GREEN_NAME, color.getGreen()). + attribute(0, BLUE_NAME, color.getBlue()). + attribute(0, ALPHA_NAME, color.getAlpha()). + closeStartEmpty(); + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(null, ELEMENT_NAME)) { + ctx.throwStartTagNameError(null, ELEMENT_NAME); + } + // get values + int red = ctx.attributeInt(null, RED_NAME, 0); + int green = ctx.attributeInt(null, GREEN_NAME, 0); + int blue = ctx.attributeInt(null, BLUE_NAME, 0); + int alpha = ctx.attributeInt(null, ALPHA_NAME, 0); + ctx.parsePastEndTag(null, ELEMENT_NAME); + // create + return new Color(red, green, blue, alpha); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/DimensionMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/DimensionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..44a0f264bf020637c2243ad1219d351776dd8ff3 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/DimensionMapper.java @@ -0,0 +1,101 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.jibxhelpers; + +import org.jibx.runtime.IAliasable; +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + +import java.awt.Dimension; + +/** + * DimensionMapper + * + * @author Created by Jasper Potts (Jun 12, 2007) + */ +public class DimensionMapper implements IMarshaller, IUnmarshaller, IAliasable { + private static final String ELEMENT_NAME = "dimension"; + private static final String WIDTH_NAME = "width"; + private static final String HEIGHT_NAME = "height"; + + private String uri; + private int index; + private String name; + + public DimensionMapper() { + uri = null; + index = 0; + name = ELEMENT_NAME; + } + + public DimensionMapper(String uri, int index, String name) { + this.uri = uri; + this.index = index; + this.name = name; + } + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(uri, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof Dimension)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + Dimension dimension = (Dimension) object; + ctx.startTagAttributes(index, name). + attribute(index, WIDTH_NAME, dimension.width). + attribute(index, HEIGHT_NAME, dimension.height). + closeStartEmpty(); + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(uri, name)) { + ctx.throwStartTagNameError(uri, name); + } + // get values + int width = ctx.attributeInt(uri, WIDTH_NAME, index); + int height = ctx.attributeInt(uri, HEIGHT_NAME, index); + // state finished parsing + ctx.parsePastEndTag(uri, name); + // create + return new Dimension(width, height); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/InsetsMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/InsetsMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e50cb1495518a1b572d6380177309ef516f4d0a7 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/InsetsMapper.java @@ -0,0 +1,117 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.jibxhelpers; + +import org.jibx.runtime.IAliasable; +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + +import java.awt.Insets; + +/** + * InsetsMapper + * + * @author Created by Jasper Potts (Jun 8, 2007) + */ +public class InsetsMapper implements IMarshaller, IUnmarshaller, IAliasable { + private static final String ELEMENT_NAME = "insets"; + private static final String TOP_NAME = "top"; + private static final String BOTTOM_NAME = "bottom"; + private static final String LEFT_NAME = "left"; + private static final String RIGHT_NAME = "right"; + + private String uri; + private int index; + private String name; + + public InsetsMapper() { + uri = null; + index = 0; + name = ELEMENT_NAME; + } + + public InsetsMapper(String uri, int index, String name) { + this.uri = uri; + this.index = index; + this.name = name; +// System.out.println("InsetsMapper.CONSTRCUTED with uri="+uri+" index="+index+" name="+name); + } + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(uri, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof Insets)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { +// System.out.println("InsetsMapper.marshal name="+name); + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + Insets insets = (Insets) object; + ctx.startTagAttributes(index, name). + attribute(index, TOP_NAME, insets.top). + attribute(index, BOTTOM_NAME, insets.bottom). + attribute(index, LEFT_NAME, insets.left). + attribute(index, RIGHT_NAME, insets.right). + closeStartEmpty(); + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(uri, name)) { +// System.out.println("InsetsMapper.unmarshal name="+name+" uri="+uri+" currentNode="+ctx.getName()); + ctx.throwStartTagNameError(uri, name); + } else { +// System.out.println("InsetsMapper.unmarshal name="+name+" uri="+uri+" currentNode="+ctx.getName()); + } + // get values + int top = ctx.attributeInt(uri, TOP_NAME, index); + int bottom = ctx.attributeInt(uri, BOTTOM_NAME, index); + int left = ctx.attributeInt(uri, LEFT_NAME, index); + int right = ctx.attributeInt(uri, RIGHT_NAME, index); + // create new hashmap if needed + Insets insets = (Insets) object; + if (insets == null) { + insets = new Insets(top, left, bottom, right); + } else { + insets.set(top, left, bottom, right); + } + ctx.parsePastEndTag(uri, name); + return insets; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/AbstractGradient.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/AbstractGradient.java new file mode 100644 index 0000000000000000000000000000000000000000..5a94abc2cb4e42846ee0cb8886c528cf6420084a --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/AbstractGradient.java @@ -0,0 +1,280 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import java.awt.Color; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.Paint; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** @author rbair */ +public abstract class AbstractGradient extends PaintModel { + private final Comparator sorter = new Comparator() { + public int compare(GradientStop s1, GradientStop s2) { + //since a float value may be -.001 or .001, and since casting + //this to an int will round off to 0, I have to do a more direct + //comparison + float v = s1.getPosition() - s2.getPosition(); + + if (v < 0) return -1; + else if (v == 0) return 0; + else return 1; + } + }; + private PropertyChangeListener stopListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("position")) { + if (stops.contains((GradientStop) evt.getSource())) { + resortModel(true); + } else { + System.err.println("[WARNING] The position of an orphaned stop was changed."); + } + } else { + firePropertyChange("paint", null, getPaint()); + } + } + }; + + private List stops = new ArrayList(); + private List unmodifiable; + private CycleMethod cycleMethod; + + protected AbstractGradient() { + unmodifiable = Collections.unmodifiableList(stops); + cycleMethod = CycleMethod.NO_CYCLE; + setStops(new GradientStop(0, new Matte(Color.BLUE, null)), + new GradientStop(1, new Matte(Color.WHITE, null))); + } + + /** + * Copy stops and cycleMethod from src to dst + * + * @param dst The gradient to update to same stops and cycle method as this gradient + */ + protected void copyTo(AbstractGradient dst) { + dst.stops.clear(); + List stops = new ArrayList(); + for (GradientStop stop : this.stops) { + stops.add(stop.clone()); + } + dst.setStops(stops); + dst.cycleMethod = this.cycleMethod; + } + + + public PaintControlType getPaintControlType() { + return PaintControlType.control_line; + } + + public void setCycleMethod(CycleMethod method) { + CycleMethod old = cycleMethod; + Paint oldp = getPaint(); + cycleMethod = method == null ? CycleMethod.NO_CYCLE : method; + firePropertyChange("cycleMethod", old, cycleMethod); + firePropertyChange("paint", oldp, getPaint()); + } + + public final CycleMethod getCycleMethod() { + return cycleMethod; + } + + public void setStops(GradientStop... stops) { + if (stops == null || stops.length < 1) { + throw new IllegalArgumentException("Must have more than one stop"); + } + List old = new ArrayList(this.stops); + for (GradientStop stop : old) { + stop.removePropertyChangeListener(stopListener); + } + Paint oldp = getPaint(); + this.stops.clear(); + Collections.addAll(this.stops, stops); + for (GradientStop stop : this.stops) { + stop.addPropertyChangeListener(stopListener); + } + resortModel(false); + firePropertyChange("stops", old, getStops()); + firePropertyChange("paint", oldp, getPaint()); + } + + public final void setStops(List stops) { + setStops(stops == null ? null : stops.toArray(new GradientStop[0])); + } + + public final List getStops() { + return unmodifiable; + } + + private void resortModel(boolean fireEvent) { + Collections.sort(this.stops, sorter); + if (fireEvent) { + Paint oldp = getPaint(); + firePropertyChange("stops", null, getStops()); + firePropertyChange("paint", oldp, getPaint()); + } + } + + //adds a new stop, and interoplates the proper color to use based on + //its position + public GradientStop addStop(float position) { + GradientStop prevStop = null; + GradientStop nextStop = null; + for (GradientStop stop : stops) { + if (stop.getPosition() <= position) { + prevStop = stop; + } else if (stop.getPosition() >= position) { + nextStop = stop; + } + } + + Matte c = null; + if (prevStop != null && nextStop != null) { + //interpolate the value of c + c = interpolate(prevStop.getColor(), nextStop.getColor(), + position / (nextStop.getPosition() - prevStop.getPosition())); + } else if (prevStop != null) { + c = prevStop.getColor().clone(); + } else if (nextStop != null) { + c = nextStop.getColor().clone(); + } + + return addStop(position, c); + } + + public GradientStop addStop(float position, Matte color) { + GradientStop s = new GradientStop(position, color); + s.addPropertyChangeListener(stopListener); + List old = new ArrayList(stops); + Paint oldp = getPaint(); + stops.add(s); + resortModel(false); + firePropertyChange("stops", old, getStops()); + firePropertyChange("paint", oldp, getPaint()); + + return s; + } + + public GradientStop removeStop(GradientStop s) { + List old = new ArrayList(stops); + Paint oldp = getPaint(); + stops.remove(s); + s.removePropertyChangeListener(stopListener); + resortModel(false); + firePropertyChange("stops", old, getStops()); + firePropertyChange("paint", oldp, getPaint()); + return s; + } + + @Override public Paint getPaint() { + if (stops.size() == 0) { + return null; + } + + //there are stops.size() number of main stops. Between each is + //a fractional stop. Thus, there are: + //stops.size() + stops.size() - 1 + //number of fractions and colors. + + float[] fractions = new float[stops.size() + stops.size() - 1]; + Matte[] colors = new Matte[fractions.length]; + + //for each stop, create the stop and it's associated fraction + int index = 0; // the index into fractions and colors + for (int i = 0; i < stops.size(); i++) { + GradientStop s = stops.get(i); + //copy over the stop's data + colors[index] = s.getColor(); + fractions[index] = s.getPosition(); + + //If this isn't the last stop, then add in the fraction + if (index < fractions.length - 1) { + float f1 = s.getPosition(); + float f2 = stops.get(i + 1).getPosition(); + + index++; + fractions[index] = f1 + (f2 - f1) * s.getMidpoint(); + colors[index] = interpolate(colors[index - 1], stops.get(i + 1).getColor(), .5f); + } + + index++; + } + + for (int i = 1; i < fractions.length; i++) { + //to avoid an error with LinearGradientPaint where two fractions + //are identical, bump up the fraction value by a miniscule amount + //if it is identical to the previous one + //NOTE: The <= is critical because the previous value may already + //have been bumped up + if (fractions[i] <= fractions[i - 1]) { + fractions[i] = fractions[i - 1] + .000001f; + } + } + + //another boundary condition where multiple stops are all at the end. The + //previous loop bumped all but one of these past 1.0, which is bad. + //so remove any fractions (and their colors!) that are beyond 1.0 + int outOfBoundsIndex = -1; + for (int i = 0; i < fractions.length; i++) { + if (fractions[i] > 1) { + outOfBoundsIndex = i; + break; + } + } + + if (outOfBoundsIndex >= 0) { + float[] f = fractions; + Matte[] c = colors; + fractions = new float[outOfBoundsIndex]; + colors = new Matte[outOfBoundsIndex]; + System.arraycopy(f, 0, fractions, 0, outOfBoundsIndex); + System.arraycopy(c, 0, colors, 0, outOfBoundsIndex); + } + + return createPaint(fractions, colors, cycleMethod); + } + + protected abstract Paint createPaint(float[] fractions, Matte[] colors, CycleMethod method); + + protected static Matte interpolate(Matte v0, Matte v1, float fraction) { + return new Matte(interpolate(v0.getColor(), v1.getColor(), fraction), v0.getUiDefaults()); + } + + protected static Color interpolate(Color v0, Color v1, float fraction) { + int r = v0.getRed() + + (int) ((v1.getRed() - v0.getRed()) * fraction + 0.5f); + int g = v0.getGreen() + + (int) ((v1.getGreen() - v0.getGreen()) * fraction + 0.5f); + int b = v0.getBlue() + + (int) ((v1.getBlue() - v0.getBlue()) * fraction + 0.5f); + int a = v0.getAlpha() + + (int) ((v1.getAlpha() - v0.getAlpha()) * fraction + 0.5f); + return new Color(r, g, b, a); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Gradient.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Gradient.java new file mode 100644 index 0000000000000000000000000000000000000000..ed239ed370bf326d7e8e6c397b752cb11ffe1730 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Gradient.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import java.awt.Color; +import java.awt.LinearGradientPaint; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.Paint; + +/** + * Represents a GradientPaint or LinearGradientPaint. + * + * @author rbair + */ +public class Gradient extends AbstractGradient implements Cloneable { + protected Paint createPaint(float[] fractions, Matte[] mattes, CycleMethod method) { + Color[] colors = new Color[mattes.length]; + for (int i = 0; i < colors.length; i++) { + colors[i] = mattes[i].getColor(); + } + return new LinearGradientPaint(0, 0, 1, 0, fractions, colors, method); + } + + @Override public Gradient clone() { + Gradient gradient = new Gradient(); + copyTo(gradient); + return gradient; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/GradientStop.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/GradientStop.java new file mode 100644 index 0000000000000000000000000000000000000000..f462fedde7d9f28a9f7cd0fad9c107cacc50a589 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/GradientStop.java @@ -0,0 +1,123 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import org.jdesktop.beans.AbstractBean; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** Each stop is defined linearly, at positions between 0 and 1. */ +public final class GradientStop extends AbstractBean implements Cloneable { + private float position; + private Matte color; + private PropertyChangeListener matteListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("color", null, color); + } + }; + + /** + * The midpoint to the right of the stop. Must be 0 <= midpoint <= 1. The midpoint value of the last Stop is + * ignored. + */ + private float midpoint; + + public GradientStop() {} + + public GradientStop(float position, Matte color) { + if (color == null) { + throw new IllegalArgumentException("Color must not be null"); + } + + this.position = clamp(0, 1, position); + this.color = color; + this.midpoint = .5f; + + if (this.color != null) { + this.color.addPropertyChangeListener("color", matteListener); + } + } + + + public GradientStop clone() { + GradientStop clone = new GradientStop(this.position, this.color.clone()); + clone.midpoint = midpoint; + return clone; + } + + public final float getPosition() { + return position; + } + + public final void setPosition(float position) { + float old = this.position; + this.position = clamp(0, 1, position); + firePropertyChange("position", old, this.position); + } + + public final Matte getColor() { + return color; + } + + public final void setColor(Matte c) { + if (c == null) throw new IllegalArgumentException("Color must not be null"); + Matte old = this.color; + if (old != null) old.removePropertyChangeListener(matteListener); + this.color = c; + if (this.color != null) this.color.addPropertyChangeListener(matteListener); + firePropertyChange("color", old, c); + } + + public final void setOpacity(int opacity) { + int old = getOpacity(); + color.setAlpha(opacity); + firePropertyChange("opacity", old, getOpacity()); + } + + public final int getOpacity() { + return color.getAlpha(); + } + + public final float getMidpoint() { + return midpoint; + } + + public final void setMidpoint(float midpoint) { + float old = this.midpoint; + this.midpoint = clamp(0, 1, midpoint); + firePropertyChange("midpoint", old, this.midpoint); + } + + private float clamp(float lo, float hi, float value) { + if (value < lo) { + return lo; + } else if (value > hi) { + return hi; + } else { + return value; + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Matte.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Matte.java new file mode 100644 index 0000000000000000000000000000000000000000..634909f30a14beeb478bc349bd22b92f927a4426 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Matte.java @@ -0,0 +1,610 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +import javax.swing.UIDefaults; +import java.awt.Color; +import java.awt.Paint; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Representing a single uniform color. Basically, it represents the java.awt.Color. It can either be absolute or + * derived from a UIDefault color. + * + * @author rbair & jasper potts + */ +public class Matte extends PaintModel implements HasUIDefaults { + private float[] tmpf1 = new float[3]; + private float[] tmpf2 = new float[3]; + + private int red; + private int green; + private int blue; + private int alpha; + private Color cached = null; + + /** + * The name of the ui default key to derive this color from. + */ + private String uiDefaultParentName = null; + /** + * The name of the bean property, or client property, on this component + * from which to extract a color used for painting. So for example the color + * used in a painter could be the background of the component. + */ + private String componentPropertyName = null; + private float hueOffset = 0, saturationOffset = 0, brightnessOffset = 0; + private int alphaOffset = 0; + /** + * When true this color will become a UIResource in the UIManager defaults + * table. If false, then it will not be a UIResource. This is sometimes + * required, such as with colors installed on renderers. + */ + private boolean uiResource = true; + + /** This is a local UIDefaults that contains all the UIDefaults in the Model. */ + private transient UIDefaults uiDefaults = new UIDefaults(); + private PropertyChangeListener uiDefaultsChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + if (uiDefaultParentName != null && uiDefaultParentName.equals(evt.getPropertyName())) { + updateARGBFromOffsets(); + } + } + }; + + // ================================================================================================================= + // Constructors + + /** propected constructor for JIBX */ + protected Matte() {} + + public Matte(Color c, UIDefaults uiDefaults) { + if (c != null) { + this.red = c.getRed(); + this.green = c.getGreen(); + this.blue = c.getBlue(); + this.alpha = c.getAlpha(); + } + setUiDefaults(uiDefaults); + } + + // ================================================================================================================= + // JIBX Methods + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + protected void postSet(IUnmarshallingContext context) { + // walk up till we get synth model + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof HasUIDefaults) { + UIDefaults uiDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults(); + if (uiDefaults != null) { + setUiDefaults(uiDefaults); + break; + } + } + } + } + + // ================================================================================================================= + // Matte methods + + /** + * Is the matte an absolute color ot derived from a parent ui default + * + * @return true if this is a absolute not uidefault derived color + */ + public boolean isAbsolute() { + return uiDefaultParentName == null; + } + + /** + * Set all properties of this matte to be the same as srcMatte and fire all the change events + * + * @param srcMatte the matte to copy properties from + */ + public void copy(Matte srcMatte) { + // keep old values + Color oldColor = getColor(); + String oldParentName = uiDefaultParentName; + String oldComponentPropertyName = componentPropertyName; + boolean oldUiResource = uiResource; + int oldR = red, oldG = green, oldB = blue, oldA = alpha; + float oldH = hueOffset, oldS = saturationOffset, oldBr = brightnessOffset; + // set properties + if (uiResource != srcMatte.uiResource) { + uiResource = srcMatte.uiResource; + firePropertyChange("uiResource", oldUiResource, isUiResource()); + } + if (red != srcMatte.red) { + red = srcMatte.red; + firePropertyChange("red", oldR, getRed()); + } + if (green != srcMatte.green) { + green = srcMatte.green; + firePropertyChange("green", oldG, getGreen()); + } + if (blue != srcMatte.blue) { + blue = srcMatte.blue; + firePropertyChange("blue", oldB, getBlue()); + } + if (alpha != srcMatte.alpha) { + alpha = srcMatte.alpha; + firePropertyChange("alpha", oldA, getAlpha()); + } + if (hueOffset != srcMatte.hueOffset) { + hueOffset = srcMatte.hueOffset; + firePropertyChange("hueOffset", oldH, getHueOffset()); + } + if (saturationOffset != srcMatte.saturationOffset) { + saturationOffset = srcMatte.saturationOffset; + firePropertyChange("saturationOffset", oldS, getSaturationOffset()); + } + if (brightnessOffset != srcMatte.brightnessOffset) { + brightnessOffset = srcMatte.brightnessOffset; + firePropertyChange("brightnessOffset", oldBr, getBrightnessOffset()); + } + if (alphaOffset != srcMatte.alphaOffset) { + alphaOffset = srcMatte.alphaOffset; + firePropertyChange("alphaOffset", oldA, getAlphaOffset()); + } + if (uiDefaultParentName != srcMatte.uiDefaultParentName) { + uiDefaultParentName = srcMatte.uiDefaultParentName; + firePropertyChange("uiDefaultParentName", oldParentName, getUiDefaultParentName()); + } + if (componentPropertyName != srcMatte.componentPropertyName) { + componentPropertyName = srcMatte.componentPropertyName; + firePropertyChange("componentPropertyName", oldComponentPropertyName, getComponentPropertyName()); + } + if (uiDefaults != srcMatte.uiDefaults) { + setUiDefaults(srcMatte.uiDefaults); + } + if (!oldColor.equals(srcMatte.getColor())) { + firePropertyChange("paint", oldColor, getColor()); + firePropertyChange("color", oldColor, getColor()); + fireHSBChange(oldR, oldG, oldB); + } + } + + // ================================================================================================================= + // PaintModel methods + + public PaintControlType getPaintControlType() { + return PaintControlType.none; + } + + // ================================================================================================================= + // Bean Methods + + /** + * Get the local UIDefaults that contains all the UIDefaults in the Model. + * + * @return The UIDefaults for the model that contains this Matte, can be null if this Matte is not part of a bigger + * model + */ + public UIDefaults getUiDefaults() { + return uiDefaults; + } + + /** + * Set the local UIDefaults that contains all the UIDefaults in the Model. + * + * @param uiDefaults The UIDefaults for the model that contains this Matte, can be null if this Matte is not part of + * a bigger model + */ + public void setUiDefaults(UIDefaults uiDefaults) { + if (uiDefaults != this.uiDefaults) { + UIDefaults old = getUiDefaults(); + if (old != null) old.removePropertyChangeListener(uiDefaultsChangeListener); + this.uiDefaults = uiDefaults; + if (uiDefaults != null) this.uiDefaults.addPropertyChangeListener(uiDefaultsChangeListener); + firePropertyChange("uiDefaults", old, getUiDefaults()); + } + } + + /** + * Get the name if the uidefault color that is the parent that this matte is derived from. If null then this is a + * absolute color. + * + * @return Parent color ui default name + */ + public String getUiDefaultParentName() { + return uiDefaultParentName; + } + + /** + * Set the name if the uidefault color that is the parent that this matte is derived from. If null then this is a + * absolute color. + * + * @param uiDefaultParentName Parent color ui default name + */ + public void setUiDefaultParentName(String uiDefaultParentName) { + String old = getUiDefaultParentName(); + this.uiDefaultParentName = uiDefaultParentName; + firePropertyChange("uiDefaultParentName", old, getUiDefaultParentName()); + if (isAbsolute()) { + // reset offsets + float oldH = hueOffset, oldS = saturationOffset, oldB = brightnessOffset; + int oldA = alphaOffset; + hueOffset = 0; + saturationOffset = 0; + brightnessOffset = 0; + alphaOffset = 0; + firePropertyChange("hueOffset", oldH, getHueOffset()); + firePropertyChange("saturationOffset", oldS, getSaturationOffset()); + firePropertyChange("brightnessOffset", oldB, getBrightnessOffset()); + firePropertyChange("alphaOffset", oldA, getAlphaOffset()); + } + updateARGBFromOffsets(); + } + + /** + * Sets the property to use for extracting the color for whatever component + * is passed to the painter. Can be a key in client properties. Can be null. + * @param name + */ + public void setComponentPropertyName(String name) { + String old = componentPropertyName; + firePropertyChange("componentPropertyName", old, componentPropertyName = name); + } + + /** + * Gets the name of the bean property, or client property, on this component + * from which to extract a color used for painting. So for example the color + * used in a painter could be the background of the component. + * + * @return + */ + public String getComponentPropertyName() { + return componentPropertyName; + } + + /** + * Sets whether this color should be represented as a UIResource in UIDefaults + * @param b true if the color should be a ui resource + */ + public void setUiResource(boolean b) { + boolean old = uiResource; + firePropertyChange("uiResource", old, uiResource = b); + } + + /** + * When false this color will become a non-UIResource in the UIManager defaults + * table. This is sometimes required to force swing to use the given color, + * such as with renderers. + * @return false if the color should not be a uiresource + */ + public boolean isUiResource() { + return uiResource; + } + + public float getHueOffset() { + return hueOffset; + } + + public void setHueOffset(float hueOffset) { + float old = getHueOffset(); + this.hueOffset = hueOffset; + firePropertyChange("hueOffset", old, getHueOffset()); + updateARGBFromOffsets(); + } + + public float getSaturationOffset() { + return saturationOffset; + } + + public void setSaturationOffset(float satOffset) { + float old = getSaturationOffset(); + this.saturationOffset = satOffset; + firePropertyChange("saturationOffset", old, getSaturationOffset()); + updateARGBFromOffsets(); + } + + public float getBrightnessOffset() { + return brightnessOffset; + } + + public void setBrightnessOffset(float brightOffset) { + float old = getBrightnessOffset(); + this.brightnessOffset = brightOffset; + firePropertyChange("brightnessOffset", old, getBrightnessOffset()); + updateARGBFromOffsets(); + } + + public int getAlphaOffset() { + return alphaOffset; + } + + public void setAlphaOffset(int alphaOffset) { + int old = getAlphaOffset(); + this.alphaOffset = alphaOffset; + firePropertyChange("alphaOffset", old, alphaOffset); + updateARGBFromOffsets(); + } + + + public void setRed(int red) { + red = clamp(red); + if (this.red != red) { + Color old = getColor(); + int oldr = this.red; + this.red = red; + firePropertyChange("paint", old, getColor()); + firePropertyChange("color", old, getColor()); + firePropertyChange("red", oldr, red); + fireHSBChange(oldr, green, blue); + updateOffsetsFromARGB(); + } + } + + public final int getRed() { + return red; + } + + public void setGreen(int green) { + green = clamp(green); + if (this.green != green) { + Color old = getColor(); + int oldg = this.green; + this.green = green; + firePropertyChange("paint", old, getColor()); + firePropertyChange("color", old, getColor()); + firePropertyChange("green", oldg, green); + fireHSBChange(red, oldg, blue); + updateOffsetsFromARGB(); + } + } + + public final int getGreen() { + return green; + } + + public void setBlue(int blue) { + blue = clamp(blue); + if (this.blue != blue) { + Color old = getColor(); + int oldb = this.blue; + this.blue = blue; + firePropertyChange("paint", old, getColor()); + firePropertyChange("color", old, getColor()); + firePropertyChange("blue", oldb, blue); + fireHSBChange(red, green, oldb); + updateOffsetsFromARGB(); + } + } + + public final int getBlue() { + return blue; + } + + public void setAlpha(int alpha) { + alpha = clamp(alpha); + if (this.alpha != alpha) { + int old = getAlpha(); + this.alpha = alpha; + firePropertyChange("alpha", old, alpha); + firePropertyChange("paint", old, getColor()); + firePropertyChange("color", old, getColor()); + updateOffsetsFromARGB(); + } + } + + public final int getAlpha() { + return alpha; + } + + public Color getColor() { + if (cached == null || red != cached.getRed() || green != cached.getGreen() || + blue != cached.getBlue() || alpha != cached.getAlpha()) { + cached = new Color(red, green, blue, alpha); + } + return cached; + } + + public void setColor(Color c) { + setColor(c, false); + } + + public void setColor(Color c, boolean dontSetAlpha) { + Color oldColor = getColor(); + int oldR = red, oldG = green, oldB = blue, oldA = alpha; + cached = c; + red = c.getRed(); + green = c.getGreen(); + blue = c.getBlue(); + if (!dontSetAlpha) alpha = c.getAlpha(); + updateOffsetsFromARGB(); + firePropertyChange("red", oldR, getRed()); + firePropertyChange("green", oldG, getGreen()); + firePropertyChange("blue", oldB, getBlue()); + fireHSBChange(oldR, oldG, oldB); + if (!dontSetAlpha) firePropertyChange("alpha", oldA, getAlpha()); + firePropertyChange("paint", oldColor, getColor()); + firePropertyChange("color", oldColor, getColor()); + } + + @Override public Paint getPaint() { + return getColor(); + } + + + @Override public String toString() { + if (isAbsolute()) { + return Matte.class.getName() + "[r=" + red + ", g=" + green + ", b=" + blue + ", a=" + alpha + "]"; + } else { + return Matte.class.getName() + "[base=" + uiDefaultParentName + ", H+" + hueOffset + + ", S+" + saturationOffset + ", B+" + brightnessOffset + ", A+" + alphaOffset + "]"; + } + } + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Matte matte = (Matte) o; + if (alpha != matte.alpha) return false; + if (alphaOffset != matte.alphaOffset) return false; + if (Float.compare(matte.alpha, alpha) != 0) return false; + if (blue != matte.blue) return false; + if (Float.compare(matte.brightnessOffset, brightnessOffset) != 0) + return false; + if (green != matte.green) return false; + if (Float.compare(matte.hueOffset, hueOffset) != 0) return false; + if (red != matte.red) return false; + if (uiResource != matte.uiResource) return false; + if (Float.compare(matte.saturationOffset, saturationOffset) != 0) + return false; + if (componentPropertyName != null ? + !componentPropertyName.equals(componentPropertyName) : + matte.componentPropertyName != null) return false; + + if (uiDefaultParentName != null ? + !uiDefaultParentName.equals(matte.uiDefaultParentName) : + matte.uiDefaultParentName != null) return false; + return true; + } + + public int hashCode() { + int result; + result = red; + result = 31 * result + green; + result = 31 * result + blue; + result = 31 * result + alpha; + result = 31 * result + (uiDefaultParentName != null ? + uiDefaultParentName.hashCode() : 0); + result = 31 * result + (componentPropertyName != null ? + componentPropertyName.hashCode() : 0); + result = 31 * result + hueOffset != +0.0f ? + Float.floatToIntBits(hueOffset) : 0; + result = 31 * result + saturationOffset != +0.0f ? + Float.floatToIntBits(saturationOffset) : 0; + result = 31 * result + brightnessOffset != +0.0f ? + Float.floatToIntBits(brightnessOffset) : 0; + result = 31 * result + (uiResource ? 1 : 0); + return result; + } + + @Override public Matte clone() { + Matte m = new Matte(); + m.red = red; + m.green = green; + m.blue = blue; + m.alpha = alpha; + m.brightnessOffset = brightnessOffset; + m.hueOffset = hueOffset; + m.saturationOffset = saturationOffset; + m.alphaOffset = alphaOffset; + m.uiDefaultParentName = uiDefaultParentName; + m.componentPropertyName = componentPropertyName; + m.uiResource = uiResource; + m.setUiDefaults(uiDefaults); + return m; + } + + // ================================================================================================================= + // Private Helper Methods + + private void updateOffsetsFromARGB() { + if (!isAbsolute()) { + tmpf1 = Color.RGBtoHSB(red, green, blue, tmpf1); + Color parentColor = uiDefaults.getColor(uiDefaultParentName); + tmpf2 = Color.RGBtoHSB(parentColor.getRed(), parentColor.getGreen(), parentColor.getBlue(), tmpf2); + // update offset properties and fire events + float oldH = hueOffset, oldS = saturationOffset, oldB = brightnessOffset; + int oldA = alphaOffset; + hueOffset = tmpf1[0] - tmpf2[0]; + saturationOffset = tmpf1[1] - tmpf2[1]; + brightnessOffset = tmpf1[2] - tmpf2[2]; + alphaOffset = alpha - parentColor.getAlpha(); + firePropertyChange("hueOffset", oldH, getHueOffset()); + firePropertyChange("saturationOffset", oldS, getSaturationOffset()); + firePropertyChange("brightnessOffset", oldB, getBrightnessOffset()); + firePropertyChange("alphaOffset", oldA, getAlphaOffset()); + } + } + + private void updateARGBFromOffsets() { + if (!isAbsolute()) { + Color oldColor = getColor(); + // get parent color HSB + Color parentColor = uiDefaults.getColor(uiDefaultParentName); + tmpf1 = Color.RGBtoHSB(parentColor.getRed(), parentColor.getGreen(), parentColor.getBlue(), tmpf1); + // apply offsets + tmpf1[0] = clamp(tmpf1[0] + hueOffset); + tmpf1[1] = clamp(tmpf1[1] + saturationOffset); + tmpf1[2] = clamp(tmpf1[2] + brightnessOffset); + int oldA = getAlpha(); + alpha = clamp(parentColor.getAlpha() + alphaOffset); + updateRGB(tmpf1); + // update fire events + firePropertyChange("alpha", oldA, getAlpha()); + firePropertyChange("paint", oldColor, getColor()); + firePropertyChange("color", oldColor, getColor()); + } + } + + private void updateRGB(float[] hsb) { + int oldR = red, oldG = green, oldB = blue; + int rgb = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]); + red = (rgb >> 16) & 0xFF; + green = (rgb >> 8) & 0xFF; + blue = rgb & 0xFF; + firePropertyChange("red", oldR, getRed()); + firePropertyChange("green", oldG, getGreen()); + firePropertyChange("blue", oldB, getBlue()); + } + + private void fireHSBChange(int oldR, int oldG, int oldB) { + tmpf1 = Color.RGBtoHSB(oldR, oldG, oldB, tmpf1); + tmpf2 = Color.RGBtoHSB(red, green, blue, tmpf2); + firePropertyChange("hue", tmpf1[0], tmpf2[0]); + firePropertyChange("saturation", tmpf1[1], tmpf2[1]); + firePropertyChange("brightness", tmpf1[2], tmpf2[2]); + } + + private float clamp(float value) { + if (value < 0) { + value = 0; + } else if (value > 1) { + value = 1; + } + return value; + } + + private int clamp(int value) { + if (value < 0) { + value = 0; + } else if (value > 255) { + value = 255; + } + return value; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/PaintModel.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/PaintModel.java new file mode 100644 index 0000000000000000000000000000000000000000..15b67f55a2eefab37c30d6fa87797822c482e859 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/PaintModel.java @@ -0,0 +1,64 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import org.jdesktop.beans.AbstractBean; + +import java.awt.Paint; + +/** + * I'd have just called it Paint, but sadly, that name was already taken, and would have been too confusing. + *

+ * Whenever size or position values are required (for example with Texture or Gradient), they are specified in the unit + * square: that is, between 0 and 1 inclusive. They can then later be scaled as necessary by any painting code. + * + * @author rbair + */ +public abstract class PaintModel extends AbstractBean implements Cloneable { + public static enum PaintControlType { + none, control_line, control_rect + } + + protected PaintModel() { } + + /** + * @return an instance of Paint that is represented by this PaintModel. This is often not a reversable operation, + * and hence there is no "setPaint" method. Rather, tweaking the exposed properties of the PaintModel fires, + * when necessary, property change events for the "paint" property, and results in different values returned + * from this method. + */ + public abstract Paint getPaint(); + + /** + * Get the type of controls for this paint model + * + * @return The type of paint controls, one of PaintControlType.none, PaintControlType.control_line or + * PaintControlType.control_rect + */ + public abstract PaintControlType getPaintControlType(); + + + public abstract PaintModel clone(); +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/RadialGradient.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/RadialGradient.java new file mode 100644 index 0000000000000000000000000000000000000000..3e66092320b60d7d99af08ca81b96ee88bcebc58 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/RadialGradient.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import java.awt.Color; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.Paint; +import java.awt.RadialGradientPaint; + +/** + * Represents a RadialGradientPaint. + * + * @author rbair + */ +public class RadialGradient extends AbstractGradient { + protected Paint createPaint(float[] fractions, Matte[] mattes, CycleMethod method) { + Color[] colors = new Color[mattes.length]; + for (int i = 0; i < colors.length; i++) { + colors[i] = mattes[i].getColor(); + } + return new RadialGradientPaint(.5f, .5f, 1, fractions, colors, method); + } + + @Override public RadialGradient clone() { + RadialGradient gradient = new RadialGradient(); + copyTo(gradient); + return gradient; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Texture.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Texture.java new file mode 100644 index 0000000000000000000000000000000000000000..8fd4b2a7b3935830588923f02e9f7a80700f6a2a --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Texture.java @@ -0,0 +1,69 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.paint; + +import java.awt.Paint; +import java.awt.TexturePaint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; + +/** + * Represents a TexturePaint. + * + * @author rbair + */ +public class Texture extends PaintModel { + private static final Rectangle2D RECT = new Rectangle2D.Double(0, 0, 1, 1); + private BufferedImage img; + + public Texture() { + } + + public PaintControlType getPaintControlType() { + return PaintControlType.control_rect; + } + + public void setImage(BufferedImage img) { + BufferedImage old = this.img; + this.img = img; + firePropertyChange("paint", old, this.img); + firePropertyChange("image", old, this.img); + } + + public final BufferedImage getImage() { + return img; + } + + public Paint getPaint() { + return new TexturePaint(img, RECT); + } + + + public Texture clone() { + Texture newTexture = new Texture(); + newTexture.img = this.img; + return newTexture; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasPath.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasPath.java new file mode 100644 index 0000000000000000000000000000000000000000..f5459e1dcdbd7c72edab94f0535ea8817c08c6e7 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasPath.java @@ -0,0 +1,34 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.utils; + +/** + * HasPath - interface for model nodes that can provide there path in the tree + * + * @author Created by Jasper Potts (Jul 2, 2007) + */ +public interface HasPath { + public String getPath(); +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasResources.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasResources.java new file mode 100644 index 0000000000000000000000000000000000000000..82f9c0dd8a93c0f9e9b645207d37463a8e25175f --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasResources.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.utils; + +import java.io.File; + +/** + * HasResources - interface for model nodes that have resources + * + * @author Created by Jasper Potts (Jul 2, 2007) + */ +public interface HasResources { + + public File getResourcesDir(); + + public File getImagesDir(); + + public File getTemplatesDir(); + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasUIDefaults.java b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasUIDefaults.java new file mode 100644 index 0000000000000000000000000000000000000000..c774d796c1c1008094e457c5866ef43970e00db2 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasUIDefaults.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.swingx.designer.utils; + +import javax.swing.UIDefaults; + +/** + * HasUIDefaults - A tagging interface for any class that has UIDefaults + * + * @author Created by Jasper Potts (Jun 22, 2007) + */ +public interface HasUIDefaults { + public UIDefaults getUiDefaults(); +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/DefaultsGenerator.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/DefaultsGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..948686cb0244dd465ebb895a0aaaf617545ac212 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/DefaultsGenerator.java @@ -0,0 +1,726 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.generator; + +import org.jdesktop.swingx.designer.Canvas; +import org.jdesktop.swingx.designer.font.Typeface; +import org.jdesktop.swingx.designer.paint.Matte; +import org.jdesktop.swingx.designer.paint.PaintModel; +import static org.jdesktop.synthdesigner.generator.GeneratorUtils.makePretty; +import static org.jdesktop.synthdesigner.generator.GeneratorUtils.toConstantName; +import static org.jdesktop.synthdesigner.generator.ObjectCodeConvertors.convert; +import static org.jdesktop.synthdesigner.generator.TemplateWriter.read; +import static org.jdesktop.synthdesigner.generator.TemplateWriter.writeSrcFile; +import org.jdesktop.synthdesigner.synthmodel.SynthModel; +import org.jdesktop.synthdesigner.synthmodel.UIComponent; +import org.jdesktop.synthdesigner.synthmodel.UIFont; +import org.jdesktop.synthdesigner.synthmodel.UIIconRegion; +import org.jdesktop.synthdesigner.synthmodel.UIPaint; +import org.jdesktop.synthdesigner.synthmodel.UIProperty; +import org.jdesktop.synthdesigner.synthmodel.UIRegion; +import org.jdesktop.synthdesigner.synthmodel.UIState; +import org.jdesktop.synthdesigner.synthmodel.UIStateType; +import org.jdesktop.synthdesigner.synthmodel.UIStyle; + +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.border.LineBorder; +import javax.swing.border.MatteBorder; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Insets; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import org.jdesktop.synthdesigner.synthmodel.PainterBorder; + +/** + * DefaultsGenerator + *

+ * There are two main sets of defaults that must be configured. The first is + * the actual UI defaults tree. The second is a map of components + regions, which + * are used to decide what SynthStyle to use. + * + * @author Jasper Potts + * @author Richard Bair + */ +public class DefaultsGenerator { + private static String stateTypeImplTemplate; + + private static String getStateTypeTemplate() { + if (stateTypeImplTemplate == null) { + //load the painter template file into an in-memory string to improve performance + //when generating a lot of classes + try { + stateTypeImplTemplate = read("resources/StateImpl.template"); + } catch (IOException e) { + System.err.println("Failed to read template files."); + throw new RuntimeException(e); + } + } + return stateTypeImplTemplate; + } + + /** + * Generate the defaults file and all painter files for a SynthModel. This method + * is the main entry point, called by the Generator class. + * + * @param uiDefaultInit The buffer to write ui default put methods of the form d.put("activeCaption", new + * ColorUIResource(123, 45, 200)); + * @param styleInit The buffer to write out code to generate Synth Style populating the styles map m + * = new HashMap() + * @param model The Synth Model we are writing out defaults class for + * @param variables The variables map pre populated with "PACKAGE" and "LAF_NAME" + * @param packageNamePrefix The package name associated with this synth look and feel. For example, + * org.mypackage.mylaf + * @param painterPackageRoot The directory to write painters out to + */ + public static void generateDefaults(StringBuilder uiDefaultInit, StringBuilder styleInit, SynthModel model, + Map variables, String packageNamePrefix, + File painterPackageRoot) { + // write color palette + uiDefaultInit.append(" //Color palette\n"); + writeColorPalette(uiDefaultInit, model.getColorPalette()); + uiDefaultInit.append("\n"); + // write fonts palette + uiDefaultInit.append(" //Font palette\n"); + uiDefaultInit.append(" d.put(\"defaultFont\", new FontUIResource(defaultFont));\n"); + writeFontPalette(uiDefaultInit, model.getFontPalette()); + uiDefaultInit.append("\n"); + // TODO: Other palettes + uiDefaultInit.append(" //Border palette\n"); + uiDefaultInit.append("\n"); + // write global style + uiDefaultInit.append(" //The global style definition\n"); + writeStyle(model.getStyle(), uiDefaultInit, ""); + uiDefaultInit.append("\n"); + // write components + for (UIComponent c : model.getComponents()) { + String prefix = escape(c.getKey()); + uiDefaultInit.append(" //Initialize ").append(prefix) + .append("\n"); + writeRegion(c, c, prefix, uiDefaultInit, + styleInit, variables, packageNamePrefix, painterPackageRoot); + uiDefaultInit.append("\n"); + } + } + + private static void writeColorPalette(StringBuilder uiDefaultInit, List colors) { + for (UIPaint color : colors) { + uiDefaultInit.append(" d.put(\"") + .append(color.getName()) + .append("\",") + .append(convertPaint(color.getValue())) + .append(");\n"); + } + } + + private static void writeFontPalette(StringBuilder uiDefaultInit, List fonts) { + for (UIFont font : fonts) { + // We have no way of doing CSS style font lists yet so will just + // just the first font + if (!font.getFonts().isEmpty()){ + Typeface t = font.getFonts().get(0); + if (t.isAbsolute()){ + Font f = t.getFont(); + uiDefaultInit.append(" d.put(\"") + .append(font.getName()) + .append("\", new javax.swing.plaf.FontUIResource(\"") + .append(f.getName()) + .append("\", ") + .append(f.getStyle()) + .append(", ") + .append(f.getSize()) + .append("));\n"); + } else { + uiDefaultInit.append(" d.put(\"") + .append(font.getName()) + .append("\", new DerivedFont(\"") + .append(t.getUiDefaultParentName()) + .append("\", ") + .append(t.getSizeOffset()) + .append("f, "); + switch (t.getBold()){ + case Default: + uiDefaultInit.append("null"); + break; + case On: + uiDefaultInit.append("true"); + break; + case Off: + uiDefaultInit.append("false"); + break; + } + uiDefaultInit.append(", "); + switch (t.getItalic()){ + case Default: + uiDefaultInit.append("null"); + break; + case On: + uiDefaultInit.append("true"); + break; + case Off: + uiDefaultInit.append("false"); + break; + } + uiDefaultInit.append("));\n"); + } + } + } + } + + /** + * Write out the UIDefaults entries for a style + * + * @param style The style to write defaults entries for + * @param uiDefaultInit The buffer to write ui default put methods of the form d.put("activeCaption", new + * ColorUIResource(123, 45, 200)); + * @param prefix The prefix for the style property names, for the model path where the style is from, should + * end with a "." + */ + private static void writeStyle(UIStyle style, StringBuilder uiDefaultInit, String prefix) { + if (!style.isTextForegroundInherited()) writeMatte(prefix + "textForeground", style.getTextForeground(), uiDefaultInit); + if (!style.isTextBackgroundInherited()) writeMatte(prefix + "textBackground", style.getTextBackground(), uiDefaultInit); + if (!style.isBackgroundInherited()) writeMatte(prefix + "background", style.getBackground(), uiDefaultInit); + if (!style.isFontInherited()) writeTypeFace(prefix + "font", style.getFont(), uiDefaultInit); + for (UIProperty property : style.getUiProperties()) { + switch (property.getType()) { + case BOOLEAN: + Boolean b = ((Boolean)property.getValue()); + if (b != null) { + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", ") + .append(b ? "Boolean.TRUE" : "Boolean.FALSE") + .append(");\n"); + } + break; + case STRING: + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", \"") + .append(property.getValue().toString()) + .append("\");\n"); + break; + case INT: + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", new Integer(") + .append(((Integer) property.getValue()).intValue()) + .append("));\n"); + break; + case FLOAT: + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", new Float(") + .append(((Float) property.getValue()).floatValue()) + .append("f));\n"); + break; + case DOUBLE: + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", new Double(") + .append(((Double) property.getValue()).doubleValue()) + .append("));\n"); + break; + case COLOR: + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", ") + .append(convertPaint((Matte)property.getValue())) + .append(");\n"); + break; + case FONT: + writeTypeFace(prefix.replace("\"", "\\\"") + property.getName(), + (Typeface) property.getValue(), uiDefaultInit); + break; + case INSETS: + Insets i = (Insets) property.getValue(); + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", new InsetsUIResource(") + .append(i.top).append(", ").append(i.left).append(", ").append(i.bottom).append(", ") + .append(i.right) + .append("));\n"); + break; + case DIMENSION: + Dimension d = (Dimension) property.getValue(); + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", new DimensionUIResource(") + .append(d.width).append(", ").append(d.height) + .append("));\n"); + break; + case BORDER: + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(property.getName()) + .append("\", new BorderUIResource("); + uiDefaultInit.append(convertBorder( + (Border)property.getValue())); + uiDefaultInit.append("));\n"); + break; + } + } + } + + private static void writeMatte(String propertyName, Matte matte, StringBuilder uiDefaultInit) { + if (matte==null) System.err.println("Error matte is NULL for ["+propertyName+"]"); + uiDefaultInit.append(" d.put(\"") + .append(propertyName) + .append("\", ") + .append(convertPaint(matte)) + .append(");\n"); + } + + private static void writeTypeFace(String propertyName, Typeface typeface, StringBuilder uiDefaultInit) { + uiDefaultInit.append(" d.put(\"") + .append(propertyName) + .append("\", new DerivedFont(\"") + .append(typeface.getUiDefaultParentName()) + .append("\", ") + .append(typeface.getSizeOffset()) + .append("f, "); + switch (typeface.getBold()) { + case Default: + uiDefaultInit.append("null,"); + break; + case Off: + uiDefaultInit.append("Boolean.FALSE,"); + break; + case On: + uiDefaultInit.append("Boolean.TRUE,"); + break; + } + switch (typeface.getItalic()) { + case Default: + uiDefaultInit.append("null"); + break; + case Off: + uiDefaultInit.append("Boolean.FALSE"); + break; + case On: + uiDefaultInit.append("Boolean.TRUE"); + break; + } + uiDefaultInit.append("));\n"); + } + + + /** + * Write out code for a Component or Region + * + * @param comp This may be the same as the region reg or is the parent component + * containing the region + * @param region The region we are writing out + * @param prefix This is dot sperated path of component and sub regions to and including the region + * reg of the form [Comp].[Region]......[Region] path + * @param uiDefaultInit This is for inserting into org.mypackage.mylaf.MyDefaults#getDefaults() method + * @param styleInit This is for inserting into org.mypackage.mylaf.MyDefaults#initialize() method + * @param variables The variables map pre populated with "PACKAGE" and "LAF_NAME" + * @param packageNamePrefix The package name associated with this synth look and feel. For example, + * org.mypackage.mylaf + * @param painterPackageRoot The directory to write painters out to + */ + private static void writeRegion(UIComponent comp, UIRegion region, String prefix, StringBuilder uiDefaultInit, + StringBuilder styleInit, Map variables, + String packageNamePrefix, File painterPackageRoot) { + // register component with LAF + String regionCode = GeneratorUtils.getRegionNameCaps(region.getName()); + if (regionCode == null) { + throw new IllegalStateException("We were asked to encode a region we know nothing about: " + region.getName()); + } else { + regionCode = "Region." + regionCode; + } + + //construct the list of States that accompany this registration. + StringBuffer regString = new StringBuffer(); //like: Enabled,Disabled,Foo,Default,Etc + List types = comp.getStateTypes(); //state types are only defined on the UIComponent level + if (types != null && types.size() > 0) { + for (UIStateType type : types) { + regString.append(type.getKey()); + regString.append(","); + } + //remove the last "," + regString.deleteCharAt(regString.length()-1); + } + + styleInit.append(" register(") + .append(regionCode) + .append(", \"") + .append(prefix); + styleInit.append("\""); + styleInit.append(");\n"); + + // write content margins + Insets i = (Insets) region.getContentMargins(); + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(".contentMargins") + .append("\", new InsetsUIResource(") + .append(i.top).append(", ").append(i.left).append(", ").append(i.bottom).append(", ").append(i.right) + .append("));\n"); + // write opaque if true + if (region instanceof UIComponent && ((UIComponent)region).isOpaque()) { + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(".opaque") + .append("\", Boolean.TRUE);\n"); + } + //write the State, if necessary + if (!regString.equals("Enabled,MouseOver,Pressed,Disabled,Focused,Selected,Default") && types.size() > 0) { + //there were either custom states, or the normal states were in a custom order + //so go ahead and write out prefix.State + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(".States") + .append("\", \"") + .append(regString) + .append("\");\n"); + } + //write out any custom states, if necessary + for (UIStateType type : types) { + String synthState = type.getKey(); + if (!"Enabled".equals(synthState) && + !"MouseOver".equals(synthState) && + !"Pressed".equals(synthState) && + !"Disabled".equals(synthState) && + !"Focused".equals(synthState) && + !"Selected".equals(synthState) && + !"Default".equals(synthState)) { + //what we have here, gentlemen, is a bona-fide custom state. + try { + //if the type is not one of the standard types, then construct a name for + //the new type, and write out a new subclass of State. + java.lang.String className = makePretty(prefix) + synthState + "State"; + java.lang.String body = type.getCodeSnippet(); + variables.put("STATE_NAME", className); + variables.put("STATE_KEY", synthState); + variables.put("BODY", body); + + writeSrcFile(getStateTypeTemplate(), variables, new java.io.File(painterPackageRoot, className + ".java")); + + variables.remove("STATE_NAME"); + variables.remove("STATE_KEY"); + variables.remove("BODY"); + + uiDefaultInit.append(" d.put(\"") + .append(prefix) + .append(".") + .append(synthState) + .append("\", new ") + .append(className) + .append("());\n"); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + // write region style + writeStyle(region.getStyle(), uiDefaultInit, prefix + "."); + + try { + boolean hasCanvas = hasCanvas(region); + if (hasCanvas) { + PainterGenerator.writePainter(region, variables, painterPackageRoot, prefix); + } + String fileNamePrefix = makePretty(prefix) + "Painter"; + // write states ui defaults + for (UIState state : region.getBackgroundStates()) { + String statePrefix = prefix + "[" + state.getName() + "]"; + // write state style + writeStyle(state.getStyle(), uiDefaultInit, statePrefix + "."); + // write painter + if (hasCanvas) { + writeLazyPainter(state, uiDefaultInit, statePrefix, packageNamePrefix, fileNamePrefix, "background"); + } + } + for (UIState state : region.getForegroundStates()) { + String statePrefix = prefix + "[" + state.getName() + "]"; + // write state style + writeStyle(state.getStyle(), uiDefaultInit, statePrefix + "."); + // write painter + if (hasCanvas) { + writeLazyPainter(state, uiDefaultInit, statePrefix, packageNamePrefix, fileNamePrefix, "foreground"); + } + } + for (UIState state : region.getBorderStates()) { + String statePrefix = prefix + "[" + state.getName() + "]"; + // write state style + writeStyle(state.getStyle(), uiDefaultInit, statePrefix + "."); + // write painter + if (hasCanvas) { + writeLazyPainter(state, uiDefaultInit, statePrefix, packageNamePrefix, fileNamePrefix, "border"); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + // handle sub regions + for (UIRegion subRegion : region.getSubRegions()) { + String subregionName = prefix + ":" + escape(subRegion.getKey()); + if (subRegion instanceof UIIconRegion) { + writeIconRegion(comp, (UIIconRegion) subRegion, prefix, uiDefaultInit, + variables, packageNamePrefix, painterPackageRoot); + } else if (subRegion instanceof UIComponent) { + // inner named component + UIComponent subComponent = (UIComponent) subRegion; + writeRegion(subComponent, subRegion, subregionName, + uiDefaultInit, styleInit, variables, packageNamePrefix, painterPackageRoot); + } else { + writeRegion(comp, subRegion, subregionName, uiDefaultInit, styleInit, variables, + packageNamePrefix, painterPackageRoot); + } + } + } + + private static void writeLazyPainter(UIState state, StringBuilder uiDefaultInit, String statePrefix, String packageNamePrefix, String fileNamePrefix, String painterSuffix) { + Canvas canvas = state.getCanvas(); + if (!canvas.isBlank()) { + Insets si = canvas.getStretchingInsets(); + boolean inverted = state.isInverted(); + UIStyle.CacheMode cache = state.getStyle().getCacheMode(); + String cacheModeString = null; + switch (cache) { + case NO_CACHING: cacheModeString = "AbstractRegionPainter.PaintContext.CacheMode.NO_CACHING"; break; + case FIXED_SIZES: cacheModeString = "AbstractRegionPainter.PaintContext.CacheMode.FIXED_SIZES"; break; + case NINE_SQUARE_SCALE: cacheModeString = "AbstractRegionPainter.PaintContext.CacheMode.NINE_SQUARE_SCALE"; break; + } + double maxH = state.getStyle().getMaxHozCachedImgScaling(); + double maxV = state.getStyle().getMaxVertCachedImgScaling(); + String stateConstant = toConstantName(painterSuffix + "_" + UIState.keysToString(state.getStateKeys())); + + uiDefaultInit.append(" d.put(\"") + .append(statePrefix) + .append(".").append(painterSuffix).append("Painter\", new LazyPainter(\"") + .append(packageNamePrefix).append(".").append(fileNamePrefix) + .append("\", ") + .append(fileNamePrefix).append(".").append(stateConstant).append(", ") + .append(convert(si)).append(", ") + .append(convert(canvas.getSize())).append(", ") + .append(inverted).append(", ") + .append(cacheModeString).append(", ") + .append(maxH == Double.POSITIVE_INFINITY ? "Double.POSITIVE_INFINITY" : maxH).append(", ") + .append(maxV == Double.POSITIVE_INFINITY ? "Double.POSITIVE_INFINITY" : maxV).append("));\n"); + } + } + + + /** + * Write out code for a IconRegion + * + * @param comp This may be the same as the region region or is the parent component + * containing the region + * @param region The region we are writing out + * @param prefix This is [Comp][Region]......[Region] path + * @param key The key for this icon. + * @param uiDefaultInit This is for inserting into org.mypackage.mylaf.MyDefaults#getDefaults() method + * @param variables The variables map pre populated with "PACKAGE" and "LAF_NAME" + * @param packageNamePrefix The package name associated with this synth look and feel. For example, + * org.mypackage.mylaf + * @param painterPackageRoot The directory to write painters out to + */ + private static void writeIconRegion(UIComponent comp, UIIconRegion region, String prefix, + StringBuilder uiDefaultInit, Map variables, + String packageNamePrefix, File painterPackageRoot) { + + Dimension size = null; + String fileNamePrefix = makePretty(prefix) + "Painter"; + // write states ui defaults + for (UIState state : region.getBackgroundStates()) {// TODO: Handle Background,Foreground and Borders States Lists? Actually not sure that IconRegions need support borders or foregrounds + Canvas canvas = state.getCanvas(); + if (!canvas.isBlank()) { + String statePrefix = prefix + "[" + state.getName() + "]"; + // Put Painter in UiDefaults + writeLazyPainter(state, uiDefaultInit, statePrefix, packageNamePrefix, fileNamePrefix, region.getKey()); + size = canvas.getSize(); + } + } + + if (size != null) { + // Put SynthIconImpl wrapper in UiDefaults + String key = region.getBasicKey() == null ? prefix + "." + region.getKey() : region.getBasicKey(); + uiDefaultInit.append(" d.put(\"") + .append(key) + .append("\", new NimbusIcon(\"") //TODO should this be wrapped in an IconUIResource? + .append(prefix) + .append("\", \"") + .append(region.getKey()) + .append("Painter") + .append("\", ") + .append(size.width) + .append(", ") + .append(size.height) + .append("));\n"); + } + + // handle sub regions + if (region.getSubRegions().length > 0) { + // there is no meaning to a sub region inside a IconRegion + throw new IllegalStateException("You can not have sub regions inside UiIconRegions. \"" + + comp.getSubRegions()[0].getName() + "\" is inside \"" + + prefix.substring(0, prefix.length() - 1) + "\""); + } + } + + /** + * Utility method for escaping all double quotes with backslash double-quote. + */ + private static String escape(String s) { + return s.replace("\"", "\\\""); + } + + private static String convertPaint(PaintModel paint){ + if (paint instanceof Matte){ + Matte matte = (Matte)paint; + if (matte.isAbsolute()){ + String colorParams = convert(matte.getColor()); + if (matte.isUiResource()) { + return "new ColorUIResource(" + colorParams + ")"; + } else { + return colorParams; + } + } else { + String s = "getDerivedColor(\"" + + matte.getUiDefaultParentName()+"\","+ + matte.getHueOffset()+"f,"+matte.getSaturationOffset()+ + "f,"+matte.getBrightnessOffset()+"f,"+ + matte.getAlphaOffset(); + if (matte.isUiResource()) { + return s + ")"; + } else { + return s + ",false)"; + } + } + } else { + //TODO: What about gradients etc here? + System.err.println("Error: Could not write paint in " + + "DefaultsGenerator as it was not a Matte. = "+ + paint.getClass().getName()); + return ""; + } + } + + private static String convertBorder(Border val) { + StringBuilder uiDefaultInit = new StringBuilder(); + Insets i; + if (val instanceof PainterBorder) { + PainterBorder pb = (PainterBorder) val; + i = pb.getBorderInsets(); + uiDefaultInit.append("new PainterBorder(\"") + .append(pb.getPainterName()) + .append("\", new Insets(") + .append(i.top).append(", ") + .append(i.left).append(", ") + .append(i.bottom).append(", ") + .append(i.right) + .append("))"); + } else if (val instanceof EmptyBorder) { + i = ((EmptyBorder) val).getBorderInsets(); + uiDefaultInit.append("BorderFactory.createEmptyBorder(") + .append(i.top).append(", ") + .append(i.left).append(", ") + .append(i.bottom).append(", ") + .append(i.right) + .append(")"); + } else if (val instanceof LineBorder) { + LineBorder border = (LineBorder) val; + uiDefaultInit.append("BorderFactory.createLineBorder(") + .append(convert(border.getLineColor())) + .append(",") + .append(border.getThickness()) + .append(")"); + } else if (val instanceof EtchedBorder) { + EtchedBorder border = (EtchedBorder) val; + uiDefaultInit.append("BorderFactory.createEtchedBorder(") + .append(border.getEtchType()) + .append(",") + .append(convert(border.getHighlightColor())) + .append(",") + .append(convert(border.getShadowColor())) + .append(")"); + } else if (val instanceof BevelBorder) { + BevelBorder border = (BevelBorder) val; + uiDefaultInit.append("BorderFactory.createEtchedBorder(") + .append(border.getBevelType()) + .append(",") + .append(convert(border.getHighlightOuterColor())) + .append(",") + .append(convert(border.getHighlightInnerColor())) + .append(",") + .append(convert(border.getShadowOuterColor())) + .append(",") + .append(convert(border.getShadowInnerColor())) + .append(")"); + } else if (val instanceof MatteBorder) { + MatteBorder border = (MatteBorder) val; + i = border.getBorderInsets(); + uiDefaultInit.append("BorderFactory.createEmptyBorder(") + .append(i.top).append(", ") + .append(i.left).append(", ") + .append(i.bottom).append(", ") + .append(i.right).append(", ") + .append(convert(border.getMatteColor())) + .append(")"); + } else if (val instanceof CompoundBorder) { + CompoundBorder border = (CompoundBorder) val; + uiDefaultInit.append("BorderFactory.createEmptyBorder(") + .append(convertBorder(border.getOutsideBorder())) + .append(",") + .append(convertBorder(border.getInsideBorder())) + .append(")"); + } + return uiDefaultInit.toString(); + } + + private static boolean hasCanvas(UIRegion region) { + for (UIState s : region.getBackgroundStates()) { + if (!s.getCanvas().isBlank()) return true; + } + for (UIState s : region.getBorderStates()) { + if (!s.getCanvas().isBlank()) return true; + } + for (UIState s : region.getForegroundStates()) { + if (!s.getCanvas().isBlank()) return true; + } + for (UIRegion subregion : region.getSubRegions()) { + if (hasCanvas(subregion)) return true; + } + return false; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/Generator.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/Generator.java new file mode 100644 index 0000000000000000000000000000000000000000..6ab4b87d18ad38d9f28eb5895ed16b9be4478094 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/Generator.java @@ -0,0 +1,289 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.generator; + +import static org.jdesktop.synthdesigner.generator.TemplateWriter.read; +import static org.jdesktop.synthdesigner.generator.TemplateWriter.writeSrcFile; +import org.jdesktop.synthdesigner.synthmodel.SynthModel; +import org.jibx.runtime.BindingDirectory; +import org.jibx.runtime.IBindingFactory; +import org.jibx.runtime.IUnmarshallingContext; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Generates the various Java artifacts based on a SynthModel. + *

+ * Generated source files are split up among two different locations. There are those source files that are meant to be + * edited (generally, only the LookAndFeel class itself) and those that are autogenerated (everything else). + *

+ * All autogenerated files are placed in "buildPackageRoot" and are package private. A LAF author (one who has access to + * the generated sources) will be able to access any of the generated classes. Those referencing the library, however, + * will only be able to access the main LookAndFeel class itself (since everything else is package private). + * + * @author Richard Bair + * @author Jasper Potts + */ +public class Generator { + /** A map of variables that are used for variable substitution in the template files. */ + private Map variables; + + private boolean full = false; + private File buildPackageRoot; + private File srcPackageRoot; + private String packageNamePrefix; + private String lafName; + private SynthModel model; + + /** + * MAIN APPLICATION + *

+ * This is for using the generator as part of the java build process + * + * @param args The commandline arguments + */ + public static void main(String[] args) { + if (args.length == 0 || (args.length % 2) != 0) { + System.out.println("Usage: generator [-options]\n" + + " -full True if we should build the whole LAF or false for building just states and painters.\n" + + " -skinFile Path to the skin.laf file for the LAF to be generated from.\n" + + " -buildDir The directory beneath which the build-controlled artifacts (such as the Painters) should\n" + + " be placed. This is the root directory beneath which the necessary packages and source\n" + + " files will be created.\n" + + " -srcDir The directory beneath which the normal user-controlled artifacts (such as the core\n" + + " LookAndFeel file) should be placed. These are one-time generated files. This is the root\n" + + " directory beneath which the necessary packages and source files will be created.\n" + + " -resourcesDir The resources directory containing templates and images.\n" + + " -packagePrefix The package name associated with this synth look and feel. For example,\n" + + " \"org.mypackage.mylaf\"\n" + + " -lafName The name of the laf, such as \"MyLAF\".\n"); + } else { + boolean full = false; + File skinFile = new File(System.getProperty("user.dir")); + File buildDir = new File(System.getProperty("user.dir")); + File srcDir = new File(System.getProperty("user.dir")); + File resourcesDir = new File(System.getProperty("user.dir")); + String packagePrefix = "org.mypackage.mylaf"; + String lafName = "MyLAF"; + for (int i = 0; i < args.length; i += 2) { + String key = args[i].trim().toLowerCase(); + String value = args[i + 1].trim(); + if ("-full".equals(key)) { + full = Boolean.parseBoolean(value); + } else if ("-skinfile".equals(key)) { + skinFile = new File(value); + } else if ("-builddir".equals(key)) { + buildDir = new File(value); + } else if ("-srcdir".equals(key)) { + srcDir = new File(value); + } else if ("-resourcesdir".equals(key)) { + resourcesDir = new File(value); + } else if ("-packageprefix".equals(key)) { + packagePrefix = value; + } else if ("-lafname".equals(key)) { + lafName = value; + } + } + System.out.println("### GENERATING LAF CODE ################################"); + System.out.println(" full :" + full); + System.out.println(" skinFile :" + skinFile.getAbsolutePath()); + System.out.println(" buildDir :" + buildDir.getAbsolutePath()); + System.out.println(" srcDir :" + srcDir.getAbsolutePath()); + System.out.println(" resourcesDir :" + resourcesDir.getAbsolutePath()); + System.out.println(" packagePrefix :" +packagePrefix); + System.out.println(" lafName :" +lafName); + try { + // LOAD SKIN MODEL + IBindingFactory bindingFactory = BindingDirectory.getFactory(SynthModel.class); + IUnmarshallingContext mctx = bindingFactory.createUnmarshallingContext(); + mctx.setDocument(new FileInputStream(skinFile), "UTF-8"); + // pass resources directory in as user context so it can be used in SynthModel preSet + mctx.setUserContext(resourcesDir); + SynthModel model = (SynthModel) mctx.unmarshalElement(); + // create and run generator + Generator generator = new Generator(full, buildDir, srcDir, packagePrefix, lafName, model); + generator.generate(); + } catch (Exception e) { + System.err.println("Error loading skin and generating java src:"); + e.printStackTrace(); + } + } + } + + /** + * Creates a new Generator, capable of outputting the source code artifacts related to a given SynthModel. It is + * capable of generating the one-time artifacts in addition to the regeneration of build-controlled artifacts. + * + * @param full True if we should build the whole LAF or false for building just states and painters. + * @param buildDir The directory beneath which the build-controlled artifacts (such as the Painters) should + * be placed. This is the root directory beneath which the necessary packages and source + * files will be created. + * @param srcDir The directory beneath which the normal user-controlled artifacts (such as the core + * LookAndFeel file) should be placed. These are one-time generated files. This is the root + * directory beneath which the necessary packages and source files will be created. + * @param packageNamePrefix The package name associated with this synth look and feel. For example, + * org.mypackage.mylaf + * @param lafName The name of the laf, such as MyLAF. + * @param model The actual SynthModel to base these generated files on. + */ + public Generator(boolean full, File buildDir, File srcDir, String packageNamePrefix, String lafName, + SynthModel model) { + this.full = full; + //validate the input variables + if (packageNamePrefix == null) { + throw new IllegalArgumentException("You must specify a package name prefix"); + } + if (buildDir == null) { + throw new IllegalArgumentException("You must specify the build directory"); + } + if (srcDir == null) { + throw new IllegalArgumentException("You must specify the source directory"); + } + if (model == null) { + throw new IllegalArgumentException("You must specify the SynthModel"); + } + if (lafName == null) { + throw new IllegalArgumentException("You must specify the name of the look and feel"); + } + + //construct the map which is used to do variable substitution of the template + //files + variables = new HashMap(); + variables.put("PACKAGE", packageNamePrefix); + variables.put("LAF_NAME", lafName); + + //generate and save references to the package-root directories. + //(That is, given the buildDir and srcDir, generate references to the + //org.mypackage.mylaf subdirectories) + buildPackageRoot = new File(buildDir, packageNamePrefix.replaceAll("\\.", "\\/")); + buildPackageRoot.mkdirs(); + srcPackageRoot = new File(srcDir, packageNamePrefix.replaceAll("\\.", "\\/")); + srcPackageRoot.mkdirs(); + + //save the variables + this.packageNamePrefix = packageNamePrefix; + this.lafName = lafName; + this.model = model; + } + + public void generate() { + //Generate the one-time files. If these files already exist, skip the + //ones that exist and create the missing ones. Register warnings for the + //already existing files. + + //TODO Skip existing files, send warnings, etc. + if (full) { + try { + //create the LookAndFeel file + String template = read("resources/LookAndFeel.template"); + writeSrcFile(template, variables, new File(srcPackageRoot, lafName + "LookAndFeel.java")); + } catch (IOException e) { + e.printStackTrace(); + } + } + //create the painters and such. + regenerate(); + } + + public void regenerate() { + try { + if (full) { + //first, create the AbstractRegionPainter.java file. + String template = read("resources/AbstractRegionPainter.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "AbstractRegionPainter.java")); + + //write out BlendingMode.java + template = read("resources/BlendingMode.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "BlendingMode.java")); + + //create the SynthPainterImpl class + template = read("resources/SynthPainterImpl.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "SynthPainterImpl.java")); + + //create the IconImpl class + template = read("resources/IconImpl.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, lafName + "Icon.java")); + + //create the StyleImpl class + template = read("resources/StyleImpl.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, lafName + "Style.java")); + + //write out Effect.java + template = read("resources/Effect.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "Effect.java")); + + //write out EffectUtils.java + template = read("resources/EffectUtils.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "EffectUtils.java")); + + //write out ShadowEffect.java + template = read("resources/ShadowEffect.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "ShadowEffect.java")); + + //write out DropShadowEffect.java + template = read("resources/DropShadowEffect.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "DropShadowEffect.java")); + + //write out InnerShadowEffect.java + template = read("resources/InnerShadowEffect.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "InnerShadowEffect.java")); + + //write out InnerGlowEffect.java + template = read("resources/InnerGlowEffect.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "InnerGlowEffect.java")); + + //write out OuterGlowEffect.java + template = read("resources/OuterGlowEffect.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "OuterGlowEffect.java")); + + //write out State.java + template = read("resources/State.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "State.java")); + + template = read("resources/ImageCache.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "ImageCache.java")); + + template = read("resources/ImageScalingHelper.template"); + writeSrcFile(template, variables, new File(buildPackageRoot, "ImageScalingHelper.java")); + } + //next, populate the first set of ui defaults based on what is in the + //various palettes of the synth model + StringBuilder uiDefaultInit = new StringBuilder(); + StringBuilder styleInit = new StringBuilder(); + DefaultsGenerator.generateDefaults(uiDefaultInit, styleInit, model, variables, packageNamePrefix, + buildPackageRoot); + variables.put("UI_DEFAULT_INIT", uiDefaultInit.toString()); + variables.put("STYLE_INIT", styleInit.toString()); + writeSrcFile(read("resources/Defaults.template"), variables, + new File(buildPackageRoot, lafName + "Defaults.java")); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/GeneratorUtils.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/GeneratorUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..0d0fb75f52aa01891b417bd11178f37b05a510f1 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/GeneratorUtils.java @@ -0,0 +1,295 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.generator; + +import javax.swing.plaf.synth.Region; +import javax.swing.plaf.synth.SynthConstants; + +/** + * GeneratorUtils + * + * @author Richard Bair + * @author Jasper Potts + */ +class GeneratorUtils { + private GeneratorUtils() {} + + /** + * Given a synth state, create the appropriate name as it would be used for a ui default key. + *

+ * For example: + *

+ * enabled enabled+over enabled+over+selected + */ + static String toUIDefaultKey(int state) { + StringBuffer buffer = new StringBuffer(); + if ((state & SynthConstants.DEFAULT) == SynthConstants.DEFAULT) { + buffer.append("default"); + } + if ((state & SynthConstants.DISABLED) == SynthConstants.DISABLED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("disabled"); + } + if ((state & SynthConstants.ENABLED) == SynthConstants.ENABLED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("enabled"); + } + if ((state & SynthConstants.FOCUSED) == SynthConstants.FOCUSED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("focused"); + } + if ((state & SynthConstants.MOUSE_OVER) == SynthConstants.MOUSE_OVER) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("over"); + } + if ((state & SynthConstants.PRESSED) == SynthConstants.PRESSED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("down"); + } + if ((state & SynthConstants.SELECTED) == SynthConstants.SELECTED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("selected"); + } + return buffer.toString(); + } + + //takes a states string of the form Enabled+Foo+Bar. + //removes any whitespace. Replaces the + signs with And. + static String toClassName(String states) { + String s = states.replace(" ", ""); + s = states.replace("+", "And"); + return s; + } + + //takes a states string of the form Enabled+Foo+Bar. + //removes any whitespace. Replaces the + signs with _. + //capitalizes the whole lot + static String toConstantName(String states) { + String s = states.replace(" ", ""); + s = states.replace("+", "_"); + return s.toUpperCase(); + } + + /** + * Given a string "s" of the form: + * + * A.\"A.a\".B + * + * Make it such that: + * + * AAAB + * + * For example, ComboBox.\"ComboBox.arrowButton\" would become + * ComboBoxComboBoxArrowButton + * + * @param s + * @return + */ + static String makePretty(String s) { + char[] src = s.toCharArray(); + char[] dst = new char[src.length]; + int dstIndex = 0; + for (int i=0; i + * SynthConstants.ENABLED | SynthConstants.MOUSE_OVER + */ + static String toJavaList(int state) { + StringBuffer buffer = new StringBuffer(); + if ((state & SynthConstants.DEFAULT) == SynthConstants.DEFAULT) { + buffer.append("SynthConstants.DEFAULT"); + } + if ((state & SynthConstants.DISABLED) == SynthConstants.DISABLED) { + if (buffer.length() > 0) buffer.append(" | "); + buffer.append("SynthConstants.DISABLED"); + } + if ((state & SynthConstants.ENABLED) == SynthConstants.ENABLED) { + if (buffer.length() > 0) buffer.append(" | "); + buffer.append("SynthConstants.ENABLED"); + } + if ((state & SynthConstants.FOCUSED) == SynthConstants.FOCUSED) { + if (buffer.length() > 0) buffer.append(" | "); + buffer.append("SynthConstants.FOCUSED"); + } + if ((state & SynthConstants.MOUSE_OVER) == SynthConstants.MOUSE_OVER) { + if (buffer.length() > 0) buffer.append(" | "); + buffer.append("SynthConstants.MOUSE_OVER"); + } + if ((state & SynthConstants.PRESSED) == SynthConstants.PRESSED) { + if (buffer.length() > 0) buffer.append(" | "); + buffer.append("SynthConstants.PRESSED"); + } + if ((state & SynthConstants.SELECTED) == SynthConstants.SELECTED) { + if (buffer.length() > 0) buffer.append(" | "); + buffer.append("SynthConstants.SELECTED"); + } + return buffer.toString(); + } + + /** + * Checks the given region name to discover if it is one of the standard synth regions. If so, return the name in + * caps and such. Otherwise, return a big fat null. + *

+ * I have to do this because, unfortunately, synth's Region doesn't implement equals. + */ + static String getRegionNameCaps(String regionName) { + if (Region.ARROW_BUTTON.getName().equals(regionName)) { + return "ARROW_BUTTON"; + } else if (Region.BUTTON.getName().equals(regionName)) { + return "BUTTON"; + } else if (Region.CHECK_BOX.getName().equals(regionName)) { + return "CHECK_BOX"; + } else if (Region.CHECK_BOX_MENU_ITEM.getName().equals(regionName)) { + return "CHECK_BOX_MENU_ITEM"; + } else if (Region.COLOR_CHOOSER.getName().equals(regionName)) { + return "COLOR_CHOOSER"; + } else if (Region.COMBO_BOX.getName().equals(regionName)) { + return "COMBO_BOX"; + } else if (Region.DESKTOP_ICON.getName().equals(regionName)) { + return "DESKTOP_ICON"; + } else if (Region.DESKTOP_PANE.getName().equals(regionName)) { + return "DESKTOP_PANE"; + } else if (Region.EDITOR_PANE.getName().equals(regionName)) { + return "EDITOR_PANE"; + } else if (Region.FILE_CHOOSER.getName().equals(regionName)) { + return "FILE_CHOOSER"; + } else if (Region.FORMATTED_TEXT_FIELD.getName().equals(regionName)) { + return "FORMATTED_TEXT_FIELD"; + } else if (Region.INTERNAL_FRAME.getName().equals(regionName)) { + return "INTERNAL_FRAME"; + } else if (Region.INTERNAL_FRAME_TITLE_PANE.getName().equals(regionName)) { + return "INTERNAL_FRAME_TITLE_PANE"; + } else if (Region.LABEL.getName().equals(regionName)) { + return "LABEL"; + } else if (Region.LIST.getName().equals(regionName)) { + return "LIST"; + } else if (Region.MENU.getName().equals(regionName)) { + return "MENU"; + } else if (Region.MENU_BAR.getName().equals(regionName)) { + return "MENU_BAR"; + } else if (Region.MENU_ITEM.getName().equals(regionName)) { + return "MENU_ITEM"; + } else if (Region.MENU_ITEM_ACCELERATOR.getName().equals(regionName)) { + return "MENU_ITEM_ACCELERATOR"; + } else if (Region.OPTION_PANE.getName().equals(regionName)) { + return "OPTION_PANE"; + } else if (Region.PANEL.getName().equals(regionName)) { + return "PANEL"; + } else if (Region.PASSWORD_FIELD.getName().equals(regionName)) { + return "PASSWORD_FIELD"; + } else if (Region.POPUP_MENU.getName().equals(regionName)) { + return "POPUP_MENU"; + } else if (Region.POPUP_MENU_SEPARATOR.getName().equals(regionName)) { + return "POPUP_MENU_SEPARATOR"; + } else if (Region.PROGRESS_BAR.getName().equals(regionName)) { + return "PROGRESS_BAR"; + } else if (Region.RADIO_BUTTON.getName().equals(regionName)) { + return "RADIO_BUTTON"; + } else if (Region.RADIO_BUTTON_MENU_ITEM.getName().equals(regionName)) { + return "RADIO_BUTTON_MENU_ITEM"; + } else if (Region.ROOT_PANE.getName().equals(regionName)) { + return "ROOT_PANE"; + } else if (Region.SCROLL_BAR.getName().equals(regionName)) { + return "SCROLL_BAR"; + } else if (Region.SCROLL_BAR_THUMB.getName().equals(regionName)) { + return "SCROLL_BAR_THUMB"; + } else if (Region.SCROLL_BAR_TRACK.getName().equals(regionName)) { + return "SCROLL_BAR_TRACK"; + } else if (Region.SCROLL_PANE.getName().equals(regionName)) { + return "SCROLL_PANE"; + } else if (Region.SEPARATOR.getName().equals(regionName)) { + return "SEPARATOR"; + } else if (Region.SLIDER.getName().equals(regionName)) { + return "SLIDER"; + } else if (Region.SLIDER_THUMB.getName().equals(regionName)) { + return "SLIDER_THUMB"; + } else if (Region.SLIDER_TRACK.getName().equals(regionName)) { + return "SLIDER_TRACK"; + } else if (Region.SPINNER.getName().equals(regionName)) { + return "SPINNER"; + } else if (Region.SPLIT_PANE.getName().equals(regionName)) { + return "SPLIT_PANE"; + } else if (Region.SPLIT_PANE_DIVIDER.getName().equals(regionName)) { + return "SPLIT_PANE_DIVIDER"; + } else if (Region.TABBED_PANE.getName().equals(regionName)) { + return "TABBED_PANE"; + } else if (Region.TABBED_PANE_CONTENT.getName().equals(regionName)) { + return "TABBED_PANE_CONTENT"; + } else if (Region.TABBED_PANE_TAB.getName().equals(regionName)) { + return "TABBED_PANE_TAB"; + } else if (Region.TABBED_PANE_TAB_AREA.getName().equals(regionName)) { + return "TABBED_PANE_TAB_AREA"; + } else if (Region.TABLE.getName().equals(regionName)) { + return "TABLE"; + } else if (Region.TABLE_HEADER.getName().equals(regionName)) { + return "TABLE_HEADER"; + } else if (Region.TEXT_AREA.getName().equals(regionName)) { + return "TEXT_AREA"; + } else if (Region.TEXT_FIELD.getName().equals(regionName)) { + return "TEXT_FIELD"; + } else if (Region.TEXT_PANE.getName().equals(regionName)) { + return "TEXT_PANE"; + } else if (Region.TOGGLE_BUTTON.getName().equals(regionName)) { + return "TOGGLE_BUTTON"; + } else if (Region.TOOL_BAR.getName().equals(regionName)) { + return "TOOL_BAR"; + } else if (Region.TOOL_BAR_CONTENT.getName().equals(regionName)) { + return "TOOL_BAR_CONTENT"; + } else if (Region.TOOL_BAR_DRAG_WINDOW.getName().equals(regionName)) { + return "TOOL_BAR_DRAG_WINDOW"; + } else if (Region.TOOL_BAR_SEPARATOR.getName().equals(regionName)) { + return "TOOL_BAR_SEPARATOR"; + } else if (Region.TOOL_TIP.getName().equals(regionName)) { + return "TOOL_TIP"; + } else if (Region.TREE.getName().equals(regionName)) { + return "TREE"; + } else if (Region.TREE_CELL.getName().equals(regionName)) { + return "TREE_CELL"; + } else if (Region.VIEWPORT.getName().equals(regionName)) { + return "VIEWPORT"; + } + System.err.println("[Info] Couldn't find a Region for " + regionName); + return null; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/ObjectCodeConvertors.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/ObjectCodeConvertors.java new file mode 100644 index 0000000000000000000000000000000000000000..88b1e9baff69884e4b3ce25c5712001c6e159671 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/ObjectCodeConvertors.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.generator; + +import java.awt.*; + +/** + * ObjectCodeConvertors + * + * @author Richard Bair + * @author Jasper Potts + */ +public class ObjectCodeConvertors { + static java.math.MathContext ctx = new java.math.MathContext(3); + + /** + * Given a value (x), encode it such that 0 -> 1 is to the left of a, 1 -> 2 is between a and b, and 2 -> 3 + * is to the right of b. + * + * @param w width in the case of the x axis, height in the case of the y axis. + */ + static float encode(float x, float a, float b, float w) { + float r = 0; + if (x < a) { + r = (x / a); + } else if (x > b) { + r = 2 + ((x - b) / (w - b)); + } else if (x == a && x == b) { + return 1.5f; + } else { + r = 1 + ((x - a) / (b - a)); + } + + if (Float.isNaN(r)) { + System.err.println("[Error] Encountered NaN: encode(" + x + ", " + a + ", " + b + ", " + w + ")"); + return 0; + } else if (Float.isInfinite(r)) { + System.err.println("[Error] Encountered Infinity: encode(" + x + ", " + a + ", " + b + ", " + w + ")"); + return 0; + } else if (r < 0) { + System.err.println("[Error] encoded value was less than 0: encode(" + x + ", " + a + ", " + b + ", " + w + ")"); + return 0; + } else if (r > 3) { + System.err.println("[Error] encoded value was greater than 3: encode(" + x + ", " + a + ", " + b + ", " + w + ")"); + return 3; + } else { + //for prettyness sake (and since we aren't really going to miss + //any accuracy here) I'm rounding this to 3 decimal places +// return java.math.BigDecimal.valueOf(r).round(ctx).doubleValue(); + return r; + } + } + + static String convert(Paint paint) { + //TODO need to support writing out other Paints, such as gradients + if (paint instanceof Color) { + return convert((Color) paint); + } else { + System.err.println("[WARNING] Unable to encode a paint in the encode(Paint) method: " + paint); + return "null"; + } + } + + /** + * Given a Color, write out the java code required to create a new Color. + * + * @param color The color to convert + * @return String of the code for the color + */ + static String convert(Color color) { + return "new Color(" + + color.getRed() + ", " + + color.getGreen() + ", " + + color.getBlue() + ", " + + color.getAlpha() + ")"; + } + + static String convert(Insets i) { + return "new Insets(" + i.top + ", " + i.left + ", " + i.bottom + ", " + i.right + ")"; + } + + static String convert(Dimension d) { + return "new Dimension(" + d.width + ", " + d.height + ")"; + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/PainterGenerator.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/PainterGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..781fb21ba933ecee9628d75b6210a27147def150 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/PainterGenerator.java @@ -0,0 +1,758 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.generator; + +import org.jdesktop.swingx.designer.BezierControlPoint; +import org.jdesktop.swingx.designer.Canvas; +import org.jdesktop.swingx.designer.EllipseShape; +import org.jdesktop.swingx.designer.Layer; +import org.jdesktop.swingx.designer.PaintedShape; +import org.jdesktop.swingx.designer.PathShape; +import org.jdesktop.swingx.designer.RectangleShape; +import org.jdesktop.swingx.designer.SimpleShape; +import org.jdesktop.swingx.designer.TemplateLayer; +import org.jdesktop.swingx.designer.paint.Gradient; +import org.jdesktop.swingx.designer.paint.Matte; +import org.jdesktop.swingx.designer.paint.PaintModel; +import org.jdesktop.swingx.designer.paint.RadialGradient; +import org.jdesktop.swingx.designer.paint.GradientStop; +import org.jdesktop.swingx.designer.paint.AbstractGradient; +import static org.jdesktop.synthdesigner.generator.GeneratorUtils.makePretty; +import static org.jdesktop.synthdesigner.generator.GeneratorUtils.toClassName; +import static org.jdesktop.synthdesigner.generator.GeneratorUtils.toConstantName; +import static org.jdesktop.synthdesigner.generator.TemplateWriter.read; +import static org.jdesktop.synthdesigner.generator.TemplateWriter.writeSrcFile; +import org.jdesktop.synthdesigner.synthmodel.UIIconRegion; +import org.jdesktop.synthdesigner.synthmodel.UIRegion; +import org.jdesktop.synthdesigner.synthmodel.UIState; + +import java.awt.*; +import java.awt.geom.Point2D; +import java.beans.Beans; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.JList; +import javax.swing.JTable; +import javax.swing.text.JTextComponent; + +/** + * PainterGenerator - Class for generating Painter class java source from a Canvas + * + * Following in the general theory that is used to generate a Painter file. + * + * Each Painter file represents a Region. So there is one painter file per region. In + * skin.laf we support Icon subregions, which are really just hacked versions of the + * parent region. + * + * In order to generate the most compact and efficient bytecode possible for the + * Painters, we actually perform the generation sequence in two steps. The first + * step is the analysis phase, where we walk through the SynthModel for the region + * and discover commonality among the different states in the region. For example, + * do they have common paths? Do they have common colors? Gradients? Is the painting + * code for the different states identical other than for colors? + * + * We gather this information up. On the second pass, we use this data to determine the + * methods that need to be generated, and the class variables that need to be generated. + * We try to keep the actual bytecode count as small as possible so that we may reduce + * the overall size of the look and feel significantly. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class PainterGenerator { + private static String painterImplTemplate; + private static String getPainterImplTemplate() { + if (painterImplTemplate == null) { + //load the painter template file into an in-memory string to improve performance + //when generating a lot of classes + try { + painterImplTemplate = read("resources/PainterImpl.template"); + } catch (IOException e) { + System.err.println("Failed to read template files."); + throw new RuntimeException(e); + } + } + return painterImplTemplate; + } + + + //a handful of counters, incremented whenever the associated object type is encounted. + //These counters form the basis of the field and method suffixes. + //These are all 1 based, because I felt like it :-) + private int colorCounter = 1; + private int gradientCounter = 1; + private int radialCounter = 1; + private int pathCounter = 1; + private int rectCounter = 1; + private int roundRectCounter = 1; + private int ellipseCounter = 1; + + private int stateTypeCounter = 1; + + //during the first pass, we will construct these maps + private Map colors = new HashMap(); + /** + * Code=>method name. + */ + private Map methods = new HashMap(); + + //these variables hold the generated code + /** + * The source code in this variable will be used to define the various state types + */ + private StringBuilder stateTypeCode = new StringBuilder(); + /** + * The source code in this variable will be used to define the switch statement for painting + */ + private StringBuilder switchCode = new StringBuilder(); + /** + * The source code in this variable will be used to define the methods for painting each state + */ + private StringBuilder paintingCode = new StringBuilder(); + /** + * The source code in this variable will be used to add getExtendedCacheKeys + * implementation if needed. + */ + private StringBuilder getExtendedCacheKeysCode = new StringBuilder(); + /** + * The source code in this variable will be used to define the methods for decoding gradients + * and shapes. + */ + private StringBuilder gradientsCode = new StringBuilder(); + private StringBuilder colorCode = new StringBuilder(); + private StringBuilder shapesCode = new StringBuilder(); + /** + * Map of component colors keyed by state constant name + */ + private Map> componentColorsMap = + new LinkedHashMap>(); + /** + * For the current state the list of all component colors used by this + * painter, the index in this list is also the index in the runtime array + * of defaults and keys. + */ + private List componentColors = null; + + PainterGenerator(UIRegion r) { + generate(r); + } + + private void generate(UIRegion r) { + for (UIState state : r.getBackgroundStates()) { + System.out.println("------>" + state.getName()); + + Canvas canvas = state.getCanvas(); + String type = r instanceof UIIconRegion ? ((UIIconRegion)r).getKey() : "Background"; + generate(state, canvas, type); + } + for (UIState state : r.getForegroundStates()) { + Canvas canvas = state.getCanvas(); + generate(state, canvas, "Foreground"); + } + for (UIState state : r.getBorderStates()) { + Canvas canvas = state.getCanvas(); + generate(state, canvas, "Border"); + } + //now check for any uiIconRegions, since these are collapsed together. + for (UIRegion sub : r.getSubRegions()) { + if (sub instanceof UIIconRegion) { + generate(sub); + } + } + //generate all the code for component colors + if (!componentColorsMap.isEmpty()) { + getExtendedCacheKeysCode + .append(" protected Object[] getExtendedCacheKeys(JComponent c) {\n") + .append(" Object[] extendedCacheKeys = null;\n") + .append(" switch(state) {\n"); + for (Map.Entry> entry : componentColorsMap.entrySet()) { + getExtendedCacheKeysCode + .append(" case ") + .append(entry.getKey()).append(":\n") + .append(" extendedCacheKeys = new Object[] {\n"); + for (int i=0; i(); + + stateTypeCode.append(" static final int ").append(stateType).append(" = ").append(stateTypeCounter++).append(";\n"); + + if (canvas.isBlank()) { + return; + } + + switchCode.append(" case ").append(stateType).append(": ").append(paintMethodName).append("(g); break;\n"); + paintingCode.append(" private void ").append(paintMethodName).append("(Graphics2D g) {\n"); + + //start by setting up common info needed to encode the control points + Insets in = canvas.getStretchingInsets(); + float a = in.left; + float b = canvas.getSize().width - in.right; + float c = in.top; + float d = canvas.getSize().height - in.bottom; + float width = canvas.getSize().width; + float height = canvas.getSize().height; + float cw = b - a; + float ch = d - c; + + Layer[] layers = canvas.getLayers().toArray(new Layer[0]); + for (int index=layers.length-1; index >= 0; index--) { + Layer layer = layers[index]; + if (layer instanceof TemplateLayer) { + continue; + } + //shapes must be painted in reverse order + List shapes = layer.getShapes(); + for (int i=shapes.size()-1; i>=0; i--) { + SimpleShape s = shapes.get(i); + if (s instanceof PaintedShape) { + PaintedShape shape = (PaintedShape)s; + PaintModel paint = shape.getPaintModel(); + + /* + We attempt to write the minimal number of bytecodes as possible when + generating code. Due to the inherit complexities in determining what + is extraneous, we use the following system: + + We first generate the code for the shape. Then, we check to see if + this shape has already been generated. If so, then we defer to an + existing method. If not, then we will create a new methods, stick + the code in it, and refer to that method. + */ + + String shapeMethodName = null; // will contain the name of the method which creates the shape + String shapeVariable = null; // will be one of rect, roundRect, ellipse, or path. + String shapeMethodBody = null; + + if (shape instanceof RectangleShape) { + RectangleShape rshape = (RectangleShape) shape; + float x1 = encode((float)rshape.getX1(), a, b, width); + float y1 = encode((float)rshape.getY1(), c, d, height); + float x2 = encode((float)rshape.getX2(), a, b, width); + float y2 = encode((float)rshape.getY2(), c, d, height); + if (rshape.isRounded()) { + //it is a rounded rectangle + float rounding = (float)rshape.getRounding(); + + shapeMethodBody = + " roundRect.setRoundRect(" + + writeDecodeX(x1) + ", //x\n" + + " " + writeDecodeY(y1) + ", //y\n" + + " " + writeDecodeX(x2) + " - " + writeDecodeX(x1) + ", //width\n" + + " " + writeDecodeY(y2) + " - " + writeDecodeY(y1) + ", //height\n" + + " " + rounding + "f, " + rounding + "f); //rounding"; + shapeVariable = "roundRect"; + } else { + shapeMethodBody = + " rect.setRect(" + + writeDecodeX(x1) + ", //x\n" + + " " + writeDecodeY(y1) + ", //y\n" + + " " + writeDecodeX(x2) + " - " + writeDecodeX(x1) + ", //width\n" + + " " + writeDecodeY(y2) + " - " + writeDecodeY(y1) + "); //height"; + shapeVariable = "rect"; + } + } else if (shape instanceof EllipseShape) { + EllipseShape eshape = (EllipseShape) shape; + float x1 = encode((float)eshape.getX1(), a, b, width); + float y1 = encode((float)eshape.getY1(), c, d, height); + float x2 = encode((float)eshape.getX2(), a, b, width); + float y2 = encode((float)eshape.getY2(), c, d, height); + shapeMethodBody = + " ellipse.setFrame(" + + writeDecodeX(x1) + ", //x\n" + + " " + writeDecodeY(y1) + ", //y\n" + + " " + writeDecodeX(x2) + " - " + writeDecodeX(x1) + ", //width\n" + + " " + writeDecodeY(y2) + " - " + writeDecodeY(y1) + "); //height"; + shapeVariable = "ellipse"; + } else if (shape instanceof PathShape) { + PathShape pshape = (PathShape) shape; + List controlPoints = pshape.getBezierControlPoints(); + BezierControlPoint first, last; + first = last = controlPoints.get(0); + StringBuilder buffer = new StringBuilder(); + buffer.append(" path.reset();\n"); + buffer.append(" path.moveTo(" + writeDecodeX(encode((float)first.getX(), a, b, width)) + ", " + writeDecodeY(encode((float)first.getY(), c, d, height)) + ");\n"); + for (int j=1; j stops = g.getStops(); + // there are stops.size() number of main stops. Between each is a + // fractional stop. Thus, there are: stops.size() + stops.size() - 1 + // number of fractions and colors. + float[] fractions = new float[stops.size() + stops.size() - 1]; + String[] colors = new String[fractions.length]; + //for each stop, create the stop and it's associated fraction + int index = 0; // the index into fractions and colors + for (int i = 0; i < stops.size(); i++) { + GradientStop s = stops.get(i); + //copy over the stop's data + colors[index] = encodeMatte(s.getColor()); + fractions[index] = s.getPosition(); + + //If this isn't the last stop, then add in the fraction + if (index < fractions.length - 1) { + float f1 = s.getPosition(); + float f2 = stops.get(i + 1).getPosition(); + index++; + fractions[index] = f1 + (f2 - f1) * s.getMidpoint(); + colors[index] = "decodeColor("+ + colors[index - 1]+","+ + encodeMatte(stops.get(i + 1).getColor())+",0.5f)"; + } + index++; + } + // Check boundry conditions + for (int i = 1; i < fractions.length; i++) { + //to avoid an error with LinearGradientPaint where two fractions + //are identical, bump up the fraction value by a miniscule amount + //if it is identical to the previous one + //NOTE: The <= is critical because the previous value may already + //have been bumped up + if (fractions[i] <= fractions[i - 1]) { + fractions[i] = fractions[i - 1] + .000001f; + } + } + //another boundary condition where multiple stops are all at the end. The + //previous loop bumped all but one of these past 1.0, which is bad. + //so remove any fractions (and their colors!) that are beyond 1.0 + int outOfBoundsIndex = -1; + for (int i = 0; i < fractions.length; i++) { + if (fractions[i] > 1) { + outOfBoundsIndex = i; + break; + } + } + if (outOfBoundsIndex >= 0) { + float[] f = fractions; + String[] c = colors; + fractions = new float[outOfBoundsIndex]; + colors = new String[outOfBoundsIndex]; + System.arraycopy(f, 0, fractions, 0, outOfBoundsIndex); + System.arraycopy(c, 0, colors, 0, outOfBoundsIndex); + } + // build string + b.append(" new float[] { "); + for (int i = 0; i < fractions.length; i++) { + if (i>0)b.append(','); + b.append(fractions[i]); + b.append('f'); + } + b.append(" },\n new Color[] { "); + for (int i = 0; i < colors.length; i++) { + if (i>0) b.append(",\n "); + b.append(colors[i]); + } + b.append("}"); + } + + private String encodeRadial(PaintedShape ps, RadialGradient g) { + float centerX1 = (float)ps.getPaintX1(); + float centerY1 = (float)ps.getPaintY1(); + float x2 = (float)ps.getPaintX2(); + float y2 = (float)ps.getPaintY2(); + float radius = (float)Point2D.distance(centerX1, centerY1, x2, y2); + StringBuilder b = new StringBuilder(); + + b.append(" return decodeRadialGradient(("); + b.append(centerX1); + b.append("f * w) + x, ("); + b.append(centerY1); + b.append("f * h) + y, "); + b.append(radius); + b.append("f,\n"); + encodeGradientColorsAndFractions(g,b); + b.append(");"); + + String methodBody = b.toString(); + String methodName = methods.get(methodBody); + if (methodName == null) { + methodName = "decodeRadial" + radialCounter++; + gradientsCode.append(" private Paint ").append(methodName).append("(Shape s) {\n"); + gradientsCode.append(" Rectangle2D bounds = s.getBounds2D();\n"); + gradientsCode.append(" float x = (float)bounds.getX();\n"); + gradientsCode.append(" float y = (float)bounds.getY();\n"); + gradientsCode.append(" float w = (float)bounds.getWidth();\n"); + gradientsCode.append(" float h = (float)bounds.getHeight();\n"); + gradientsCode.append(methodBody); + gradientsCode.append("\n }\n\n"); + methods.put(methodBody, methodName); + } + return methodName; + } + + //note that this method is not thread-safe. In fact, none of this class is. + static void writePainter(UIRegion r, Map variables, File painterPackageRoot, String prefix) throws IOException { + //Need only write out the stuff for this region, don't need to worry about subregions + //since this method will be called for each of those (and they go in their own file, anyway). + //The only subregion that we compound into this is the one for icons. + + String painterName = makePretty(prefix) + "Painter"; + PainterGenerator gen = new PainterGenerator(r); + System.out.println("Generating source file: " + painterName + ".java"); + System.out.println(gen.stateTypeCode.toString()); + variables.put("PAINTER_NAME", painterName); + variables.put("STATIC_DECL", gen.stateTypeCode.toString()); + variables.put("COLORS_DECL", gen.colorCode.toString()); + variables.put("DO_PAINT_SWITCH_BODY", gen.switchCode.toString()); + variables.put("PAINTING_DECL", gen.paintingCode.toString()); + variables.put("GET_EXTENDED_CACHE_KEYS", gen.getExtendedCacheKeysCode.toString()); + variables.put("SHAPES_DECL", gen.shapesCode.toString()); + variables.put("GRADIENTS_DECL", gen.gradientsCode.toString()); + + writeSrcFile(getPainterImplTemplate(), variables, new File(painterPackageRoot, painterName + ".java")); + + variables.remove("PAINTER_NAME"); + variables.remove("STATIC_DECL"); + variables.remove("COLORS_DECL"); + variables.remove("DO_PAINT_SWITCH_BODY"); + variables.remove("PAINTING_DECL"); + variables.remove("SHAPES_DECL"); + variables.remove("GRADIENTS_DECL"); + } + + /** + * Represents the usage of a color from a component within a painter. That + * is, a painter can use colors from the component when it paints. This + * class represents the usage of such a color, containing a reference to + * the name of the property that contains the color, and the various + * derivation offsets to apply to that color. + */ + private static class ComponentColor { + public String propertyName; + public String defaultColorVariableName; + private float saturationOffset = 0, brightnessOffset = 0; + private int alphaOffset = 0; + + private ComponentColor(String propertyName, + String defaultColorVariableName, + float saturationOffset, + float brightnessOffset, + int alphaOffset) { + this.propertyName = propertyName; + this.defaultColorVariableName = defaultColorVariableName; + this.saturationOffset = saturationOffset; + this.brightnessOffset = brightnessOffset; + this.alphaOffset = alphaOffset; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ComponentColor c = (ComponentColor)o; + if (alphaOffset != c.alphaOffset) return false; + if (Float.compare(saturationOffset, c.saturationOffset) != 0) + return false; + if (Float.compare(brightnessOffset, c.brightnessOffset) != 0) + return false; + if (defaultColorVariableName != null ? + !defaultColorVariableName.equals(c.defaultColorVariableName) : + c.defaultColorVariableName != null) return false; + if (propertyName != null ? !propertyName.equals(c.propertyName) : + c.propertyName != null) return false; + return true; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 61 * hash + (this.propertyName != null ? + this.propertyName.hashCode() : 0); + hash = 61 * hash + (this.defaultColorVariableName != null ? + this.defaultColorVariableName.hashCode() : 0); + hash = 61 * hash + Float.floatToIntBits(this.saturationOffset); + hash = 61 * hash + Float.floatToIntBits(this.brightnessOffset); + hash = 61 * hash + this.alphaOffset; + return hash; + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/TemplateWriter.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/TemplateWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..9a76c80a7847ec6a9a9a0b0364bb61ed8a390682 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/TemplateWriter.java @@ -0,0 +1,114 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.generator; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.util.Map; + +/** + * TemplateWriter - Class for writing Java Source files using a src template and variable subsitution + * + * @author Richard Bair + * @author Jasper Potts + */ +public class TemplateWriter { + + /** + * Write a Java source file by taking a template file and applying variable substitution and writing to the output + * file. + * + * @param template The template to use + * @param variables Map of the variable names and values to substitute in the template + * @param output The file to write to + * @throws IOException If there was a problem writing the Java source file + */ + static void writeSrcFile(String template, Map variables, File output) throws IOException { + TemplateReader in = new TemplateReader(variables, template); + PrintWriter out = + new PrintWriter(new FileWriter(output)); + + String line = in.readLine(); + while (line != null) { + out.println(line); + line = in.readLine(); + } + + out.close(); + } + + /** + * Read a template file into a string + * + * @param name The template file path relative to Generator class + * @return The contents of the template file as string + * @throws IOException If there was a problem reading the template file + */ + static String read(String name) throws IOException { + InputStream in = Generator.class.getResourceAsStream(name); + if (in==null) throw new IOException("Could not find template ["+name+ + "] relative to class ["+Generator.class.getName()+"]"); + byte[] data = new byte[4096]; + int length = -1; + StringBuilder buffer = new StringBuilder(); + while ((length = in.read(data)) != -1) { + buffer.append(new String(data, 0, length)); + } + return buffer.toString(); + } + + /** A BufferedReader implementation that automatically performs string replacements as needed. */ + private static final class TemplateReader extends BufferedReader { + private Map variables; + + TemplateReader(Map variables, String template) { + super(new StringReader(template)); + this.variables = variables; + } + + /** + * @return a line of text from the template but with variables substituted. Other methods will return the text + * sans substitution. Call this method. + * @throws java.io.IOException + */ + public String readLine() throws IOException { + return substituteVariables(super.readLine()); + } + + private String substituteVariables(String input) { + if (input == null) return null; + for (Map.Entry variable : variables.entrySet()) { + input = input.replace("${" + variable.getKey() + "}", variable.getValue()); + } + return input; + } + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/CustomUIDefault.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/CustomUIDefault.java new file mode 100644 index 0000000000000000000000000000000000000000..6d4740b8b2bf842762422de2c08bee8b2fa6171e --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/CustomUIDefault.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +/** + * CustomUIDefault + * + * @author Richard Bair + * @author Jasper Potts + */ +public class CustomUIDefault extends UIDefault { + private static int counter = -1; + + public CustomUIDefault() { + super("Unnamed" + (++counter == 0 ? "" : counter), null); + } + + public void setName(String id) { + super.setName(id); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/HasUIStyle.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/HasUIStyle.java new file mode 100644 index 0000000000000000000000000000000000000000..e73b43405d94b05e2bdd450a0d72ba52f940aab4 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/HasUIStyle.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +/** + * HasUIStyle - A marker interface for all classes that have a UIStyle + * + * @author Richard Bair + * @author Jasper Potts + */ +public interface HasUIStyle { + + public UIStyle getStyle(); +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/PainterBorder.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/PainterBorder.java new file mode 100644 index 0000000000000000000000000000000000000000..b3e53db3c948275889933cfdfb4497127c839cf5 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/PainterBorder.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import javax.swing.border.EmptyBorder; + +/** + * Represents a border that refers to a Painter to do it's work. This border + * doesn't actually render -- it is just used as part of the model. + * + * @author Richard Bair + */ +public class PainterBorder extends EmptyBorder { + private String painterName; + public PainterBorder(String painterName, int top, int left, int bottom, int right) { + super(top, left, bottom, right); + this.painterName = painterName; + } + + public String getPainterName() { return painterName; } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/SynthModel.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/SynthModel.java new file mode 100644 index 0000000000000000000000000000000000000000..70a18c50ea505499d6cff16366370a7d317c157f --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/SynthModel.java @@ -0,0 +1,530 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.utils.HasResources; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JDesktopPane; +import javax.swing.JEditorPane; +import javax.swing.JFileChooser; +import javax.swing.JFormattedTextField; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JProgressBar; +import javax.swing.JRadioButton; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JRootPane; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.JToolTip; +import javax.swing.JTree; +import javax.swing.JViewport; +import javax.swing.UIDefaults; +import javax.swing.plaf.basic.BasicLookAndFeel; +import javax.swing.plaf.metal.MetalLookAndFeel; +import static javax.swing.plaf.synth.SynthConstants.*; +import javax.swing.table.JTableHeader; +import java.awt.Insets; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Models a Synth look and feel. Contains all of the colors, fonts, painters, states, etc that compose a synth look and + * feel. + *

+ * To model Synth properly, I need to both Model the way Synth works (with styles, and so forth) and the way a look and + * feel works (UIDefaults table, etc) since both of these are supported ways of doing things in Synth. + *

+ * One important (but non-visual) thing that needs to be configurable is the support for InputMaps per component. In + * Synth, an input map can be associated with the main Synth element, meaning it applies to everything. Or it can be + * associated with a single style. An Inputmap can have an id, and it can contain multiple key/action pairs (where + * actions are denoted by name). + *

+ * It looks like Regions can have InputMaps? Sounds fishy to me. I think only Components really have input maps. + *

+ * I would like some way of denoting special keys between mac and other platforms. For example, cut, copy, paste etc + * should be different. In general, the ctrl key and apple (meta) key are reversed from what is typically on windows. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class SynthModel extends AbstractBean implements HasUIDefaults, HasUIStyle, HasResources { + //I'm going to want: + //entries related to the Control color, and other colors of the Basic LAF + //entries related to fonts (standard fonts) used in the Basic LAF + //entries related to standard insets, borders, dimensions, icons + //entries related to component specific entries in the LAF + private List colors; + private List fonts; + private List insets; + private List borders; + private List dimensions; + private List icons; + private List components; + /** + * This is a local UIDefaults that contains all the UIDefaults in this synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + */ + private transient UIDefaults modelDefaults = new UIDefaults(); + private transient UIStyle globalStyle = new UIStyle(); + + private transient File resourcesDir; + private transient File imagesDir; + private transient File templatesDir; + + /** Default constructor used by JIBX to create new empty SynthModel */ + protected SynthModel() { + this(false); + } + + public SynthModel(boolean populateWithDefaults) { + // create observable lists that fire changes on as property changes + colors = new ArrayList(); + fonts = new ArrayList(); + insets = new ArrayList(); + borders = new ArrayList(); + dimensions = new ArrayList(); + icons = new ArrayList(); + components = new ArrayList(); + + if (populateWithDefaults) { + //get the ui defaults from the SynthLookAndFeel. Using the UIDefaults table, + //pre initialize everything. +// SynthLookAndFeel synth = new SynthLookAndFeel(); + BasicLookAndFeel synth = new MetalLookAndFeel(); + UIDefaults defaults = synth.getDefaults(); + + //pre-init the palettes + colors.add(new UIColor("desktop", defaults.getColor("desktop"), modelDefaults)); + colors.add(new UIColor("activeCaption", defaults.getColor("activeCaption"), modelDefaults)); + colors.add(new UIColor("activeCaptionText", defaults.getColor("activeCaptionText"), modelDefaults)); + colors.add(new UIColor("activeCaptionBorder", defaults.getColor("activeCaptionBorder"), modelDefaults)); + colors.add(new UIColor("inactiveCaption", defaults.getColor("inactiveCaption"), modelDefaults)); + colors.add(new UIColor("inactiveCaptionText", defaults.getColor("inactiveCaptionText"), modelDefaults)); + colors.add(new UIColor("inactiveCaptionBorder", defaults.getColor("inactiveCaptionBorder"), modelDefaults)); + colors.add(new UIColor("window", defaults.getColor("window"), modelDefaults)); + colors.add(new UIColor("windowBorder", defaults.getColor("windowBorder"), modelDefaults)); + colors.add(new UIColor("windowText", defaults.getColor("windowText"), modelDefaults)); + colors.add(new UIColor("menu", defaults.getColor("menu"), modelDefaults)); + colors.add(new UIColor("menuText", defaults.getColor("menuText"), modelDefaults)); + colors.add(new UIColor("text", defaults.getColor("text"), modelDefaults)); + colors.add(new UIColor("textText", defaults.getColor("textText"), modelDefaults)); + colors.add(new UIColor("textHighlight", defaults.getColor("textHighlight"), modelDefaults)); + colors.add(new UIColor("textHighlightText", defaults.getColor("textHighlightText"), modelDefaults)); + colors.add(new UIColor("textInactiveText", defaults.getColor("textInactiveText"), modelDefaults)); + colors.add(new UIColor("control", defaults.getColor("control"), modelDefaults)); + colors.add(new UIColor("controlText", defaults.getColor("controlText"), modelDefaults)); + colors.add(new UIColor("controlHighlight", defaults.getColor("controlHighlight"), modelDefaults)); + colors.add(new UIColor("controlLHighlight", defaults.getColor("controlLHighlight"), modelDefaults)); + colors.add(new UIColor("controlShadow", defaults.getColor("controlShadow"), modelDefaults)); + colors.add(new UIColor("controlDkShadow", defaults.getColor("controlDkShadow"), modelDefaults)); + colors.add(new UIColor("scrollbar", defaults.getColor("scrollbar"), modelDefaults)); + colors.add(new UIColor("info", defaults.getColor("info"), modelDefaults)); + colors.add(new UIColor("infoText", defaults.getColor("infoText"), modelDefaults)); + + fonts.add(new UIFont("dialogPlain", defaults.getFont("Button.font"), modelDefaults)); + fonts.add(new UIFont("serifPlain", defaults.getFont("TextPane.font"), modelDefaults)); + fonts.add(new UIFont("sansSerifPlain", defaults.getFont("ToolTip.font"), modelDefaults)); + fonts.add(new UIFont("monospacedPlain", defaults.getFont("TextArea.font"), modelDefaults)); + fonts.add(new UIFont("dialogBold", defaults.getFont("InternalFrame.titleFont"), modelDefaults)); + + insets.add(new UIInsets("zeroInsets", new Insets(0, 0, 0, 0))); + insets.add(new UIInsets("twoInsets", new Insets(2, 2, 2, 2))); + insets.add(new UIInsets("threeInsets", new Insets(3, 3, 3, 3))); + + borders.add(new UIBorder("marginBorder", defaults.getBorder("MenuItem.border"))); + borders.add(new UIBorder("etchedBorder", defaults.getBorder("TitledBorder.border"))); + borders.add(new UIBorder("loweredBevelBorder", defaults.getBorder("Table.scrollPaneBorder"))); + borders.add(new UIBorder("blackLineBorder", defaults.getBorder("ToolTip.border"))); + + //TODO have to deal with the special arrow button region + + //pre-init the list of UI components + UIComponent button = new UIComponent("Button", JButton.class.getName(), "ButtonUI"); + addStates(this, button, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(button); + + UIComponent toggleButton = + new UIComponent("ToggleButton", JToggleButton.class.getName(), "ToggleButtonUI"); + addStates(this, toggleButton, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED, SELECTED, + SELECTED | PRESSED, SELECTED | MOUSE_OVER, DISABLED | SELECTED); + components.add(toggleButton); + + UIComponent radioButton = + new UIComponent("RadioButton", JRadioButton.class.getName(), "RadioButtonUI"); + addStates(this, radioButton, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED, SELECTED, + SELECTED | PRESSED, SELECTED | MOUSE_OVER, DISABLED | SELECTED); + components.add(radioButton); + + UIComponent checkBox = + new UIComponent("CheckBox", JCheckBox.class.getName(), "CheckBoxUI"); + addStates(this, checkBox, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED, SELECTED, + SELECTED | PRESSED, SELECTED | MOUSE_OVER, DISABLED | SELECTED); + components.add(checkBox); + + UIComponent colorChooser = + new UIComponent("ColorChooser", JColorChooser.class.getName(), "ColorChooserUI"); + addStates(this, colorChooser, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(colorChooser); + + UIComponent comboBox = + new UIComponent("ComboBox", JComboBox.class.getName(), "ComboBoxUI"); + addStates(this, comboBox, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(comboBox); + + UIComponent fileChooser = + new UIComponent("FileChooser", JFileChooser.class.getName(), "FileChooserUI"); + addStates(this, fileChooser, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(fileChooser); + + //not represented in Synth +// UIComponent fileView = new UIComponent ("FileView", +// list(DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + + UIComponent internalFrame = + new UIComponent("InternalFrame", JInternalFrame.class.getName(), "InternalFrameUI"); + addStates(this, internalFrame, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //has an internal frame title pane region + components.add(internalFrame); + + //TODO DesktopIcon ??? + + UIComponent desktop = + new UIComponent("Desktop", JDesktopPane.class.getName(), "DesktopPaneUI"); + addStates(this, desktop, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(desktop); + + UIComponent label = new UIComponent("Label", JLabel.class.getName(), "LabelUI"); + addStates(this, label, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(label); + + UIComponent list = new UIComponent("List", JList.class.getName(), "ListUI"); + addStates(this, list, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(list); + + UIComponent menuBar = new UIComponent("MenuBar", JMenuBar.class.getName(), "MenuBarUI"); + addStates(this, menuBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(menuBar); + + UIComponent menuItem = + new UIComponent("MenuItem", JMenuItem.class.getName(), "MenuItemUI"); + addStates(this, menuItem, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //has a menuItemAccelerator region + components.add(menuItem); + + UIComponent radioButtonMenuItem = + new UIComponent("RadioButtonMenuItem", JRadioButtonMenuItem.class.getName(), + "RadioButtonMenuItemUI"); + addStates(this, radioButtonMenuItem, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(radioButtonMenuItem); + + UIComponent checkBoxMenuItem = + new UIComponent("CheckBoxMenuItem", JCheckBoxMenuItem.class.getName(), + "CheckBoxMenuItemUI"); + addStates(this, checkBoxMenuItem, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(checkBoxMenuItem); + + UIComponent menu = new UIComponent("Menu", JMenu.class.getName(), "MenuUI"); + addStates(this, menu, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(menu); + + UIComponent popupMenu = + new UIComponent("PopupMenu", JPopupMenu.class.getName(), "PopupMenuUI"); + addStates(this, popupMenu, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //has a popupMenuSeparator region + components.add(popupMenu); + + UIComponent optionPane = + new UIComponent("OptionPane", JOptionPane.class.getName(), "OptionPaneUI"); + addStates(this, optionPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(optionPane); + + UIComponent panel = new UIComponent("Panel", JPanel.class.getName(), "PanelUI"); + addStates(this, panel, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(panel); + + UIComponent progressBar = + new UIComponent("ProgressBar", JProgressBar.class.getName(), "ProgressBarUI"); + addStates(this, progressBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(progressBar); + + UIComponent separator = + new UIComponent("Separator", JSeparator.class.getName(), "SeparatorUI"); + addStates(this, separator, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(separator); + + UIRegion scrollBarThumb = new UIRegion("ScrollBar.Thumb"); + addStates(this, scrollBarThumb, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + UIRegion scrollBarTrack = new UIRegion("ScrollBar.Track"); + addStates(this, scrollBarTrack, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + UIComponent scrollBar = + new UIComponent("ScrollBar", JScrollBar.class.getName(), "ScrollBarUI", scrollBarThumb, + scrollBarTrack); + addStates(this, scrollBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(scrollBar); + + UIComponent scrollPane = + new UIComponent("ScrollPane", JScrollPane.class.getName(), "ScrollPaneUI"); + addStates(this, scrollPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(scrollPane); + + UIComponent viewport = + new UIComponent("Viewport", JViewport.class.getName(), "ViewportUI"); + addStates(this, viewport, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(viewport); + + UIComponent slider = new UIComponent("Slider", JSlider.class.getName(), "SliderUI"); + addStates(this, slider, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //has sliderThumb and sliderTrack sub regions + components.add(slider); + + UIComponent spinner = new UIComponent("Spinner", JSpinner.class.getName(), "SpinnerUI"); + addStates(this, spinner, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(spinner); + + UIComponent splitPane = + new UIComponent("SplitPane", JSplitPane.class.getName(), "SplitPaneUI"); + addStates(this, splitPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //has splitPaneDivider sub region + components.add(splitPane); + + UIComponent tabbedPane = + new UIComponent("TabbedPane", JTabbedPane.class.getName(), "TabbedPaneUI"); + addStates(this, tabbedPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //has tabbedPaneContent and tabbedPaneTab and TabbedPaneTabArea sub regions + components.add(tabbedPane); + + UIComponent table = new UIComponent("Table", JTable.class.getName(), "TableUI"); + addStates(this, table, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(table); + + UIComponent tableHeader = + new UIComponent("TableHeader", JTableHeader.class.getName(), "TableHeaderUI"); + addStates(this, tableHeader, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(tableHeader); + + UIComponent textField = + new UIComponent("TextField", JTextField.class.getName(), "TextFieldUI"); + addStates(this, textField, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(textField); + + UIComponent formattedTextField = + new UIComponent("FormattedTextField", JFormattedTextField.class.getName(), + "FormattedTextFieldUI"); + addStates(this, formattedTextField, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(formattedTextField); + + UIComponent passwordField = + new UIComponent("PasswordField", JPasswordField.class.getName(), "PasswordFieldUI"); + addStates(this, passwordField, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(passwordField); + + UIComponent textArea = + new UIComponent("TextArea", JTextArea.class.getName(), "TextAreaUI"); + addStates(this, textArea, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(textArea); + + UIComponent textPane = + new UIComponent("TextPane", JTextPane.class.getName(), "TextPaneUI"); + addStates(this, textPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(textPane); + + UIComponent editorPane = + new UIComponent("EditorPane", JEditorPane.class.getName(), "EditorPaneUI"); + addStates(this, editorPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(editorPane); + + /* + * The only thing not represented in Synth as a region. I suppose we'll have + * to make it a CustomUIComponent + */ +// UIComponent titledBorder = new UIComponent ("TitledBorder", +// list(DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + + UIComponent toolBar = new UIComponent("ToolBar", JToolBar.class.getName(), "ToolBarUI"); + addStates(this, toolBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //toolBarContent, toolBarDragWindow, toolBarSeparator sub regions + components.add(toolBar); + + UIComponent toolTip = new UIComponent("ToolTip", JToolTip.class.getName(), "ToolTipUI"); + addStates(this, toolTip, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(toolTip); + + //tooltip manager + + UIComponent tree = new UIComponent("Tree", JTree.class.getName(), "TreeUI"); + addStates(this, tree, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + //treeCell sub region + components.add(tree); + + UIComponent rootPane = + new UIComponent("RootPane", JRootPane.class.getName(), "RootPaneUI"); + addStates(this, rootPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED); + components.add(rootPane); + } + } + + public List getColorPalette() { + return colors; + } + + public List getFontPalette() { + return fonts; + } + + public List getInsetPalette() { + return insets; + } + + public List getBorderPalette() { + return borders; + } + + public List getDimensionPalette() { + return dimensions; + } + + public List getIconPalette() { + return icons; + } + + public List getComponents() { + return components; + } + + /** + * Get the local UIDefaults that contains all the UIDefaults in this synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + * + * @return The UIDefaults for the synth model + */ + public UIDefaults getUiDefaults() { + return modelDefaults; + } + + public UIStyle getStyle() { + return globalStyle; + } + + // by default there are no painters assigned to the various states + private static void addStates(SynthModel model, UIRegion parentRegion, int... states) { + for (int state : states) { + List stateList = new ArrayList(); + if ((state & ENABLED) != 0) { + stateList.add(UIStateType.ENABLED_KEY); + } + if ((state & MOUSE_OVER) != 0) { + stateList.add(UIStateType.MOUSE_OVER_KEY); + } + if ((state & PRESSED) != 0) { + stateList.add(UIStateType.PRESSED_KEY); + } + if ((state & DISABLED) != 0) { + stateList.add(UIStateType.DISABLED_KEY); + } + if ((state & FOCUSED) != 0) { + stateList.add(UIStateType.FOCUSED_KEY); + } + if ((state & SELECTED) != 0) { + stateList.add(UIStateType.SELECTED_KEY); + } + if ((state & DEFAULT) != 0) { + stateList.add(UIStateType.DEFAULT_KEY); + } + parentRegion.addBackgroundState(new UIState(model, parentRegion, stateList.toArray(new String[stateList.size()]))); + } + } + + public File getResourcesDir() { + return resourcesDir; + } + + public void setResourcesDir(File resourcesDir) { + System.out.println("SynthModel.setResourcesDir(" + resourcesDir + ")"); + File old = getResourcesDir(); + this.resourcesDir = resourcesDir; + firePropertyChange("resourcesDir", old, getResourcesDir()); + } + + public File getImagesDir() { + return imagesDir; + } + + public void setImagesDir(File imagesDir) { + System.out.println("SynthModel.setImagesDir(" + imagesDir + ")"); + File old = getImagesDir(); + this.imagesDir = imagesDir; + firePropertyChange("imagesDir", old, getImagesDir()); + } + + public File getTemplatesDir() { + return templatesDir; + } + + public void setTemplatesDir(File templatesDir) { + System.out.println("SynthModel.setTemplatesDir(" + templatesDir + ")"); + File old = getTemplatesDir(); + this.templatesDir = templatesDir; + firePropertyChange("templatesDir", old, getTemplatesDir()); + } + + // ================================================================================================================= + // JIBX Methods + + public void preSet(IUnmarshallingContext context) { + File resourcesDir = (File) context.getUserContext(); + this.resourcesDir = resourcesDir; + this.imagesDir = new File(resourcesDir, "images"); + this.templatesDir = new File(resourcesDir, "templates"); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/SynthModel.jibx.xml b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/SynthModel.jibx.xml new file mode 100644 index 0000000000000000000000000000000000000000..981772abc2b0d573210d446763e712a78bc52948 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/SynthModel.jibx.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIBorder.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIBorder.java new file mode 100644 index 0000000000000000000000000000000000000000..46c35ed1b082d3cab4386f168f45b7e5ac8063eb --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIBorder.java @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import javax.swing.border.Border; + +/** + * UIBorder + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIBorder extends UIDefault { + + public UIBorder() { + } + + public UIBorder(String id, Border b) { + super(id, b); + } + + public Border getBorder() { + return super.getValue(); + } + + public void setBorder(Border b) { + Border old = getBorder(); + super.setValue(b); + firePropertyChange("border", old, b); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIColor.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIColor.java new file mode 100644 index 0000000000000000000000000000000000000000..572d346132515b2b60a3a91a524b6ea88ce49f85 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIColor.java @@ -0,0 +1,58 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.swingx.designer.paint.Matte; + +import javax.swing.UIDefaults; +import java.awt.Color; + +/** + * UIColor + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIColor extends UIPaint { + + public UIColor() { + } + + public UIColor(String id, Matte value) { + super(id, value); + } + + public UIColor(String id, Color color, UIDefaults modelDefaults) { + this(id, new Matte(color, modelDefaults)); + } + + public Matte getPaint() { + return (Matte) super.getPaint(); + } + + public void setPaint(Matte c) { + super.setPaint(c); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIComponent.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..028124ab36371ec3295b39cf877e07b406aa1585 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIComponent.java @@ -0,0 +1,138 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.swingx.designer.utils.HasUIDefaults; + +import java.util.List; +import java.util.ArrayList; + +/** + * UIComponent - model node that represents the designs for a single swing component + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIComponent extends UIRegion implements HasUIDefaults { + + /** The classname of the swing component that this UIComponent represents */ + private String type; + /** The name of the component if its a named component or null if its a generic component */ + private String componentName = null; + /** If this components is opaque which means that when it is painted all of its bounds are filled */ + private boolean opaque = false; + /** + * A list of state types that are available to this region and sub regions of this component but not subcomponents + * of this component. If this list is empty then the standard synth set of state types are assumed. + */ + private List stateTypes; + + // ================================================================================================================= + // Contructors + + /** no-args contructor for JIBX */ + protected UIComponent() { + super(); + // create new observable list for state types so we get events for when the model changes + stateTypes = new ArrayList(); + } + + public UIComponent(String name, String type, String ui, UIRegion... subRegions) { + super(name, ui, subRegions); + this.type = type; + for (UIRegion r : subRegions) { + r.setRegion(this); + } + // create new observable list for state types so we get events for when the model changes + stateTypes = new ArrayList(); + } + + // ================================================================================================================= + // Bean Methods + + public String getComponentName() { + return componentName; + } + + public void setComponentName(String componentName) { + String old = getComponentName(); + this.componentName = componentName; + firePropertyChange("componentName", old, getComponentName()); + } + + public boolean isOpaque() { + return opaque; + } + + public void setOpaque(boolean opaque) { + boolean old = isOpaque(); + this.opaque = opaque; + firePropertyChange("opaque", old, isOpaque()); + } + + public String getType() { + return type; + } + + public void setType(String type) { + String old = getType(); + this.type = type; + firePropertyChange("type", old, getType()); + } + + /** + * Get the list of state types that are available to this region and sub regions of this component but not + * subcomponents of this component. If this list is empty then the standard synth set of state types are assumed. + * + * @return List of available state types + */ + public List getStateTypes() { + return stateTypes; + } + + @Override public String getKey() { + if (key == null || "".equals(key)) { + if (componentName == null || "".equals(componentName)) { + return getName(); + } else { + return "\"" + componentName + "\""; + } + } else { + return key; + } + } + + @Override public String getTitle() { + if (title == null || "".equals(title)) { + if (componentName == null || "".equals(componentName)) { + return getName(); + } else { + return componentName; + } + } else { + return title; + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIDefault.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIDefault.java new file mode 100644 index 0000000000000000000000000000000000000000..2f0bf09a8d6584407782641a936ffa6b856cdc93 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIDefault.java @@ -0,0 +1,116 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +import javax.swing.UIDefaults; + +/** + * Represents an entry in the UI defaults table. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIDefault extends AbstractBean implements HasUIDefaults { + private String name; + private T value; + /** + * This is a local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + */ + private transient UIDefaults modelDefaults = null; + + public UIDefault() { + } + + public UIDefault(String name, T value) { + this.name = name; + this.value = value; + } + + public UIDefault(String name, T value, UIDefaults modelDefaults) { + this.name = name; + this.value = value; + this.modelDefaults = modelDefaults; + } + + // ================================================================================================================= + // JIBX Methods + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + private void postSet(IUnmarshallingContext context) { + // walk up till we get synth model + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof HasUIDefaults) { + modelDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults(); + if (modelDefaults != null) break; + } + } + } + + // ================================================================================================================= + // Bean Methods + + /** + * Get the local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + * + * @return The UIDefaults for the synth model + */ + public UIDefaults getUiDefaults() { + return modelDefaults; + } + + public void setValue(T t) { + T old = this.value; + this.value = t; + firePropertyChange("value", old, getValue()); + } + + public T getValue() { + return value; + } + + public final String getName() { + return name; + } + + public void setName(String name) { + String old = this.name; + firePropertyChange("name", old, name); + this.name = name; + // update model defaults + if (old != null) modelDefaults.remove(old); + modelDefaults.put(getName(), getValue()); + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIDimension.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIDimension.java new file mode 100644 index 0000000000000000000000000000000000000000..e611ad6274378d492003d17823836a5e62542df8 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIDimension.java @@ -0,0 +1,48 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import java.awt.Dimension; + +/** + * UIDimension + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIDimension extends UIDefault { + public UIDimension() { + } + + public Dimension getDimension() { + return super.getValue(); + } + + public void setDimension(Dimension d) { + Dimension old = getDimension(); + super.setValue(d); + firePropertyChange("dimension", old, d); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIFont.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIFont.java new file mode 100644 index 0000000000000000000000000000000000000000..efb6fdba35c5212f2d7359c45ad9c516b4b1a834 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIFont.java @@ -0,0 +1,79 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import java.awt.Font; +import org.jdesktop.swingx.designer.font.Typeface; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import javax.swing.UIDefaults; + +/** + * Represents a single font entry in the UIDefaults table. Each UIFont takes a + * list of Typefaces. These typefaces are listed by order of preference. Thus, + * when putting a font into UIDefaults, the code can check whether each font + * exists, and when it finds the first font that does, insert it. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIFont extends UIDefault> implements Cloneable { + + private void updateUIDefaults() { + if (getUiDefaults() != null) { + for (Typeface t : getFonts()) { + if (t.isFontSupported()) { + getUiDefaults().put(getName(), t.getFont()); + return; + } + } + } + + //TODO must not have found any. Default to the Default platform font + getUiDefaults().put(getName(), new Font("Arial", Font.PLAIN, 12)); + } + + public UIFont() { + setValue(new ArrayList()); + } + + public UIFont(String id, List values, UIDefaults defaults) { + super(id, values, defaults); + updateUIDefaults(); + } + + public UIFont(String id, Font font, UIDefaults modelDefaults) { + this(id, Arrays.asList(new Typeface(font, modelDefaults)), modelDefaults); + } + + public List getFonts() { + return super.getValue(); + } + + private void setFonts(List values) { + super.setValue(values); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIIcon.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIIcon.java new file mode 100644 index 0000000000000000000000000000000000000000..d1a25833de121f19701c7d9a7df943a3de39d177 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIIcon.java @@ -0,0 +1,49 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import javax.swing.Icon; + +/** + * UIIcon + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIIcon extends UIDefault { + + public UIIcon() { + } + + public Icon getIcon() { + return super.getValue(); + } + + public void setIcon(Icon i) { + Icon old = getIcon(); + super.setValue(i); + firePropertyChange("icon", old, i); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIIconRegion.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIIconRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..74590ee9789bdbc6d8d464614c13a6b0ac573ffc --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIIconRegion.java @@ -0,0 +1,55 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +/** + * A UIRegion subclass which is used for generating icons. For example, JRadioButton and JCheckBox represent themselves + * mainly via their icons. However, from the designers perspective, the main design isn't an "icon", but just a region + * on the button. + *

+ * That type of region is represented by a UIIconRegion. UIIconRegion contains a string which references the UIDefault + * value associated with this icon. For example, RadioButton.icon. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIIconRegion extends UIRegion { + /** The UiDefaults key which this icon should be stored for basic LaF to find it. This is absolute */ + private String basicKey = null; + + public UIIconRegion() { + super(); + } + + public String getBasicKey() { + return basicKey; + } + + public void setBasicKey(String basicKey) { + String old = getBasicKey(); + this.basicKey = basicKey; + firePropertyChange("basicKey",old,getBasicKey()); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIInsets.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIInsets.java new file mode 100644 index 0000000000000000000000000000000000000000..3e320de6682c7bbd0c77dab7f59ee67cca430510 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIInsets.java @@ -0,0 +1,62 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import java.awt.Insets; + +/** + * UIInsets + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIInsets extends UIDefault { + + public UIInsets() { + } + + public UIInsets(String id, Insets value) { + super(id, value); + } + + public Insets getInsets() { + return super.getValue(); + } + + public void setInsets(Insets i) { + Insets old = getInsets(); + super.setValue(i); + firePropertyChange("insets", old, i); + // update model defaults + getUiDefaults().put(getName(), i); + } + + + public String toString() { + return "UiInset(" + getName() + ")" + + ((getInsets() == null) ? " NONE" : "(" + getInsets().top + "," + getInsets().left + "," + + getInsets().bottom + "," + getInsets().right + ")"); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIPaint.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIPaint.java new file mode 100644 index 0000000000000000000000000000000000000000..931b3f41feea7262dbed1a0d2f73366b769e80a8 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIPaint.java @@ -0,0 +1,84 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.swingx.designer.paint.Matte; +import org.jdesktop.swingx.designer.paint.PaintModel; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * UIPaint + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIPaint extends UIDefault { + + /** Listener to keep model UiDefaults up to date for this UiPaint */ + private PropertyChangeListener matteListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + PaintModel paintModel = getValue(); + if (paintModel instanceof Matte) { + getUiDefaults().put(getName(), ((Matte) paintModel).getColor()); + } + // propogate the paint change up as PaintModel is a mutable object + if (evt.getPropertyName().equals("paint")) { + firePropertyChange("paint", null, getPaint()); + firePropertyChange("value", null, getPaint()); + } + } + }; + + public UIPaint() {} + + public UIPaint(String id, PaintModel value) { + super(id, value, (value instanceof Matte) ? ((Matte) value).getUiDefaults() : null); + // update model defaults + if (value instanceof Matte) { + Matte matte = (Matte) value; + if (getUiDefaults() != null) getUiDefaults().put(getName(), matte.getColor()); + matte.addPropertyChangeListener(matteListener); + } + } + + public PaintModel getPaint() { + return super.getValue(); + } + + public void setPaint(PaintModel c) { + PaintModel old = getPaint(); + if (old instanceof Matte) old.removePropertyChangeListener(matteListener); + super.setValue(c); + firePropertyChange("paint", old, c); + // update model defaults + if (c instanceof Matte) { + Matte matte = (Matte) c; + getUiDefaults().put(getName(), matte.getColor()); + matte.addPropertyChangeListener(matteListener); + } + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIProperty.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIProperty.java new file mode 100644 index 0000000000000000000000000000000000000000..1a57a58f816adf9211d4a541ed89f860904adc9c --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIProperty.java @@ -0,0 +1,85 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; + +/** + * UIProperty + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIProperty extends AbstractBean { + public static enum PropertyType { + BOOLEAN, INT, FLOAT, DOUBLE, STRING, FONT, COLOR, INSETS, DIMENSION, BORDER + } + + private String name; + private PropertyType type; + private Object value; + + protected UIProperty() { + } + + public UIProperty(String name, PropertyType type, Object value) { + this.name = name; + this.type = type; + this.value = value; + } + + // ================================================================================================================= + // Bean Methods + + public String getName() { + return name; + } + + public void setName(String name) { + String old = getName(); + this.name = name; + firePropertyChange("name", old, getName()); + } + + public PropertyType getType() { + return type; + } + + public void setType(PropertyType type) { + PropertyType old = getType(); + this.type = type; + firePropertyChange("type", old, getType()); + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + Object old = getValue(); + this.value = value; + firePropertyChange("value", old, getValue()); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIRegion.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..1ee4f35653a3af119323ef2dc65f54020cfeb6de --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIRegion.java @@ -0,0 +1,253 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +import javax.swing.UIDefaults; +import java.awt.Insets; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; +import java.util.ArrayList; + +/** + * Represents a "Region" in synth, which also includes entire components. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIRegion extends AbstractBean implements HasUIDefaults, HasUIStyle { + private String name;//the code-wise name of the region + protected String key; //the UIdefaults key for this region + protected String title; //the user friendly name/title of this region + /** List of background states */ + private List backgroundStates; + /** List of foreground states */ + private List foregroundStates; + /** List of border states */ + private List borderStates; + private UIStyle style = new UIStyle(); + protected Insets contentMargins = new Insets(0, 0, 0, 0); + /** Sub regions, if any */ + private List subRegions; + + //together with name, these two fields allow me to reconstruct, in + //code, a synth Region, including a custom Region, if you make one. + private String ui; + private boolean subregion; + /** + * This is a local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + */ + private transient UIDefaults modelDefaults = null; + + private UIRegion region; //the region that this region belongs to + + // ================================================================================================================= + // Constructors + + /** no-args contructor for JIBX */ + protected UIRegion() { + subRegions = new ArrayList(); + backgroundStates = new ArrayList(); + foregroundStates = new ArrayList(); + borderStates = new ArrayList(); + style.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("style." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }); + } + + public UIRegion(String name, UIRegion... subRegions) { + this(name, null, true, subRegions); + } + + public UIRegion(String name, String ui, UIRegion... subRegions) { + this(name, ui, false, subRegions); + } + + public UIRegion(String name, String ui, boolean subregion, UIRegion... subRegions) { + this(); + this.name = name; + this.ui = ui; + this.subregion = subregion; + if (subRegions != null) { + for (UIRegion r : subRegions) { + if (r != null) { + this.subRegions.add(r); + r.getStyle().setParentStyle(getStyle()); + } + } + } + } + + // ================================================================================================================= + // JIBX Methods + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + private void preSet(IUnmarshallingContext context) { + // walk up till we get synth model + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof HasUIDefaults) { + modelDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults(); + if (modelDefaults != null) break; + } + } + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof UIRegion && context.getStackObject(i) != this) { + region = (UIRegion) context.getStackObject(i); + break; + } + } + } + + // ================================================================================================================= + // Bean Methods + + public Insets getContentMargins() { + return contentMargins; + } + + public void setContentMargins(Insets contentMargins) { + Insets old = getContentMargins(); + this.contentMargins = contentMargins; + firePropertyChange("contentMargins", old, getContentMargins()); + } + + void setRegion(UIRegion r) { + this.region = r; + } + + public UIRegion getRegion() { + return region; + } + + /** + * Get the local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + * + * @return The UIDefaults for the synth model + */ + public UIDefaults getUiDefaults() { + return modelDefaults; + } + + public String getName() { + return name; + } + + public final UIRegion[] getSubRegions() { + return subRegions.toArray(new UIRegion[0]); + } + + public final UIState[] getBackgroundStates() { + return backgroundStates.toArray(new UIState[0]); + } + + public final UIState[] getForegroundStates() { + return foregroundStates.toArray(new UIState[0]); + } + + public final UIState[] getBorderStates() { + return borderStates.toArray(new UIState[0]); + } + + public UIStyle getStyle() { + return style; + } + + public final boolean isSubRegion() { + return subregion; + } + + public final String getUi() { + return ui; + } + + public void addBackgroundState(UIState state) { + // check if we already have that state + for (UIState uiState : backgroundStates) { + if (uiState.getName().equals(state.getName())) return; + } + backgroundStates.add(state); + state.setRegion(this); + firePropertyChange("backgroundStates", null, backgroundStates); + } + + public void removeBackgroundState(UIState state) { + if (backgroundStates.remove(state)) { + firePropertyChange("backgroundStates", null, backgroundStates); + } + } + + public void addForegroundState(UIState state) { + // check if we already have that state + for (UIState uiState : foregroundStates) { + if (uiState.getName().equals(state.getName())) return; + } + foregroundStates.add(state); + state.setRegion(this); + firePropertyChange("foregroundStates", null, foregroundStates); + } + + public void removeForegroundState(UIState state) { + if (foregroundStates.remove(state)) { + firePropertyChange("foregroundStates", null, foregroundStates); + } + } + + public void addBorderState(UIState state) { + // check if we already have that state + for (UIState uiState : borderStates) { + if (uiState.getName().equals(state.getName())) return; + } + borderStates.add(state); + state.setRegion(this); + firePropertyChange("borderStates", null, borderStates); + } + + public void removeBorderState(UIState state) { + if (borderStates.remove(state)) { + firePropertyChange("borderStates", null, borderStates); + } + } + + + public String getKey() { + return key == null || "".equals(key) ? name : key; + } + + public String getTitle() { + return title == null || "".equals(title) ? name : title; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIState.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIState.java new file mode 100644 index 0000000000000000000000000000000000000000..4d747a4e2d4a0c090d53e5b6a57cd009205a8662 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIState.java @@ -0,0 +1,298 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.Canvas; +import org.jdesktop.swingx.designer.utils.HasPath; +import org.jdesktop.swingx.designer.utils.HasUIDefaults; +import org.jibx.runtime.IUnmarshallingContext; + +import javax.swing.UIDefaults; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a State in the Synth LAF. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIState extends AbstractBean implements HasUIStyle, HasPath { + + private List stateKeys; + private boolean inverted; //indicates whether to invert the meaning of the 9-square stretching insets + /** A cached string representing the list of stateKeys deliminated with "+" */ + private String cachedName = null; + private Canvas canvas; + private UIStyle style; + /** the region that this state belongs to */ + private UIRegion region; + /** + * This is a local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + */ + private transient UIDefaults modelDefaults = null; + + // ================================================================================================================= + // Contructors + + public UIState() { + // Create state keys as event list so model changes are propogated + stateKeys = new ArrayList(); + } + + public UIState(SynthModel model, UIRegion parentRegion, String... stateTypeKeys) { + // Create state keys as event list so model changes are propogated + stateKeys = new ArrayList(); + this.stateKeys.addAll(Arrays.asList(stateTypeKeys)); + // + modelDefaults = model.getUiDefaults(); + region = parentRegion; + // create new canvas + canvas = new Canvas(100, 30); + canvas.setUiDefaults(modelDefaults); + String canvasPath = getPath(); + canvas.setResourcesDir(new File(model.getResourcesDir(), canvasPath)); + canvas.setTemplatesDir(new File(model.getTemplatesDir(), canvasPath)); + canvas.setImagesDir(new File(model.getImagesDir(), canvasPath)); + canvas.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("canvas." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }); + // create new style + style = new UIStyle(); + style.setParentStyle(region.getStyle()); + style.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("style." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }); + } + + // ================================================================================================================= + // JIBX Methods + + /** + * JIBX needs this + * + * @param stateKeys The new list of states + */ + private void setStateKeys(List stateKeys) { + if (stateKeys != this.stateKeys) { + this.stateKeys.clear(); + this.stateKeys.addAll(stateKeys); + } + } + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + private void preSet(IUnmarshallingContext context) { + // walk up till we get synth model + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof HasUIDefaults) { + modelDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults(); + if (modelDefaults != null) break; + } + } + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof UIRegion) { + region = (UIRegion) context.getStackObject(i); + break; + } + } + } + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + private void postSet(IUnmarshallingContext context) { + // add listeners to pass canvas and style events up tree + canvas.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("canvas." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }); + style.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("style." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }); + } + + // ================================================================================================================= + // Bean Methods + + /** + * Get path to this UI State of the form /RegionA/RegionB/StateName + * + * @return Path to this state + */ + public String getPath() { + StringBuilder buf = new StringBuilder(getName()); + UIRegion region = getRegion(); + // check if we are foreground background or border + boolean found = false; + for (UIState state : region.getBackgroundStates()) { + if (state == this) { + buf.insert(0, "Background/"); + found = true; + break; + } + } + if (!found) { + for (UIState state : region.getForegroundStates()) { + if (state == this) { + buf.insert(0, "Foreground/"); + found = true; + break; + } + } + } + if (!found) { + for (UIState state : region.getBorderStates()) { + if (state == this) { + buf.insert(0, "Border/"); + found = true; + break; + } + } + } + // add parent regions + while (region != null) { + buf.insert(0, '/'); + if (region instanceof UIComponent && ((UIComponent) region).getComponentName() != null) { + buf.insert(0, ((UIComponent) region).getComponentName()); + } else { + buf.insert(0, region.getName()); + } + region = region.getRegion(); + } + return buf.toString(); + } + + void setRegion(UIRegion r) { + this.region = r; + this.style.setParentStyle(r.getStyle()); + } + + public UIRegion getRegion() { + return region; + } + + /** + * Get the local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the + * indervidual UIDefaults nodes + * + * @return The UIDefaults for the synth model + */ + public UIDefaults getUIDefaults() { + return modelDefaults; + } + + + /** + * Get the list of state type keys for this state. This state is applied when the current component state matches as + * many as possible of these state types. + * + * @return List of state types that need to be true for this state. This is direct access to the data and changes to + * the returned list will effect this UiState. + */ + public List getStateKeys() { + return stateKeys; + } + + public void setInverted(boolean b) { + boolean old = inverted; + inverted = b; + firePropertyChange("invert", old, b); + } + + public final boolean isInverted() { + return inverted; + } + + /** + * Get the name of this state + * + * @return + */ + public String getName() { + if (cachedName == null) { + StringBuilder buf = new StringBuilder(); + List keys = new ArrayList(stateKeys); + Collections.sort(keys); + for (Iterator iter = keys.iterator(); iter.hasNext();) { + buf.append(iter.next()); + if (iter.hasNext()) buf.append('+'); + } + cachedName = buf.toString(); + } + return cachedName; + } + + public final Canvas getCanvas() { + return canvas; + } + + public void setCanvas(Canvas c) { + Canvas old = canvas; + canvas = c; + firePropertyChange("canvas", old, c); + } + + public UIStyle getStyle() { + return style; + } + + // ================================================================================================================= + // JIBX Helper Methods + + public static String keysToString(List keys) { + StringBuilder buf = new StringBuilder(); + for (Iterator iter = keys.iterator(); iter.hasNext();) { + buf.append(iter.next()); + if (iter.hasNext()) buf.append('+'); + } + return buf.toString(); + } + + public static List stringToKeys(String keysString) { + return Arrays.asList(keysString.split("\\+")); + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIStateType.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIStateType.java new file mode 100644 index 0000000000000000000000000000000000000000..811ca8fa17c15792ab2bbfe73137ce7b388e1046 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIStateType.java @@ -0,0 +1,129 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; + +/** + * UIStateType - A UIComponents has a collection of these which constitute the avilables states which can be chosen in + * the components regions. A UIStateType can be either a custom state or one of the predefined standard states. + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIStateType extends AbstractBean { + /* Keys for standard synth states */ + public static final String ENABLED_KEY = "Enabled"; + public static final String MOUSE_OVER_KEY = "MouseOver"; + public static final String PRESSED_KEY = "Pressed"; + public static final String DISABLED_KEY = "Disabled"; + public static final String FOCUSED_KEY = "Focused"; + public static final String SELECTED_KEY = "Selected"; + public static final String DEFAULT_KEY = "Default"; + public static final String[] STANDARD_SYNTH_STATE_KEYS = new String[]{ + ENABLED_KEY, MOUSE_OVER_KEY, PRESSED_KEY, DISABLED_KEY, FOCUSED_KEY, SELECTED_KEY, DEFAULT_KEY + }; + public static final UIStateType[] STANDARD_SYNTH_STATES = new UIStateType[]{ + new UIStateType(ENABLED_KEY), + new UIStateType(MOUSE_OVER_KEY), + new UIStateType(PRESSED_KEY), + new UIStateType(DISABLED_KEY), + new UIStateType(FOCUSED_KEY), + new UIStateType(SELECTED_KEY), + new UIStateType(DEFAULT_KEY) + }; + + /** Unique string for the ui key for this state, must be unique within a components set of UiStateTypes */ + private String key; + /** + * Snippet of java code that defines calculates the value of this state for a particular component. The varaiable + * c is the component. You end with a return statement returning boolean true/false for the current + * value of this state for this component. This can be null if the key is one of that standard synth states defined + * in constants in this class. + */ + private String codeSnippet; + + /** JIBX no-args contructor */ + private UIStateType() {} + + private UIStateType(String key) { + this.key = key; + this.codeSnippet = null; + } + + public UIStateType(String key, String codeSnippet) { + this.key = key; + this.codeSnippet = codeSnippet; + } + + // ================================================================================================================= + // Bean Methods + + /** + * Get the ui defaults key for this state type. Unique string for the ui key for this state, must be unique within a + * components set of UiStateTypes. + * + * @return Unique ui default key + */ + public String getKey() { + return key; + } + + /** + * Get the snippet of java code that defines calculates the value of this state for a particular component. The + * varaiable c is the component. You end with a return statement returning boolean true/false for the + * current value of this state for this component. This can be null if the key is one of that standard synth states + * defined in constants in this class. + * + * @return Snippet of java code or null if this is a synth standard state + */ + public String getCodeSnippet() { + return codeSnippet; + } + + /** + * Set the snippet of java code that defines calculates the value of this state for a particular component. The + * varaiable c is the component. You end with a return statement returning boolean true/false for the + * current value of this state for this component. This can be null if the key is one of that standard synth states + * defined in constants in this class. + * + * @param codeSnippet Snippet of java code or null if this is a synth standard state + */ + public void setCodeSnippet(String codeSnippet) { + this.codeSnippet = codeSnippet; + } + + /** + * Returns if this state type is a standard synth type and has no code snippet or a custom type that has a code + * snippet. It is used by JIBX to determin if the code snippet should be written to XML. + * + * @return true if codeSnippet is non null + */ + public boolean hasCodeSnippet() { + return codeSnippet != null; + } + + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIStyle.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIStyle.java new file mode 100644 index 0000000000000000000000000000000000000000..3e926bf8e4a077101d93952735e55a2384ceafe0 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/UIStyle.java @@ -0,0 +1,467 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel; + +import org.jdesktop.beans.AbstractBean; +import org.jdesktop.swingx.designer.font.Typeface; +import org.jdesktop.swingx.designer.paint.Matte; +import org.jibx.runtime.IUnmarshallingContext; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; +import java.util.ArrayList; + +/** + * UIStyle + * + * @author Richard Bair + * @author Jasper Potts + */ +public class UIStyle extends AbstractBean { + public static enum CacheMode {NO_CACHING,FIXED_SIZES,NINE_SQUARE_SCALE} + public static enum HintAlphaInterpolation { + DEFAULT, QUALITY, SPEED + } + + public static enum HintAntialiasing { + DEFAULT, ON, OFF + } + + public static enum HintColorRendering { + DEFAULT, QUALITY, SPEED + } + + public static enum HintDithering { + DEFAULT, DISABLE, ENABLE + } + + public static enum HintFractionalMetrics { + DEFAULT, ON, OFF + } + + public static enum HintInterpolation { + NEAREST_NEIGHBOR, BILINEAR, BICUBIC + } + + public static enum HintRendering { + DEFAULT, QUALITY, SPEED + } + + public static enum HintStrokeControl { + DEFAULT, NORMALIZE, PURE + } + + public static enum HintTextAntialiasing { + DEFAULT, ON, OFF, GASP, LCD_HBGR, LCD_HRGB, LCD_VBGR, LCD_VRGB + } + + private Typeface font = null; + private boolean fontInherited = true; + private Matte textForeground = null; + private boolean textForegroundInherited = true; + private Matte textBackground = null; + private boolean textBackgroundInherited = true; + private Matte background = null; + private boolean backgroundInherited = true; + + private boolean cacheSettingsInherited = true; + private CacheMode cacheMode = CacheMode.FIXED_SIZES; + private double maxHozCachedImgScaling = 1; + private double maxVertCachedImgScaling = 1; + + private HintAlphaInterpolation hintAlphaInterpolation = null; + private HintAntialiasing hintAntialiasing = null; + private HintColorRendering hintColorRendering = null; + private HintDithering hintDithering = null; + private HintFractionalMetrics hintFractionalMetrics = null; + private HintInterpolation hintInterpolation = null; + private HintRendering hintRendering = null; + private HintStrokeControl hintStrokeControl = null; + private HintTextAntialiasing hintTextAntialiasing = null; + private List uiProperties; + private UIStyle parentStyle = null; + + private PropertyChangeListener textForegoundListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("textForeground." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + private PropertyChangeListener textBackgroundListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("textBackground." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + private PropertyChangeListener backgroundListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + firePropertyChange("background." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + + // ================================================================================================================= + // Constructors + + public UIStyle() { + uiProperties = new ArrayList(); + } + + // ================================================================================================================= + // JIBX Methods + + /** + * Called by JIBX after all fields have been set + * + * @param context The JIBX Unmarshalling Context + */ + private void postSet(IUnmarshallingContext context) { + // walk up till we get a parent style + for (int i = 0; i < context.getStackDepth(); i++) { + if (context.getStackObject(i) instanceof HasUIStyle) { + HasUIStyle hasStyle = (HasUIStyle) context.getStackObject(i); + if (hasStyle.getStyle() != this) { + parentStyle = hasStyle.getStyle(); + if (parentStyle != null) break; + } + } + } + } + + // ================================================================================================================= + // Bean Methods + + public UIStyle getParentStyle() { + return parentStyle; + } + + public void setParentStyle(UIStyle parentStyle) { + UIStyle old = getParentStyle(); + this.parentStyle = parentStyle; + firePropertyChange("parentStyle", old, getParentStyle()); + } + + public List getUiProperties() { + return uiProperties; + } + + public void addUiProperty(UIProperty uiProperty) { + uiProperties.add(uiProperty); + // todo not quite sure what events we want here + fireIndexedPropertyChange("uiProperties", uiProperties.size(), null, uiProperty); +// firePropertyChange("uiProperties", null, uiProperties); + } + + public void removeUiProperty(UIProperty uiProperty) { + int index = uiProperties.indexOf(uiProperty); + if (index != -1) { + uiProperties.remove(uiProperty); + // todo not quite sure what events we want here + fireIndexedPropertyChange("uiProperties", index, null, uiProperty); +// firePropertyChange("uiProperties", null, uiProperties); + } + } + + public Typeface getFont() { + if (isFontInherited()) { + return parentStyle == null ? font : parentStyle.getFont(); + } else { + return font; + } + } + + public void setFont(Typeface font) { + Typeface old = getFont(); + this.font = font; + firePropertyChange("font", old, font); + } + + public boolean isFontInherited() { + return fontInherited; + } + + public void setFontInherited(boolean b) { + boolean old = isFontInherited(); + fontInherited = b; + firePropertyChange("fontInherited", old, b); + + if (!fontInherited && font == null && parentStyle != null && parentStyle.getFont() != null) { + font = parentStyle.getFont().clone(); + firePropertyChange("font", null, font); + } + } + + public Matte getTextForeground() { + if (isTextForegroundInherited()) { + return parentStyle == null ? null : parentStyle.getTextForeground(); + } else { + return textForeground; + } + } + + public boolean isTextForegroundInherited() { + return textForegroundInherited; + } + + public void setTextForegroundInherited(boolean b) { + boolean old = isTextForegroundInherited(); + textForegroundInherited = b; + firePropertyChange("foregroundInherited", old, b); + + if (!textForegroundInherited && textForeground == null && parentStyle != null && + parentStyle.getTextForeground() != null) { + textForeground = parentStyle.getTextForeground().clone(); + firePropertyChange("textForeground", null, textForeground); + } + } + + public void setTextForeground(Matte textForeground) { + Matte old = this.textForeground; + if (old != null) old.removePropertyChangeListener(textForegoundListener); + this.textForeground = textForeground; + if (this.textForeground != null) this.textForeground.addPropertyChangeListener(textForegoundListener); + firePropertyChange("textForeground", old, this.textForeground); + } + + public Matte getTextBackground() { + if (isTextBackgroundInherited()) { + return parentStyle == null ? null : parentStyle.getBackground(); + } else { + return textBackground; + } + } + + public boolean isTextBackgroundInherited() { + return textBackgroundInherited; + } + + public void setTextBackgroundInherited(boolean b) { + boolean old = isBackgroundInherited(); + textBackgroundInherited = b; + firePropertyChange("textBackgroundInherited", old, b); + + if (!textBackgroundInherited && textBackground == null && parentStyle != null && + parentStyle.getTextBackground() != null) { + textBackground = parentStyle.getTextBackground().clone(); + firePropertyChange("textBackground", null, textBackground); + } + } + + public void setTextBackground(Matte textBackground) { + Matte old = this.textBackground; + if (old != null) old.removePropertyChangeListener(textBackgroundListener); + this.textBackground = textBackground; + if (this.textBackground != null) this.textBackground.addPropertyChangeListener(textBackgroundListener); + firePropertyChange("textBackground", old, this.textBackground); + } + + public Matte getBackground() { + if (isBackgroundInherited()) { + return parentStyle == null ? null : parentStyle.getBackground(); + } else { + return background; + } + } + + public boolean isBackgroundInherited() { + return backgroundInherited; + } + + public void setBackgroundInherited(boolean b) { + boolean old = isBackgroundInherited(); + backgroundInherited = b; + firePropertyChange("backgroundInherited", old, b); + + if (!backgroundInherited && background == null && parentStyle != null && parentStyle.getBackground() != null) { + background = parentStyle.getBackground().clone(); + firePropertyChange("background", null, background); + } + } + + public void setBackground(Matte background) { + Matte old = this.background; + if (old != null) old.removePropertyChangeListener(backgroundListener); + this.background = background; + if (this.background != null) this.background.addPropertyChangeListener(backgroundListener); + firePropertyChange("background", old, this.background); + } + + public HintAlphaInterpolation getHintAlphaInterpolation() { + return hintAlphaInterpolation; + } + + public void setHintAlphaInterpolation(HintAlphaInterpolation hintAlphaInterpolation) { + HintAlphaInterpolation old = getHintAlphaInterpolation(); + this.hintAlphaInterpolation = hintAlphaInterpolation; + firePropertyChange("hintAlphaInterpolation", old, getHintAlphaInterpolation()); + } + + public HintAntialiasing getHintAntialiasing() { + return hintAntialiasing; + } + + public void setHintAntialiasing(HintAntialiasing hintAntialiasing) { + HintAntialiasing old = getHintAntialiasing(); + this.hintAntialiasing = hintAntialiasing; + firePropertyChange("hintAntialiasing", old, getHintAntialiasing()); + } + + public HintColorRendering getHintColorRendering() { + return hintColorRendering; + } + + public void setHintColorRendering(HintColorRendering hintColorRendering) { + HintColorRendering old = getHintColorRendering(); + this.hintColorRendering = hintColorRendering; + firePropertyChange("hintColorRendering", old, getHintColorRendering()); + } + + public HintDithering getHintDithering() { + return hintDithering; + } + + public void setHintDithering(HintDithering hintDithering) { + HintDithering old = getHintDithering(); + this.hintDithering = hintDithering; + firePropertyChange("hintDithering", old, getHintDithering()); + } + + public HintFractionalMetrics getHintFractionalMetrics() { + return hintFractionalMetrics; + } + + public void setHintFractionalMetrics(HintFractionalMetrics hintFractionalMetrics) { + HintFractionalMetrics old = getHintFractionalMetrics(); + this.hintFractionalMetrics = hintFractionalMetrics; + firePropertyChange("hintFractionalMetrics", old, getHintFractionalMetrics()); + } + + public HintInterpolation getHintInterpolation() { + return hintInterpolation; + } + + public void setHintInterpolation(HintInterpolation hintInterpolation) { + HintInterpolation old = getHintInterpolation(); + this.hintInterpolation = hintInterpolation; + firePropertyChange("hintInterpolation", old, getHintInterpolation()); + } + + public HintRendering getHintRendering() { + return hintRendering; + } + + public void setHintRendering(HintRendering hintRendering) { + HintRendering old = getHintRendering(); + this.hintRendering = hintRendering; + firePropertyChange("hintRendering", old, getHintRendering()); + } + + public HintStrokeControl getHintStrokeControl() { + return hintStrokeControl; + } + + public void setHintStrokeControl(HintStrokeControl hintStrokeControl) { + HintStrokeControl old = getHintStrokeControl(); + this.hintStrokeControl = hintStrokeControl; + firePropertyChange("hintStrokeControl", old, getHintStrokeControl()); + } + + public HintTextAntialiasing getHintTextAntialiasing() { + return hintTextAntialiasing; + } + + public void setHintTextAntialiasing(HintTextAntialiasing hintTextAntialiasing) { + HintTextAntialiasing old = getHintTextAntialiasing(); + this.hintTextAntialiasing = hintTextAntialiasing; + firePropertyChange("hintTextAntialiasing", old, getHintTextAntialiasing()); + } + + public boolean isCacheSettingsInherited() { + return cacheSettingsInherited; + } + + public void setCacheSettingsInherited(boolean cacheSettingsInherited) { + boolean old = isCacheSettingsInherited(); + this.cacheSettingsInherited = cacheSettingsInherited; + firePropertyChange("cacheSettingsInherited", old, isCacheSettingsInherited()); + } + + public CacheMode getCacheMode() { + if (isCacheSettingsInherited()) { + return (parentStyle == null)?CacheMode.FIXED_SIZES : parentStyle.getCacheMode(); + } else { + return cacheMode; + } + } + + public void setCacheMode(CacheMode cacheMode) { + CacheMode old = this.cacheMode; + this.cacheMode = cacheMode; + if (isCacheSettingsInherited()) { + setCacheSettingsInherited(false); + UIStyle parent = getParentStyle(); + setMaxHozCachedImgScaling(parent == null ? 1 : parent.getMaxHozCachedImgScaling()); + setMaxVertCachedImgScaling(parent == null ? 1 : parent.getMaxVertCachedImgScaling()); + } + firePropertyChange("cacheMode",old,cacheMode); + } + + public double getMaxHozCachedImgScaling() { + if (isCacheSettingsInherited()) { + return parentStyle == null ? 1 : parentStyle.getMaxHozCachedImgScaling(); + } else { + return maxHozCachedImgScaling; + } + } + + public void setMaxHozCachedImgScaling(double maxHozCachedImgScaling) { + double old = getMaxHozCachedImgScaling(); + this.maxHozCachedImgScaling = maxHozCachedImgScaling; + if (isCacheSettingsInherited()) { + setCacheSettingsInherited(false); + setCacheMode((parentStyle == null)?CacheMode.FIXED_SIZES : parentStyle.getCacheMode()); + setMaxVertCachedImgScaling(parentStyle == null ? 1 : parentStyle.getMaxVertCachedImgScaling()); + } + firePropertyChange("maxHozCachedImgScaling", old, getMaxHozCachedImgScaling()); + } + + public double getMaxVertCachedImgScaling() { + if (isCacheSettingsInherited()) { + return parentStyle == null ? 1 : parentStyle.getMaxVertCachedImgScaling(); + } else { + return maxVertCachedImgScaling; + } + } + + public void setMaxVertCachedImgScaling(double maxVertCachedImgScaling) { + double old = getMaxVertCachedImgScaling(); + this.maxVertCachedImgScaling = maxVertCachedImgScaling; + if (isCacheSettingsInherited()) { + setCacheSettingsInherited(false); + setCacheMode((parentStyle == null)?CacheMode.FIXED_SIZES : parentStyle.getCacheMode()); + setMaxHozCachedImgScaling(parentStyle == null ? 1 : parentStyle.getMaxHozCachedImgScaling()); + } + firePropertyChange("maxVertCachedImgScaling", old, getMaxVertCachedImgScaling()); + } +} + diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/BorderMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/BorderMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..da35f401bc42879c82ed5835e665e297da58ff31 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/BorderMapper.java @@ -0,0 +1,285 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel.jibxhelpers; + +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IAliasable; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; +import org.jdesktop.swingx.designer.jibxhelpers.ColorMapper; + +import javax.swing.border.LineBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.border.BevelBorder; +import javax.swing.border.MatteBorder; +import javax.swing.border.CompoundBorder; +import javax.swing.border.Border; +import javax.swing.BorderFactory; +import java.awt.Insets; +import java.awt.Color; +import org.jdesktop.synthdesigner.synthmodel.PainterBorder; + +/** + * BorderMapper - JIBX xml mapper for swing standard borders + * + * @author Jasper Potts + */ +public class BorderMapper implements IMarshaller, IUnmarshaller, IAliasable { + private static enum BorderType { + empty, line, etched, bevel, matte, compound, painter + } + private static enum SubType { + raised(EtchedBorder.RAISED), lowered(EtchedBorder.LOWERED); + private int subtype; + + SubType(int type) { + this.subtype = type; + } + + public int getSubType() { + return subtype; + } + } + private static final String ELEMENT_NAME = "border"; + private static final String TYPE_NAME = "type"; + private static final String SUB_TYPE_NAME = "subtype"; + private static final String TOP_NAME = "top"; + private static final String BOTTOM_NAME = "bottom"; + private static final String LEFT_NAME = "left"; + private static final String RIGHT_NAME = "right"; + private static final String THICKNESS_NAME = "thickness"; + private static final String INSIDE_NAME = "inside"; + private static final String OUTSIDE_NAME = "outside"; + private static final String PAINTER_NAME = "painter"; + + private String uri; + private int index; + private String name; + + public BorderMapper() { + uri = null; + index = 0; + name = ELEMENT_NAME; + } + + public BorderMapper(String uri, int index, String name) { + this.uri = uri; + this.index = index; + this.name = name; + } + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws + JiBXException { + return iUnmarshallingContext.isAt(uri, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) + throws JiBXException { + if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + if (object instanceof PainterBorder) { + PainterBorder border = (PainterBorder) object; + Insets insets = border.getBorderInsets(); + ctx.startTagAttributes(index, name) + .attribute(index, TYPE_NAME, BorderType.painter.toString()) + .attribute(index, PAINTER_NAME, border.getPainterName()) + .attribute(index, TOP_NAME, insets.top) + .attribute(index, BOTTOM_NAME, insets.bottom) + .attribute(index, LEFT_NAME, insets.left) + .attribute(index, RIGHT_NAME, insets.right) + .closeStartContent(); + ctx.endTag(index, name); + } else if (object instanceof EmptyBorder) { + Insets insets = ((EmptyBorder) object).getBorderInsets(); + ctx.startTagAttributes(index, name) + .attribute(index, TYPE_NAME, + BorderType.empty.toString()) + .attribute(index, TOP_NAME, insets.top) + .attribute(index, BOTTOM_NAME, insets.bottom) + .attribute(index, LEFT_NAME, insets.left) + .attribute(index, RIGHT_NAME, insets.right) + .closeStartEmpty(); + } else if (object instanceof LineBorder) { + LineBorder border = (LineBorder) object; + ctx.startTagAttributes(index, name). + attribute(index, TYPE_NAME, BorderType.line.toString()). + attribute(index, THICKNESS_NAME, border.getThickness()). + closeStartContent(); + new ColorMapper().marshal(border.getLineColor(), ctx); + ctx.endTag(index, name); + } else if (object instanceof EtchedBorder) { + EtchedBorder border = (EtchedBorder) object; + ctx.startTagAttributes(index, name). + attribute(index, TYPE_NAME, + BorderType.etched.toString()). + attribute(index, SUB_TYPE_NAME, + border.getEtchType()==EtchedBorder.RAISED? + SubType.raised.toString(): + SubType.lowered.toString()). + closeStartContent(); + new ColorMapper().marshal(border.getHighlightColor(), ctx); + new ColorMapper().marshal(border.getShadowColor(), ctx); + ctx.endTag(index, name); + } else if (object instanceof BevelBorder) { + BevelBorder border = (BevelBorder) object; + ctx.startTagAttributes(index, name). + attribute(index, TYPE_NAME, + BorderType.bevel.toString()). + attribute(index, SUB_TYPE_NAME, + border.getBevelType()==BevelBorder.RAISED? + SubType.raised.toString(): + SubType.lowered.toString()). + closeStartContent(); + new ColorMapper().marshal(border.getHighlightInnerColor(), ctx); + new ColorMapper().marshal(border.getHighlightOuterColor(), ctx); + new ColorMapper().marshal(border.getShadowInnerColor(), ctx); + new ColorMapper().marshal(border.getHighlightOuterColor(), ctx); + ctx.endTag(index, name); + } else if (object instanceof MatteBorder) { + MatteBorder border = (MatteBorder) object; + Insets insets = ((EmptyBorder) object).getBorderInsets(); + ctx.startTagAttributes(index, name) + .attribute(index, TYPE_NAME, + BorderType.matte.toString()) + .attribute(index, TOP_NAME, insets.top) + .attribute(index, BOTTOM_NAME, insets.bottom) + .attribute(index, LEFT_NAME, insets.left) + .attribute(index, RIGHT_NAME, insets.right) + .closeStartContent(); + new ColorMapper().marshal(border.getMatteColor(), ctx); + // todo: we should support tiled icons here to be 100% complete + ctx.endTag(index, name); + } else if (object instanceof CompoundBorder) { + CompoundBorder border = (CompoundBorder) object; + ctx.startTagAttributes(index, name) + .attribute(index, TYPE_NAME, + BorderType.compound.toString()) + .closeStartContent(); + new BorderMapper(null,0, INSIDE_NAME).marshal(border.getInsideBorder(),ctx); + new BorderMapper(null,0, OUTSIDE_NAME).marshal(border.getOutsideBorder(),ctx); + ctx.endTag(index, name); + } else { + throw new JiBXException("Invalid object type for marshaller"); + } + } + } + + public Object unmarshal(Object object, + IUnmarshallingContext iUnmarshallingContext) + throws JiBXException { + Border border = null; + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(uri, name)) { + ctx.throwStartTagNameError(uri, name); + } + // get type + BorderType type = BorderType.valueOf(ctx.attributeText(uri, TYPE_NAME) + .toLowerCase()); + int top,bottom,left,right; + Color color; + switch(type){ + case empty: + top = ctx.attributeInt(uri, TOP_NAME, index); + bottom = ctx.attributeInt(uri, BOTTOM_NAME, index); + left = ctx.attributeInt(uri, LEFT_NAME, index); + right = ctx.attributeInt(uri, RIGHT_NAME, index); + border = BorderFactory.createEmptyBorder(top,left,bottom,right); + break; + case line: + int thickness = ctx.attributeInt(uri, THICKNESS_NAME, index); + ctx.parsePastStartTag(uri,name); + color = (Color)new ColorMapper().unmarshal(null,ctx); + border = BorderFactory.createLineBorder(color,thickness); + break; + case etched: + SubType etchedType = SubType.valueOf( + ctx.attributeText(uri, SUB_TYPE_NAME).toLowerCase()); + ctx.parsePastStartTag(uri,name); + Color highColor = (Color)new ColorMapper() + .unmarshal(null,ctx); + Color shadowColor = (Color)new ColorMapper() + .unmarshal(null,ctx); + border = BorderFactory.createEtchedBorder( + etchedType.getSubType(),highColor,shadowColor); + break; + case bevel: + SubType bevelType = SubType.valueOf( + ctx.attributeText(uri, SUB_TYPE_NAME).toLowerCase()); + ctx.parsePastStartTag(uri,name); + Color innerHighColor = (Color)new ColorMapper() + .unmarshal(null,ctx); + Color outerHighColor = (Color)new ColorMapper() + .unmarshal(null,ctx); + Color innerShadowColor = (Color)new ColorMapper() + .unmarshal(null,ctx); + Color outerShadowColor = (Color)new ColorMapper() + .unmarshal(null,ctx); + border = BorderFactory.createBevelBorder( + bevelType.getSubType(),outerHighColor,innerHighColor, + outerShadowColor,innerShadowColor); + break; + case matte: + top = ctx.attributeInt(uri, TOP_NAME, index); + bottom = ctx.attributeInt(uri, BOTTOM_NAME, index); + left = ctx.attributeInt(uri, LEFT_NAME, index); + right = ctx.attributeInt(uri, RIGHT_NAME, index); + ctx.parsePastStartTag(uri,name); + color = (Color)new ColorMapper().unmarshal(null,ctx); + border = BorderFactory.createMatteBorder(top,left,bottom,right, + color); + break; + case compound: + ctx.parsePastStartTag(uri,name); + Border inside = (Border) new BorderMapper(null,0, INSIDE_NAME) + .unmarshal(null,ctx); + Border outside = (Border) new BorderMapper(null,0, OUTSIDE_NAME) + .unmarshal(null,ctx); + border = BorderFactory.createCompoundBorder(outside, inside); + break; + case painter: + String painterName = ctx.attributeText(uri, PAINTER_NAME); + top = ctx.attributeInt(uri, TOP_NAME, index); + bottom = ctx.attributeInt(uri, BOTTOM_NAME, index); + left = ctx.attributeInt(uri, LEFT_NAME, index); + right = ctx.attributeInt(uri, RIGHT_NAME, index); + border = new PainterBorder(painterName, top, left, bottom, right); + } + ctx.parsePastEndTag(uri, name); + return border; + } +} + diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/ClassConverter.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/ClassConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..ca59d1aac7f0cedfc280e6daca6a0d8b4c842e03 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/ClassConverter.java @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel.jibxhelpers; + +/** + * ClassConverter + * + * @author Created by Jasper Potts (Jul 16, 2007) + */ +public class ClassConverter { + + public static String classToString(Class c) { + return c == null ? "" : c.getName(); + } + + public static Class stringToClass(String className) { + if (className == null || className.length() == 0) { + return null; + } + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) classLoader = ClassConverter.class.getClassLoader(); + return classLoader.loadClass(className); + } catch (ClassNotFoundException e) { + System.err.println("Failed to find class with name [" + className + "] in ClassConverter"); + e.printStackTrace(); + return null; + } + } + +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/ClassMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/ClassMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5d3d7650fbc5b2a43feb243946f6fd358b982a4f --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/ClassMapper.java @@ -0,0 +1,78 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel.jibxhelpers; + +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + + +public class ClassMapper implements IMarshaller, IUnmarshaller { + private static final String ELEMENT_NAME = "type"; + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(null, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof Class)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + Class clazz = (Class) object; + ctx.startTagAttributes(0, ELEMENT_NAME). + attribute(0, "value", clazz.getName()). + closeStartEmpty(); + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(null, ELEMENT_NAME)) { + ctx.throwStartTagNameError(null, ELEMENT_NAME); + } + // get values + String value = ctx.attributeText(null, "value", null); + ctx.parsePastEndTag(null, ELEMENT_NAME); + // create + try { + return Class.forName(value); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/FontMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/FontMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..b815c0c4b97c5425aad8ab5705accf88c00f48f5 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/FontMapper.java @@ -0,0 +1,86 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel.jibxhelpers; + +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + +import java.awt.Font; + +/** + * FontMapper + * + * @author Created by Jasper Potts (Jun 8, 2007) + */ +public class FontMapper implements IMarshaller, IUnmarshaller { + private static final String ELEMENT_NAME = "font"; + private static final String FAMILY_NAME = "family"; + private static final String STYLE_NAME = "style"; + private static final String SIZE_NAME = "size"; + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(null, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof Font)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + Font font = (Font) object; + ctx.startTagAttributes(0, ELEMENT_NAME). + attribute(0, FAMILY_NAME, font.getFamily()). + attribute(0, STYLE_NAME, font.getStyle()). + attribute(0, SIZE_NAME, font.getSize()). + closeStartEmpty(); + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(null, ELEMENT_NAME)) { + ctx.throwStartTagNameError(null, ELEMENT_NAME); + } + // get values + String name = ctx.attributeText(null, FAMILY_NAME, null); + int style = ctx.attributeInt(null, STYLE_NAME, 0); + int size = ctx.attributeInt(null, SIZE_NAME, 0); + ctx.parsePastEndTag(null, ELEMENT_NAME); + // create + return new Font(name, style, size); + } +} diff --git a/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/UIPropertyMapper.java b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/UIPropertyMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..002ab6b9defbc5d9186fd21d75a3ea8d24f51651 --- /dev/null +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/synthmodel/jibxhelpers/UIPropertyMapper.java @@ -0,0 +1,155 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package org.jdesktop.synthdesigner.synthmodel.jibxhelpers; + +import org.jdesktop.swingx.designer.jibxhelpers.DimensionMapper; +import org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper; +import org.jdesktop.synthdesigner.synthmodel.UIProperty; +import org.jibx.runtime.IMarshallable; +import org.jibx.runtime.IMarshaller; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshaller; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.jibx.runtime.impl.MarshallingContext; +import org.jibx.runtime.impl.UnmarshallingContext; + +/** + * UIPropertyMapper + * + * @author Created by Jasper Potts (Jul 10, 2007) + */ +public class UIPropertyMapper implements IMarshaller, IUnmarshaller { + private static final String ELEMENT_NAME = "uiProperty"; + private static final String NAME_NAME = "name"; + private static final String TYPE_NAME = "type"; + private static final String VALUE_NAME = "value"; + + public boolean isExtension(int i) { + return false; + } + + public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + return iUnmarshallingContext.isAt(null, ELEMENT_NAME); + } + + public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException { + if (!(object instanceof UIProperty)) { + throw new JiBXException("Invalid object type for marshaller"); + } else if (!(iMarshallingContext instanceof MarshallingContext)) { + throw new JiBXException("Invalid object type for marshaller"); + } else { + MarshallingContext ctx = (MarshallingContext) iMarshallingContext; + UIProperty property = (UIProperty) object; + ctx.startTagAttributes(0, ELEMENT_NAME); + ctx.attribute(0, NAME_NAME, property.getName()); + ctx.attribute(0, TYPE_NAME, property.getType().toString()); + switch (property.getType()) { + case BOOLEAN: + case DOUBLE: + case INT: + case FLOAT: + case STRING: + ctx.attribute(0, VALUE_NAME, property.getValue().toString()); + ctx.closeStartEmpty(); + break; + case INSETS: + ctx.closeStartContent(); + new InsetsMapper().marshal(property.getValue(), ctx); + ctx.endTag(0, ELEMENT_NAME); + break; + case COLOR: + case FONT: + ctx.closeStartContent(); + if (property.getValue() instanceof IMarshallable) { + ((IMarshallable) property.getValue()).marshal(ctx); + } else { + throw new JiBXException("Mapped value is not marshallable"); + } + ctx.endTag(0, ELEMENT_NAME); + break; + case DIMENSION: + ctx.closeStartContent(); + new DimensionMapper().marshal(property.getValue(), ctx); + ctx.endTag(0, ELEMENT_NAME); + break; + case BORDER: + ctx.closeStartContent(); + new BorderMapper().marshal(property.getValue(), ctx); + ctx.endTag(0, ELEMENT_NAME); + break; + } + } + } + + public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException { + // make sure we're at the appropriate start tag + UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext; + if (!ctx.isAt(null, ELEMENT_NAME)) { + ctx.throwStartTagNameError(null, ELEMENT_NAME); + } + // get values + Object value = null; + String name = ctx.attributeText(null, NAME_NAME, null); + UIProperty.PropertyType type = UIProperty.PropertyType.valueOf(ctx.attributeText(null, TYPE_NAME, null)); + switch (type) { + case BOOLEAN: + value = Boolean.parseBoolean(ctx.attributeText(null, VALUE_NAME, null)); + break; + case DOUBLE: + value = Double.parseDouble(ctx.attributeText(null, VALUE_NAME, null)); + break; + case INT: + value = Integer.parseInt(ctx.attributeText(null, VALUE_NAME, null)); + break; + case FLOAT: + value = Float.parseFloat(ctx.attributeText(null, VALUE_NAME, null)); + break; + case STRING: + value = ctx.attributeText(null, VALUE_NAME, null); + break; + case INSETS: + ctx.parsePastStartTag(null, ELEMENT_NAME); + value = new InsetsMapper().unmarshal(value, ctx); + break; + case COLOR: + case FONT: + ctx.parsePastStartTag(null, ELEMENT_NAME); + value = ctx.unmarshalElement(); + break; + case DIMENSION: + ctx.parsePastStartTag(null, ELEMENT_NAME); + value = new DimensionMapper().unmarshal(value, ctx); + break; + case BORDER: + ctx.parsePastStartTag(null, ELEMENT_NAME); + value = new BorderMapper().unmarshal(value, ctx); + break; + } + ctx.parsePastEndTag(null, ELEMENT_NAME); + // create + return new UIProperty(name, type, value); + } +} diff --git a/src/share/classes/com/sun/java/swing/Painter.java b/src/share/classes/com/sun/java/swing/Painter.java new file mode 100644 index 0000000000000000000000000000000000000000..e424839dfdac19e90f88ed163a51188e6e8ab6e6 --- /dev/null +++ b/src/share/classes/com/sun/java/swing/Painter.java @@ -0,0 +1,33 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.java.swing; + +/** + * This class is preserved for backward compatibility with JDK 6. + * + * @deprecated Use {@link javax.swing.Painter} instead. + */ +public interface Painter extends javax.swing.Painter { +} diff --git a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index acb944dfa561fb7f6337fb1c61ee105259d9862d..fa2b69c9b25532660e95e42db1941caff54ddc15 100644 --- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -134,6 +134,15 @@ class GTKFileChooserUI extends SynthFileChooserUI { super(filechooser); } + protected ActionMap createActionMap() { + ActionMap map = new ActionMapUIResource(); + map.put("approveSelection", getApproveSelectionAction()); + map.put("cancelSelection", getCancelSelectionAction()); + map.put("Go Up", getChangeToParentDirectoryAction()); + map.put("fileNameCompletion", getFileNameCompletionAction()); + return map; + } + public String getFileName() { JFileChooser fc = getFileChooser(); String typedInName = fileNameTextField != null ? diff --git a/src/share/classes/com/sun/java/swing/plaf/nimbus/AbstractRegionPainter.java b/src/share/classes/com/sun/java/swing/plaf/nimbus/AbstractRegionPainter.java new file mode 100644 index 0000000000000000000000000000000000000000..b554dbd71934ee7481563039d6ce27f29cdfc162 --- /dev/null +++ b/src/share/classes/com/sun/java/swing/plaf/nimbus/AbstractRegionPainter.java @@ -0,0 +1,33 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.java.swing.plaf.nimbus; + +/** + * This class is preserved for backward compatibility with JDK 6. + * + * @deprecated Use {@link javax.swing.plaf.nimbus.AbstractRegionPainter} instead. + */ +public abstract class AbstractRegionPainter extends javax.swing.plaf.nimbus.AbstractRegionPainter { +} diff --git a/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java b/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java new file mode 100644 index 0000000000000000000000000000000000000000..bff3973b0c4d3e3db8744ed0d54e0a1f3707ec33 --- /dev/null +++ b/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java @@ -0,0 +1,33 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.java.swing.plaf.nimbus; + +/** + * This class is preserved for backward compatibility with JDK 6. + * + * @deprecated Use {@link javax.swing.plaf.nimbus.NimbusLookAndFeel} instead. + */ +public class NimbusLookAndFeel extends javax.swing.plaf.nimbus.NimbusLookAndFeel { +} diff --git a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index 788fe9fec387a3c4020795de6c804be6b871d6f8..e24067efad15f4c3492d5fe5d654ed24bbd46fad 100644 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -1009,6 +1009,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "PopupMenu.background", MenuBackgroundColor, "PopupMenu.foreground", MenuTextColor, "PopupMenu.popupSound", "win.sound.menuPopup", + "PopupMenu.consumeEventOnClose", Boolean.TRUE, // Menus "Menu.font", MenuFont, diff --git a/src/share/classes/com/sun/media/sound/SoftAudioPusher.java b/src/share/classes/com/sun/media/sound/SoftAudioPusher.java index d19ff412bd8094208f5a76a798c6b90ab5597dae..43773347a41f72c3141b2eb944c4b88b2237c925 100644 --- a/src/share/classes/com/sun/media/sound/SoftAudioPusher.java +++ b/src/share/classes/com/sun/media/sound/SoftAudioPusher.java @@ -54,6 +54,7 @@ public class SoftAudioPusher implements Runnable { return; active = true; audiothread = new Thread(this); + audiothread.setDaemon(true); audiothread.setPriority(Thread.MAX_PRIORITY); audiothread.start(); } diff --git a/src/share/classes/com/sun/media/sound/SoftChannel.java b/src/share/classes/com/sun/media/sound/SoftChannel.java index 8bb5f2ef66a0baf5da7f5f2568bf4769400f97b1..96a575f2c8ee11900b694529973ff215f5a3cb1f 100644 --- a/src/share/classes/com/sun/media/sound/SoftChannel.java +++ b/src/share/classes/com/sun/media/sound/SoftChannel.java @@ -93,7 +93,6 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { protected double portamento_time = 1; // keyschanges per control buffer time protected int[] portamento_lastnote = new int[128]; protected int portamento_lastnote_ix = 0; - private int portamento_control_note = -1; private boolean portamento = false; private boolean mono = false; private boolean mute = false; @@ -369,12 +368,12 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { voice.setSoloMute(solomute); if (releaseTriggered) return; - if (portamento_control_note != -1) { + if (controller[84] != 0) { voice.co_noteon_keynumber[0] - = (tuning.getTuning(portamento_control_note) / 100.0) + = (tuning.getTuning(controller[84]) / 100.0) * (1f / 128f); voice.portamento = true; - portamento_control_note = -1; + controlChange(84, 0); } else if (portamento) { if (mono) { if (portamento_lastnote[0] != -1) { @@ -382,7 +381,7 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { = (tuning.getTuning(portamento_lastnote[0]) / 100.0) * (1f / 128f); voice.portamento = true; - portamento_control_note = -1; + controlChange(84, 0); } portamento_lastnote[0] = noteNumber; } else { @@ -449,19 +448,19 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { } } - if (portamento_control_note != -1) { + if (controller[84] != 0) { boolean n_found = false; for (int i = 0; i < voices.length; i++) { if (voices[i].on && voices[i].channel == channel && voices[i].active - && voices[i].note == portamento_control_note + && voices[i].note == controller[84] && voices[i].releaseTriggered == false) { voices[i].portamento = true; voices[i].setNote(noteNumber); n_found = true; } } - portamento_control_note = -1; + controlChange(84, 0); if (n_found) return; } @@ -556,6 +555,18 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { && voices[i].releaseTriggered == false) { voices[i].noteOff(velocity); } + // We must also check stolen voices + if (voices[i].stealer_channel == this && voices[i].stealer_noteNumber == noteNumber) { + SoftVoice v = voices[i]; + v.stealer_releaseTriggered = false; + v.stealer_channel = null; + v.stealer_performer = null; + v.stealer_voiceID = -1; + v.stealer_noteNumber = 0; + v.stealer_velocity = 0; + v.stealer_extendedConnectionBlocks = null; + v.stealer_channelmixer = null; + } } // Try play back note-off triggered voices, @@ -1141,9 +1152,6 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { } } break; - case 84: - portamento_control_note = value; - break; case 98: nrpn_control = (nrpn_control & (127 << 7)) + value; rpn_control = RPN_NULL_VALUE; diff --git a/src/share/classes/com/sun/media/sound/SoftChorus.java b/src/share/classes/com/sun/media/sound/SoftChorus.java index 0a9f64439502e28ba74e481ad38e750621b99262..59778cdbb1e4df22842a44114a2ddfb8c30ba60b 100644 --- a/src/share/classes/com/sun/media/sound/SoftChorus.java +++ b/src/share/classes/com/sun/media/sound/SoftChorus.java @@ -38,11 +38,11 @@ public class SoftChorus implements SoftAudioProcessor { private float[] delaybuffer; private int rovepos = 0; - private volatile float gain = 1; - private volatile float rgain = 0; - private volatile float delay = 0; + private float gain = 1; + private float rgain = 0; + private float delay = 0; private float lastdelay = 0; - private volatile float feedback = 0; + private float feedback = 0; public VariableDelay(int maxbuffersize) { delaybuffer = new float[maxbuffersize]; @@ -115,10 +115,8 @@ public class SoftChorus implements SoftAudioProcessor { private static class LFODelay { - private volatile double c_cos_delta; - private volatile double c_sin_delta; - private double c_cos = 1; - private double c_sin = 0; + private double phase = 1; + private double phase_step = 0; private double depth = 0; private VariableDelay vdelay; private double samplerate; @@ -139,13 +137,11 @@ public class SoftChorus implements SoftAudioProcessor { public void setRate(double rate) { double g = (Math.PI * 2) * (rate / controlrate); - c_cos_delta = Math.cos(g); - c_sin_delta = Math.sin(g); + phase_step = g; } public void setPhase(double phase) { - c_cos = Math.cos(phase); - c_sin = Math.sin(phase); + this.phase = phase; } public void setFeedBack(float feedback) { @@ -161,16 +157,16 @@ public class SoftChorus implements SoftAudioProcessor { } public void processMix(float[] in, float[] out, float[] rout) { - c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta; - c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta; - vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2))); + phase += phase_step; + while(phase > (Math.PI * 2)) phase -= (Math.PI * 2); + vdelay.setDelay((float) (depth * 0.5 * (Math.cos(phase) + 2))); vdelay.processMix(in, out, rout); } public void processReplace(float[] in, float[] out, float[] rout) { - c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta; - c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta; - vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2))); + phase += phase_step; + while(phase > (Math.PI * 2)) phase -= (Math.PI * 2); + vdelay.setDelay((float) (depth * 0.5 * (Math.cos(phase) + 2))); vdelay.processReplace(in, out, rout); } diff --git a/src/share/classes/com/sun/media/sound/SoftFilter.java b/src/share/classes/com/sun/media/sound/SoftFilter.java index 0468f15bec06cf06e097263867e14caac80a41a9..c7ed4872b8b656164598ab4ca905ff47cb9e3d4a 100644 --- a/src/share/classes/com/sun/media/sound/SoftFilter.java +++ b/src/share/classes/com/sun/media/sound/SoftFilter.java @@ -543,8 +543,6 @@ public class SoftFilter { public void filter1(SoftAudioBuffer sbuffer) { - float[] buffer = sbuffer.array(); - if (dirty) { filter1calc(); dirty = false; @@ -559,6 +557,7 @@ public class SoftFilter { if (wet > 0 || last_wet > 0) { + float[] buffer = sbuffer.array(); int len = buffer.length; float a0 = this.last_a0; float q = this.last_q; @@ -577,14 +576,16 @@ public class SoftFilter { q += q_delta; gain += gain_delta; wet += wet_delta; - y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; - y2 = (1 - q * a0) * y2 + (a0) * y1; + float ga0 = (1 - q * a0); + y1 = ga0 * y1 + (a0) * (buffer[i] - y2); + y2 = ga0 * y2 + (a0) * y1; buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet); } } else if (a0_delta == 0 && q_delta == 0) { + float ga0 = (1 - q * a0); for (int i = 0; i < len; i++) { - y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; - y2 = (1 - q * a0) * y2 + (a0) * y1; + y1 = ga0 * y1 + (a0) * (buffer[i] - y2); + y2 = ga0 * y2 + (a0) * y1; buffer[i] = y2 * gain; } } else { @@ -592,8 +593,9 @@ public class SoftFilter { a0 += a0_delta; q += q_delta; gain += gain_delta; - y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; - y2 = (1 - q * a0) * y2 + (a0) * y1; + float ga0 = (1 - q * a0); + y1 = ga0 * y1 + (a0) * (buffer[i] - y2); + y2 = ga0 * y2 + (a0) * y1; buffer[i] = y2 * gain; } } diff --git a/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java b/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java index 98d205b6deb6214dd2799c867d4e40678d0e6140..b647ba77908420232f69834816db182aa300abc6 100644 --- a/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java +++ b/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java @@ -216,6 +216,7 @@ public class SoftJitterCorrector extends AudioInputStream { }; thread = new Thread(runnable); + thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } diff --git a/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java b/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java index adfe9e08de3f5f36095a7d7a5ce607e45a495d53..5e2ea0b499949276fdd5aab448fc7736024b05a0 100644 --- a/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java +++ b/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java @@ -45,6 +45,13 @@ public class SoftLowFrequencyOscillator implements SoftProcess { private double sin_factor = 0; private static double PI2 = 2.0 * Math.PI; + public SoftLowFrequencyOscillator() { + // If sin_step is 0 then sin_stepfreq must be -INF + for (int i = 0; i < sin_stepfreq.length; i++) { + sin_stepfreq[i] = Double.NEGATIVE_INFINITY; + } + } + public void reset() { for (int i = 0; i < used_count; i++) { out[i][0] = 0; @@ -53,7 +60,8 @@ public class SoftLowFrequencyOscillator implements SoftProcess { freq[i][0] = 0; delay_counter[i] = 0; sin_phase[i] = 0; - sin_stepfreq[i] = 0; + // If sin_step is 0 then sin_stepfreq must be -INF + sin_stepfreq[i] = Double.NEGATIVE_INFINITY; sin_step[i] = 0; } used_count = 0; diff --git a/src/share/classes/com/sun/media/sound/SoftMainMixer.java b/src/share/classes/com/sun/media/sound/SoftMainMixer.java index 1f38058b052975115dbe87cc115c8ea4ac01b934..b62d1d480aff7239181eacdb3c9372ecc8284586 100644 --- a/src/share/classes/com/sun/media/sound/SoftMainMixer.java +++ b/src/share/classes/com/sun/media/sound/SoftMainMixer.java @@ -48,16 +48,18 @@ public class SoftMainMixer { public final static int CHANNEL_LEFT = 0; public final static int CHANNEL_RIGHT = 1; - public final static int CHANNEL_EFFECT1 = 2; - public final static int CHANNEL_EFFECT2 = 3; - public final static int CHANNEL_EFFECT3 = 4; - public final static int CHANNEL_EFFECT4 = 5; + public final static int CHANNEL_MONO = 2; + public final static int CHANNEL_EFFECT1 = 3; + public final static int CHANNEL_EFFECT2 = 4; + public final static int CHANNEL_EFFECT3 = 5; + public final static int CHANNEL_EFFECT4 = 6; public final static int CHANNEL_LEFT_DRY = 10; public final static int CHANNEL_RIGHT_DRY = 11; public final static int CHANNEL_SCRATCH1 = 12; public final static int CHANNEL_SCRATCH2 = 13; public final static int CHANNEL_CHANNELMIXER_LEFT = 14; public final static int CHANNEL_CHANNELMIXER_RIGHT = 15; + public final static int CHANNEL_CHANNELMIXER_MONO = 16; protected boolean active_sensing_on = false; private long msec_last_activity = -1; private boolean pusher_silent = false; @@ -485,8 +487,10 @@ public class SoftMainMixer { // to channelmixer left,right input/output SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT]; SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT]; + SoftAudioBuffer monobak = buffers[CHANNEL_MONO]; buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT]; - buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT]; + buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_RIGHT]; + buffers[CHANNEL_MONO] = buffers[CHANNEL_CHANNELMIXER_MONO]; int bufferlen = buffers[CHANNEL_LEFT].getSize(); @@ -503,6 +507,7 @@ public class SoftMainMixer { for (ModelChannelMixer cmixer : act_registeredMixers) { for (int i = 0; i < cbuffer.length; i++) Arrays.fill(cbuffer[i], 0); + buffers[CHANNEL_MONO].clear(); boolean hasactivevoices = false; for (int i = 0; i < voicestatus.length; i++) if (voicestatus[i].active) @@ -517,6 +522,26 @@ public class SoftMainMixer { } } + if(!buffers[CHANNEL_MONO].isSilent()) + { + float[] mono = buffers[CHANNEL_MONO].array(); + float[] left = buffers[CHANNEL_LEFT].array(); + if (nrofchannels != 1) { + float[] right = buffers[CHANNEL_RIGHT].array(); + for (int i = 0; i < bufferlen; i++) { + float v = mono[i]; + left[i] += v; + right[i] += v; + } + } + else + { + for (int i = 0; i < bufferlen; i++) { + left[i] += mono[i]; + } + } + } + for (int i = 0; i < cbuffer.length; i++) { float[] cbuff = cbuffer[i]; float[] obuff = obuffer[i]; @@ -539,6 +564,7 @@ public class SoftMainMixer { buffers[CHANNEL_LEFT] = leftbak; buffers[CHANNEL_RIGHT] = rightbak; + buffers[CHANNEL_MONO] = monobak; } @@ -547,6 +573,27 @@ public class SoftMainMixer { if (voicestatus[i].channelmixer == null) voicestatus[i].processAudioLogic(buffers); + if(!buffers[CHANNEL_MONO].isSilent()) + { + float[] mono = buffers[CHANNEL_MONO].array(); + float[] left = buffers[CHANNEL_LEFT].array(); + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + if (nrofchannels != 1) { + float[] right = buffers[CHANNEL_RIGHT].array(); + for (int i = 0; i < bufferlen; i++) { + float v = mono[i]; + left[i] += v; + right[i] += v; + } + } + else + { + for (int i = 0; i < bufferlen; i++) { + left[i] += mono[i]; + } + } + } + // Run effects if (synth.chorus_on) chorus.processAudio(); @@ -665,7 +712,7 @@ public class SoftMainMixer { / synth.getControlRate()); control_mutex = synth.control_mutex; - buffers = new SoftAudioBuffer[16]; + buffers = new SoftAudioBuffer[17]; for (int i = 0; i < buffers.length; i++) { buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat()); } diff --git a/src/share/classes/com/sun/media/sound/SoftSynthesizer.java b/src/share/classes/com/sun/media/sound/SoftSynthesizer.java index 3f6c12fc76554bb5c456c2a38a6b30b5e02e4b71..ab46b2dc9a970d9153288826445a72c4d9f2959b 100644 --- a/src/share/classes/com/sun/media/sound/SoftSynthesizer.java +++ b/src/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -889,9 +889,12 @@ public class SoftSynthesizer implements AudioSynthesizer, return; } synchronized (control_mutex) { + Throwable causeException = null; try { - if (line != null) + if (line != null) { + // can throw IllegalArgumentException setFormat(line.getFormat()); + } AudioInputStream ais = openStream(getFormat(), info); @@ -900,10 +903,13 @@ public class SoftSynthesizer implements AudioSynthesizer, if (line == null) { - if(testline != null) + if (testline != null) { line = testline; - else + } else { + // can throw LineUnavailableException, + // IllegalArgumentException, SecurityException line = AudioSystem.getSourceDataLine(getFormat()); + } } double latency = this.latency; @@ -911,6 +917,8 @@ public class SoftSynthesizer implements AudioSynthesizer, if (!line.isOpen()) { int bufferSize = getFormat().getFrameSize() * (int)(getFormat().getFrameRate() * (latency/1000000f)); + // can throw LineUnavailableException, + // IllegalArgumentException, SecurityException line.open(getFormat(), bufferSize); // Remember that we opened that line @@ -954,13 +962,22 @@ public class SoftSynthesizer implements AudioSynthesizer, weakstream.sourceDataLine = sourceDataLine; } - - } catch (LineUnavailableException e) { + causeException = e; + } catch (IllegalArgumentException e) { + causeException = e; + } catch (SecurityException e) { + causeException = e; + } + + if (causeException != null) { if (isOpen()) close(); // am: need MidiUnavailableException(Throwable) ctor! - throw new MidiUnavailableException(e.toString()); + MidiUnavailableException ex = new MidiUnavailableException( + "Can not open line"); + ex.initCause(causeException); + throw ex; } } diff --git a/src/share/classes/com/sun/media/sound/SoftVoice.java b/src/share/classes/com/sun/media/sound/SoftVoice.java index 49662b78706b2765c72b0b1cd44254059cd0fa89..cec2e3047acb24aaeab8c5439bad5108b161eb4a 100644 --- a/src/share/classes/com/sun/media/sound/SoftVoice.java +++ b/src/share/classes/com/sun/media/sound/SoftVoice.java @@ -782,6 +782,7 @@ public class SoftVoice extends VoiceStatus { SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT]; SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT]; + SoftAudioBuffer mono = buffer[SoftMainMixer.CHANNEL_MONO]; SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1]; SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2]; SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY]; @@ -803,13 +804,22 @@ public class SoftVoice extends VoiceStatus { mixAudioStream(rightdry, left, last_out_mixer_left, out_mixer_left); } else { - mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); - if (rightdry != null) - mixAudioStream(rightdry, right, last_out_mixer_right, - out_mixer_right); + if(rightdry == null && + last_out_mixer_left == last_out_mixer_right && + out_mixer_left == out_mixer_right) + { + mixAudioStream(leftdry, mono, last_out_mixer_left, out_mixer_left); + } else - mixAudioStream(leftdry, right, last_out_mixer_right, + { + mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); + if (rightdry != null) + mixAudioStream(rightdry, right, last_out_mixer_right, out_mixer_right); + else + mixAudioStream(leftdry, right, last_out_mixer_right, + out_mixer_right); + } } if (rightdry == null) { diff --git a/src/share/classes/java/awt/Color.java b/src/share/classes/java/awt/Color.java index f99e2bfdd0c7a02e0d9c1be80e437480f2519b88..0710dbb7e650314074763c615ede7a7cecefb1b3 100644 --- a/src/share/classes/java/awt/Color.java +++ b/src/share/classes/java/awt/Color.java @@ -687,7 +687,7 @@ public class Color implements Paint, java.io.Serializable { * @since JDK1.0 */ public boolean equals(Object obj) { - return obj instanceof Color && ((Color)obj).value == this.value; + return obj instanceof Color && ((Color)obj).getRGB() == this.getRGB(); } /** diff --git a/src/share/classes/javax/sound/midi/MetaMessage.java b/src/share/classes/javax/sound/midi/MetaMessage.java index 7718f8caf38cd8ac10a7bf0b4d370349c0cd3825..8b27fa1f490c0a6f59333de42820c33dbf74f7c9 100644 --- a/src/share/classes/javax/sound/midi/MetaMessage.java +++ b/src/share/classes/javax/sound/midi/MetaMessage.java @@ -102,6 +102,29 @@ public class MetaMessage extends MidiMessage { this(defaultMessage); } + /** + * Constructs a new {@code MetaMessage} and sets the message parameters. + * The contents of the message can be changed by using + * the {@code setMessage} method. + * + * @param type meta-message type (must be less than 128) + * @param data the data bytes in the MIDI message + * @param length an amount of bytes in the {@code data} byte array; + * it should be non-negative and less than or equal to + * {@code data.length} + * @throws InvalidMidiDataException if the parameter values do not specify + * a valid MIDI meta message + * @see #setMessage(int, byte[], int) + * @see #getType() + * @see #getData() + * @since 1.7 + */ + public MetaMessage(int type, byte[] data, int length) + throws InvalidMidiDataException { + super(null); + setMessage(type, data, length); // can throw InvalidMidiDataException + } + /** * Constructs a new MetaMessage. diff --git a/src/share/classes/javax/sound/midi/ShortMessage.java b/src/share/classes/javax/sound/midi/ShortMessage.java index 716d7b0ef4ff4b750f7ed8088c35612fec853fe7..2dddc3c7a8536672a28247d8a3d7ddcefc9facc7 100644 --- a/src/share/classes/javax/sound/midi/ShortMessage.java +++ b/src/share/classes/javax/sound/midi/ShortMessage.java @@ -187,6 +187,83 @@ public class ShortMessage extends MidiMessage { length = 3; } + /** + * Constructs a new {@code ShortMessage} which represents a MIDI + * message that takes no data bytes. + * The contents of the message can be changed by using one of + * the {@code setMessage} methods. + * + * @param status the MIDI status byte + * @throws InvalidMidiDataException if {@code status} does not specify + * a valid MIDI status byte for a message that requires no data bytes + * @see #setMessage(int) + * @see #setMessage(int, int, int) + * @see #setMessage(int, int, int, int) + * @see #getStatus() + * @since 1.7 + */ + public ShortMessage(int status) throws InvalidMidiDataException { + super(null); + setMessage(status); // can throw InvalidMidiDataException + } + + /** + * Constructs a new {@code ShortMessage} which represents a MIDI message + * that takes up to two data bytes. If the message only takes one data byte, + * the second data byte is ignored. If the message does not take + * any data bytes, both data bytes are ignored. + * The contents of the message can be changed by using one of + * the {@code setMessage} methods. + * + * @param status the MIDI status byte + * @param data1 the first data byte + * @param data2 the second data byte + * @throws InvalidMidiDataException if the status byte or all data bytes + * belonging to the message do not specify a valid MIDI message + * @see #setMessage(int) + * @see #setMessage(int, int, int) + * @see #setMessage(int, int, int, int) + * @see #getStatus() + * @see #getData1() + * @see #getData2() + * @since 1.7 + */ + public ShortMessage(int status, int data1, int data2) + throws InvalidMidiDataException { + super(null); + setMessage(status, data1, data2); // can throw InvalidMidiDataException + } + + /** + * Constructs a new {@code ShortMessage} which represents a channel + * MIDI message that takes up to two data bytes. If the message only takes + * one data byte, the second data byte is ignored. If the message does not + * take any data bytes, both data bytes are ignored. + * The contents of the message can be changed by using one of + * the {@code setMessage} methods. + * + * @param command the MIDI command represented by this message + * @param channel the channel associated with the message + * @param data1 the first data byte + * @param data2 the second data byte + * @throws InvalidMidiDataException if the command value, channel value + * or all data bytes belonging to the message do not specify + * a valid MIDI message + * @see #setMessage(int) + * @see #setMessage(int, int, int) + * @see #setMessage(int, int, int, int) + * @see #getCommand() + * @see #getChannel() + * @see #getData1() + * @see #getData2() + * @since 1.7 + */ + public ShortMessage(int command, int channel, int data1, int data2) + throws InvalidMidiDataException { + super(null); + setMessage(command, channel, data1, data2); + } + /** * Constructs a new ShortMessage. diff --git a/src/share/classes/javax/sound/midi/SysexMessage.java b/src/share/classes/javax/sound/midi/SysexMessage.java index a3833fffdbe0e5eaaa3c95cbe294ba34936887e2..387d066033952f7e33c678c849ba99c51d0f8aa5 100644 --- a/src/share/classes/javax/sound/midi/SysexMessage.java +++ b/src/share/classes/javax/sound/midi/SysexMessage.java @@ -120,6 +120,54 @@ public class SysexMessage extends MidiMessage { data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF); } + /** + * Constructs a new {@code SysexMessage} and sets the data for + * the message. The first byte of the data array must be a valid system + * exclusive status byte (0xF0 or 0xF7). + * The contents of the message can be changed by using one of + * the {@code setMessage} methods. + * + * @param data the system exclusive message data including the status byte + * @param length the length of the valid message data in the array, + * including the status byte; it should be non-negative and less than + * or equal to {@code data.length} + * @throws InvalidMidiDataException if the parameter values + * do not specify a valid MIDI meta message. + * @see #setMessage(byte[], int) + * @see #setMessage(int, byte[], int) + * @see #getData() + * @since 1.7 + */ + public SysexMessage(byte[] data, int length) + throws InvalidMidiDataException { + super(null); + setMessage(data, length); + } + + /** + * Constructs a new {@code SysexMessage} and sets the data for the message. + * The contents of the message can be changed by using one of + * the {@code setMessage} methods. + * + * @param status the status byte for the message; it must be a valid system + * exclusive status byte (0xF0 or 0xF7) + * @param data the system exclusive message data (without the status byte) + * @param length the length of the valid message data in the array; + * it should be non-negative and less than or equal to + * {@code data.length} + * @throws InvalidMidiDataException if the parameter values + * do not specify a valid MIDI meta message. + * @see #setMessage(byte[], int) + * @see #setMessage(int, byte[], int) + * @see #getData() + * @since 1.7 + */ + public SysexMessage(int status, byte[] data, int length) + throws InvalidMidiDataException { + super(null); + setMessage(status, data, length); + } + /** * Constructs a new SysexMessage. diff --git a/src/share/classes/javax/sound/sampled/FloatControl.java b/src/share/classes/javax/sound/sampled/FloatControl.java index 650ec4901c3dab584ca8f5782eb55bb9454cb6c7..12a31402bc28507a046ed1827d0a794311a7bfe8 100644 --- a/src/share/classes/javax/sound/sampled/FloatControl.java +++ b/src/share/classes/javax/sound/sampled/FloatControl.java @@ -131,13 +131,31 @@ public abstract class FloatControl extends Control { * @param minLabel the label for the minimum value, such as "Left" or "Off" * @param midLabel the label for the midpoint value, such as "Center" or "Default" * @param maxLabel the label for the maximum value, such as "Right" or "Full" + * + * @throws IllegalArgumentException if {@code minimum} is greater + * than {@code maximum} or {@code initialValue} does not fall + * within the allowable range */ protected FloatControl(Type type, float minimum, float maximum, - float precision, int updatePeriod, float initialValue, - String units, String minLabel, String midLabel, String maxLabel) { + float precision, int updatePeriod, float initialValue, + String units, String minLabel, String midLabel, String maxLabel) { super(type); + if (minimum > maximum) { + throw new IllegalArgumentException("Minimum value " + minimum + + " exceeds maximum value " + maximum + "."); + } + if (initialValue < minimum) { + throw new IllegalArgumentException("Initial value " + initialValue + + " smaller than allowable minimum value " + minimum + "."); + } + if (initialValue > maximum) { + throw new IllegalArgumentException("Initial value " + initialValue + + " exceeds allowable maximum value " + maximum + "."); + } + + this.minimum = minimum; this.maximum = maximum; @@ -167,10 +185,15 @@ public abstract class FloatControl extends Control { * @param initialValue the value that the control starts with when constructed * @param units the label for the units in which the control's values are expressed, * such as "dB" or "frames per second" + * + * @throws IllegalArgumentException if {@code minimum} is greater + * than {@code maximum} or {@code initialValue} does not fall + * within the allowable range */ protected FloatControl(Type type, float minimum, float maximum, - float precision, int updatePeriod, float initialValue, String units) { - this(type, minimum, maximum, precision, updatePeriod, initialValue, units, "", "", ""); + float precision, int updatePeriod, float initialValue, String units) { + this(type, minimum, maximum, precision, updatePeriod, + initialValue, units, "", "", ""); } @@ -306,9 +329,21 @@ public abstract class FloatControl extends Control { * @param to final value after the shift * @param microseconds maximum duration of the shift in microseconds * + * @throws IllegalArgumentException if either {@code from} or {@code to} + * value does not fall within the allowable range + * * @see #getUpdatePeriod */ public void shift(float from, float to, int microseconds) { + // test "from" value, "to" value will be tested by setValue() + if (from < minimum) { + throw new IllegalArgumentException("Requested value " + from + + " smaller than allowable minimum value " + minimum + "."); + } + if (from > maximum) { + throw new IllegalArgumentException("Requested value " + from + + " exceeds allowable maximum value " + maximum + "."); + } setValue(to); } diff --git a/src/share/classes/javax/sound/sampled/spi/MixerProvider.java b/src/share/classes/javax/sound/sampled/spi/MixerProvider.java index d5c161ea34d6c362656d667163b660991a9268aa..c79bb1114a6b87fe6f1ab65eb89d73a3a0b5c2fa 100644 --- a/src/share/classes/javax/sound/sampled/spi/MixerProvider.java +++ b/src/share/classes/javax/sound/sampled/spi/MixerProvider.java @@ -42,9 +42,15 @@ public abstract class MixerProvider { /** * Indicates whether the mixer provider supports the mixer represented by * the specified mixer info object. + *

+ * The full set of mixer info objects that represent the mixers supported + * by this {@code MixerProvider} may be obtained + * through the {@code getMixerInfo} method. + * * @param info an info object that describes the mixer for which support is queried - * @return true if the specified mixer is supported, - * otherwise false + * @return {@code true} if the specified mixer is supported, + * otherwise {@code false} + * @see #getMixerInfo() */ public boolean isMixerSupported(Mixer.Info info) { @@ -62,17 +68,34 @@ public abstract class MixerProvider { /** * Obtains the set of info objects representing the mixer * or mixers provided by this MixerProvider. - * @return set of mixer info objects + *

+ * The {@code isMixerSupported} method returns {@code true} + * for all the info objects returned by this method. + * The corresponding mixer instances for the info objects + * are returned by the {@code getMixer} method. + * + * @return a set of mixer info objects + * @see #getMixer(javax.sound.sampled.Mixer.Info) getMixer(Mixer.Info) + * @see #isMixerSupported(javax.sound.sampled.Mixer.Info) isMixerSupported(Mixer.Info) */ public abstract Mixer.Info[] getMixerInfo(); /** * Obtains an instance of the mixer represented by the info object. + *

+ * The full set of the mixer info objects that represent the mixers + * supported by this {@code MixerProvider} may be obtained + * through the {@code getMixerInfo} method. + * Use the {@code isMixerSupported} method to test whether + * this {@code MixerProvider} supports a particular mixer. + * * @param info an info object that describes the desired mixer * @return mixer instance * @throws IllegalArgumentException if the info object specified does not - * match the info object for a mixer supported by this MixerProvider. + * match the info object for a mixer supported by this MixerProvider. + * @see #getMixerInfo() + * @see #isMixerSupported(javax.sound.sampled.Mixer.Info) isMixerSupported(Mixer.Info) */ public abstract Mixer getMixer(Mixer.Info info); } diff --git a/src/share/classes/javax/swing/DefaultCellEditor.java b/src/share/classes/javax/swing/DefaultCellEditor.java index da1bbcc53d8df488efc956fb6bb9b6ee4c2b253e..3320d379d3582717112a6d6c27f6466bbd2119d8 100644 --- a/src/share/classes/javax/swing/DefaultCellEditor.java +++ b/src/share/classes/javax/swing/DefaultCellEditor.java @@ -266,6 +266,26 @@ public class DefaultCellEditor extends AbstractCellEditor boolean isSelected, int row, int column) { delegate.setValue(value); + if (editorComponent instanceof JCheckBox) { + //in order to avoid a "flashing" effect when clicking a checkbox + //in a table, it is important for the editor to have as a border + //the same border that the renderer has, and have as the background + //the same color as the renderer has. This is primarily only + //needed for JCheckBox since this editor doesn't fill all the + //visual space of the table cell, unlike a text field. + TableCellRenderer renderer = table.getCellRenderer(row, column); + Component c = renderer.getTableCellRendererComponent(table, value, + isSelected, true, row, column); + if (c != null) { + editorComponent.setOpaque(true); + editorComponent.setBackground(c.getBackground()); + if (c instanceof JComponent) { + editorComponent.setBorder(((JComponent)c).getBorder()); + } + } else { + editorComponent.setOpaque(false); + } + } return editorComponent; } diff --git a/src/share/classes/javax/swing/DefaultListCellRenderer.java b/src/share/classes/javax/swing/DefaultListCellRenderer.java index 4d523e0f78af067599a8a21cdd8cd8755b34ef8d..2cb42272ae8bba0b6c79f43b5b8be8719abccd3f 100644 --- a/src/share/classes/javax/swing/DefaultListCellRenderer.java +++ b/src/share/classes/javax/swing/DefaultListCellRenderer.java @@ -34,6 +34,7 @@ import java.awt.Color; import java.awt.Rectangle; import java.io.Serializable; +import sun.swing.DefaultLookup; /** @@ -79,8 +80,9 @@ public class DefaultListCellRenderer extends JLabel * getListCellRendererComponent method and set the border * of the returned component directly. */ - protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); + private static final Border DEFAULT_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); + protected static Border noFocusBorder = DEFAULT_NO_FOCUS_BORDER; /** * Constructs a default renderer object for an item @@ -90,14 +92,21 @@ public class DefaultListCellRenderer extends JLabel super(); setOpaque(true); setBorder(getNoFocusBorder()); + setName("List.cellRenderer"); } - - private static Border getNoFocusBorder() { + private Border getNoFocusBorder() { + Border border = DefaultLookup.getBorder(this, ui, "List.cellNoFocusBorder"); if (System.getSecurityManager() != null) { + if (border != null) return border; return SAFE_NO_FOCUS_BORDER; } else { - return UIManager.getBorder("List.noFocusBorder"); + if (border != null && + (noFocusBorder == null || + noFocusBorder == DEFAULT_NO_FOCUS_BORDER)) { + return border; + } + return noFocusBorder; } } @@ -118,8 +127,8 @@ public class DefaultListCellRenderer extends JLabel && !dropLocation.isInsert() && dropLocation.getIndex() == index) { - bg = UIManager.getColor("List.dropCellBackground"); - fg = UIManager.getColor("List.dropCellForeground"); + bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground"); + fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground"); isSelected = true; } @@ -148,10 +157,10 @@ public class DefaultListCellRenderer extends JLabel Border border = null; if (cellHasFocus) { if (isSelected) { - border = UIManager.getBorder("List.focusSelectedCellHighlightBorder"); + border = DefaultLookup.getBorder(this, ui, "List.focusSelectedCellHighlightBorder"); } if (border == null) { - border = UIManager.getBorder("List.focusCellHighlightBorder"); + border = DefaultLookup.getBorder(this, ui, "List.focusCellHighlightBorder"); } } else { border = getNoFocusBorder(); @@ -161,7 +170,6 @@ public class DefaultListCellRenderer extends JLabel return this; } - /** * Overridden for performance reasons. * See the Implementation Note @@ -172,6 +180,7 @@ public class DefaultListCellRenderer extends JLabel * and differs from the JList's background; * false otherwise */ + @Override public boolean isOpaque() { Color back = getBackground(); Component p = getParent(); @@ -190,6 +199,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void validate() {} /** @@ -199,6 +209,7 @@ public class DefaultListCellRenderer extends JLabel * * @since 1.5 */ + @Override public void invalidate() {} /** @@ -208,6 +219,7 @@ public class DefaultListCellRenderer extends JLabel * * @since 1.5 */ + @Override public void repaint() {} /** @@ -215,12 +227,14 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void revalidate() {} /** * Overridden for performance reasons. * See the Implementation Note * for more information. */ + @Override public void repaint(long tm, int x, int y, int width, int height) {} /** @@ -228,6 +242,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void repaint(Rectangle r) {} /** @@ -235,6 +250,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { // Strings get interned... if (propertyName == "text" @@ -251,6 +267,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {} /** @@ -258,6 +275,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, char oldValue, char newValue) {} /** @@ -265,6 +283,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, short oldValue, short newValue) {} /** @@ -272,6 +291,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, int oldValue, int newValue) {} /** @@ -279,6 +299,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, long oldValue, long newValue) {} /** @@ -286,6 +307,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, float oldValue, float newValue) {} /** @@ -293,6 +315,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, double oldValue, double newValue) {} /** @@ -300,6 +323,7 @@ public class DefaultListCellRenderer extends JLabel * See the Implementation Note * for more information. */ + @Override public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {} /** @@ -321,5 +345,4 @@ public class DefaultListCellRenderer extends JLabel implements javax.swing.plaf.UIResource { } - } diff --git a/src/share/classes/javax/swing/JComboBox.java b/src/share/classes/javax/swing/JComboBox.java index 42ef6466979461e08bb6e5fdd26bfee63f8fcf1c..838ce5d7d295ba747d78cb45d786e6ab488bc364 100644 --- a/src/share/classes/javax/swing/JComboBox.java +++ b/src/share/classes/javax/swing/JComboBox.java @@ -34,12 +34,10 @@ import java.awt.event.*; import java.io.Serializable; import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; import javax.swing.event.*; import javax.swing.plaf.*; -import javax.swing.border.*; import javax.accessibility.*; @@ -227,7 +225,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { private void init() { installAncestorListener(); - setOpaque(true); + setUIProperty("opaque",true); updateUI(); } diff --git a/src/share/classes/javax/swing/JScrollPane.java b/src/share/classes/javax/swing/JScrollPane.java index 13c1365c025e7f485823adbe943f4dc4f84f4d39..b2be43cd15fc8fed68cff816399266e945f28828 100644 --- a/src/share/classes/javax/swing/JScrollPane.java +++ b/src/share/classes/javax/swing/JScrollPane.java @@ -32,15 +32,12 @@ import javax.accessibility.*; import java.awt.Component; import java.awt.ComponentOrientation; -import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Insets; -import java.awt.Color; import java.awt.LayoutManager; import java.awt.Point; import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; import java.beans.PropertyChangeEvent; @@ -304,7 +301,7 @@ public class JScrollPane extends JComponent implements ScrollPaneConstants, Acce if (view != null) { setViewportView(view); } - setOpaque(true); + setUIProperty("opaque",true); updateUI(); if (!this.getComponentOrientation().isLeftToRight()) { diff --git a/src/share/classes/javax/swing/JSpinner.java b/src/share/classes/javax/swing/JSpinner.java index ddd92b9b4e48f1da85cf1f3acabbad48dcabefe3..ed7bfc80ceda7a77caed229460f5ed2396169cff 100644 --- a/src/share/classes/javax/swing/JSpinner.java +++ b/src/share/classes/javax/swing/JSpinner.java @@ -28,7 +28,6 @@ package javax.swing; import java.awt.*; import java.awt.event.*; -import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.plaf.SpinnerUI; @@ -154,7 +153,7 @@ public class JSpinner extends JComponent implements Accessible } this.model = model; this.editor = createEditor(model); - setOpaque(true); + setUIProperty("opaque",true); updateUI(); } diff --git a/src/share/classes/javax/swing/JSplitPane.java b/src/share/classes/javax/swing/JSplitPane.java index 1e38b9f8b63bd8c000c753b2c0e2a424718199b1..b5d8ec7d2b513997df020fb823acf83e2c2c85f4 100644 --- a/src/share/classes/javax/swing/JSplitPane.java +++ b/src/share/classes/javax/swing/JSplitPane.java @@ -246,7 +246,8 @@ public class JSplitPane extends JComponent implements Accessible * layout, using two buttons for the components. */ public JSplitPane() { - this(JSplitPane.HORIZONTAL_SPLIT, false, + this(JSplitPane.HORIZONTAL_SPLIT, + UIManager.getBoolean("SplitPane.continuousLayout"), new JButton(UIManager.getString("SplitPane.leftButtonText")), new JButton(UIManager.getString("SplitPane.rightButtonText"))); } @@ -263,7 +264,8 @@ public class JSplitPane extends JComponent implements Accessible */ @ConstructorProperties({"orientation"}) public JSplitPane(int newOrientation) { - this(newOrientation, false); + this(newOrientation, + UIManager.getBoolean("SplitPane.continuousLayout")); } @@ -307,7 +309,9 @@ public class JSplitPane extends JComponent implements Accessible public JSplitPane(int newOrientation, Component newLeftComponent, Component newRightComponent){ - this(newOrientation, false, newLeftComponent, newRightComponent); + this(newOrientation, + UIManager.getBoolean("SplitPane.continuousLayout"), + newLeftComponent, newRightComponent); } diff --git a/src/share/classes/javax/swing/JTable.java b/src/share/classes/javax/swing/JTable.java index 1b770d89153affe5ed6ca4b75cef929b0596bbbc..dc9adebc4d47947eb2e445552d2176f8370df7cb 100644 --- a/src/share/classes/javax/swing/JTable.java +++ b/src/share/classes/javax/swing/JTable.java @@ -731,6 +731,37 @@ public class JTable extends JComponent implements TableModelListener, Scrollable return; } scrollPane.setColumnHeaderView(getTableHeader()); + // configure the scrollpane for any LAF dependent settings + configureEnclosingScrollPaneUI(); + } + } + } + + /** + * This is a sub-part of configureEnclosingScrollPane() that configures + * anything on the scrollpane that may change when the look and feel + * changes. It needed to be split out from configureEnclosingScrollPane() so + * that it can be called from updateUI() when the LAF changes without + * causing the regression found in bug 6687962. This was because updateUI() + * is called from the constructor which then caused + * configureEnclosingScrollPane() to be called by the constructor which + * changes its contract for any subclass that overrides it. So by splitting + * it out in this way configureEnclosingScrollPaneUI() can be called both + * from configureEnclosingScrollPane() and updateUI() in a safe manor. + */ + private void configureEnclosingScrollPaneUI() { + Container p = getParent(); + if (p instanceof JViewport) { + Container gp = p.getParent(); + if (gp instanceof JScrollPane) { + JScrollPane scrollPane = (JScrollPane)gp; + // Make certain we are the viewPort's view and not, for + // example, the rowHeaderView of the scrollPane - + // an implementor of fixed columns might do this. + JViewport viewport = scrollPane.getViewport(); + if (viewport == null || viewport.getView() != this) { + return; + } // scrollPane.getViewport().setBackingStoreEnabled(true); Border border = scrollPane.getBorder(); if (border == null || border instanceof UIResource) { @@ -740,6 +771,24 @@ public class JTable extends JComponent implements TableModelListener, Scrollable scrollPane.setBorder(scrollPaneBorder); } } + // add JScrollBar corner component if available from LAF and not already set by the user + Component corner = + scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); + if (corner == null || corner instanceof UIResource){ + corner = null; + Object componentClass = UIManager.get( + "Table.scrollPaneCornerComponent"); + if (componentClass instanceof Class){ + try { + corner = (Component) + ((Class)componentClass).newInstance(); + } catch (Exception e) { + // just ignore and don't set corner + } + } + scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, + corner); + } } } } @@ -783,6 +832,13 @@ public class JTable extends JComponent implements TableModelListener, Scrollable return; } scrollPane.setColumnHeaderView(null); + // remove ScrollPane corner if one was added by the LAF + Component corner = + scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); + if (corner instanceof UIResource){ + scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, + null); + } } } } @@ -3592,6 +3648,9 @@ public class JTable extends JComponent implements TableModelListener, Scrollable tableHeader.updateUI(); } + // Update UI applied to parent ScrollPane + configureEnclosingScrollPaneUI(); + setUI((TableUI)UIManager.getUI(this)); } diff --git a/src/share/classes/javax/swing/MultiUIDefaults.java b/src/share/classes/javax/swing/MultiUIDefaults.java index d5904d05ca2da401d1eda4175498f93a349c842c..20eeeafa24a4513ff7953d88138dc71e2e608449 100644 --- a/src/share/classes/javax/swing/MultiUIDefaults.java +++ b/src/share/classes/javax/swing/MultiUIDefaults.java @@ -26,7 +26,10 @@ package javax.swing; import java.util.Enumeration; +import java.util.HashSet; import java.util.Locale; +import java.util.Map.Entry; +import java.util.Set; @@ -48,7 +51,7 @@ class MultiUIDefaults extends UIDefaults tables = new UIDefaults[0]; } - + @Override public Object get(Object key) { Object value = super.get(key); @@ -66,7 +69,7 @@ class MultiUIDefaults extends UIDefaults return null; } - + @Override public Object get(Object key, Locale l) { Object value = super.get(key,l); @@ -84,7 +87,7 @@ class MultiUIDefaults extends UIDefaults return null; } - + @Override public int size() { int n = super.size(); for (UIDefaults table : tables) { @@ -93,12 +96,12 @@ class MultiUIDefaults extends UIDefaults return n; } - + @Override public boolean isEmpty() { return size() == 0; } - + @Override public Enumeration keys() { Enumeration[] enums = new Enumeration[1 + tables.length]; @@ -112,7 +115,7 @@ class MultiUIDefaults extends UIDefaults return new MultiUIDefaultsEnumerator(enums); } - + @Override public Enumeration elements() { Enumeration[] enums = new Enumeration[1 + tables.length]; @@ -126,6 +129,19 @@ class MultiUIDefaults extends UIDefaults return new MultiUIDefaultsEnumerator(enums); } + @Override + public Set> entrySet() { + Set> set = new HashSet>(); + if (tables == null) return set; + for (UIDefaults table : tables) { + if (table != null) { + set.addAll(table.entrySet()); + } + } + return set; + } + + @Override protected void getUIError(String msg) { if (tables.length > 0) { tables[0].getUIError(msg); @@ -164,7 +180,7 @@ class MultiUIDefaults extends UIDefaults } } - + @Override public Object remove(Object key) { Object value = super.remove(key); @@ -182,7 +198,7 @@ class MultiUIDefaults extends UIDefaults return null; } - + @Override public void clear() { super.clear(); for (UIDefaults table : tables) { @@ -192,6 +208,7 @@ class MultiUIDefaults extends UIDefaults } } + @Override public synchronized String toString() { StringBuffer buf = new StringBuffer(); buf.append("{"); diff --git a/src/share/classes/javax/swing/Painter.java b/src/share/classes/javax/swing/Painter.java new file mode 100644 index 0000000000000000000000000000000000000000..2c6135e5c163b896b8795ea0b62d42ee26b0a407 --- /dev/null +++ b/src/share/classes/javax/swing/Painter.java @@ -0,0 +1,105 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing; + +import java.awt.Graphics2D; + +/** + *

A painting delegate. The Painter interface defines exactly one method, + * paint. It is used in situations where the developer can change + * the painting routine of a component without having to resort to subclassing + * the component. It is also generically useful when doing any form of painting + * delegation.

+ * + *

Painters are simply encapsulations of Java2D code and make + * it fairly trivial to reuse existing Painters or to combine + * them together. Implementations of this interface are also trivial to write, + * such that if you can't find a Painter that does what you need, + * you can write one with minimal effort. Writing a Painter requires + * knowledge of Java2D.

+ * + *

A Painter may be created with a type parameter. This type will be + * expected in the paint method. For example, you may wish to write a + * Painter that only works with subclasses of {@link java.awt.Component}. + * In that case, when the Painter is declared, you may declare that + * it requires a Component, allowing the paint method to be type safe. Ex: + *


+ *     Painter p = new Painter() {
+ *         public void paint(Graphics2D g, Component c, int width, int height) {
+ *             g.setColor(c.getBackground());
+ *             //and so forth
+ *         }
+ *     }
+ * 

+ * + *

This interface makes no guarantees of threadsafety.

+ * + * @author rbair + */ +public interface Painter { + /** + *

Renders to the given {@link java.awt.Graphics2D} object. Implementations + * of this method may modify state on the Graphics2D, and are not + * required to restore that state upon completion. In most cases, it is recommended + * that the caller pass in a scratch graphics object. The Graphics2D + * must never be null.

+ * + *

State on the graphics object may be honored by the paint method, + * but may not be. For instance, setting the antialiasing rendering hint on the + * graphics may or may not be respected by the Painter implementation.

+ * + *

The supplied object parameter acts as an optional configuration argument. + * For example, it could be of type Component. A Painter + * that expected it could then read state from that Component and + * use the state for painting. For example, an implementation may read the + * backgroundColor and use that.

+ * + *

Generally, to enhance reusability, most standard Painters ignore + * this parameter. They can thus be reused in any context. The object + * may be null. Implementations must not throw a NullPointerException if the object + * parameter is null.

+ * + *

Finally, the width and height arguments specify the + * width and height that the Painter should paint into. More + * specifically, the specified width and height instruct the painter that it should + * paint fully within this width and height. Any specified clip on the + * g param will further constrain the region.

+ * + *

For example, suppose I have a Painter implementation that draws + * a gradient. The gradient goes from white to black. It "stretches" to fill the + * painted region. Thus, if I use this Painter to paint a 500 x 500 + * region, the far left would be black, the far right would be white, and a smooth + * gradient would be painted between. I could then, without modification, reuse the + * Painter to paint a region that is 20x20 in size. This region would + * also be black on the left, white on the right, and a smooth gradient painted + * between.

+ * + * @param g The Graphics2D to render to. This must not be null. + * @param object an optional configuration parameter. This may be null. + * @param width width of the area to paint. + * @param height height of the area to paint. + */ + public void paint(Graphics2D g, T object, int width, int height); +} diff --git a/src/share/classes/javax/swing/UIManager.java b/src/share/classes/javax/swing/UIManager.java index bd6f6ac9144f3bf4805dffd0efbbe73880cb8a49..44388fe34d5b6d3af1bafe366ac029ffd34a4b84 100644 --- a/src/share/classes/javax/swing/UIManager.java +++ b/src/share/classes/javax/swing/UIManager.java @@ -383,6 +383,8 @@ public class UIManager implements Serializable ArrayList iLAFs = new ArrayList(4); iLAFs.add(new LookAndFeelInfo( "Metal", "javax.swing.plaf.metal.MetalLookAndFeel")); + iLAFs.add(new LookAndFeelInfo( + "Nimbus", "javax.swing.plaf.nimbus.NimbusLookAndFeel")); iLAFs.add(new LookAndFeelInfo("CDE/Motif", "com.sun.java.swing.plaf.motif.MotifLookAndFeel")); diff --git a/src/share/classes/javax/swing/border/TitledBorder.java b/src/share/classes/javax/swing/border/TitledBorder.java index eb50e95ee9e31048e3aea07bfa920fe9cc4a7628..7540bdf248e315176bcc16a904a9b76c6702cb40 100644 --- a/src/share/classes/javax/swing/border/TitledBorder.java +++ b/src/share/classes/javax/swing/border/TitledBorder.java @@ -133,7 +133,7 @@ public class TitledBorder extends AbstractBorder * @param title the title the border should display */ public TitledBorder(String title) { - this(null, title, LEADING, TOP, null, null); + this(null, title, LEADING, DEFAULT_POSITION, null, null); } /** @@ -143,7 +143,7 @@ public class TitledBorder extends AbstractBorder * @param border the border */ public TitledBorder(Border border) { - this(border, "", LEADING, TOP, null, null); + this(border, "", LEADING, DEFAULT_POSITION, null, null); } /** @@ -154,7 +154,7 @@ public class TitledBorder extends AbstractBorder * @param title the title the border should display */ public TitledBorder(Border border, String title) { - this(border, title, LEADING, TOP, null, null); + this(border, title, LEADING, DEFAULT_POSITION, null, null); } /** @@ -502,7 +502,33 @@ public class TitledBorder extends AbstractBorder /** * Returns the title-position of the titled border. */ - public int getTitlePosition() { return titlePosition; } + public int getTitlePosition() { + if (titlePosition == DEFAULT_POSITION) { + Object value = UIManager.get("TitledBorder.position"); + if (value instanceof String) { + String s = (String)value; + if ("ABOVE_TOP".equalsIgnoreCase(s)) { + return ABOVE_TOP; + } else if ("TOP".equalsIgnoreCase(s)) { + return TOP; + } else if ("BELOW_TOP".equalsIgnoreCase(s)) { + return BELOW_TOP; + } else if ("ABOVE_BOTTOM".equalsIgnoreCase(s)) { + return ABOVE_BOTTOM; + } else if ("BOTTOM".equalsIgnoreCase(s)) { + return BOTTOM; + } else if ("BELOW_BOTTOM".equalsIgnoreCase(s)) { + return BELOW_BOTTOM; + } + } else if (value instanceof Integer) { + int i = (Integer)value; + if (i >= 0 && i <= 6) { + return i; + } + } + } + return titlePosition; + } /** * Returns the title-justification of the titled border. @@ -613,7 +639,7 @@ public class TitledBorder extends AbstractBorder Font font = getFont(c); FontMetrics fm = c.getFontMetrics(font); JComponent jc = (c instanceof JComponent) ? (JComponent)c : null; - switch (titlePosition) { + switch (getTitlePosition()) { case ABOVE_TOP: case BELOW_BOTTOM: minSize.width = Math.max(SwingUtilities2.stringWidth(jc, fm, diff --git a/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java b/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java index ef05d87f035304d4dc3efb1542fce6e5a72209bb..80b449ce7c5d3a3a530eb1deea7e0c4956f9f64c 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -29,7 +29,6 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.accessibility.*; -import javax.swing.FocusManager; import javax.swing.plaf.*; import javax.swing.border.*; import javax.swing.text.*; @@ -187,6 +186,23 @@ public class BasicComboBoxUI extends ComboBoxUI { */ private boolean sameBaseline; + /** + * Indicates whether or not the combo box button should be square. + * If square, then the width and height are equal, and are both set to + * the height of the combo (minus appropriate insets). + */ + private boolean squareButton = true; + + /** + * Optional: if specified, these insets act as padding around the cell + * renderer when laying out and painting the "selected" item in the + * combo box. BasicComboBoxUI uses a single combo box renderer for rendering + * both the main combo box item and also all the items in the dropdown + * for the combo box. padding allows you to specify addition insets in + * addition to those specified by the cell renderer. + */ + private Insets padding; + // Used for calculating the default size. private static ListCellRenderer getDefaultListCellRenderer() { ListCellRenderer renderer = (ListCellRenderer)AppContext. @@ -226,6 +242,7 @@ public class BasicComboBoxUI extends ComboBoxUI { return new BasicComboBoxUI(); } + @Override public void installUI( JComponent c ) { isMinimumSizeDirty = true; @@ -265,6 +282,7 @@ public class BasicComboBoxUI extends ComboBoxUI { comboBox.setKeySelectionManager(keySelectionManager); } + @Override public void uninstallUI( JComponent c ) { setPopupVisible( comboBox, false); popup.uninstallingUI(); @@ -317,7 +335,13 @@ public class BasicComboBoxUI extends ComboBoxUI { LookAndFeel.installProperty( comboBox, "opaque", Boolean.TRUE); Long l = (Long)UIManager.get("ComboBox.timeFactor"); - timeFactor = (l!=null) ? l.longValue() : 1000L; + timeFactor = l == null ? 1000L : l.longValue(); + + //NOTE: this needs to default to true if not specified + Boolean b = (Boolean)UIManager.get("ComboBox.squareButton"); + squareButton = b == null ? true : b; + + padding = UIManager.getInsets("ComboBox.padding"); } /** @@ -530,6 +554,7 @@ public class BasicComboBoxUI extends ComboBoxUI { * BasicComboBoxUI. */ public class KeyHandler extends KeyAdapter { + @Override public void keyPressed( KeyEvent e ) { getHandler().keyPressed(e); } @@ -761,6 +786,8 @@ public class BasicComboBoxUI extends ComboBoxUI { } comboBox.configureEditor(comboBox.getEditor(),comboBox.getSelectedItem()); + + editor.addPropertyChangeListener(propertyChangeListener); } /** @@ -774,6 +801,7 @@ public class BasicComboBoxUI extends ComboBoxUI { editor.removeFocusListener(focusListener); } + editor.removePropertyChangeListener(propertyChangeListener); editor.removeFocusListener(getHandler()); comboBox.getEditor().removeActionListener(getHandler()); } @@ -868,7 +896,7 @@ public class BasicComboBoxUI extends ComboBoxUI { //================================= // begin ComponentUI Implementation - + @Override public void paint( Graphics g, JComponent c ) { hasFocus = comboBox.hasFocus(); if ( !comboBox.isEditable() ) { @@ -878,6 +906,7 @@ public class BasicComboBoxUI extends ComboBoxUI { } } + @Override public Dimension getPreferredSize( JComponent c ) { return getMinimumSize(c); } @@ -885,15 +914,19 @@ public class BasicComboBoxUI extends ComboBoxUI { /** * The minumum size is the size of the display area plus insets plus the button. */ + @Override public Dimension getMinimumSize( JComponent c ) { if ( !isMinimumSizeDirty ) { return new Dimension(cachedMinimumSize); } Dimension size = getDisplaySize(); Insets insets = getInsets(); + //calculate the width and height of the button + int buttonHeight = size.height; + int buttonWidth = squareButton ? buttonHeight : arrowButton.getPreferredSize().width; + //adjust the size based on the button width size.height += insets.top + insets.bottom; - int buttonSize = size.height - (insets.top + insets.bottom); - size.width += insets.left + insets.right + buttonSize; + size.width += insets.left + insets.right + buttonWidth; cachedMinimumSize.setSize( size.width, size.height ); isMinimumSizeDirty = false; @@ -901,6 +934,7 @@ public class BasicComboBoxUI extends ComboBoxUI { return new Dimension(size); } + @Override public Dimension getMaximumSize( JComponent c ) { return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); } @@ -913,6 +947,7 @@ public class BasicComboBoxUI extends ComboBoxUI { * @see javax.swing.JComponent#getBaseline(int, int) * @since 1.6 */ + @Override public int getBaseline(JComponent c, int width, int height) { super.getBaseline(c, width, height); int baseline = -1; @@ -967,6 +1002,7 @@ public class BasicComboBoxUI extends ComboBoxUI { * @see javax.swing.JComponent#getBaseline(int, int) * @since 1.6 */ + @Override public Component.BaselineResizeBehavior getBaselineResizeBehavior( JComponent c) { super.getBaselineResizeBehavior(c); @@ -1001,6 +1037,7 @@ public class BasicComboBoxUI extends ComboBoxUI { } // This is currently hacky... + @Override public int getAccessibleChildrenCount(JComponent c) { if ( comboBox.isEditable() ) { return 2; @@ -1011,6 +1048,7 @@ public class BasicComboBoxUI extends ComboBoxUI { } // This is currently hacky... + @Override public Accessible getAccessibleChild(JComponent c, int i) { // 0 = the popup // 1 = the editor @@ -1204,8 +1242,15 @@ public class BasicComboBoxUI extends ComboBoxUI { shouldValidate = true; } - currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y, - bounds.width,bounds.height, shouldValidate); + int x = bounds.x, y = bounds.y, w = bounds.width, h = bounds.height; + if (padding != null) { + x = bounds.x + padding.left; + y = bounds.y + padding.top; + w = bounds.width - (padding.left + padding.right); + h = bounds.height - (padding.top + padding.bottom); + } + + currentValuePane.paintComponent(g,c,comboBox,x,y,w,h,shouldValidate); } /** @@ -1333,6 +1378,12 @@ public class BasicComboBoxUI extends ComboBoxUI { result.height = Math.max(result.height,d.height); } + // calculate in the padding + if (padding != null) { + result.width += padding.left + padding.right; + result.height += padding.top + padding.bottom; + } + // Set the cached value cachedDisplaySize.setSize(result.width, result.height); isDisplaySizeDirty = false; @@ -1591,91 +1642,99 @@ public class BasicComboBoxUI extends ComboBoxUI { // public void propertyChange(PropertyChangeEvent e) { String propertyName = e.getPropertyName(); - JComboBox comboBox = (JComboBox)e.getSource(); - - if ( propertyName == "model" ) { - ComboBoxModel newModel = (ComboBoxModel)e.getNewValue(); - ComboBoxModel oldModel = (ComboBoxModel)e.getOldValue(); - - if ( oldModel != null && listDataListener != null ) { - oldModel.removeListDataListener( listDataListener ); + if (e.getSource() == editor){ + // If the border of the editor changes then this can effect + // the size of the editor which can cause the combo's size to + // become invalid so we need to clear size caches + if ("border".equals(propertyName)){ + isMinimumSizeDirty = true; + isDisplaySizeDirty = true; + comboBox.revalidate(); } + } else { + JComboBox comboBox = (JComboBox)e.getSource(); + if ( propertyName == "model" ) { + ComboBoxModel newModel = (ComboBoxModel)e.getNewValue(); + ComboBoxModel oldModel = (ComboBoxModel)e.getOldValue(); - if ( newModel != null && listDataListener != null ) { - newModel.addListDataListener( listDataListener ); - } + if ( oldModel != null && listDataListener != null ) { + oldModel.removeListDataListener( listDataListener ); + } - if ( editor != null ) { - comboBox.configureEditor( comboBox.getEditor(), comboBox.getSelectedItem() ); + if ( newModel != null && listDataListener != null ) { + newModel.addListDataListener( listDataListener ); + } + + if ( editor != null ) { + comboBox.configureEditor( comboBox.getEditor(), comboBox.getSelectedItem() ); + } + isMinimumSizeDirty = true; + isDisplaySizeDirty = true; + comboBox.revalidate(); + comboBox.repaint(); } - isMinimumSizeDirty = true; - isDisplaySizeDirty = true; - comboBox.revalidate(); - comboBox.repaint(); - } - else if ( propertyName == "editor" && comboBox.isEditable() ) { - addEditor(); - comboBox.revalidate(); - } - else if ( propertyName == "editable" ) { - if ( comboBox.isEditable() ) { - comboBox.setRequestFocusEnabled( false ); + else if ( propertyName == "editor" && comboBox.isEditable() ) { addEditor(); - } else { - comboBox.setRequestFocusEnabled( true ); - removeEditor(); + comboBox.revalidate(); } - - updateToolTipTextForChildren(); - - comboBox.revalidate(); - } - else if ( propertyName == "enabled" ) { - boolean enabled = comboBox.isEnabled(); - if ( editor != null ) - editor.setEnabled(enabled); - if ( arrowButton != null ) - arrowButton.setEnabled(enabled); - comboBox.repaint(); - } - else if ( propertyName == "focusable" ) { - boolean focusable = comboBox.isFocusable(); - if ( editor != null ) - editor.setFocusable(focusable); - if ( arrowButton != null ) - arrowButton.setFocusable(focusable); - comboBox.repaint(); - } - else if ( propertyName == "maximumRowCount" ) { - if ( isPopupVisible( comboBox ) ) { - setPopupVisible(comboBox, false); - setPopupVisible(comboBox, true); + else if ( propertyName == "editable" ) { + if ( comboBox.isEditable() ) { + comboBox.setRequestFocusEnabled( false ); + addEditor(); + } else { + comboBox.setRequestFocusEnabled( true ); + removeEditor(); + } + updateToolTipTextForChildren(); + comboBox.revalidate(); } - } - else if ( propertyName == "font" ) { - listBox.setFont( comboBox.getFont() ); - if ( editor != null ) { - editor.setFont( comboBox.getFont() ); + else if ( propertyName == "enabled" ) { + boolean enabled = comboBox.isEnabled(); + if ( editor != null ) + editor.setEnabled(enabled); + if ( arrowButton != null ) + arrowButton.setEnabled(enabled); + comboBox.repaint(); + } + else if ( propertyName == "focusable" ) { + boolean focusable = comboBox.isFocusable(); + if ( editor != null ) + editor.setFocusable(focusable); + if ( arrowButton != null ) + arrowButton.setFocusable(focusable); + comboBox.repaint(); + } + else if ( propertyName == "maximumRowCount" ) { + if ( isPopupVisible( comboBox ) ) { + setPopupVisible(comboBox, false); + setPopupVisible(comboBox, true); + } + } + else if ( propertyName == "font" ) { + listBox.setFont( comboBox.getFont() ); + if ( editor != null ) { + editor.setFont( comboBox.getFont() ); + } + isMinimumSizeDirty = true; + comboBox.validate(); + } + else if ( propertyName == JComponent.TOOL_TIP_TEXT_KEY ) { + updateToolTipTextForChildren(); + } + else if ( propertyName == BasicComboBoxUI.IS_TABLE_CELL_EDITOR ) { + Boolean inTable = (Boolean)e.getNewValue(); + isTableCellEditor = inTable.equals(Boolean.TRUE) ? true : false; + } + else if (propertyName == "prototypeDisplayValue") { + isMinimumSizeDirty = true; + isDisplaySizeDirty = true; + comboBox.revalidate(); + } + else if (propertyName == "renderer") { + isMinimumSizeDirty = true; + isDisplaySizeDirty = true; + comboBox.revalidate(); } - isMinimumSizeDirty = true; - comboBox.validate(); - } - else if ( propertyName == JComponent.TOOL_TIP_TEXT_KEY ) { - updateToolTipTextForChildren(); - } - else if ( propertyName == BasicComboBoxUI.IS_TABLE_CELL_EDITOR ) { - Boolean inTable = (Boolean)e.getNewValue(); - isTableCellEditor = inTable.equals(Boolean.TRUE) ? true : false; - } - else if (propertyName == "prototypeDisplayValue") { - isMinimumSizeDirty = true; - isDisplaySizeDirty = true; - comboBox.revalidate(); - } - else if (propertyName == "renderer") { - isMinimumSizeDirty = true; - isDisplaySizeDirty = true; - comboBox.revalidate(); } } @@ -1809,18 +1868,23 @@ public class BasicComboBoxUI extends ComboBoxUI { int height = cb.getHeight(); Insets insets = getInsets(); - int buttonSize = height - (insets.top + insets.bottom); + int buttonHeight = height - (insets.top + insets.bottom); + int buttonWidth = buttonHeight; + if (arrowButton != null) { + Insets arrowInsets = arrowButton.getInsets(); + buttonWidth = squareButton ? + buttonHeight : + arrowButton.getPreferredSize().width + arrowInsets.left + arrowInsets.right; + } Rectangle cvb; - if ( arrowButton != null ) { - if(BasicGraphicsUtils.isLeftToRight(cb)) { - arrowButton.setBounds( width - (insets.right + buttonSize), - insets.top, - buttonSize, buttonSize); - } - else { - arrowButton.setBounds( insets.left, insets.top, - buttonSize, buttonSize); + if (arrowButton != null) { + if (BasicGraphicsUtils.isLeftToRight(cb)) { + arrowButton.setBounds(width - (insets.right + buttonWidth), + insets.top, buttonWidth, buttonHeight); + } else { + arrowButton.setBounds(insets.left, insets.top, + buttonWidth, buttonHeight); } } if ( editor != null ) { @@ -1829,7 +1893,6 @@ public class BasicComboBoxUI extends ComboBoxUI { } } - // // ActionListener // diff --git a/src/share/classes/javax/swing/plaf/basic/BasicListUI.java b/src/share/classes/javax/swing/plaf/basic/BasicListUI.java index a7ec88835b84b09dac0f07529ef1a5ed21224860..7704d10e102fce2072279c044842b7f3e48d6031 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicListUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicListUI.java @@ -480,6 +480,12 @@ public class BasicListUI extends ListUI if (renderer == null) { ListCellRenderer lcr = (ListCellRenderer)UIManager.get( "List.cellRenderer"); + + // fix for 6711072 some LAFs like Nimbus do not provide this + // UIManager key and we should not through a NPE here because of it + if (lcr == null) { + lcr = new DefaultListCellRenderer(); + } renderer = lcr.getListCellRendererComponent( list, "a", -1, false, false); lafDefaults.put(BASELINE_COMPONENT_KEY, renderer); diff --git a/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java index a58cc467c5f58601e6776532ce6ed3c1e09e02ad..61c70c9bb0b9ed5edcbdd944bc09ea2db0a60ab5 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -111,6 +111,11 @@ public class BasicMenuItemUI extends MenuItemUI String prefix = getPropertyPrefix(); acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont"); + // use default if missing so that BasicMenuItemUI can be used in other + // LAFs like Nimbus + if (acceleratorFont == null) { + acceleratorFont = UIManager.getFont("MenuItem.font"); + } Object opaque = UIManager.get(getPropertyPrefix() + ".opaque"); if (opaque != null) { @@ -130,7 +135,7 @@ public class BasicMenuItemUI extends MenuItemUI LookAndFeel.installBorder(menuItem, prefix + ".border"); oldBorderPainted = menuItem.isBorderPainted(); LookAndFeel.installProperty(menuItem, "borderPainted", - UIManager.get(prefix + ".borderPainted")); + UIManager.getBoolean(prefix + ".borderPainted")); LookAndFeel.installColorsAndFont(menuItem, prefix + ".background", prefix + ".foreground", diff --git a/src/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java b/src/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java index e743602c73d0df6c5a426a471e762f4ab28f7ebf..0d31dc30cf55b55f18a5d407dfb128672cfc7953 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicProgressBarUI.java @@ -158,6 +158,7 @@ public class BasicProgressBarUI extends ProgressBarUI { "ProgressBar.foreground", "ProgressBar.font"); cellLength = UIManager.getInt("ProgressBar.cellLength"); + if (cellLength == 0) cellLength = 1; cellSpacing = UIManager.getInt("ProgressBar.cellSpacing"); selectionForeground = UIManager.getColor("ProgressBar.selectionForeground"); selectionBackground = UIManager.getColor("ProgressBar.selectionBackground"); diff --git a/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java b/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java index 7db1e11e62ec3ce6f4da5a0a5c581546a2ad51d5..b22a58795e673a5268fef91d6c627fec91588e0b 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -112,6 +112,24 @@ public class BasicScrollBarUI */ private int scrollBarValue; + /** + * Distance between the increment button and the track. This may be a negative + * number. If negative, then an overlap between the button and track will occur, + * which is useful for shaped buttons. + * + * TODO This should be made protected in a feature release + */ + private int incrGap; + + /** + * Distance between the decrement button and the track. This may be a negative + * number. If negative, then an overlap between the button and track will occur, + * which is useful for shaped buttons. + * + * TODO This should be made protected in a feature release + */ + private int decrGap; + static void loadActionMap(LazyActionMap map) { map.put(new Actions(Actions.POSITIVE_UNIT_INCREMENT)); map.put(new Actions(Actions.POSITIVE_BLOCK_INCREMENT)); @@ -186,6 +204,31 @@ public class BasicScrollBarUI LookAndFeel.installProperty(scrollbar, "opaque", Boolean.TRUE); scrollBarValue = scrollbar.getValue(); + + incrGap = UIManager.getInt("ScrollBar.incrementButtonGap"); + decrGap = UIManager.getInt("ScrollBar.decrementButtonGap"); + + // TODO this can be removed when incrGap/decrGap become protected + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + String scaleKey = (String)scrollbar.getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if ("large".equals(scaleKey)){ + scrollBarWidth *= 1.15; + incrGap *= 1.15; + decrGap *= 1.15; + } else if ("small".equals(scaleKey)){ + scrollBarWidth *= 0.857; + incrGap *= 0.857; + decrGap *= 0.714; + } else if ("mini".equals(scaleKey)){ + scrollBarWidth *= 0.714; + incrGap *= 0.714; + decrGap *= 0.714; + } + } } @@ -442,20 +485,23 @@ public class BasicScrollBarUI g.setColor(trackHighlightColor); if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + //paint the distance between the start of the track and top of the thumb int x = insets.left; - int y = decrButton.getY() + decrButton.getHeight(); + int y = trackRect.y; int w = scrollbar.getWidth() - (insets.left + insets.right); int h = thumbR.y - y; g.fillRect(x, y, w, h); - } - else { + } else { + //if left-to-right, fill the area between the start of the track and + //the left edge of the thumb. If right-to-left, fill the area between + //the end of the thumb and end of the track. int x, w; if (scrollbar.getComponentOrientation().isLeftToRight()) { - x = decrButton.getX() + decrButton.getWidth(); + x = trackRect.x; w = thumbR.x - x; } else { x = thumbR.x + thumbR.width; - w = decrButton.getX() - x; + w = trackRect.x + trackRect.width - x; } int y = insets.top; int h = scrollbar.getHeight() - (insets.top + insets.bottom); @@ -471,19 +517,23 @@ public class BasicScrollBarUI g.setColor(trackHighlightColor); if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + //fill the area between the bottom of the thumb and the end of the track. int x = insets.left; int y = thumbR.y + thumbR.height; int w = scrollbar.getWidth() - (insets.left + insets.right); - int h = incrButton.getY() - y; + int h = trackRect.y + trackRect.height - y; g.fillRect(x, y, w, h); } else { + //if left-to-right, fill the area between the right of the thumb and the + //end of the track. If right-to-left, then fill the area to the left of + //the thumb and the start of the track. int x, w; if (scrollbar.getComponentOrientation().isLeftToRight()) { x = thumbR.x + thumbR.width; - w = incrButton.getX() - x; + w = trackRect.x + trackRect.width - x; } else { - x = incrButton.getX() + incrButton.getWidth(); + x = trackRect.x; w = thumbR.x - x; } int y = insets.top; @@ -610,11 +660,13 @@ public class BasicScrollBarUI int incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH); /* The thumb must fit within the height left over after we - * subtract the preferredSize of the buttons and the insets. + * subtract the preferredSize of the buttons and the insets + * and the gaps */ int sbInsetsH = sbInsets.top + sbInsets.bottom; int sbButtonsH = decrButtonH + incrButtonH; - float trackH = sbSize.height - (sbInsetsH + sbButtonsH); + int gaps = decrGap + incrGap; + float trackH = sbSize.height - (sbInsetsH + sbButtonsH) - gaps; /* Compute the height and origin of the thumb. The case * where the thumb is at the bottom edge is handled specially @@ -632,11 +684,11 @@ public class BasicScrollBarUI thumbH = Math.max(thumbH, getMinimumThumbSize().height); thumbH = Math.min(thumbH, getMaximumThumbSize().height); - int thumbY = incrButtonY - thumbH; + int thumbY = incrButtonY - incrGap - thumbH; if (value < (sb.getMaximum() - sb.getVisibleAmount())) { float thumbRange = trackH - thumbH; thumbY = (int)(0.5f + (thumbRange * ((value - min) / (range - extent)))); - thumbY += decrButtonY + decrButtonH; + thumbY += decrButtonY + decrButtonH + decrGap; } /* If the buttons don't fit, allocate half of the available @@ -652,8 +704,8 @@ public class BasicScrollBarUI /* Update the trackRect field. */ - int itrackY = decrButtonY + decrButtonH; - int itrackH = incrButtonY - itrackY; + int itrackY = decrButtonY + decrButtonH + decrGap; + int itrackH = incrButtonY - incrGap - itrackY; trackRect.setBounds(itemX, itrackY, itemW, itrackH); /* If the thumb isn't going to fit, zero it's bounds. Otherwise @@ -671,11 +723,11 @@ public class BasicScrollBarUI } } else { - if ((thumbY + thumbH) > incrButtonY) { - thumbY = incrButtonY - thumbH; + if ((thumbY + thumbH) > incrButtonY - incrGap) { + thumbY = incrButtonY - incrGap - thumbH; } - if (thumbY < (decrButtonY + decrButtonH)) { - thumbY = decrButtonY + decrButtonH + 1; + if (thumbY < (decrButtonY + decrButtonH + decrGap)) { + thumbY = decrButtonY + decrButtonH + decrGap + 1; } setThumbBounds(itemX, thumbY, itemW, thumbH); } @@ -710,13 +762,16 @@ public class BasicScrollBarUI } int leftButtonX = sbInsets.left; int rightButtonX = sbSize.width - (sbInsets.right + rightButtonW); + int leftGap = ltr ? decrGap : incrGap; + int rightGap = ltr ? incrGap : decrGap; /* The thumb must fit within the width left over after we - * subtract the preferredSize of the buttons and the insets. + * subtract the preferredSize of the buttons and the insets + * and the gaps */ int sbInsetsW = sbInsets.left + sbInsets.right; int sbButtonsW = leftButtonW + rightButtonW; - float trackW = sbSize.width - (sbInsetsW + sbButtonsW); + float trackW = sbSize.width - (sbInsetsW + sbButtonsW) - (leftGap + rightGap); /* Compute the width and origin of the thumb. Enforce * the thumbs min/max dimensions. The case where the thumb @@ -735,7 +790,7 @@ public class BasicScrollBarUI thumbW = Math.max(thumbW, getMinimumThumbSize().width); thumbW = Math.min(thumbW, getMaximumThumbSize().width); - int thumbX = ltr ? rightButtonX - thumbW : leftButtonX + leftButtonW; + int thumbX = ltr ? rightButtonX - rightGap - thumbW : leftButtonX + leftButtonW + leftGap; if (value < (max - sb.getVisibleAmount())) { float thumbRange = trackW - thumbW; if( ltr ) { @@ -743,7 +798,7 @@ public class BasicScrollBarUI } else { thumbX = (int)(0.5f + (thumbRange * ((max - extent - value) / (range - extent)))); } - thumbX += leftButtonX + leftButtonW; + thumbX += leftButtonX + leftButtonW + leftGap; } /* If the buttons don't fit, allocate half of the available @@ -752,7 +807,7 @@ public class BasicScrollBarUI int sbAvailButtonW = (sbSize.width - sbInsetsW); if (sbAvailButtonW < sbButtonsW) { rightButtonW = leftButtonW = sbAvailButtonW / 2; - rightButtonX = sbSize.width - (sbInsets.right + rightButtonW); + rightButtonX = sbSize.width - (sbInsets.right + rightButtonW + rightGap); } (ltr ? decrButton : incrButton).setBounds(leftButtonX, itemY, leftButtonW, itemH); @@ -760,8 +815,8 @@ public class BasicScrollBarUI /* Update the trackRect field. */ - int itrackX = leftButtonX + leftButtonW; - int itrackW = rightButtonX - itrackX; + int itrackX = leftButtonX + leftButtonW + leftGap; + int itrackW = rightButtonX - rightGap - itrackX; trackRect.setBounds(itrackX, itemY, itrackW, itemH); /* Make sure the thumb fits between the buttons. Note @@ -778,11 +833,11 @@ public class BasicScrollBarUI } } else { - if (thumbX + thumbW > rightButtonX) { - thumbX = rightButtonX - thumbW; + if (thumbX + thumbW > rightButtonX - rightGap) { + thumbX = rightButtonX - rightGap - thumbW; } - if (thumbX < leftButtonX + leftButtonW) { - thumbX = leftButtonX + leftButtonW + 1; + if (thumbX < leftButtonX + leftButtonW + leftGap) { + thumbX = leftButtonX + leftButtonW + leftGap + 1; } setThumbBounds(thumbX, itemY, thumbW, itemH); } @@ -1151,20 +1206,15 @@ public class BasicScrollBarUI int thumbMin, thumbMax, thumbPos; if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { - thumbMin = decrButton.getY() + decrButton.getHeight(); - thumbMax = incrButton.getY() - thumbR.height; + thumbMin = trackRect.y; + thumbMax = trackRect.y + trackRect.height - thumbR.height; thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getY() - offset))); setThumbBounds(thumbR.x, thumbPos, thumbR.width, thumbR.height); trackLength = getTrackBounds().height; } else { - if (scrollbar.getComponentOrientation().isLeftToRight()) { - thumbMin = decrButton.getX() + decrButton.getWidth(); - thumbMax = incrButton.getX() - thumbR.width; - } else { - thumbMin = incrButton.getX() + incrButton.getWidth(); - thumbMax = decrButton.getX() - thumbR.width; - } + thumbMin = trackRect.x; + thumbMax = trackRect.x + trackRect.width - thumbR.width; thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getX() - offset))); setThumbBounds(thumbPos, thumbR.y, thumbR.width, thumbR.height); trackLength = getTrackBounds().width; diff --git a/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index 0a858d41c18b33f37740fcbebcb14f07b15b0031..97e2f60f52b2b8ac6949e40fef910b47795786a4 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -205,6 +205,9 @@ public class BasicSliderUI extends SliderUI{ focusColor = UIManager.getColor("Slider.focus"); focusInsets = (Insets)UIManager.get( "Slider.focusInsets" ); + // use default if missing so that BasicSliderUI can be used in other + // LAFs like Nimbus + if (focusInsets == null) focusInsets = new InsetsUIResource(2,2,2,2); } protected TrackListener createTrackListener(JSlider slider) { diff --git a/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java b/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java index 2f0bffae8ab896df9192a647925f3a24dc88b0ec..b35a75ed700e7d330426b1f92c643b38ab4d7a04 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -347,8 +347,9 @@ public class BasicSplitPaneUI extends SplitPaneUI // This plus 2 here is to provide backwards consistancy. Previously, // the old size did not include the 2 pixel border around the divider, // it now does. - LookAndFeel.installProperty(splitPane, "dividerSize", - UIManager.get("SplitPane.dividerSize")); + Integer dividerSize = (Integer)UIManager.get("SplitPane.dividerSize"); + if (divider == null) dividerSize = 10; + LookAndFeel.installProperty(splitPane, "dividerSize", dividerSize); divider.setDividerSize(splitPane.getDividerSize()); dividerSize = divider.getDividerSize(); diff --git a/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index a266b77141e9f50091cc177cf4cff00880402267..5a94a3631959b63c1856d02d9e9dd352b6cef16b 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -379,6 +379,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { opaque = Boolean.FALSE; } LookAndFeel.installProperty(tabPane, "opaque", opaque); + + // Fix for 6711145 BasicTabbedPanuUI should not throw a NPE if these + // keys are missing. So we are setting them to there default values here + // if the keys are missing. + if (tabInsets == null) tabInsets = new Insets(0,4,1,4); + if (selectedTabPadInsets == null) selectedTabPadInsets = new Insets(2,2,2,1); + if (tabAreaInsets == null) tabAreaInsets = new Insets(3,2,0,2); + if (contentBorderInsets == null) contentBorderInsets = new Insets(2,2,3,3); } protected void uninstallDefaults() { diff --git a/src/share/classes/javax/swing/plaf/basic/BasicTableUI.java b/src/share/classes/javax/swing/plaf/basic/BasicTableUI.java index 585e01dc26b3a80205c1179f3f0cbf57b8a8b7cc..16ceab73ee2a8f8f9e954bd5234ff7fc6ac9ce45 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicTableUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicTableUI.java @@ -1414,17 +1414,20 @@ public class BasicTableUI extends TableUI Color sbg = table.getSelectionBackground(); if (sbg == null || sbg instanceof UIResource) { - table.setSelectionBackground(UIManager.getColor("Table.selectionBackground")); + sbg = UIManager.getColor("Table.selectionBackground"); + table.setSelectionBackground(sbg != null ? sbg : UIManager.getColor("textHighlight")); } Color sfg = table.getSelectionForeground(); if (sfg == null || sfg instanceof UIResource) { - table.setSelectionForeground(UIManager.getColor("Table.selectionForeground")); + sfg = UIManager.getColor("Table.selectionForeground"); + table.setSelectionForeground(sfg != null ? sfg : UIManager.getColor("textHighlightText")); } Color gridColor = table.getGridColor(); if (gridColor == null || gridColor instanceof UIResource) { - table.setGridColor(UIManager.getColor("Table.gridColor")); + gridColor = UIManager.getColor("Table.gridColor"); + table.setGridColor(gridColor != null ? gridColor : Color.GRAY); } // install the scrollpane border diff --git a/src/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 166c6fc8a8674cfe21f356fcc8211834f707ee4d..cef9166355f58b7dd1f3c603440db0ff5e9d5dc4 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -27,13 +27,10 @@ package javax.swing.plaf.basic; import java.util.*; import java.awt.*; import java.awt.event.*; -import java.awt.font.*; import java.awt.datatransfer.*; -import java.awt.dnd.*; import java.awt.im.InputContext; import java.beans.*; import java.io.*; -import java.net.*; import javax.swing.*; import javax.swing.plaf.*; import javax.swing.text.*; @@ -785,11 +782,15 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { installDefaults(); installDefaults2(); - // common case is background painted... this can - // easily be changed by subclasses or from outside - // of the component. - LookAndFeel.installProperty(editor, "opaque", Boolean.TRUE); - LookAndFeel.installProperty(editor, "autoscrolls", Boolean.TRUE); + // This is a workaround as these should not override what synth has + // set them to + if (!(this instanceof sun.swing.plaf.synth.SynthUI)){ + // common case is background painted... this can + // easily be changed by subclasses or from outside + // of the component. + LookAndFeel.installProperty(editor, "opaque", Boolean.TRUE); + LookAndFeel.installProperty(editor, "autoscrolls", Boolean.TRUE); + } // attach to the model and editor editor.addPropertyChangeListener(updateHandler); diff --git a/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java b/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java index 05e3183b52467698e5671bd863c622139133d278..8fdc88d946f673ae822dfc8d7cd41ed9dd9b6716 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java @@ -2402,15 +2402,25 @@ public class BasicTreeUI extends TreeUI } leadRow = getRowForPath(tree, newPath); - if(repaint) { - if(bounds != null) - tree.repaint(bounds); + if (repaint) { + if (bounds != null) { + tree.repaint(getRepaintPathBounds(bounds)); + } bounds = getPathBounds(tree, newPath); - if(bounds != null) - tree.repaint(bounds); + if (bounds != null) { + tree.repaint(getRepaintPathBounds(bounds)); + } } } + private Rectangle getRepaintPathBounds(Rectangle bounds) { + if (UIManager.getBoolean("Tree.repaintWholeRow")) { + bounds.x = 0; + bounds.width = tree.getWidth(); + } + return bounds; + } + private TreePath getLeadSelectionPath() { return tree.getLeadSelectionPath(); } @@ -3643,14 +3653,6 @@ public class BasicTreeUI extends TreeUI focusGained(e); } - private Rectangle getRepaintPathBounds(Rectangle bounds) { - if(UIManager.getBoolean("Tree.repaintWholeRow")) { - bounds.x = 0; - bounds.width = tree.getWidth(); - } - return bounds; - } - // // CellEditorListener // diff --git a/src/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java b/src/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java new file mode 100644 index 0000000000000000000000000000000000000000..55fb19599c777b979e2ca16eccac566e22fbad6b --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/AbstractRegionPainter.java @@ -0,0 +1,735 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.*; +import java.awt.image.*; +import java.lang.reflect.Method; +import javax.swing.*; +import javax.swing.plaf.UIResource; +import javax.swing.Painter; +import java.awt.print.PrinterGraphics; +import static javax.swing.plaf.nimbus.NimbusLookAndFeel.deriveARGB; + +/** + * Convenient base class for defining Painter instances for rendering a + * region or component in Nimbus. + * + * @author Jasper Potts + * @author Richard Bair + */ +public abstract class AbstractRegionPainter implements Painter { + /** + * PaintContext, which holds a lot of the state needed for cache hinting and x/y value decoding + * The data contained within the context is typically only computed once and reused over + * multiple paint calls, whereas the other values (w, h, f, leftWidth, etc) are recomputed + * for each call to paint. + * + * This field is retrieved from subclasses on each paint operation. It is up + * to the subclass to compute and cache the PaintContext over multiple calls. + */ + private PaintContext ctx; + /** + * The scaling factor. Recomputed on each call to paint. + */ + private float f; + /* + Various metrics used for decoding x/y values based on the canvas size + and stretching insets. + + On each call to paint, we first ask the subclass for the PaintContext. + From the context we get the canvas size and stretching insets, and whether + the algorithm should be "inverted", meaning the center section remains + a fixed size and the other sections scale. + + We then use these values to compute a series of metrics (listed below) + which are used to decode points in a specific axis (x or y). + + The leftWidth represents the distance from the left edge of the region + to the first stretching inset, after accounting for any scaling factor + (such as DPI scaling). The centerWidth is the distance between the leftWidth + and the rightWidth. The rightWidth is the distance from the right edge, + to the right inset (after scaling has been applied). + + The same logic goes for topHeight, centerHeight, and bottomHeight. + + The leftScale represents the proportion of the width taken by the left section. + The same logic is applied to the other scales. + + The various widths/heights are used to decode control points. The + various scales are used to decode bezier handles (or anchors). + */ + /** + * The width of the left section. Recomputed on each call to paint. + */ + private float leftWidth; + /** + * The height of the top section. Recomputed on each call to paint. + */ + private float topHeight; + /** + * The width of the center section. Recomputed on each call to paint. + */ + private float centerWidth; + /** + * The height of the center section. Recomputed on each call to paint. + */ + private float centerHeight; + /** + * The width of the right section. Recomputed on each call to paint. + */ + private float rightWidth; + /** + * The height of the bottom section. Recomputed on each call to paint. + */ + private float bottomHeight; + /** + * The scaling factor to use for the left section. Recomputed on each call to paint. + */ + private float leftScale; + /** + * The scaling factor to use for the top section. Recomputed on each call to paint. + */ + private float topScale; + /** + * The scaling factor to use for the center section, in the horizontal + * direction. Recomputed on each call to paint. + */ + private float centerHScale; + /** + * The scaling factor to use for the center section, in the vertical + * direction. Recomputed on each call to paint. + */ + private float centerVScale; + /** + * The scaling factor to use for the right section. Recomputed on each call to paint. + */ + private float rightScale; + /** + * The scaling factor to use for the bottom section. Recomputed on each call to paint. + */ + private float bottomScale; + + /** + * Create a new AbstractRegionPainter + */ + protected AbstractRegionPainter() { } + + /** + * @inheritDoc + */ + @Override + public final void paint(Graphics2D g, JComponent c, int w, int h) { + //don't render if the width/height are too small + if (w <= 0 || h <=0) return; + + Object[] extendedCacheKeys = getExtendedCacheKeys(c); + ctx = getPaintContext(); + PaintContext.CacheMode cacheMode = ctx == null ? PaintContext.CacheMode.NO_CACHING : ctx.cacheMode; + if (cacheMode == PaintContext.CacheMode.NO_CACHING || + !ImageCache.getInstance().isImageCachable(w, h) || + g instanceof PrinterGraphics) { + // no caching so paint directly + paint0(g, c, w, h, extendedCacheKeys); + } else if (cacheMode == PaintContext.CacheMode.FIXED_SIZES) { + paintWithFixedSizeCaching(g, c, w, h, extendedCacheKeys); + } else { + // 9 Square caching + paintWith9SquareCaching(g, ctx, c, w, h, extendedCacheKeys); + } + } + + /** + * Get any extra attributes which the painter implementation would like + * to include in the image cache lookups. This is checked for every call + * of the paint(g, c, w, h) method. + * + * @param c The component on the current paint call + * @return Array of extra objects to be included in the cache key + */ + protected Object[] getExtendedCacheKeys(JComponent c) { + return null; + } + + /** + *

Gets the PaintContext for this painting operation. This method is called on every + * paint, and so should be fast and produce no garbage. The PaintContext contains + * information such as cache hints. It also contains data necessary for decoding + * points at runtime, such as the stretching insets, the canvas size at which the + * encoded points were defined, and whether the stretching insets are inverted.

+ * + *

This method allows for subclasses to package the painting of different states + * with possibly different canvas sizes, etc, into one AbstractRegionPainter implementation.

+ * + * @return a PaintContext associated with this paint operation. + */ + protected abstract PaintContext getPaintContext(); + + /** + *

Configures the given Graphics2D. Often, rendering hints or compositiing rules are + * applied to a Graphics2D object prior to painting, which should affect all of the + * subsequent painting operations. This method provides a convenient hook for configuring + * the Graphics object prior to rendering, regardless of whether the render operation is + * performed to an intermediate buffer or directly to the display.

+ * + * @param g The Graphics2D object to configure. Will not be null. + */ + protected void configureGraphics(Graphics2D g) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + + /** + * Actually performs the painting operation. Subclasses must implement this method. + * The graphics object passed may represent the actual surface being rendererd to, + * or it may be an intermediate buffer. It has also been pre-translated. Simply render + * the component as if it were located at 0, 0 and had a width of width + * and a height of height. For performance reasons, you may want to read + * the clip from the Graphics2D object and only render within that space. + * + * @param g The Graphics2D surface to paint to + * @param c The JComponent related to the drawing event. For example, if the + * region being rendered is Button, then c will be a + * JButton. If the region being drawn is ScrollBarSlider, then the + * component will be JScrollBar. This value may be null. + * @param width The width of the region to paint. Note that in the case of + * painting the foreground, this value may differ from c.getWidth(). + * @param height The height of the region to paint. Note that in the case of + * painting the foreground, this value may differ from c.getHeight(). + * @param extendedCacheKeys The result of the call to getExtendedCacheKeys() + */ + protected abstract void doPaint(Graphics2D g, JComponent c, int width, + int height, Object[] extendedCacheKeys); + + /** + * Decodes and returns a float value representing the actual pixel location for + * the given encoded X value. + * + * @param x an encoded x value (0...1, or 1...2, or 2...3) + * @return the decoded x value + */ + protected final float decodeX(float x) { + if (ctx.canvasSize == null) return x; + + if (x >= 0 && x <= 1) { + return x * leftWidth; + } else if (x > 1 && x < 2) { + return ((x-1) * centerWidth) + leftWidth; + } else if (x >= 2 && x <= 3) { + return ((x-2) * rightWidth) + leftWidth + centerWidth; + } else { + throw new AssertionError("Invalid x"); + } + } + + /** + * Decodes and returns a float value representing the actual pixel location for + * the given encoded y value. + * + * @param y an encoded y value (0...1, or 1...2, or 2...3) + * @return the decoded y value + */ + protected final float decodeY(float y) { + if (ctx.canvasSize == null) return y; + + if (y >= 0 && y <= 1) { + return y * topHeight; + } else if (y > 1 && y < 2) { + return ((y-1) * centerHeight) + topHeight; + } else if (y >= 2 && y <= 3) { + return ((y-2) * bottomHeight) + topHeight + centerHeight; + } else { + throw new AssertionError("Invalid y"); + } + } + + /** + * Decodes and returns a float value representing the actual pixel location for + * the anchor point given the encoded X value of the control point, and the offset + * distance to the anchor from that control point. + * + * @param x an encoded x value of the bezier control point (0...1, or 1...2, or 2...3) + * @param dx the offset distance to the anchor from the control point x + * @return the decoded x location of the control point + */ + protected final float decodeAnchorX(float x, float dx) { + if (ctx.canvasSize == null) return x + dx; + + if (x >= 0 && x <= 1) { + return decodeX(x) + (dx * leftScale); + } else if (x > 1 && x < 2) { + return decodeX(x) + (dx * centerHScale); + } else if (x >= 2 && x <= 3) { + return decodeX(x) + (dx * rightScale); + } else { + throw new AssertionError("Invalid x"); + } + } + + /** + * Decodes and returns a float value representing the actual pixel location for + * the anchor point given the encoded Y value of the control point, and the offset + * distance to the anchor from that control point. + * + * @param y an encoded y value of the bezier control point (0...1, or 1...2, or 2...3) + * @param dy the offset distance to the anchor from the control point y + * @return the decoded y position of the control point + */ + protected final float decodeAnchorY(float y, float dy) { + if (ctx.canvasSize == null) return y + dy; + + if (y >= 0 && y <= 1) { + return decodeY(y) + (dy * topScale); + } else if (y > 1 && y < 2) { + return decodeY(y) + (dy * centerVScale); + } else if (y >= 2 && y <= 3) { + return decodeY(y) + (dy * bottomScale); + } else { + throw new AssertionError("Invalid y"); + } + } + + /** + * Decodes and returns a color, which is derived from a base color in UI + * defaults. + * + * @param key A key corrosponding to the value in the UI Defaults table + * of UIManager where the base color is defined + * @param hOffset The hue offset used for derivation. + * @param sOffset The saturation offset used for derivation. + * @param bOffset The brightness offset used for derivation. + * @param aOffset The alpha offset used for derivation. Between 0...255 + * @return The derived color, whos color value will change if the parent + * uiDefault color changes. + */ + protected final Color decodeColor(String key, float hOffset, float sOffset, + float bOffset, int aOffset) { + if (UIManager.getLookAndFeel() instanceof NimbusLookAndFeel){ + NimbusLookAndFeel laf = (NimbusLookAndFeel) UIManager.getLookAndFeel(); + return laf.getDerivedColor(key, hOffset, sOffset, bOffset, aOffset, true); + } else { + // can not give a right answer as painter sould not be used outside + // of nimbus laf but do the best we can + return Color.getHSBColor(hOffset,sOffset,bOffset); + } + } + + /** + * Decodes and returns a color, which is derived from a offset between two + * other colors. + * + * @param color1 The first color + * @param color2 The second color + * @param midPoint The offset between color 1 and color 2, a value of 0.0 is + * color 1 and 1.0 is color 2; + * @return The derived color + */ + protected final Color decodeColor(Color color1, Color color2, + float midPoint) { + return new Color(deriveARGB(color1, color2, midPoint)); + } + + /** + * Given parameters for creating a LinearGradientPaint, this method will + * create and return a linear gradient paint. One primary purpose for this + * method is to avoid creating a LinearGradientPaint where the start and + * end points are equal. In such a case, the end y point is slightly + * increased to avoid the overlap. + * + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @param midpoints + * @param colors + * @return a valid LinearGradientPaint. This method never returns null. + */ + protected final LinearGradientPaint decodeGradient(float x1, float y1, float x2, float y2, float[] midpoints, Color[] colors) { + if (x1 == x2 && y1 == y2) { + y2 += .00001f; + } + return new LinearGradientPaint(x1, y1, x2, y2, midpoints, colors); + } + + /** + * Given parameters for creating a RadialGradientPaint, this method will + * create and return a radial gradient paint. One primary purpose for this + * method is to avoid creating a RadialGradientPaint where the radius + * is non-positive. In such a case, the radius is just slightly + * increased to avoid 0. + * + * @param x + * @param y + * @param r + * @param midpoints + * @param colors + * @return a valid RadialGradientPaint. This method never returns null. + */ + protected final RadialGradientPaint decodeRadialGradient(float x, float y, float r, float[] midpoints, Color[] colors) { + if (r == 0f) { + r = .00001f; + } + return new RadialGradientPaint(x, y, r, midpoints, colors); + } + + /** + * Get a color property from the given JComponent. First checks for a + * getXXX() method and if that fails checks for a client + * property with key property. If that still fails to return + * a Color then defaultColor is returned. + * + * @param c The component to get the color property from + * @param property The name of a bean style property or client property + * @param defaultColor The color to return if no color was obtained from + * the component. + * @return The color that was obtained from the component or defaultColor + */ + protected final Color getComponentColor(JComponent c, String property, + Color defaultColor, + float saturationOffset, + float brightnessOffset, + int alphaOffset) { + Color color = null; + if (c != null) { + // handle some special cases for performance + if ("background".equals(property)) { + color = c.getBackground(); + } else if ("foreground".equals(property)) { + color = c.getForeground(); + } else if (c instanceof JList && "selectionForeground".equals(property)) { + color = ((JList) c).getSelectionForeground(); + } else if (c instanceof JList && "selectionBackground".equals(property)) { + color = ((JList) c).getSelectionBackground(); + } else if (c instanceof JTable && "selectionForeground".equals(property)) { + color = ((JTable) c).getSelectionForeground(); + } else if (c instanceof JTable && "selectionBackground".equals(property)) { + color = ((JTable) c).getSelectionBackground(); + } else { + String s = "get" + Character.toUpperCase(property.charAt(0)) + property.substring(1); + try { + Method method = c.getClass().getMethod(s); + color = (Color) method.invoke(c); + } catch (Exception e) { + //don't do anything, it just didn't work, that's all. + //This could be a normal occurance if you use a property + //name referring to a key in clientProperties instead of + //a real property + } + if (color == null) { + Object value = c.getClientProperty(property); + if (value instanceof Color) { + color = (Color) value; + } + } + } + } + // we return the defaultColor if the color found is null, or if + // it is a UIResource. This is done because the color for the + // ENABLED state is set on the component, but you don't want to use + // that color for the over state. So we only respect the color + // specified for the property if it was set by the user, as opposed + // to set by us. + if (color == null || color instanceof UIResource) { + return defaultColor; + } else if (saturationOffset != 0 || brightnessOffset != 0 || alphaOffset != 0) { + float[] tmp = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); + tmp[1] = clamp(tmp[1] + saturationOffset); + tmp[2] = clamp(tmp[2] + brightnessOffset); + int alpha = clamp(color.getAlpha() + alphaOffset); + return new Color((Color.HSBtoRGB(tmp[0], tmp[1], tmp[2]) & 0xFFFFFF) | (alpha <<24)); + } else { + return color; + } + } + + /** + * A class encapsulating state useful when painting. Generally, instances of this + * class are created once, and reused for each paint request without modification. + * This class contains values useful when hinting the cache engine, and when decoding + * control points and bezier curve anchors. + */ + protected static class PaintContext { + protected static enum CacheMode { + NO_CACHING, FIXED_SIZES, NINE_SQUARE_SCALE + } + + private static Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); + + private Insets stretchingInsets; + private Dimension canvasSize; + private boolean inverted; + private CacheMode cacheMode; + private double maxHorizontalScaleFactor; + private double maxVerticalScaleFactor; + + private float a; // insets.left + private float b; // canvasSize.width - insets.right + private float c; // insets.top + private float d; // canvasSize.height - insets.bottom; + private float aPercent; // only used if inverted == true + private float bPercent; // only used if inverted == true + private float cPercent; // only used if inverted == true + private float dPercent; // only used if inverted == true + + /** + * Creates a new PaintContext which does not attempt to cache or scale any cached + * images. + * + * @param insets The stretching insets. May be null. If null, then assumed to be 0, 0, 0, 0. + * @param canvasSize The size of the canvas used when encoding the various x/y values. May be null. + * If null, then it is assumed that there are no encoded values, and any calls + * to one of the "decode" methods will return the passed in value. + * @param inverted Whether to "invert" the meaning of the 9-square grid and stretching insets + */ + public PaintContext(Insets insets, Dimension canvasSize, boolean inverted) { + this(insets, canvasSize, inverted, null, 1, 1); + } + + /** + * Creates a new PaintContext. + * + * @param insets The stretching insets. May be null. If null, then assumed to be 0, 0, 0, 0. + * @param canvasSize The size of the canvas used when encoding the various x/y values. May be null. + * If null, then it is assumed that there are no encoded values, and any calls + * to one of the "decode" methods will return the passed in value. + * @param inverted Whether to "invert" the meaning of the 9-square grid and stretching insets + * @param cacheMode A hint as to which caching mode to use. If null, then set to no caching. + * @param maxH The maximium scale in the horizontal direction to use before punting and redrawing from scratch. + * For example, if maxH is 2, then we will attempt to scale any cached images up to 2x the canvas + * width before redrawing from scratch. Reasonable maxH values may improve painting performance. + * If set too high, then you may get poor looking graphics at higher zoom levels. Must be >= 1. + * @param maxV The maximium scale in the vertical direction to use before punting and redrawing from scratch. + * For example, if maxV is 2, then we will attempt to scale any cached images up to 2x the canvas + * height before redrawing from scratch. Reasonable maxV values may improve painting performance. + * If set too high, then you may get poor looking graphics at higher zoom levels. Must be >= 1. + */ + public PaintContext(Insets insets, Dimension canvasSize, boolean inverted, + CacheMode cacheMode, double maxH, double maxV) { + if (maxH < 1 || maxH < 1) { + throw new IllegalArgumentException("Both maxH and maxV must be >= 1"); + } + + this.stretchingInsets = insets == null ? EMPTY_INSETS : insets; + this.canvasSize = canvasSize; + this.inverted = inverted; + this.cacheMode = cacheMode == null ? CacheMode.NO_CACHING : cacheMode; + this.maxHorizontalScaleFactor = maxH; + this.maxVerticalScaleFactor = maxV; + + if (canvasSize != null) { + a = insets.left; + b = canvasSize.width - insets.right; + c = insets.top; + d = canvasSize.height - insets.bottom; + this.canvasSize = canvasSize; + this.inverted = inverted; + if (inverted) { + float available = canvasSize.width - (b - a); + aPercent = available > 0f ? a / available : 0f; + bPercent = available > 0f ? b / available : 0f; + available = canvasSize.height - (d - c); + cPercent = available > 0f ? c / available : 0f; + dPercent = available > 0f ? d / available : 0f; + } + } + } + } + + //---------------------- private methods + + //initializes the class to prepare it for being able to decode points + private void prepare(float w, float h) { + //if no PaintContext has been specified, reset the values and bail + //also bail if the canvasSize was not set (since decoding will not work) + if (ctx == null || ctx.canvasSize == null) { + f = 1f; + leftWidth = centerWidth = rightWidth = 0f; + topHeight = centerHeight = bottomHeight = 0f; + leftScale = centerHScale = rightScale = 0f; + topScale = centerVScale = bottomScale = 0f; + return; + } + + //calculate the scaling factor, and the sizes for the various 9-square sections + Number scale = (Number)UIManager.get("scale"); + f = scale == null ? 1f : scale.floatValue(); + + if (ctx.inverted) { + centerWidth = (ctx.b - ctx.a) * f; + float availableSpace = w - centerWidth; + leftWidth = availableSpace * ctx.aPercent; + rightWidth = availableSpace * ctx.bPercent; + centerHeight = (ctx.d - ctx.c) * f; + availableSpace = h - centerHeight; + topHeight = availableSpace * ctx.cPercent; + bottomHeight = availableSpace * ctx.dPercent; + } else { + leftWidth = ctx.a * f; + rightWidth = (float)(ctx.canvasSize.getWidth() - ctx.b) * f; + centerWidth = w - leftWidth - rightWidth; + topHeight = ctx.c * f; + bottomHeight = (float)(ctx.canvasSize.getHeight() - ctx.d) * f; + centerHeight = h - topHeight - bottomHeight; + } + + leftScale = ctx.a == 0f ? 0f : leftWidth / ctx.a; + centerHScale = (ctx.b - ctx.a) == 0f ? 0f : centerWidth / (ctx.b - ctx.a); + rightScale = (ctx.canvasSize.width - ctx.b) == 0f ? 0f : rightWidth / (ctx.canvasSize.width - ctx.b); + topScale = ctx.c == 0f ? 0f : topHeight / ctx.c; + centerVScale = (ctx.d - ctx.c) == 0f ? 0f : centerHeight / (ctx.d - ctx.c); + bottomScale = (ctx.canvasSize.height - ctx.d) == 0f ? 0f : bottomHeight / (ctx.canvasSize.height - ctx.d); + } + + private void paintWith9SquareCaching(Graphics2D g, PaintContext ctx, + JComponent c, int w, int h, + Object[] extendedCacheKeys) { + // check if we can scale to the requested size + Dimension canvas = ctx.canvasSize; + Insets insets = ctx.stretchingInsets; + + if (w <= (canvas.width * ctx.maxHorizontalScaleFactor) && h <= (canvas.height * ctx.maxVerticalScaleFactor)) { + // get image at canvas size + VolatileImage img = getImage(g.getDeviceConfiguration(), c, canvas.width, canvas.height, extendedCacheKeys); + if (img != null) { + // calculate dst inserts + // todo: destination inserts need to take into acount scale factor for high dpi. Note: You can use f for this, I think + Insets dstInsets; + if (ctx.inverted){ + int leftRight = (w-(canvas.width-(insets.left+insets.right)))/2; + int topBottom = (h-(canvas.height-(insets.top+insets.bottom)))/2; + dstInsets = new Insets(topBottom,leftRight,topBottom,leftRight); + } else { + dstInsets = insets; + } + // paint 9 square scaled + Object oldScaleingHints = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR); + ImageScalingHelper.paint(g, 0, 0, w, h, img, insets, dstInsets, + ImageScalingHelper.PaintType.PAINT9_STRETCH, ImageScalingHelper.PAINT_ALL); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + oldScaleingHints!=null?oldScaleingHints:RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + } else { + // render directly + paint0(g, c, w, h, extendedCacheKeys); + } + } else { + // paint directly + paint0(g, c, w, h, extendedCacheKeys); + } + } + + private void paintWithFixedSizeCaching(Graphics2D g, JComponent c, int w, + int h, Object[] extendedCacheKeys) { + VolatileImage img = getImage(g.getDeviceConfiguration(), c, w, h, extendedCacheKeys); + if (img != null) { + //render cached image + g.drawImage(img, 0, 0, null); + } else { + // render directly + paint0(g, c, w, h, extendedCacheKeys); + } + } + + /** Gets the rendered image for this painter at the requested size, either from cache or create a new one */ + private VolatileImage getImage(GraphicsConfiguration config, JComponent c, + int w, int h, Object[] extendedCacheKeys) { + ImageCache imageCache = ImageCache.getInstance(); + //get the buffer for this component + VolatileImage buffer = (VolatileImage) imageCache.getImage(config, w, h, this, extendedCacheKeys); + + int renderCounter = 0; //to avoid any potential, though unlikely, infinite loop + do { + //validate the buffer so we can check for surface loss + int bufferStatus = VolatileImage.IMAGE_INCOMPATIBLE; + if (buffer != null) { + bufferStatus = buffer.validate(config); + } + + //If the buffer status is incompatible or restored, then we need to re-render to the volatile image + if (bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE || bufferStatus == VolatileImage.IMAGE_RESTORED) { + //if the buffer is null (hasn't been created), or isn't the right size, or has lost its contents, + //then recreate the buffer + if (buffer == null || buffer.getWidth() != w || buffer.getHeight() != h || + bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE) { + //clear any resources related to the old back buffer + if (buffer != null) { + buffer.flush(); + buffer = null; + } + //recreate the buffer + buffer = config.createCompatibleVolatileImage(w, h, + Transparency.TRANSLUCENT); + // put in cache for future + imageCache.setImage(buffer, config, w, h, this, extendedCacheKeys); + } + //create the graphics context with which to paint to the buffer + Graphics2D bg = buffer.createGraphics(); + //clear the background before configuring the graphics + bg.setComposite(AlphaComposite.Clear); + bg.fillRect(0, 0, w, h); + bg.setComposite(AlphaComposite.SrcOver); + configureGraphics(bg); + // paint the painter into buffer + paint0(bg, c, w, h, extendedCacheKeys); + //close buffer graphics + bg.dispose(); + } + } while (buffer.contentsLost() && renderCounter++ < 3); + // check if we failed + if (renderCounter == 3) return null; + // return image + return buffer; + } + + //convenience method which creates a temporary graphics object by creating a + //clone of the passed in one, configuring it, drawing with it, disposing it. + //These steps have to be taken to ensure that any hints set on the graphics + //are removed subsequent to painting. + private void paint0(Graphics2D g, JComponent c, int width, int height, + Object[] extendedCacheKeys) { + prepare(width, height); + g = (Graphics2D)g.create(); + configureGraphics(g); + doPaint(g, c, width, height, extendedCacheKeys); + g.dispose(); + } + + private float clamp(float value) { + if (value < 0) { + value = 0; + } else if (value > 1) { + value = 1; + } + return value; + } + + private int clamp(int value) { + if (value < 0) { + value = 0; + } else if (value > 255) { + value = 255; + } + return value; + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/Defaults.template b/src/share/classes/javax/swing/plaf/nimbus/Defaults.template new file mode 100644 index 0000000000000000000000000000000000000000..a0f5afc22c878c58ab07ce5d626a1d16e6817f1c --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/Defaults.template @@ -0,0 +1,878 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package ${PACKAGE}; + +import javax.swing.Painter; +import java.awt.Graphics; +import sun.font.FontManager; +import sun.swing.plaf.synth.DefaultSynthStyle; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.DimensionUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.InsetsUIResource; +import javax.swing.plaf.synth.Region; +import javax.swing.plaf.synth.SynthStyle; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.image.BufferedImage; +import static java.awt.image.BufferedImage.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import javax.swing.border.Border; +import javax.swing.plaf.UIResource; + +/** + * This class contains all the implementation details related to + * ${LAF_NAME}. It contains all the code for initializing the UIDefaults table, + * as well as for selecting + * a SynthStyle based on a JComponent/Region pair. + * + * @author Richard Bair + */ +final class ${LAF_NAME}Defaults { + /** + * The map of SynthStyles. This map is keyed by Region. Each Region maps + * to a List of LazyStyles. Each LazyStyle has a reference to the prefix + * that was registered with it. This reference can then be inspected to see + * if it is the proper lazy style. + *

+ * There can be more than one LazyStyle for a single Region if there is more + * than one prefix defined for a given region. For example, both Button and + * "MyButton" might be prefixes assigned to the Region.Button region. + */ + private Map> m; + /** + * A map of regions which have been registered. + * This mapping is maintained so that the Region can be found based on + * prefix in a very fast manner. This is used in the "matches" method of + * LazyStyle. + */ + private Map registeredRegions = + new HashMap(); + /** + * Our fallback style to avoid NPEs if the proper style cannot be found in + * this class. Not sure if relying on DefaultSynthStyle is the best choice. + */ + private DefaultSynthStyle defaultStyle; + /** + * The default font that will be used. I store this value so that it can be + * set in the UIDefaults when requested. + */ + private FontUIResource defaultFont; + + /** + * Map of lists of derived colors keyed by the DerivedColorKeys + */ + private Map derivedColorsMap = + new HashMap(); + + /** Tempory key used for fetching from the derivedColorsMap */ + private final DerivedColorKey tmpDCKey = new DerivedColorKey(); + + /** Listener for changes to user defaults table */ + private DefaultsListener defaultsListener = new DefaultsListener(); + + /** Called by UIManager when this look and feel is installed. */ + void initialize() { + // add listener for derived colors + UIManager.addPropertyChangeListener(defaultsListener); + UIManager.getDefaults().addPropertyChangeListener(defaultsListener); + } + + /** Called by UIManager when this look and feel is uninstalled. */ + void uninitialize() { + // remove listener for derived colors + UIManager.getDefaults().removePropertyChangeListener(defaultsListener); + UIManager.removePropertyChangeListener(defaultsListener); + } + + /** + * Create a new ${LAF_NAME}Defaults. This constructor is only called from + * within ${LAF_NAME}LookAndFeel. + */ + ${LAF_NAME}Defaults() { + m = new HashMap>(); + + //Create the default font and default style. Also register all of the + //regions and their states that this class will use for later lookup. + //Additional regions can be registered later by 3rd party components. + //These are simply the default registrations. + defaultFont = FontManager.getFontConfigFUIR("sans", Font.PLAIN, 12); + defaultStyle = new DefaultSynthStyle(); + defaultStyle.setFont(defaultFont); + + //initialize the map of styles +${STYLE_INIT} + } + + //--------------- Methods called by ${LAF_NAME}LookAndFeel + + /** + * Called from ${LAF_NAME}LookAndFeel to initialize the UIDefaults. + * + * @param d UIDefaults table to initialize. This will never be null. + * If listeners are attached to d, then you will + * only receive notification of LookAndFeel level defaults, not + * all defaults on the UIManager. + */ + void initializeDefaults(UIDefaults d) { +${UI_DEFAULT_INIT} + } + + /** + *

Registers the given region and prefix. The prefix, if it contains + * quoted sections, refers to certain named components. If there are not + * quoted sections, then the prefix refers to a generic component type.

+ * + *

If the given region/prefix combo has already been registered, then + * it will not be registered twice. The second registration attempt will + * fail silently.

+ * + * @param region The Synth Region that is being registered. Such as Button, + * or ScrollBarThumb. + * @param prefix The UIDefault prefix. For example, could be ComboBox, or if + * a named components, "MyComboBox", or even something like + * ToolBar:"MyComboBox":"ComboBox.arrowButton" + */ + void register(Region region, String prefix) { + //validate the method arguments + if (region == null || prefix == null) { + throw new IllegalArgumentException( + "Neither Region nor Prefix may be null"); + } + + //Add a LazyStyle for this region/prefix to m. + List styles = m.get(region); + if (styles == null) { + styles = new LinkedList(); + styles.add(new LazyStyle(prefix)); + m.put(region, styles); + } else { + //iterate over all the current styles and see if this prefix has + //already been registered. If not, then register it. + for (LazyStyle s : styles) { + if (prefix.equals(s.prefix)) { + return; + } + } + styles.add(new LazyStyle(prefix)); + } + + //add this region to the map of registered regions + registeredRegions.put(region.getName(), region); + } + + /** + *

Locate the style associated with the given region, and component. + * This is called from ${LAF_NAME}LookAndFeel in the SynthStyleFactory + * implementation.

+ * + *

Lookup occurs as follows:
+ * Check the map of styles m. If the map contains no styles at + * all, then simply return the defaultStyle. If the map contains styles, + * then iterate over all of the styles for the Region r looking + * for the best match, based on prefix. If a match was made, then return + * that SynthStyle. Otherwise, return the defaultStyle.

+ * + * @param comp The component associated with this region. For example, if + * the Region is Region.Button then the component will be a JButton. + * If the Region is a subregion, such as ScrollBarThumb, then the + * associated component will be the component that subregion belongs + * to, such as JScrollBar. The JComponent may be named. It may not be + * null. + * @param r The region we are looking for a style for. May not be null. + */ + SynthStyle getStyle(JComponent comp, Region r) { + //validate method arguments + if (comp == null || r == null) { + throw new IllegalArgumentException( + "Neither comp nor r may be null"); + } + + //if there are no lazy styles registered for the region r, then return + //the default style + List styles = m.get(r); + if (styles == null || styles.size() == 0) { + return defaultStyle; + } + + //Look for the best SynthStyle for this component/region pair. + LazyStyle foundStyle = null; + for (LazyStyle s : styles) { + if (s.matches(comp)) { + //replace the foundStyle if foundStyle is null, or + //if the new style "s" is more specific (ie, its path was + //longer), or if the foundStyle was "simple" and the new style + //was not (ie: the foundStyle was for something like Button and + //the new style was for something like "MyButton", hence, being + //more specific.) In all cases, favor the most specific style + //found. + if (foundStyle == null || + (foundStyle.parts.length < s.parts.length) || + (foundStyle.parts.length == s.parts.length + && foundStyle.simple && !s.simple)) { + foundStyle = s; + } + } + } + + //return the style, if found, or the default style if not found + return foundStyle == null ? defaultStyle : foundStyle.getStyle(comp); + } + + /* + Various public helper classes. + These may be used to register 3rd party values into UIDefaults + */ + + /** + *

Derives its font value based on a parent font and a set of offsets and + * attributes. This class is an ActiveValue, meaning that it will recompute + * its value each time it is requested from UIDefaults. It is therefore + * recommended to read this value once and cache it in the UI delegate class + * until asked to reinitialize.

+ * + *

To use this class, create an instance with the key of the font in the + * UI defaults table from which to derive this font, along with a size + * offset (if any), and whether it is to be bold, italic, or left in its + * default form.

+ */ + public static final class DerivedFont implements UIDefaults.ActiveValue { + private float sizeOffset; + private Boolean bold; + private Boolean italic; + private String parentKey; + + /** + * Create a new DerivedFont. + * + * @param key The UIDefault key associated with this derived font's + * parent or source. If this key leads to a null value, or a + * value that is not a font, then null will be returned as + * the derived font. The key must not be null. + * @param sizeOffset The size offset, as a percentage, to use. For + * example, if the source font was a 12pt font and the + * sizeOffset were specified as .9, then the new font + * will be 90% of what the source font was, or, 10.8 + * pts which is rounded to 11pts. This fractional + * based offset allows for proper font scaling in high + * DPI or large system font scenarios. + * @param bold Whether the new font should be bold. If null, then this + * new font will inherit the bold setting of the source + * font. + * @param italic Whether the new font should be italicized. If null, + * then this new font will inherit the italic setting of + * the source font. + */ + public DerivedFont(String key, float sizeOffset, Boolean bold, + Boolean italic) { + //validate the constructor arguments + if (key == null) { + throw new IllegalArgumentException("You must specify a key"); + } + + //set the values + this.parentKey = key; + this.sizeOffset = sizeOffset; + this.bold = bold; + this.italic = italic; + } + + /** + * @inheritDoc + */ + @Override + public Object createValue(UIDefaults defaults) { + Font f = defaults.getFont(parentKey); + if (f != null) { + // always round size for now so we have exact int font size + // (or we may have lame looking fonts) + float size = Math.round(f.getSize2D() * sizeOffset); + int style = f.getStyle(); + if (bold != null) { + if (bold.booleanValue()) { + style = style | Font.BOLD; + } else { + style = style & ~Font.BOLD; + } + } + if (italic != null) { + if (italic.booleanValue()) { + style = style | Font.ITALIC; + } else { + style = style & ~Font.ITALIC; + } + } + return f.deriveFont(style, size); + } else { + return null; + } + } + } + + + /** + * This class is private because it relies on the constructor of the + * auto-generated AbstractRegionPainter subclasses. Hence, it is not + * generally useful, and is private. + *

+ * LazyPainter is a LazyValue class. It will create the + * AbstractRegionPainter lazily, when asked. It uses reflection to load the + * proper class and invoke its constructor. + */ + private static final class LazyPainter implements UIDefaults.LazyValue { + private int which; + private AbstractRegionPainter.PaintContext ctx; + private String className; + + LazyPainter(String className, int which, Insets insets, + Dimension canvasSize, boolean inverted) { + if (className == null) { + throw new IllegalArgumentException( + "The className must be specified"); + } + + this.className = className; + this.which = which; + this.ctx = new AbstractRegionPainter.PaintContext( + insets, canvasSize, inverted); + } + + LazyPainter(String className, int which, Insets insets, + Dimension canvasSize, boolean inverted, + AbstractRegionPainter.PaintContext.CacheMode cacheMode, + double maxH, double maxV) { + if (className == null) { + throw new IllegalArgumentException( + "The className must be specified"); + } + + this.className = className; + this.which = which; + this.ctx = new AbstractRegionPainter.PaintContext( + insets, canvasSize, inverted, cacheMode, maxH, maxV); + } + + @Override + public Object createValue(UIDefaults table) { + try { + Class c; + Object cl; + // See if we should use a separate ClassLoader + if (table == null || !((cl = table.get("ClassLoader")) + instanceof ClassLoader)) { + cl = Thread.currentThread(). + getContextClassLoader(); + if (cl == null) { + // Fallback to the system class loader. + cl = ClassLoader.getSystemClassLoader(); + } + } + + c = Class.forName(className, true, (ClassLoader)cl); + Constructor constructor = c.getConstructor( + AbstractRegionPainter.PaintContext.class, int.class); + if (constructor == null) { + throw new NullPointerException( + "Failed to find the constructor for the class: " + + className); + } + return constructor.newInstance(ctx, which); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + } + + /** + * A class which creates the NimbusStyle associated with it lazily, but also + * manages a lot more information about the style. It is less of a LazyValue + * type of class, and more of an Entry or Item type of class, as it + * represents an entry in the list of LazyStyles in the map m. + * + * The primary responsibilities of this class include: + *

    + *
  • Determining whether a given component/region pair matches this + * style
  • + *
  • Splitting the prefix specified in the constructor into its + * constituent parts to facilitate quicker matching
  • + *
  • Creating and vending a NimbusStyle lazily.
  • + *
+ */ + private final class LazyStyle { + /** + * The prefix this LazyStyle was registered with. Something like + * Button or ComboBox:"ComboBox.arrowButton" + */ + private String prefix; + /** + * Whether or not this LazyStyle represents an unnamed component + */ + private boolean simple = true; + /** + * The various parts, or sections, of the prefix. For example, + * the prefix: + * ComboBox:"ComboBox.arrowButton" + * + * will be broken into two parts, + * ComboBox and "ComboBox.arrowButton" + */ + private Part[] parts; + /** + * Cached shared style. + */ + private NimbusStyle style; + /** + * A weakly referenced hash map such that if the reference JComponent + * key is garbage collected then the entry is removed from the map. + * This cache exists so that when a JComponent has nimbus overrides + * in its client map, a unique style will be created and returned + * for that JComponent instance, always. In such a situation each + * JComponent instance must have its own instance of NimbusStyle. + */ + private WeakHashMap> overridesCache; + + /** + * Create a new LazyStyle. + * + * @param prefix The prefix associated with this style. Cannot be null. + */ + private LazyStyle(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException( + "The prefix must not be null"); + } + + this.prefix = prefix; + + //there is one odd case that needs to be supported here: cell + //renderers. A cell renderer is defined as a named internal + //component, so for example: + // List."List.cellRenderer" + //The problem is that the component named List.cellRenderer is not a + //child of a JList. Rather, it is treated more as a direct component + //Thus, if the prefix ends with "cellRenderer", then remove all the + //previous dotted parts of the prefix name so that it becomes, for + //example: "List.cellRenderer" + //Likewise, we have a hacked work around for cellRenderer, renderer, + //and listRenderer. + String temp = prefix; + if (temp.endsWith("cellRenderer\"") + || temp.endsWith("renderer\"") + || temp.endsWith("listRenderer\"")) { + temp = temp.substring(temp.lastIndexOf(":\"") + 1); + } + + //otherwise, normal code path + List sparts = split(temp); + parts = new Part[sparts.size()]; + for (int i = 0; i < parts.length; i++) { + parts[i] = new Part(sparts.get(i)); + if (parts[i].named) { + simple = false; + } + } + } + + /** + * Gets the style. Creates it if necessary. + * @return the style + */ + SynthStyle getStyle(JComponent c) { + // if the component has overrides, it gets its own unique style + // instead of the shared style. + if (c.getClientProperty("Nimbus.Overrides") != null) { + if (overridesCache == null) + overridesCache = new WeakHashMap>(); + WeakReference ref = overridesCache.get(c); + NimbusStyle s = ref == null ? null : ref.get(); + if (s == null) { + s = new NimbusStyle(prefix, c); + overridesCache.put(c, new WeakReference(s)); + } + return s; + } + + // lazily create the style if necessary + if (style == null) + style = new NimbusStyle(prefix, null); + + // return the style + return style; + } + + /** + * This LazyStyle is a match for the given component if, and only if, + * for each part of the prefix the component hierarchy matches exactly. + * That is, if given "a":something:"b", then: + * c.getName() must equals "b" + * c.getParent() can be anything + * c.getParent().getParent().getName() must equal "a". + */ + boolean matches(JComponent c) { + return matches(c, parts.length - 1); + } + + private boolean matches(Component c, int partIndex) { + if (partIndex < 0) return true; + if (c == null) return false; + //only get here if partIndex > 0 and c == null + + String name = c.getName(); + if (parts[partIndex].named && parts[partIndex].s.equals(name)) { + //so far so good, recurse + return matches(c.getParent(), partIndex - 1); + } else if (!parts[partIndex].named) { + //if c is not named, and parts[partIndex] has an expected class + //type registered, then check to make sure c is of the + //right type; + Class clazz = parts[partIndex].c; + if (clazz != null && clazz.isAssignableFrom(c.getClass())) { + //so far so good, recurse + return matches(c.getParent(), partIndex - 1); + } else if (clazz == null && + registeredRegions.containsKey(parts[partIndex].s)) { + Region r = registeredRegions.get(parts[partIndex].s); + Component parent = r.isSubregion() ? c : c.getParent(); + //special case the JInternalFrameTitlePane, because it + //doesn't fit the mold. very, very funky. + if (r == Region.INTERNAL_FRAME_TITLE_PANE && parent != null + && parent instanceof JInternalFrame.JDesktopIcon) { + JInternalFrame.JDesktopIcon icon = + (JInternalFrame.JDesktopIcon) parent; + parent = icon.getInternalFrame(); + } + //it was the name of a region. So far, so good. Recurse. + return matches(parent, partIndex - 1); + } + } + + return false; + } + + /** + * Given some dot separated prefix, split on the colons that are + * not within quotes, and not within brackets. + * + * @param prefix + * @return + */ + private List split(String prefix) { + List parts = new ArrayList(); + int bracketCount = 0; + boolean inquotes = false; + int lastIndex = 0; + for (int i = 0; i < prefix.length(); i++) { + char c = prefix.charAt(i); + + if (c == '[') { + bracketCount++; + continue; + } else if (c == '"') { + inquotes = !inquotes; + continue; + } else if (c == ']') { + bracketCount--; + if (bracketCount < 0) { + throw new RuntimeException( + "Malformed prefix: " + prefix); + } + continue; + } + + if (c == ':' && !inquotes && bracketCount == 0) { + //found a character to split on. + parts.add(prefix.substring(lastIndex, i)); + lastIndex = i + 1; + } + } + if (lastIndex < prefix.length() - 1 && !inquotes + && bracketCount == 0) { + parts.add(prefix.substring(lastIndex)); + } + return parts; + + } + + private final class Part { + private String s; + //true if this part represents a component name + private boolean named; + private Class c; + + Part(String s) { + named = s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"'; + if (named) { + this.s = s.substring(1, s.length() - 1); + } else { + this.s = s; + //TODO use a map of known regions for Synth and Swing, and + //then use [classname] instead of org_class_name style + try { + c = Class.forName("javax.swing.J" + s); + } catch (Exception e) { + } + try { + c = Class.forName(s.replace("_", ".")); + } catch (Exception e) { + } + } + } + } + } + + /** + * Get a derived color, derived colors are shared instances and will be + * updated when its parent UIDefault color changes. + * + * @param uiDefaultParentName The parent UIDefault key + * @param hOffset The hue offset + * @param sOffset The saturation offset + * @param bOffset The brightness offset + * @param aOffset The alpha offset + * @return The stored derived color + */ + public DerivedColor getDerivedColor(String uiDefaultParentName, + float hOffset, float sOffset, + float bOffset, int aOffset){ + return getDerivedColor(uiDefaultParentName, hOffset, sOffset, + bOffset, aOffset, true); + } + + /** + * Get a derived color, derived colors are shared instances and will be + * updated when its parent UIDefault color changes. + * + * @param uiDefaultParentName The parent UIDefault key + * @param hOffset The hue offset + * @param sOffset The saturation offset + * @param bOffset The brightness offset + * @param aOffset The alpha offset + * @param uiResource True if the derived color should be a UIResource, + * false if it should not be a UIResource + * @return The stored derived color + */ + public DerivedColor getDerivedColor(String uiDefaultParentName, + float hOffset, float sOffset, + float bOffset, int aOffset, + boolean uiResource){ + tmpDCKey.set(uiDefaultParentName, hOffset, sOffset, bOffset, aOffset, + uiResource); + DerivedColor color = derivedColorsMap.get(tmpDCKey); + if (color == null){ + if (uiResource) { + color = new DerivedColor.UIResource(uiDefaultParentName, + hOffset, sOffset, bOffset, aOffset); + } else { + color = new DerivedColor(uiDefaultParentName, hOffset, sOffset, + bOffset, aOffset); + } + // calculate the initial value + color.rederiveColor(); + // add the listener so that if the color changes we'll propogate it + color.addPropertyChangeListener(defaultsListener); + // add to the derived colors table + derivedColorsMap.put(new DerivedColorKey(uiDefaultParentName, + hOffset, sOffset, bOffset, aOffset, uiResource),color); + } + return color; + } + + /** + * Key class for derived colors + */ + private class DerivedColorKey { + private String uiDefaultParentName; + private float hOffset, sOffset, bOffset; + private int aOffset; + private boolean uiResource; + + DerivedColorKey(){} + + DerivedColorKey(String uiDefaultParentName, float hOffset, + float sOffset, float bOffset, int aOffset, + boolean uiResource) { + set(uiDefaultParentName, hOffset, sOffset, bOffset, aOffset, uiResource); + } + + void set (String uiDefaultParentName, float hOffset, + float sOffset, float bOffset, int aOffset, + boolean uiResource) { + this.uiDefaultParentName = uiDefaultParentName; + this.hOffset = hOffset; + this.sOffset = sOffset; + this.bOffset = bOffset; + this.aOffset = aOffset; + this.uiResource = uiResource; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DerivedColorKey)) return false; + DerivedColorKey that = (DerivedColorKey) o; + if (aOffset != that.aOffset) return false; + if (Float.compare(that.bOffset, bOffset) != 0) return false; + if (Float.compare(that.hOffset, hOffset) != 0) return false; + if (Float.compare(that.sOffset, sOffset) != 0) return false; + if (uiDefaultParentName != null ? + !uiDefaultParentName.equals(that.uiDefaultParentName) : + that.uiDefaultParentName != null) return false; + if (this.uiResource != that.uiResource) return false; + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + uiDefaultParentName.hashCode(); + result = 31 * result + hOffset != +0.0f ? + Float.floatToIntBits(hOffset) : 0; + result = 31 * result + sOffset != +0.0f ? + Float.floatToIntBits(sOffset) : 0; + result = 31 * result + bOffset != +0.0f ? + Float.floatToIntBits(bOffset) : 0; + result = 31 * result + aOffset; + result = 31 * result + (uiResource ? 1 : 0); + return result; + } + } + + /** + * Listener to update derived colors on UIManager Defaults changes + */ + private class DefaultsListener implements PropertyChangeListener { + @Override + public void propertyChange(PropertyChangeEvent evt) { + Object src = evt.getSource(); + String key = evt.getPropertyName(); + if (key.equals("lookAndFeel")){ + // LAF has been installed, this is the first point at which we + // can access our defaults table via UIManager so before now + // all derived colors will be incorrect. + // First we need to update + for (DerivedColor color : derivedColorsMap.values()) { + color.rederiveColor(); + } + } else if (src instanceof DerivedColor && key.equals("rgb")) { + // derived color that is in UIManager defaults has changed + // update all its dependent colors. Don't worry about doing + // this recursively since calling rederiveColor will cause + // another PCE to be fired, ending up here and essentially + // recursing + DerivedColor parentColor = (DerivedColor)src; + String parentKey = null; + Set> entries = + UIManager.getDefaults().entrySet(); + + for (Map.Entry entry : entries) { + Object value = entry.getValue(); + if (value == parentColor) { + parentKey = entry.getKey().toString(); + } + } + + if (parentKey == null) { + //couldn't find the DerivedColor in the UIDefaults map, + //so we just bail. + return; + } + + for (Map.Entry entry : entries) { + Object value = entry.getValue(); + if (value instanceof DerivedColor) { + DerivedColor color = (DerivedColor)entry.getValue(); + if (parentKey.equals(color.getUiDefaultParentName())) { + color.rederiveColor(); + } + } + } + } + } + } + + private static final class PainterBorder implements Border, UIResource { + private Insets insets; + private Painter painter; + private String painterKey; + + PainterBorder(String painterKey, Insets insets) { + this.insets = insets; + this.painterKey = painterKey; + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + if (painter == null) { + painter = (Painter)UIManager.get(painterKey); + if (painter == null) return; + } + + g.translate(x, y); + if (g instanceof Graphics2D) + painter.paint((Graphics2D)g, c, w, h); + else { + BufferedImage img = new BufferedImage(w, h, TYPE_INT_ARGB); + Graphics2D gfx = img.createGraphics(); + painter.paint(gfx, c, w, h); + gfx.dispose(); + g.drawImage(img, x, y, null); + img = null; + } + g.translate(-x, -y); + } + + @Override + public Insets getBorderInsets(Component c) { + return (Insets)insets.clone(); + } + + @Override + public boolean isBorderOpaque() { + return false; + } + } +} + diff --git a/src/share/classes/javax/swing/plaf/nimbus/DerivedColor.java b/src/share/classes/javax/swing/plaf/nimbus/DerivedColor.java new file mode 100644 index 0000000000000000000000000000000000000000..20b7b1aacec0faeddc320c44707baed27dbb870a --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/DerivedColor.java @@ -0,0 +1,215 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import javax.swing.UIManager; +import java.awt.Color; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyChangeListener; + +/** + * DerivedColor - A color implementation that is derived from a UIManager + * defaults table color and a set of offsets. It can be rederived at any point + * by calling rederiveColor(). For example when its parent color changes and it + * value will update to reflect the new derived color. Property change events + * are fired for the "rgb" property when the derived color changes. + * + * @author Jasper Potts + */ +class DerivedColor extends Color { + private final PropertyChangeSupport changeSupport = + new PropertyChangeSupport(this); + private final String uiDefaultParentName; + private final float hOffset, sOffset, bOffset; + private final int aOffset; + private int argbValue; + + DerivedColor(String uiDefaultParentName, float hOffset, float sOffset, float bOffset, int aOffset) { + super(0); + this.uiDefaultParentName = uiDefaultParentName; + this.hOffset = hOffset; + this.sOffset = sOffset; + this.bOffset = bOffset; + this.aOffset = aOffset; + } + + public String getUiDefaultParentName() { + return uiDefaultParentName; + } + + public float getHueOffset() { + return hOffset; + } + + public float getSaturationOffset() { + return sOffset; + } + + public float getBrightnessOffset() { + return bOffset; + } + + public int getAlphaOffset() { + return aOffset; + } + + /** + * Recalculate the derived color from the UIManager parent color and offsets + */ + public void rederiveColor() { + int old = argbValue; + Color src = UIManager.getColor(uiDefaultParentName); + if (src != null) { + float[] tmp = Color.RGBtoHSB(src.getRed(), src.getGreen(), src.getBlue(), null); + // apply offsets + tmp[0] = clamp(tmp[0] + hOffset); + tmp[1] = clamp(tmp[1] + sOffset); + tmp[2] = clamp(tmp[2] + bOffset); + int alpha = clamp(src.getAlpha() + aOffset); + argbValue = (Color.HSBtoRGB(tmp[0], tmp[1], tmp[2]) & 0xFFFFFF) | (alpha << 24); + } else { + float[] tmp = new float[3]; + tmp[0] = clamp(hOffset); + tmp[1] = clamp(sOffset); + tmp[2] = clamp(bOffset); + int alpha = clamp(aOffset); + argbValue = (Color.HSBtoRGB(tmp[0], tmp[1], tmp[2]) & 0xFFFFFF) | (alpha << 24); + } + changeSupport.firePropertyChange("rgb", old, argbValue); + } + + /** + * Returns the RGB value representing the color in the default sRGB {@link java.awt.image.ColorModel}. (Bits 24-31 + * are alpha, 16-23 are red, 8-15 are green, 0-7 are blue). + * + * @return the RGB value of the color in the default sRGB ColorModel. + * @see java.awt.image.ColorModel#getRGBdefault + * @see #getRed + * @see #getGreen + * @see #getBlue + * @since JDK1.0 + */ + @Override public int getRGB() { + return argbValue; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DerivedColor)) return false; + DerivedColor that = (DerivedColor) o; + if (aOffset != that.aOffset) return false; + if (Float.compare(that.bOffset, bOffset) != 0) return false; + if (Float.compare(that.hOffset, hOffset) != 0) return false; + if (Float.compare(that.sOffset, sOffset) != 0) return false; + if (!uiDefaultParentName.equals(that.uiDefaultParentName)) return false; + return true; + } + + @Override + public int hashCode() { + int result = uiDefaultParentName.hashCode(); + result = 31 * result + hOffset != +0.0f ? + Float.floatToIntBits(hOffset) : 0; + result = 31 * result + sOffset != +0.0f ? + Float.floatToIntBits(sOffset) : 0; + result = 31 * result + bOffset != +0.0f ? + Float.floatToIntBits(bOffset) : 0; + result = 31 * result + aOffset; + return result; + } + + /** + * Add a PropertyChangeListener to the listener list. + * The listener is registered for all properties. + * The same listener object may be added more than once, and will be called + * as many times as it is added. + * If listener is null, no exception is thrown and no action + * is taken. + * + * @param listener The PropertyChangeListener to be added + */ + public void addPropertyChangeListener(PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(listener); + } + + /** + * Remove a PropertyChangeListener from the listener list. + * This removes a PropertyChangeListener that was registered + * for all properties. + * If listener was added more than once to the same event + * source, it will be notified one less time after being removed. + * If listener is null, or was never added, no exception is + * thrown and no action is taken. + * + * @param listener The PropertyChangeListener to be removed + */ + public void removePropertyChangeListener(PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(listener); + } + + private float clamp(float value) { + if (value < 0) { + value = 0; + } else if (value > 1) { + value = 1; + } + return value; + } + + private int clamp(int value) { + if (value < 0) { + value = 0; + } else if (value > 255) { + value = 255; + } + return value; + } + + /** + * Returns a string representation of this Color. This method + * is intended to be used only for debugging purposes. The content and + * format of the returned string might vary between implementations. The + * returned string might be empty but cannot be null. + * + * @return a String representation of this Color. + */ + @Override + public String toString() { + Color src = UIManager.getColor(uiDefaultParentName); + String s = "DerivedColor(color=" + getRed() + "," + getGreen() + "," + getBlue() + + " parent=" + uiDefaultParentName + + " offsets=" + getHueOffset() + "," + getSaturationOffset() + "," + + getBrightnessOffset() + "," + getAlphaOffset(); + return src == null ? s : s + " pColor=" + src.getRed() + "," + src.getGreen() + "," + src.getBlue(); + } + + static class UIResource extends DerivedColor implements javax.swing.plaf.UIResource { + UIResource(String uiDefaultParentName, float hOffset, float sOffset, + float bOffset, int aOffset) { + super(uiDefaultParentName, hOffset, sOffset, bOffset, aOffset); + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/DropShadowEffect.java b/src/share/classes/javax/swing/plaf/nimbus/DropShadowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..b97a8e0a50396c48c472b4eedd124571ab97b877 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/DropShadowEffect.java @@ -0,0 +1,128 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.util.Arrays; + +/** + * DropShadowEffect - This effect currently only works with ARGB type buffered + * images. + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +class DropShadowEffect extends ShadowEffect { + + // ================================================================================================================= + // Effect Methods + + /** + * Get the type of this effect, one of UNDER,BLENDED,OVER. UNDER means the result of apply effect should be painted + * under the src image. BLENDED means the result of apply sffect contains a modified src image so just it should be + * painted. OVER means the result of apply effect should be painted over the src image. + * + * @return The effect type + */ + @Override + EffectType getEffectType() { + return EffectType.UNDER; + } + + /** + * Apply the effect to the src image generating the result . The result image may or may not contain the source + * image depending on what the effect type is. + * + * @param src The source image for applying the effect to + * @param dst The destination image to paint effect result into. If this is null then a new image will be created + * @param w The width of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @param h The height of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @return Image with the result of the effect + */ + @Override + BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h) { + if (src == null || src.getType() != BufferedImage.TYPE_INT_ARGB){ + throw new IllegalArgumentException("Effect only works with " + + "source images of type BufferedImage.TYPE_INT_ARGB."); + } + if (dst != null && dst.getType() != BufferedImage.TYPE_INT_ARGB){ + throw new IllegalArgumentException("Effect only works with " + + "destination images of type BufferedImage.TYPE_INT_ARGB."); + } + // calculate offset + double trangleAngle = Math.toRadians(angle - 90); + int offsetX = (int) (Math.sin(trangleAngle) * distance); + int offsetY = (int) (Math.cos(trangleAngle) * distance); + // clac expanded size + int tmpOffX = offsetX + size; + int tmpOffY = offsetX + size; + int tmpW = w + offsetX + size + size; + int tmpH = h + offsetX + size; + // create tmp buffers + int[] lineBuf = getArrayCache().getTmpIntArray(w); + byte[] tmpBuf1 = getArrayCache().getTmpByteArray1(tmpW * tmpH); + Arrays.fill(tmpBuf1, (byte) 0x00); + byte[] tmpBuf2 = getArrayCache().getTmpByteArray2(tmpW * tmpH); + // extract src image alpha channel and inverse and offset + Raster srcRaster = src.getRaster(); + for (int y = 0; y < h; y++) { + int dy = (y + tmpOffY); + int offset = dy * tmpW; + srcRaster.getDataElements(0, y, w, 1, lineBuf); + for (int x = 0; x < w; x++) { + int dx = x + tmpOffX; + tmpBuf1[offset + dx] = (byte) ((lineBuf[x] & 0xFF000000) >>> 24); + } + } + // blur + float[] kernel = EffectUtils.createGaussianKernel(size); + EffectUtils.blur(tmpBuf1, tmpBuf2, tmpW, tmpH, kernel, size); // horizontal pass + EffectUtils.blur(tmpBuf2, tmpBuf1, tmpH, tmpW, kernel, size);// vertical pass + //rescale + float spread = Math.min(1 / (1 - (0.01f * this.spread)), 255); + for (int i = 0; i < tmpBuf1.length; i++) { + int val = (int) (((int) tmpBuf1[i] & 0xFF) * spread); + tmpBuf1[i] = (val > 255) ? (byte) 0xFF : (byte) val; + } + // create color image with shadow color and greyscale image as alpha + if (dst == null) dst = new BufferedImage(w, h, + BufferedImage.TYPE_INT_ARGB); + WritableRaster shadowRaster = dst.getRaster(); + int red = color.getRed(), green = color.getGreen(), blue = color.getBlue(); + for (int y = 0; y < h; y++) { + int srcY = y + tmpOffY; + int shadowOffset = (srcY - offsetY) * tmpW; + for (int x = 0; x < w; x++) { + int srcX = x + tmpOffX; + lineBuf[x] = tmpBuf1[shadowOffset + (srcX - offsetX)] << 24 | red << 16 | green << 8 | blue; + } + shadowRaster.setDataElements(0, y, w, 1, lineBuf); + } + return dst; + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/Effect.java b/src/share/classes/javax/swing/plaf/nimbus/Effect.java new file mode 100644 index 0000000000000000000000000000000000000000..8588ef81b5d74043c64ec3513391387ecdea1410 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/Effect.java @@ -0,0 +1,133 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import sun.awt.AppContext; + +import java.awt.image.BufferedImage; +import java.lang.ref.SoftReference; + +/** + * Effect + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +abstract class Effect { + enum EffectType { + UNDER, BLENDED, OVER + } + + // ================================================================================================================= + // Abstract Methods + + /** + * Get the type of this effect, one of UNDER,BLENDED,OVER. UNDER means the result of apply effect should be painted + * under the src image. BLENDED means the result of apply sffect contains a modified src image so just it should be + * painted. OVER means the result of apply effect should be painted over the src image. + * + * @return The effect type + */ + abstract EffectType getEffectType(); + + /** + * Get the opacity to use to paint the result effected image if the EffectType is UNDER or OVER. + * + * @return The opactity for the effect, 0.0f -> 1.0f + */ + abstract float getOpacity(); + + /** + * Apply the effect to the src image generating the result . The result image may or may not contain the source + * image depending on what the effect type is. + * + * @param src The source image for applying the effect to + * @param dst The dstination image to paint effect result into. If this is null then a new image will be created + * @param w The width of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @param h The height of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @return The result of appl + */ + abstract BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h); + + // ================================================================================================================= + // Static data cache + + protected static ArrayCache getArrayCache() { + ArrayCache cache = (ArrayCache)AppContext.getAppContext().get(ArrayCache.class); + if (cache == null){ + cache = new ArrayCache(); + AppContext.getAppContext().put(ArrayCache.class,cache); + } + return cache; + } + + protected static class ArrayCache { + private SoftReference tmpIntArray = null; + private SoftReference tmpByteArray1 = null; + private SoftReference tmpByteArray2 = null; + private SoftReference tmpByteArray3 = null; + + protected int[] getTmpIntArray(int size) { + int[] tmp; + if (tmpIntArray == null || (tmp = tmpIntArray.get()) == null || tmp.length < size) { + // create new array + tmp = new int[size]; + tmpIntArray = new SoftReference(tmp); + } + return tmp; + } + + protected byte[] getTmpByteArray1(int size) { + byte[] tmp; + if (tmpByteArray1 == null || (tmp = tmpByteArray1.get()) == null || tmp.length < size) { + // create new array + tmp = new byte[size]; + tmpByteArray1 = new SoftReference(tmp); + } + return tmp; + } + + protected byte[] getTmpByteArray2(int size) { + byte[] tmp; + if (tmpByteArray2 == null || (tmp = tmpByteArray2.get()) == null || tmp.length < size) { + // create new array + tmp = new byte[size]; + tmpByteArray2 = new SoftReference(tmp); + } + return tmp; + } + + protected byte[] getTmpByteArray3(int size) { + byte[] tmp; + if (tmpByteArray3 == null || (tmp = tmpByteArray3.get()) == null || tmp.length < size) { + // create new array + tmp = new byte[size]; + tmpByteArray3 = new SoftReference(tmp); + } + return tmp; + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/EffectUtils.java b/src/share/classes/javax/swing/plaf/nimbus/EffectUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..94b4a12e7a27119db774f7a4aaca1e7336daf9ba --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/EffectUtils.java @@ -0,0 +1,426 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.AlphaComposite; +import java.awt.Graphics2D; +import java.awt.Transparency; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.ColorModel; + +/** + * EffectUtils + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +class EffectUtils { + + /** + * Clear a transparent image to 100% transparent + * + * @param img The image to clear + */ + static void clearImage(BufferedImage img) { + Graphics2D g2 = img.createGraphics(); + g2.setComposite(AlphaComposite.Clear); + g2.fillRect(0, 0, img.getWidth(), img.getHeight()); + g2.dispose(); + } + + // ================================================================================================================= + // Blur + + /** + * Apply Gaussian Blur to Image + * + * @param src The image tp + * @param dst The destination image to draw blured src image into, null if you want a new one created + * @param radius The blur kernel radius + * @return The blured image + */ + static BufferedImage gaussianBlur(BufferedImage src, BufferedImage dst, int radius) { + int width = src.getWidth(); + int height = src.getHeight(); + if (dst == null || dst.getWidth() != width || dst.getHeight() != height || src.getType() != dst.getType()) { + dst = createColorModelCompatibleImage(src); + } + float[] kernel = createGaussianKernel(radius); + if (src.getType() == BufferedImage.TYPE_INT_ARGB) { + int[] srcPixels = new int[width * height]; + int[] dstPixels = new int[width * height]; + getPixels(src, 0, 0, width, height, srcPixels); + // horizontal pass + blur(srcPixels, dstPixels, width, height, kernel, radius); + // vertical pass + //noinspection SuspiciousNameCombination + blur(dstPixels, srcPixels, height, width, kernel, radius); + // the result is now stored in srcPixels due to the 2nd pass + setPixels(dst, 0, 0, width, height, srcPixels); + } else if (src.getType() == BufferedImage.TYPE_BYTE_GRAY) { + byte[] srcPixels = new byte[width * height]; + byte[] dstPixels = new byte[width * height]; + getPixels(src, 0, 0, width, height, srcPixels); + // horizontal pass + blur(srcPixels, dstPixels, width, height, kernel, radius); + // vertical pass + //noinspection SuspiciousNameCombination + blur(dstPixels, srcPixels, height, width, kernel, radius); + // the result is now stored in srcPixels due to the 2nd pass + setPixels(dst, 0, 0, width, height, srcPixels); + } else { + throw new IllegalArgumentException("EffectUtils.gaussianBlur() src image is not a supported type, type=[" + + src.getType() + "]"); + } + return dst; + } + + /** + *

Blurs the source pixels into the destination pixels. The force of the blur is specified by the radius which + * must be greater than 0.

The source and destination pixels arrays are expected to be in the INT_ARGB + * format.

After this method is executed, dstPixels contains a transposed and filtered copy of + * srcPixels.

+ * + * @param srcPixels the source pixels + * @param dstPixels the destination pixels + * @param width the width of the source picture + * @param height the height of the source picture + * @param kernel the kernel of the blur effect + * @param radius the radius of the blur effect + */ + private static void blur(int[] srcPixels, int[] dstPixels, + int width, int height, + float[] kernel, int radius) { + float a; + float r; + float g; + float b; + + int ca; + int cr; + int cg; + int cb; + + for (int y = 0; y < height; y++) { + int index = y; + int offset = y * width; + + for (int x = 0; x < width; x++) { + a = r = g = b = 0.0f; + + for (int i = -radius; i <= radius; i++) { + int subOffset = x + i; + if (subOffset < 0 || subOffset >= width) { + subOffset = (x + width) % width; + } + + int pixel = srcPixels[offset + subOffset]; + float blurFactor = kernel[radius + i]; + + a += blurFactor * ((pixel >> 24) & 0xFF); + r += blurFactor * ((pixel >> 16) & 0xFF); + g += blurFactor * ((pixel >> 8) & 0xFF); + b += blurFactor * ((pixel) & 0xFF); + } + + ca = (int) (a + 0.5f); + cr = (int) (r + 0.5f); + cg = (int) (g + 0.5f); + cb = (int) (b + 0.5f); + + dstPixels[index] = ((ca > 255 ? 255 : ca) << 24) | + ((cr > 255 ? 255 : cr) << 16) | + ((cg > 255 ? 255 : cg) << 8) | + (cb > 255 ? 255 : cb); + index += height; + } + } + } + + /** + *

Blurs the source pixels into the destination pixels. The force of the blur is specified by the radius which + * must be greater than 0.

The source and destination pixels arrays are expected to be in the BYTE_GREY + * format.

After this method is executed, dstPixels contains a transposed and filtered copy of + * srcPixels.

+ * + * @param srcPixels the source pixels + * @param dstPixels the destination pixels + * @param width the width of the source picture + * @param height the height of the source picture + * @param kernel the kernel of the blur effect + * @param radius the radius of the blur effect + */ + static void blur(byte[] srcPixels, byte[] dstPixels, + int width, int height, + float[] kernel, int radius) { + float p; + int cp; + for (int y = 0; y < height; y++) { + int index = y; + int offset = y * width; + for (int x = 0; x < width; x++) { + p = 0.0f; + for (int i = -radius; i <= radius; i++) { + int subOffset = x + i; +// if (subOffset < 0) subOffset = 0; +// if (subOffset >= width) subOffset = width-1; + if (subOffset < 0 || subOffset >= width) { + subOffset = (x + width) % width; + } + int pixel = srcPixels[offset + subOffset] & 0xFF; + float blurFactor = kernel[radius + i]; + p += blurFactor * pixel; + } + cp = (int) (p + 0.5f); + dstPixels[index] = (byte) (cp > 255 ? 255 : cp); + index += height; + } + } + } + + static float[] createGaussianKernel(int radius) { + if (radius < 1) { + throw new IllegalArgumentException("Radius must be >= 1"); + } + + float[] data = new float[radius * 2 + 1]; + + float sigma = radius / 3.0f; + float twoSigmaSquare = 2.0f * sigma * sigma; + float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI); + float total = 0.0f; + + for (int i = -radius; i <= radius; i++) { + float distance = i * i; + int index = i + radius; + data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot; + total += data[index]; + } + + for (int i = 0; i < data.length; i++) { + data[i] /= total; + } + + return data; + } + + // ================================================================================================================= + // Get/Set Pixels helper methods + + /** + *

Returns an array of pixels, stored as integers, from a BufferedImage. The pixels are grabbed from + * a rectangular area defined by a location and two dimensions. Calling this method on an image of type different + * from BufferedImage.TYPE_INT_ARGB and BufferedImage.TYPE_INT_RGB will unmanage the + * image.

+ * + * @param img the source image + * @param x the x location at which to start grabbing pixels + * @param y the y location at which to start grabbing pixels + * @param w the width of the rectangle of pixels to grab + * @param h the height of the rectangle of pixels to grab + * @param pixels a pre-allocated array of pixels of size w*h; can be null + * @return pixels if non-null, a new array of integers otherwise + * @throws IllegalArgumentException is pixels is non-null and of length < w*h + */ + static byte[] getPixels(BufferedImage img, + int x, int y, int w, int h, byte[] pixels) { + if (w == 0 || h == 0) { + return new byte[0]; + } + + if (pixels == null) { + pixels = new byte[w * h]; + } else if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length >= w*h"); + } + + int imageType = img.getType(); + if (imageType == BufferedImage.TYPE_BYTE_GRAY) { + Raster raster = img.getRaster(); + return (byte[]) raster.getDataElements(x, y, w, h, pixels); + } else { + throw new IllegalArgumentException("Only type BYTE_GRAY is supported"); + } + } + + /** + *

Writes a rectangular area of pixels in the destination BufferedImage. Calling this method on an + * image of type different from BufferedImage.TYPE_INT_ARGB and BufferedImage.TYPE_INT_RGB + * will unmanage the image.

+ * + * @param img the destination image + * @param x the x location at which to start storing pixels + * @param y the y location at which to start storing pixels + * @param w the width of the rectangle of pixels to store + * @param h the height of the rectangle of pixels to store + * @param pixels an array of pixels, stored as integers + * @throws IllegalArgumentException is pixels is non-null and of length < w*h + */ + static void setPixels(BufferedImage img, + int x, int y, int w, int h, byte[] pixels) { + if (pixels == null || w == 0 || h == 0) { + return; + } else if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length >= w*h"); + } + int imageType = img.getType(); + if (imageType == BufferedImage.TYPE_BYTE_GRAY) { + WritableRaster raster = img.getRaster(); + raster.setDataElements(x, y, w, h, pixels); + } else { + throw new IllegalArgumentException("Only type BYTE_GRAY is supported"); + } + } + + /** + *

Returns an array of pixels, stored as integers, from a + * BufferedImage. The pixels are grabbed from a rectangular + * area defined by a location and two dimensions. Calling this method on + * an image of type different from BufferedImage.TYPE_INT_ARGB + * and BufferedImage.TYPE_INT_RGB will unmanage the image.

+ * + * @param img the source image + * @param x the x location at which to start grabbing pixels + * @param y the y location at which to start grabbing pixels + * @param w the width of the rectangle of pixels to grab + * @param h the height of the rectangle of pixels to grab + * @param pixels a pre-allocated array of pixels of size w*h; can be null + * @return pixels if non-null, a new array of integers + * otherwise + * @throws IllegalArgumentException is pixels is non-null and + * of length < w*h + */ + public static int[] getPixels(BufferedImage img, + int x, int y, int w, int h, int[] pixels) { + if (w == 0 || h == 0) { + return new int[0]; + } + + if (pixels == null) { + pixels = new int[w * h]; + } else if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length" + + " >= w*h"); + } + + int imageType = img.getType(); + if (imageType == BufferedImage.TYPE_INT_ARGB || + imageType == BufferedImage.TYPE_INT_RGB) { + Raster raster = img.getRaster(); + return (int[]) raster.getDataElements(x, y, w, h, pixels); + } + + // Unmanages the image + return img.getRGB(x, y, w, h, pixels, 0, w); + } + + /** + *

Writes a rectangular area of pixels in the destination + * BufferedImage. Calling this method on + * an image of type different from BufferedImage.TYPE_INT_ARGB + * and BufferedImage.TYPE_INT_RGB will unmanage the image.

+ * + * @param img the destination image + * @param x the x location at which to start storing pixels + * @param y the y location at which to start storing pixels + * @param w the width of the rectangle of pixels to store + * @param h the height of the rectangle of pixels to store + * @param pixels an array of pixels, stored as integers + * @throws IllegalArgumentException is pixels is non-null and + * of length < w*h + */ + public static void setPixels(BufferedImage img, + int x, int y, int w, int h, int[] pixels) { + if (pixels == null || w == 0 || h == 0) { + return; + } else if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length" + + " >= w*h"); + } + + int imageType = img.getType(); + if (imageType == BufferedImage.TYPE_INT_ARGB || + imageType == BufferedImage.TYPE_INT_RGB) { + WritableRaster raster = img.getRaster(); + raster.setDataElements(x, y, w, h, pixels); + } else { + // Unmanages the image + img.setRGB(x, y, w, h, pixels, 0, w); + } + } + + /** + *

Returns a new BufferedImage using the same color model + * as the image passed as a parameter. The returned image is only compatible + * with the image passed as a parameter. This does not mean the returned + * image is compatible with the hardware.

+ * + * @param image the reference image from which the color model of the new + * image is obtained + * @return a new BufferedImage, compatible with the color model + * of image + */ + public static BufferedImage createColorModelCompatibleImage(BufferedImage image) { + ColorModel cm = image.getColorModel(); + return new BufferedImage(cm, + cm.createCompatibleWritableRaster(image.getWidth(), + image.getHeight()), + cm.isAlphaPremultiplied(), null); + } + + /** + *

Returns a new translucent compatible image of the specified width and + * height. That is, the returned BufferedImage is compatible with + * the graphics hardware. If the method is called in a headless + * environment, then the returned BufferedImage will be compatible with + * the source image.

+ * + * @param width the width of the new image + * @param height the height of the new image + * @return a new translucent compatible BufferedImage of the + * specified width and height + */ + public static BufferedImage createCompatibleTranslucentImage(int width, + int height) { + return isHeadless() ? + new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) : + getGraphicsConfiguration().createCompatibleImage(width, height, + Transparency.TRANSLUCENT); + } + + private static boolean isHeadless() { + return GraphicsEnvironment.isHeadless(); + } + + // Returns the graphics configuration for the primary screen + private static GraphicsConfiguration getGraphicsConfiguration() { + return GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/ImageCache.java b/src/share/classes/javax/swing/plaf/nimbus/ImageCache.java new file mode 100644 index 0000000000000000000000000000000000000000..abd345820b7d26f4b2ebf2af93405cc2c927da90 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/ImageCache.java @@ -0,0 +1,217 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary set of arguments. All images are held with + * SoftReferences so they will be dropped by the GC if heap memory gets tight. When our size hits max pixel count least + * recently requested images are removed first. + * + * @author Created by Jasper Potts (Aug 7, 2007) + */ +class ImageCache { + // Ordered Map keyed by args hash, ordered by most recent accessed entry. + private final LinkedHashMap map = + new LinkedHashMap(16, 0.75f, true); + // Maximum number of pixels to cache, this is used if maxCount + private final int maxPixelCount; + // Maximum cached image size in pxiels + private final int maxSingleImagePixelSize; + // The current number of pixels stored in the cache + private int currentPixelCount = 0; + // Lock for concurrent access to map + private ReadWriteLock lock = new ReentrantReadWriteLock(); + // Reference queue for tracking lost softreferences to images in the cache + private ReferenceQueue referenceQueue = new ReferenceQueue(); + // Singleton Instance + private static final ImageCache instance = new ImageCache(); + + + /** Get static singleton instance */ + static ImageCache getInstance() { + return instance; + } + + public ImageCache() { + this.maxPixelCount = (8 * 1024 * 1024) / 4; // 8Mb of pixels + this.maxSingleImagePixelSize = 300 * 300; + } + + public ImageCache(int maxPixelCount, int maxSingleImagePixelSize) { + this.maxPixelCount = maxPixelCount; + this.maxSingleImagePixelSize = maxSingleImagePixelSize; + } + + /** Clear the cache */ + public void flush() { + lock.readLock().lock(); + try { + map.clear(); + } finally { + lock.readLock().unlock(); + } + } + + /** + * Check if the image size is to big to be stored in the cache + * + * @param w The image width + * @param h The image height + * @return True if the image size is less than max + */ + public boolean isImageCachable(int w, int h) { + return (w * h) < maxSingleImagePixelSize; + } + + /** + * Get the cached image for given keys + * + * @param config The graphics configuration, needed if cached image is a Volatile Image. Used as part of cache key + * @param w The image width, used as part of cache key + * @param h The image height, used as part of cache key + * @param args Other arguments to use as part of the cache key + * @return Returns the cached Image, or null there is no cached image for key + */ + public Image getImage(GraphicsConfiguration config, int w, int h, Object... args) { + lock.readLock().lock(); + try { + PixelCountSoftReference ref = map.get(hash(config, w, h, args)); + // check reference has not been lost and the key truly matches, in case of false positive hash match + if (ref != null && ref.equals(config,w, h, args)) { + return ref.get(); + } else { + return null; + } + } finally { + lock.readLock().unlock(); + } + } + + /** + * Sets the cached image for the specified constraints. + * + * @param image The image to store in cache + * @param config The graphics configuration, needed if cached image is a Volatile Image. Used as part of cache key + * @param w The image width, used as part of cache key + * @param h The image height, used as part of cache key + * @param args Other arguments to use as part of the cache key + * @return true if the image could be cached or false if the image is too big + */ + public boolean setImage(Image image, GraphicsConfiguration config, int w, int h, Object... args) { + if (!isImageCachable(w, h)) return false; + int hash = hash(config, w, h, args); + lock.writeLock().lock(); + try { + PixelCountSoftReference ref = map.get(hash); + // check if currently in map + if (ref != null && ref.get() == image) { + return true; + } + // clear out old + if (ref != null) { + currentPixelCount -= ref.pixelCount; + map.remove(hash); + } + // add new image to pixel count + int newPixelCount = image.getWidth(null) * image.getHeight(null); + currentPixelCount += newPixelCount; + // clean out lost references if not enough space + if (currentPixelCount > maxPixelCount) { + while ((ref = (PixelCountSoftReference)referenceQueue.poll()) != null){ + //reference lost + map.remove(ref.hash); + currentPixelCount -= ref.pixelCount; + } + } + // remove old items till there is enough free space + if (currentPixelCount > maxPixelCount) { + Iterator> mapIter = map.entrySet().iterator(); + while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) { + Map.Entry entry = mapIter.next(); + mapIter.remove(); + Image img = entry.getValue().get(); + if (img != null) img.flush(); + currentPixelCount -= entry.getValue().pixelCount; + } + } + // finaly put new in map + map.put(hash, new PixelCountSoftReference(image, referenceQueue, newPixelCount,hash, config, w, h, args)); + return true; + } finally { + lock.writeLock().unlock(); + } + } + + /** Create a unique hash from all the input */ + private int hash(GraphicsConfiguration config, int w, int h, Object ... args) { + int hash; + hash = (config != null ? config.hashCode() : 0); + hash = 31 * hash + w; + hash = 31 * hash + h; + hash = 31 * hash + Arrays.deepHashCode(args); + return hash; + } + + + /** Extended SoftReference that stores the pixel count even after the image is lost */ + private static class PixelCountSoftReference extends SoftReference { + private final int pixelCount; + private final int hash; + // key parts + private final GraphicsConfiguration config; + private final int w; + private final int h; + private final Object[] args; + + public PixelCountSoftReference(Image referent, ReferenceQueue q, int pixelCount, int hash, + GraphicsConfiguration config, int w, int h, Object[] args) { + super(referent, q); + this.pixelCount = pixelCount; + this.hash = hash; + this.config = config; + this.w = w; + this.h = h; + this.args = args; + } + + public boolean equals (GraphicsConfiguration config, int w, int h, Object[] args){ + return config == this.config && + w == this.w && + h == this.h && + Arrays.equals(args, this.args); + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/ImageScalingHelper.java b/src/share/classes/javax/swing/plaf/nimbus/ImageScalingHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..a6f6f51afe8dd973877024730f7803ade4eb0a9c --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/ImageScalingHelper.java @@ -0,0 +1,280 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; + +/** + * ImageScalingHelper + * + * @author Created by Jasper Potts (Aug 8, 2007) + */ +class ImageScalingHelper { + + /** Enumeration for the types of painting this class can handle. */ + enum PaintType { + /** + * Painting type indicating the image should be centered in the space provided. When used the mask + * is ignored. + */ + CENTER, + + /** + * Painting type indicating the image should be tiled across the specified width and height. When used the + * mask is ignored. + */ + TILE, + + /** + * Painting type indicating the image should be split into nine regions with the top, left, bottom and right + * areas stretched. + */ + PAINT9_STRETCH, + + /** + * Painting type indicating the image should be split into nine regions with the top, left, bottom and right + * areas tiled. + */ + PAINT9_TILE + } + + ; + + private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); + + static final int PAINT_TOP_LEFT = 1; + static final int PAINT_TOP = 2; + static final int PAINT_TOP_RIGHT = 4; + static final int PAINT_LEFT = 8; + static final int PAINT_CENTER = 16; + static final int PAINT_RIGHT = 32; + static final int PAINT_BOTTOM_RIGHT = 64; + static final int PAINT_BOTTOM = 128; + static final int PAINT_BOTTOM_LEFT = 256; + /** + * Specifies that all regions should be painted. If this is set any other regions specified will not be painted. + * For example PAINT_ALL | PAINT_CENTER will paint all but the center. + */ + static final int PAINT_ALL = 512; + + /** + * Paints using the algorightm specified by paintType. + * + * @param g Graphics to render to + * @param x X-coordinate + * @param y Y-coordinate + * @param w Width to render to + * @param h Height to render to + * @param image Image to render from, if null this method will do nothing + * @param sInsets Insets specifying the portion of the image that will be stretched or tiled, if null + * empty Insets will be used. + * @param dInsets Destination insets specifying the portion of the image will be stretched or tiled, if + * null empty Insets will be used. + * @param paintType Specifies what type of algorithm to use in painting + * @param mask Specifies portion of image to render, if PAINT_ALL is specified, any other regions + * specified will not be painted, for example PAINT_ALL | PAINT_CENTER paints everything but the + * center. + */ + public static void paint(Graphics g, int x, int y, int w, int h, + Image image, Insets sInsets, + Insets dInsets, PaintType paintType, int mask) { + if (image == null || image.getWidth(null) <= 0 || image.getHeight(null) <= 0) { + return; + } + if (sInsets == null) { + sInsets = EMPTY_INSETS; + } + if (dInsets == null) { + dInsets = EMPTY_INSETS; + } + int iw = image.getWidth(null); + int ih = image.getHeight(null); + + if (paintType == PaintType.CENTER) { + // Center the image + g.drawImage(image, x + (w - iw) / 2, + y + (h - ih) / 2, null); + } else if (paintType == PaintType.TILE) { + // Tile the image + int lastIY = 0; + for (int yCounter = y, maxY = y + h; yCounter < maxY; + yCounter += (ih - lastIY), lastIY = 0) { + int lastIX = 0; + for (int xCounter = x, maxX = x + w; xCounter < maxX; + xCounter += (iw - lastIX), lastIX = 0) { + int dx2 = Math.min(maxX, xCounter + iw - lastIX); + int dy2 = Math.min(maxY, yCounter + ih - lastIY); + g.drawImage(image, xCounter, yCounter, dx2, dy2, + lastIX, lastIY, lastIX + dx2 - xCounter, + lastIY + dy2 - yCounter, null); + } + } + } else { + int st = sInsets.top; + int sl = sInsets.left; + int sb = sInsets.bottom; + int sr = sInsets.right; + + int dt = dInsets.top; + int dl = dInsets.left; + int db = dInsets.bottom; + int dr = dInsets.right; + + // Constrain the insets to the size of the image + if (st + sb > ih) { + db = dt = sb = st = Math.max(0, ih / 2); + } + if (sl + sr > iw) { + dl = dr = sl = sr = Math.max(0, iw / 2); + } + + // Constrain the insets to the size of the region we're painting + // in. + if (dt + db > h) { + dt = db = Math.max(0, h / 2 - 1); + } + if (dl + dr > w) { + dl = dr = Math.max(0, w / 2 - 1); + } + + boolean stretch = (paintType == PaintType.PAINT9_STRETCH); + if ((mask & PAINT_ALL) != 0) { + mask = (PAINT_ALL - 1) & ~mask; + } + + if ((mask & PAINT_LEFT) != 0) { + drawChunk(image, g, stretch, x, y + dt, x + dl, y + h - db, + 0, st, sl, ih - sb, false); + } + if ((mask & PAINT_TOP_LEFT) != 0) { + drawImage(image, g, x, y, x + dl, y + dt, + 0, 0, sl, st); + } + if ((mask & PAINT_TOP) != 0) { + drawChunk(image, g, stretch, x + dl, y, x + w - dr, y + dt, + sl, 0, iw - sr, st, true); + } + if ((mask & PAINT_TOP_RIGHT) != 0) { + drawImage(image, g, x + w - dr, y, x + w, y + dt, + iw - sr, 0, iw, st); + } + if ((mask & PAINT_RIGHT) != 0) { + drawChunk(image, g, stretch, + x + w - dr, y + dt, x + w, y + h - db, + iw - sr, st, iw, ih - sb, false); + } + if ((mask & PAINT_BOTTOM_RIGHT) != 0) { + drawImage(image, g, x + w - dr, y + h - db, x + w, y + h, + iw - sr, ih - sb, iw, ih); + } + if ((mask & PAINT_BOTTOM) != 0) { + drawChunk(image, g, stretch, + x + dl, y + h - db, x + w - dr, y + h, + sl, ih - sb, iw - sr, ih, true); + } + if ((mask & PAINT_BOTTOM_LEFT) != 0) { + drawImage(image, g, x, y + h - db, x + dl, y + h, + 0, ih - sb, sl, ih); + } + if ((mask & PAINT_CENTER) != 0) { + drawImage(image, g, x + dl, y + dt, x + w - dr, y + h - db, + sl, st, iw - sr, ih - sb); + } + } + } + + /** + * Draws a portion of an image, stretched or tiled. + * + * @param image Image to render. + * @param g Graphics to render to + * @param stretch Whether the image should be stretched or timed in the + * provided space. + * @param dx1 X origin to draw to + * @param dy1 Y origin to draw to + * @param dx2 End x location to draw to + * @param dy2 End y location to draw to + * @param sx1 X origin to draw from + * @param sy1 Y origin to draw from + * @param sx2 Max x location to draw from + * @param sy2 Max y location to draw from + * @param xDirection Used if the image is not stretched. If true it + * indicates the image should be tiled along the x axis. + */ + private static void drawChunk(Image image, Graphics g, boolean stretch, + int dx1, int dy1, int dx2, int dy2, int sx1, + int sy1, int sx2, int sy2, + boolean xDirection) { + if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0 || sx2 - sx1 <= 0 || + sy2 - sy1 <= 0) { + // Bogus location, nothing to paint + return; + } + if (stretch) { + g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null); + } + else { + int xSize = sx2 - sx1; + int ySize = sy2 - sy1; + int deltaX; + int deltaY; + + if (xDirection) { + deltaX = xSize; + deltaY = 0; + } + else { + deltaX = 0; + deltaY = ySize; + } + while (dx1 < dx2 && dy1 < dy2) { + int newDX2 = Math.min(dx2, dx1 + xSize); + int newDY2 = Math.min(dy2, dy1 + ySize); + + g.drawImage(image, dx1, dy1, newDX2, newDY2, + sx1, sy1, sx1 + newDX2 - dx1, + sy1 + newDY2 - dy1, null); + dx1 += deltaX; + dy1 += deltaY; + } + } + } + + private static void drawImage(Image image, Graphics g, + int dx1, int dy1, int dx2, int dy2, int sx1, + int sy1, int sx2, int sy2) { + // PENDING: is this necessary, will G2D do it for me? + if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0 || sx2 - sx1 <= 0 || + sy2 - sy1 <= 0) { + // Bogus location, nothing to paint + return; + } + g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null); + } + + +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/InnerGlowEffect.java b/src/share/classes/javax/swing/plaf/nimbus/InnerGlowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..3847c9f27f110e04db4f855e125026d0f5d080f3 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/InnerGlowEffect.java @@ -0,0 +1,39 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.Color; + +/** + * InnerGlowEffect + * + * @author Created by Jasper Potts (Jun 21, 2007) + */ +class InnerGlowEffect extends InnerShadowEffect { + InnerGlowEffect() { + distance = 0; + color = new Color(255, 255, 211); + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/InnerShadowEffect.java b/src/share/classes/javax/swing/plaf/nimbus/InnerShadowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..c578c1e529562cd67aa28d73f9494ab8f7e063c4 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/InnerShadowEffect.java @@ -0,0 +1,131 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.util.Arrays; + +/** + * InnerShadowEffect - This effect currently only works with ARGB type buffered + * images. + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +class InnerShadowEffect extends ShadowEffect { + + // ================================================================================================================= + // Effect Methods + + /** + * Get the type of this effect, one of UNDER,BLENDED,OVER. UNDER means the result of apply effect should be painted + * under the src image. BLENDED means the result of apply sffect contains a modified src image so just it should be + * painted. OVER means the result of apply effect should be painted over the src image. + * + * @return The effect type + */ + Effect.EffectType getEffectType() { + return Effect.EffectType.OVER; + } + + /** + * Apply the effect to the src image generating the result . The result image may or may not contain the source + * image depending on what the effect type is. + * + * @param src The source image for applying the effect to + * @param dst The dstination image to paint effect result into. If this is null then a new image will be created + * @param w The width of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @param h The height of the src image to apply effect to, this allow the src and dst buffers to be bigger than + * the area the need effect applied to it + * @return Image with the result of the effect + */ + BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h) { + if (src == null || src.getType() != BufferedImage.TYPE_INT_ARGB){ + throw new IllegalArgumentException("Effect only works with " + + "source images of type BufferedImage.TYPE_INT_ARGB."); + } + if (dst != null && dst.getType() != BufferedImage.TYPE_INT_ARGB){ + throw new IllegalArgumentException("Effect only works with " + + "destination images of type BufferedImage.TYPE_INT_ARGB."); + } + // calculate offset + double trangleAngle = Math.toRadians(angle - 90); + int offsetX = (int) (Math.sin(trangleAngle) * distance); + int offsetY = (int) (Math.cos(trangleAngle) * distance); + // clac expanded size + int tmpOffX = offsetX + size; + int tmpOffY = offsetX + size; + int tmpW = w + offsetX + size + size; + int tmpH = h + offsetX + size; + // create tmp buffers + int[] lineBuf = getArrayCache().getTmpIntArray(w); + byte[] srcAlphaBuf = getArrayCache().getTmpByteArray1(tmpW * tmpH); + Arrays.fill(srcAlphaBuf, (byte) 0xFF); + byte[] tmpBuf1 = getArrayCache().getTmpByteArray2(tmpW * tmpH); + byte[] tmpBuf2 = getArrayCache().getTmpByteArray3(tmpW * tmpH); + // extract src image alpha channel and inverse and offset + Raster srcRaster = src.getRaster(); + for (int y = 0; y < h; y++) { + int dy = (y + tmpOffY); + int offset = dy * tmpW; + srcRaster.getDataElements(0, y, w, 1, lineBuf); + for (int x = 0; x < w; x++) { + int dx = x + tmpOffX; + srcAlphaBuf[offset + dx] = (byte) ((255 - ((lineBuf[x] & 0xFF000000) >>> 24)) & 0xFF); + } + } + // blur + float[] kernel = EffectUtils.createGaussianKernel(size * 2); + EffectUtils.blur(srcAlphaBuf, tmpBuf2, tmpW, tmpH, kernel, size * 2); // horizontal pass + EffectUtils.blur(tmpBuf2, tmpBuf1, tmpH, tmpW, kernel, size * 2);// vertical pass + //rescale + float spread = Math.min(1 / (1 - (0.01f * this.spread)), 255); + for (int i = 0; i < tmpBuf1.length; i++) { + int val = (int) (((int) tmpBuf1[i] & 0xFF) * spread); + tmpBuf1[i] = (val > 255) ? (byte) 0xFF : (byte) val; + } + // create color image with shadow color and greyscale image as alpha + if (dst == null) dst = new BufferedImage(w, h, + BufferedImage.TYPE_INT_ARGB); + WritableRaster shadowRaster = dst.getRaster(); + int red = color.getRed(), green = color.getGreen(), blue = color.getBlue(); + for (int y = 0; y < h; y++) { + int srcY = y + tmpOffY; + int offset = srcY * tmpW; + int shadowOffset = (srcY - offsetY) * tmpW; + for (int x = 0; x < w; x++) { + int srcX = x + tmpOffX; + int origianlAlphaVal = 255 - ((int) srcAlphaBuf[offset + srcX] & 0xFF); + int shadowVal = (int) tmpBuf1[shadowOffset + (srcX - offsetX)] & 0xFF; + int alphaVal = Math.min(origianlAlphaVal, shadowVal); + lineBuf[x] = ((byte) alphaVal & 0xFF) << 24 | red << 16 | green << 8 | blue; + } + shadowRaster.setDataElements(0, y, w, 1, lineBuf); + } + return dst; + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/LoweredBorder.java b/src/share/classes/javax/swing/plaf/nimbus/LoweredBorder.java new file mode 100644 index 0000000000000000000000000000000000000000..99bc834def228d5e5790a32f1d18eea2989a054a --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/LoweredBorder.java @@ -0,0 +1,201 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import javax.swing.border.Border; +import javax.swing.JComponent; +import javax.swing.plaf.UIResource; +import java.awt.Insets; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Color; +import java.awt.Transparency; +import java.awt.RenderingHints; +import java.awt.Dimension; +import java.awt.image.BufferedImage; + +/** + * LoweredBorder - A recessed rounded inner shadowed border. Used as the + * standard Nimbus TitledBorder. This class is both a painter and a swing + * border. + * + * @author Jasper Potts + */ +class LoweredBorder extends AbstractRegionPainter implements Border { + private static final int IMG_SIZE = 30; + private static final int RADIUS = 13; + private static final Insets INSETS = new Insets(10,10,10,10); + private static final PaintContext PAINT_CONTEXT = new PaintContext(INSETS, + new Dimension(IMG_SIZE,IMG_SIZE),false, + PaintContext.CacheMode.NINE_SQUARE_SCALE, + Integer.MAX_VALUE, Integer.MAX_VALUE); + + // ========================================================================= + // Painter Methods + + @Override + protected Object[] getExtendedCacheKeys(JComponent c) { + return new Object[] {c.getBackground()}; + } + + /** + * Actually performs the painting operation. Subclasses must implement this + * method. The graphics object passed may represent the actual surface being + * rendererd to, or it may be an intermediate buffer. It has also been + * pre-translated. Simply render the component as if it were located at 0, 0 + * and had a width of width and a height of + * height. For performance reasons, you may want to read the + * clip from the Graphics2D object and only render within that space. + * + * @param g The Graphics2D surface to paint to + * @param c The JComponent related to the drawing event. For example, + * if the region being rendered is Button, then c + * will be a JButton. If the region being drawn is + * ScrollBarSlider, then the component will be JScrollBar. + * This value may be null. + * @param width The width of the region to paint. Note that in the case of + * painting the foreground, this value may differ from + * c.getWidth(). + * @param height The height of the region to paint. Note that in the case of + * painting the foreground, this value may differ from + * c.getHeight(). + */ + protected void doPaint(Graphics2D g, JComponent c, int width, int height, + Object[] extendedCacheKeys) { + BufferedImage img1 = new BufferedImage(IMG_SIZE,IMG_SIZE, + BufferedImage.TYPE_INT_ARGB); + BufferedImage img2 = new BufferedImage(IMG_SIZE,IMG_SIZE, + BufferedImage.TYPE_INT_ARGB); + // draw shadow shape + Graphics2D g2 = (Graphics2D)img1.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(c.getBackground()); + g2.fillRoundRect(2,0,26,26,RADIUS,RADIUS); + g2.dispose(); + // draw shadow + InnerShadowEffect effect = new InnerShadowEffect(); + effect.setDistance(1); + effect.setSize(3); + effect.setColor(getLighter(c.getBackground(),2.1f)); + effect.setAngle(90); + effect.applyEffect(img1,img2,IMG_SIZE,IMG_SIZE); + // draw outline to img2 + g2 = (Graphics2D)img2.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.setClip(0,28,IMG_SIZE,1); + g2.setColor(getLighter(c.getBackground(),0.90f)); + g2.drawRoundRect(2,1,25,25,RADIUS,RADIUS); + g2.dispose(); + // draw final image + if (width != IMG_SIZE || height != IMG_SIZE){ + ImageScalingHelper.paint(g,0,0,width,height,img2, INSETS, INSETS, + ImageScalingHelper.PaintType.PAINT9_STRETCH, + ImageScalingHelper.PAINT_ALL); + } else { + g.drawImage(img2,0,0,c); + } + img1 = null; + img2 = null; + } + + /** + *

Gets the PaintContext for this painting operation. This method is + * called on every paint, and so should be fast and produce no garbage. The + * PaintContext contains information such as cache hints. It also contains + * data necessary for decoding points at runtime, such as the stretching + * insets, the canvas size at which the encoded points were defined, and + * whether the stretching insets are inverted.

+ *

+ *

This method allows for subclasses to package the painting of + * different states with possibly different canvas sizes, etc, into one + * AbstractRegionPainter implementation.

+ * + * @return a PaintContext associated with this paint operation. + */ + protected PaintContext getPaintContext() { + return PAINT_CONTEXT; + } + + // ========================================================================= + // Border Methods + + /** + * Returns the insets of the border. + * + * @param c the component for which this border insets value applies + */ + public Insets getBorderInsets(Component c) { + return INSETS; + } + + /** + * Returns whether or not the border is opaque. If the border is opaque, it + * is responsible for filling in it's own background when painting. + */ + public boolean isBorderOpaque() { + return false; + } + + /** + * Paints the border for the specified component with the specified position + * and size. + * + * @param c the component for which this border is being painted + * @param g the paint graphics + * @param x the x position of the painted border + * @param y the y position of the painted border + * @param width the width of the painted border + * @param height the height of the painted border + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, + int height) { + JComponent comp = (c instanceof JComponent)?(JComponent)c:null; + if (g instanceof Graphics2D){ + Graphics2D g2 = (Graphics2D)g; + g2.translate(x,y); + paint(g2,comp, width, height); + g2.translate(-x,-y); + } else { + BufferedImage img = new BufferedImage(IMG_SIZE,IMG_SIZE, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D)img.getGraphics(); + paint(g2,comp, width, height); + g2.dispose(); + ImageScalingHelper.paint(g,x,y,width,height,img,INSETS, INSETS, + ImageScalingHelper.PaintType.PAINT9_STRETCH, + ImageScalingHelper.PAINT_ALL); + } + } + + private Color getLighter(Color c, float factor){ + return new Color(Math.min((int)(c.getRed()/factor), 255), + Math.min((int)(c.getGreen()/factor), 255), + Math.min((int)(c.getBlue()/factor), 255)); + } +} + diff --git a/src/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java b/src/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java new file mode 100644 index 0000000000000000000000000000000000000000..921ca0ea74c385aade8f5ec7dcd1da08d6cbb437 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java @@ -0,0 +1,223 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import javax.swing.Painter; +import sun.swing.plaf.synth.SynthIcon; + +import javax.swing.plaf.synth.SynthContext; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import javax.swing.plaf.UIResource; + +/** + * An icon that delegates to a painter. + * @author rbair + */ +class NimbusIcon extends SynthIcon { + private int width; + private int height; + private String prefix; + private String key; + + NimbusIcon(String prefix, String key, int w, int h) { + this.width = w; + this.height = h; + this.prefix = prefix; + this.key = key; + } + + @Override + public void paintIcon(SynthContext context, Graphics g, int x, int y, + int w, int h) { + Painter painter = null; + if (context != null) { + painter = (Painter)context.getStyle().get(context, key); + } + if (painter == null){ + painter = (Painter) UIManager.get(prefix + "[Enabled]." + key); + } + + if (painter != null && context != null) { + JComponent c = context.getComponent(); + boolean rotate = false; + boolean flip = false; + //translatex and translatey are additional translations that + //must occur on the graphics context when rendering a toolbar + //icon + int translatex = 0; + int translatey = 0; + if (c instanceof JToolBar) { + JToolBar toolbar = (JToolBar)c; + rotate = toolbar.getOrientation() == JToolBar.VERTICAL; + flip = !toolbar.getComponentOrientation().isLeftToRight(); + Object o = NimbusLookAndFeel.resolveToolbarConstraint(toolbar); + //we only do the +1 hack for UIResource borders, assuming + //that the border is probably going to be our border + if (toolbar.getBorder() instanceof UIResource) { + if (o == BorderLayout.SOUTH) { + translatey = 1; + } else if (o == BorderLayout.EAST) { + translatex = 1; + } + } + } + if (g instanceof Graphics2D){ + Graphics2D gfx = (Graphics2D)g; + gfx.translate(x, y); + gfx.translate(translatex, translatey); + if (rotate) { + gfx.rotate(Math.toRadians(90)); + gfx.translate(0, -w); + painter.paint(gfx, context.getComponent(), h, w); + gfx.translate(0, w); + gfx.rotate(Math.toRadians(-90)); + } else if (flip){ + gfx.scale(-1, 1); + gfx.translate(-w,0); + painter.paint(gfx, context.getComponent(), w, h); + gfx.translate(w,0); + gfx.scale(-1, 1); + } else { + painter.paint(gfx, context.getComponent(), w, h); + } + gfx.translate(-translatex, -translatey); + gfx.translate(-x, -y); + } else { + // use image if we are printing to a Java 1.1 PrintGraphics as + // it is not a instance of Graphics2D + BufferedImage img = new BufferedImage(w,h, + BufferedImage.TYPE_INT_ARGB); + Graphics2D gfx = img.createGraphics(); + if (rotate) { + gfx.rotate(Math.toRadians(90)); + gfx.translate(0, -w); + painter.paint(gfx, context.getComponent(), h, w); + } else if (flip){ + gfx.scale(-1, 1); + gfx.translate(-w,0); + painter.paint(gfx, context.getComponent(), w, h); + } else { + painter.paint(gfx, context.getComponent(), w, h); + } + gfx.dispose(); + g.drawImage(img,x,y,null); + img = null; + } + } + } + + /** + * Implements the standard Icon interface's paintIcon method as the standard + * synth stub passes null for the context and this will cause us to not + * paint any thing, so we override here so that we can paint the enabled + * state if no synth context is available + */ + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Painter painter = (Painter)UIManager.get(prefix + "[Enabled]." + key); + if (painter != null){ + JComponent jc = (c instanceof JComponent) ? (JComponent)c : null; + Graphics2D gfx = (Graphics2D)g; + gfx.translate(x, y); + painter.paint(gfx, jc , width, height); + gfx.translate(-x, -y); + } + } + + @Override + public int getIconWidth(SynthContext context) { + if (context == null) { + return width; + } + JComponent c = context.getComponent(); + if (c instanceof JToolBar && ((JToolBar)c).getOrientation() == JToolBar.VERTICAL) { + //we only do the -1 hack for UIResource borders, assuming + //that the border is probably going to be our border + if (c.getBorder() instanceof UIResource) { + return c.getWidth() - 1; + } else { + return c.getWidth(); + } + } else { + return scale(context, width); + } + } + + @Override + public int getIconHeight(SynthContext context) { + if (context == null) { + return height; + } + JComponent c = context.getComponent(); + if (c instanceof JToolBar){ + JToolBar toolbar = (JToolBar)c; + if (toolbar.getOrientation() == JToolBar.HORIZONTAL) { + //we only do the -1 hack for UIResource borders, assuming + //that the border is probably going to be our border + if (toolbar.getBorder() instanceof UIResource) { + return c.getHeight() - 1; + } else { + return c.getHeight(); + } + } else { + return scale(context, width); + } + } else { + return scale(context, height); + } + } + + /** + * Scale a size based on the "JComponent.sizeVariant" client property of the + * component that is using this icon + * + * @param context The synthContext to get the component from + * @param size The size to scale + * @return The scaled size or original if "JComponent.sizeVariant" is not + * set + */ + private int scale(SynthContext context, int size) { + if (context == null || context.getComponent() == null){ + return size; + } + // The key "JComponent.sizeVariant" is used to match Apple's LAF + String scaleKey = (String) context.getComponent().getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null) { + if (NimbusStyle.LARGE_KEY.equals(scaleKey)) { + size *= NimbusStyle.LARGE_SCALE; + } else if (NimbusStyle.SMALL_KEY.equals(scaleKey)) { + size *= NimbusStyle.SMALL_SCALE; + } else if (NimbusStyle.MINI_KEY.equals(scaleKey)) { + // mini is not quite as small for icons as full mini is + // just too tiny + size *= NimbusStyle.MINI_SCALE + 0.07; + } + } + return size; + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java b/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java new file mode 100644 index 0000000000000000000000000000000000000000..eae031b6ba3e421d36b8afbad36a0b59c2f05261 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java @@ -0,0 +1,520 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.BorderLayout; +import static java.awt.BorderLayout.*; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.synth.Region; +import javax.swing.plaf.synth.SynthLookAndFeel; +import javax.swing.plaf.synth.SynthStyle; +import javax.swing.plaf.synth.SynthStyleFactory; +import javax.swing.plaf.UIResource; +import java.security.AccessController; +import java.awt.Color; +import java.awt.Container; +import java.awt.Graphics2D; +import java.awt.LayoutManager; +import java.awt.image.BufferedImage; +import javax.swing.GrayFilter; +import javax.swing.Icon; +import javax.swing.JToolBar; +import javax.swing.border.TitledBorder; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import sun.swing.ImageIconUIResource; +import sun.swing.plaf.synth.SynthIcon; +import sun.swing.plaf.GTKKeybindings; +import sun.swing.plaf.WindowsKeybindings; +import sun.security.action.GetPropertyAction; + +/** + *

The NimbusLookAndFeel class.

+ * + * @author Jasper Potts + * @author Richard Bair + */ +public class NimbusLookAndFeel extends SynthLookAndFeel { + + /** Set of standard region names for UIDefaults Keys */ + private static final String[] COMPONENT_KEYS = new String[]{"ArrowButton", "Button", + "CheckBox", "CheckBoxMenuItem", "ColorChooser", "ComboBox", + "DesktopPane", "DesktopIcon", "EditorPane", "FileChooser", + "FormattedTextField", "InternalFrame", + "InternalFrameTitlePane", "Label", "List", "Menu", + "MenuBar", "MenuItem", "OptionPane", "Panel", + "PasswordField", "PopupMenu", "PopupMenuSeparator", + "ProgressBar", "RadioButton", "RadioButtonMenuItem", + "RootPane", "ScrollBar", "ScrollBarTrack", "ScrollBarThumb", + "ScrollPane", "Separator", "Slider", "SliderTrack", + "SliderThumb", "Spinner", "SplitPane", "TabbedPane", + "Table", "TableHeader", "TextArea", "TextField", "TextPane", + "ToggleButton", "ToolBar", "ToolTip", "Tree", "Viewport"}; + + /** + * A reference to the auto-generated file NimbusDefaults. This file contains + * the default mappings and values for the look and feel as specified in the + * visual designer. + */ + private NimbusDefaults defaults; + + /** + * Reference to populated LAD uidefaults + */ + private UIDefaults uiDefaults; + + /** + * Create a new NimbusLookAndFeel. + */ + public NimbusLookAndFeel() { + super(); + defaults = new NimbusDefaults(); + } + + /** Called by UIManager when this look and feel is installed. */ + @Override public void initialize() { + super.initialize(); + defaults.initialize(); + // create synth style factory + setStyleFactory(new SynthStyleFactory() { + @Override + public SynthStyle getStyle(JComponent c, Region r) { + return defaults.getStyle(c, r); + } + }); + } + + + /** Called by UIManager when this look and feel is uninstalled. */ + @Override public void uninitialize() { + super.uninitialize(); + defaults.uninitialize(); + // clear all cached images to free memory + ImageCache.getInstance().flush(); + // remove the listeners and things installed by NimbusStyle + NimbusStyle.uninitialize(); + } + + /** + * @inheritDoc + */ + @Override public UIDefaults getDefaults() { + if (uiDefaults == null){ + // Detect platform + String osName = getSystemProperty("os.name"); + boolean isWindows = osName != null && osName.contains("Windows"); + + // We need to call super for basic's properties file. + uiDefaults = super.getDefaults(); + defaults.initializeDefaults(uiDefaults); + + // Install Keybindings + if (isWindows) { + WindowsKeybindings.installKeybindings(uiDefaults); + } else { + GTKKeybindings.installKeybindings(uiDefaults); + } + + // Add Titled Border + uiDefaults.put("TitledBorder.titlePosition", + TitledBorder.ABOVE_TOP); + uiDefaults.put("TitledBorder.border", new BorderUIResource( + new LoweredBorder())); + uiDefaults.put("TitledBorder.titleColor", + getDerivedColor("text",0.0f,0.0f,0.23f,0,true)); + uiDefaults.put("TitledBorder.font", + new NimbusDefaults.DerivedFont("defaultFont", + 1f, true, null)); + + // Choose Dialog button positions + uiDefaults.put("OptionPane.isYesLast", !isWindows); + + // Store Table ScrollPane Corner Component + uiDefaults.put("Table.scrollPaneCornerComponent", + TableScrollPaneCorner.class); + + // Setup the settings for ToolBarSeparator which is custom + // installed for Nimbus + uiDefaults.put("ToolBarSeparator[Enabled].backgroundPainter", + new ToolBarSeparatorPainter()); + + // Populate UIDefaults with a standard set of properties + for (String componentKey : COMPONENT_KEYS) { + String key = componentKey+".foreground"; + if (!uiDefaults.containsKey(key)){ + uiDefaults.put(key, + new NimbusProperty(componentKey,"textForeground")); + } + key = componentKey+".background"; + if (!uiDefaults.containsKey(key)){ + uiDefaults.put(key, + new NimbusProperty(componentKey,"background")); + } + key = componentKey+".font"; + if (!uiDefaults.containsKey(key)){ + uiDefaults.put(key, + new NimbusProperty(componentKey,"font")); + } + key = componentKey+".disabledText"; + if (!uiDefaults.containsKey(key)){ + uiDefaults.put(key, + new NimbusProperty(componentKey,"Disabled", + "textForeground")); + } + key = componentKey+".disabled"; + if (!uiDefaults.containsKey(key)){ + uiDefaults.put(key, + new NimbusProperty(componentKey,"Disabled", + "background")); + } + } + + // FileView icon keys are used by some applications, we don't have + // a computer icon at the moment so using home icon for now + uiDefaults.put("FileView.computerIcon", + new LinkProperty("FileChooser.homeFolderIcon")); + uiDefaults.put("FileView.directoryIcon", + new LinkProperty("FileChooser.directoryIcon")); + uiDefaults.put("FileView.fileIcon", + new LinkProperty("FileChooser.fileIcon")); + uiDefaults.put("FileView.floppyDriveIcon", + new LinkProperty("FileChooser.floppyDriveIcon")); + uiDefaults.put("FileView.hardDriveIcon", + new LinkProperty("FileChooser.hardDriveIcon")); + } + return uiDefaults; + } + + /** + * Gets the style associated with the given component and region. This + * will never return null. If an appropriate component and region cannot + * be determined, then a default style is returned. + * + * @param c a non-null reference to a JComponent + * @param r a non-null reference to the region of the component c + * @return a non-null reference to a NimbusStyle. + */ + public static NimbusStyle getStyle(JComponent c, Region r) { + return (NimbusStyle)SynthLookAndFeel.getStyle(c, r); + } + + /** + * Return a short string that identifies this look and feel. This + * String will be the unquoted String "Nimbus". + * + * @return a short string identifying this look and feel. + */ + @Override public String getName() { + return "Nimbus"; + } + + /** + * Return a string that identifies this look and feel. This String will + * be the unquoted String "Nimbus". + * + * @return a short string identifying this look and feel. + */ + @Override public String getID() { + return "Nimbus"; + } + + /** + * Returns a textual description of this look and feel. + * + * @return textual description of this look and feel. + */ + @Override public String getDescription() { + return "Nimbus Look and Feel"; + } + + /** + * @inheritDoc + * @return true + */ + @Override public boolean shouldUpdateStyleOnAncestorChanged() { + return true; + } + + /** + *

Registers a third party component with the NimbusLookAndFeel.

+ * + *

Regions represent Components and areas within Components that act as + * independent painting areas. Once registered with the NimbusLookAndFeel, + * NimbusStyles for these Regions can be retrieved via the + * getStyle method.

+ * + *

The NimbusLookAndFeel uses a standard naming scheme for entries in the + * UIDefaults table. The key for each property, state, painter, and other + * default registered in UIDefaults for a specific Region will begin with + * the specified prefix

+ * + *

For example, suppose I had a component named JFoo. Suppose I then registered + * this component with the NimbusLookAndFeel in this manner:

+ * + *

+     *     laf.register(NimbusFooUI.FOO_REGION, "Foo");
+     * 
+ * + *

In this case, I could then register properties for this component with + * UIDefaults in the following manner:

+ * + *

+     *     UIManager.put("Foo.background", new ColorUIResource(Color.BLACK));
+     *     UIManager.put("Foo.Enabled.backgroundPainter", new FooBackgroundPainter());
+     * 
+ * + *

It is also possible to register a named component with Nimbus. + * For example, suppose you wanted to style the background of a JPanel + * named "MyPanel" differently from other JPanels. You could accomplish this + * by doing the following:

+ * + *

+     *     laf.register(Region.PANEL, "\"MyPanel\"");
+     *     UIManager.put("\"MyPanel\".background", new ColorUIResource(Color.RED));
+     * 
+ * + * @param region The Synth Region that is being registered. Such as Button, or + * ScrollBarThumb, or NimbusFooUI.FOO_REGION. + * @param prefix The UIDefault prefix. For example, could be ComboBox, or if + * a named components, "MyComboBox", or even something like + * ToolBar."MyComboBox"."ComboBox.arrowButton" + */ + public void register(Region region, String prefix) { + defaults.register(region, prefix); + } + + /** + * Simple utility method that reads system keys. + */ + private String getSystemProperty(String key) { + return AccessController.doPrivileged(new GetPropertyAction(key)); + } + + @Override + public Icon getDisabledIcon(JComponent component, Icon icon) { + if (icon instanceof SynthIcon) { + SynthIcon si = (SynthIcon)icon; + BufferedImage img = EffectUtils.createCompatibleTranslucentImage( + si.getIconWidth(), si.getIconHeight()); + Graphics2D gfx = img.createGraphics(); + si.paintIcon(component, gfx, 0, 0); + gfx.dispose(); + return new ImageIconUIResource(GrayFilter.createDisabledImage(img)); + } else { + return super.getDisabledIcon(component, icon); + } + } + + /** + * Get a derived color, derived colors are shared instances and is color + * value will change when its parent UIDefault color changes. + * + * @param uiDefaultParentName The parent UIDefault key + * @param hOffset The hue offset + * @param sOffset The saturation offset + * @param bOffset The brightness offset + * @param aOffset The alpha offset + * @param uiResource True if the derived color should be a + * UIResource, false if it should not be + * @return The stored derived color + */ + public Color getDerivedColor(String uiDefaultParentName, + float hOffset, float sOffset, + float bOffset, int aOffset, + boolean uiResource) { + return defaults.getDerivedColor(uiDefaultParentName, hOffset, sOffset, + bOffset, aOffset, uiResource); + } + + /** + * Decodes and returns a color, which is derived from an offset between two + * other colors. + * + * @param color1 The first color + * @param color2 The second color + * @param midPoint The offset between color 1 and color 2, a value of 0.0 is + * color 1 and 1.0 is color 2; + * @param uiResource True if the derived color should be a UIResource + * @return The derived color + */ + protected final Color getDerivedColor(Color color1, Color color2, + float midPoint, boolean uiResource) { + int argb = deriveARGB(color1, color2, midPoint); + if (uiResource) { + return new ColorUIResource(argb); + } else { + return new Color(argb); + } + } + + /** + * Decodes and returns a color, which is derived from a offset between two + * other colors. + * + * @param color1 The first color + * @param color2 The second color + * @param midPoint The offset between color 1 and color 2, a value of 0.0 is + * color 1 and 1.0 is color 2; + * @return The derived color, which will be a UIResource + */ + protected final Color getDerivedColor(Color color1, Color color2, + float midPoint) { + return getDerivedColor(color1, color2, midPoint, true); + } + + /** + * Package private method which returns either BorderLayout.NORTH, + * BorderLayout.SOUTH, BorderLayout.EAST, or BorderLayout.WEST depending + * on the location of the toolbar in its parent. The toolbar might be + * in PAGE_START, PAGE_END, CENTER, or some other position, but will be + * resolved to either NORTH,SOUTH,EAST, or WEST based on where the toolbar + * actually IS, with CENTER being NORTH. + * + * This code is used to determine where the border line should be drawn + * by the custom toolbar states, and also used by NimbusIcon to determine + * whether the handle icon needs to be shifted to look correct. + * + * Toollbars are unfortunately odd in the way these things are handled, + * and so this code exists to unify the logic related to toolbars so it can + * be shared among the static files such as NimbusIcon and generated files + * such as the ToolBar state classes. + */ + static Object resolveToolbarConstraint(JToolBar toolbar) { + //NOTE: we don't worry about component orientation or PAGE_END etc + //because the BasicToolBarUI always uses an absolute position of + //NORTH/SOUTH/EAST/WEST. + if (toolbar != null) { + Container parent = toolbar.getParent(); + if (parent != null) { + LayoutManager m = parent.getLayout(); + if (m instanceof BorderLayout) { + BorderLayout b = (BorderLayout)m; + Object con = b.getConstraints(toolbar); + if (con == SOUTH || con == EAST || con == WEST) { + return con; + } + return NORTH; + } + } + } + return NORTH; + } + + /** + * Derives the ARGB value for a color based on an offset between two + * other colors. + * + * @param color1 The first color + * @param color2 The second color + * @param midPoint The offset between color 1 and color 2, a value of 0.0 is + * color 1 and 1.0 is color 2; + * @return the ARGB value for a new color based on this derivation + */ + static int deriveARGB(Color color1, Color color2, float midPoint) { + int r = color1.getRed() + + (int) ((color2.getRed() - color1.getRed()) * midPoint + 0.5f); + int g = color1.getGreen() + + (int) ((color2.getGreen() - color1.getGreen()) * midPoint + + 0.5f); + int b = color1.getBlue() + + (int) ((color2.getBlue() - color1.getBlue()) * midPoint + 0.5f); + int a = color1.getAlpha() + + (int) ((color2.getAlpha() - color1.getAlpha()) * midPoint + + 0.5f); + return ((a & 0xFF) << 24) | + ((r & 0xFF) << 16) | + ((g & 0xFF) << 8) | + (b & 0xFF); + } + + /** + * Simple Symbolic Link style UIDefalts Property + */ + private class LinkProperty implements UIDefaults.ActiveValue, UIResource{ + private String dstPropName; + + private LinkProperty(String dstPropName) { + this.dstPropName = dstPropName; + } + + @Override + public Object createValue(UIDefaults table) { + return UIManager.get(dstPropName); + } + } + + /** + * Nimbus Property that looks up Nimbus keys for standard key names. For + * example "Button.background" --> "Button[Enabled].backgound" + */ + private class NimbusProperty implements UIDefaults.ActiveValue, UIResource { + private String prefix; + private String state = null; + private String suffix; + private boolean isFont; + + private NimbusProperty(String prefix, String suffix) { + this.prefix = prefix; + this.suffix = suffix; + isFont = "font".equals(suffix); + } + + private NimbusProperty(String prefix, String state, String suffix) { + this(prefix,suffix); + this.state = state; + } + + /** + * Creates the value retrieved from the UIDefaults table. + * The object is created each time it is accessed. + * + * @param table a UIDefaults table + * @return the created Object + */ + @Override + public Object createValue(UIDefaults table) { + Object obj = null; + // check specified state + if (state!=null){ + obj = uiDefaults.get(prefix+"["+state+"]."+suffix); + } + // check enabled state + if (obj==null){ + obj = uiDefaults.get(prefix+"[Enabled]."+suffix); + } + // check for defaults + if (obj==null){ + if (isFont) { + obj = uiDefaults.get("defaultFont"); + } else { + obj = uiDefaults.get(suffix); + } + } + return obj; + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java b/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java new file mode 100644 index 0000000000000000000000000000000000000000..04efc91cf018f42a67e0cee2bfc7b4a39be2d890 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java @@ -0,0 +1,1259 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import javax.swing.Painter; + +import java.beans.PropertyChangeEvent; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.synth.ColorType; +import static javax.swing.plaf.synth.SynthConstants.*; +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthPainter; +import javax.swing.plaf.synth.SynthStyle; +import java.awt.Color; +import java.awt.Font; +import java.awt.Insets; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import sun.awt.AppContext; + +/** + *

A SynthStyle implementation used by Nimbus. Each Region that has been + * registered with the NimbusLookAndFeel will have an associated NimbusStyle. + * Third party components that are registered with the NimbusLookAndFeel will + * therefore be handed a NimbusStyle from the look and feel from the + * #getStyle(JComponent, Region) method.

+ * + *

This class properly reads and retrieves values placed in the UIDefaults + * according to the standard Nimbus naming conventions. It will create and + * retrieve painters, fonts, colors, and other data stored there.

+ * + *

NimbusStyle also supports the ability to override settings on a per + * component basis. NimbusStyle checks the component's client property map for + * "Nimbus.Overrides". If the value associated with this key is an instance of + * UIDefaults, then the values in that defaults table will override the standard + * Nimbus defaults in UIManager, but for that component instance only.

+ * + *

Optionally, you may specify the client property + * "Nimbus.Overrides.InheritDefaults". If true, this client property indicates + * that the defaults located in UIManager should first be read, and then + * replaced with defaults located in the component client properties. If false, + * then only the defaults located in the component client property map will + * be used. If not specified, it is assumed to be true.

+ * + *

You must specify "Nimbus.Overrides" for "Nimbus.Overrides.InheritDefaults" + * to have any effect. "Nimbus.Overrides" indicates whether there are any + * overrides, while "Nimbus.Overrides.InheritDefaults" indicates whether those + * overrides should first be initialized with the defaults from UIManager.

+ * + *

The NimbusStyle is reloaded whenever a property change event is fired + * for a component for "Nimbus.Overrides" or "Nimbus.Overrides.InheritDefaults". + * So for example, setting a new UIDefaults on a component would cause the + * style to be reloaded.

+ * + *

The values are only read out of UIManager once, and then cached. If + * you need to read the values again (for example, if the UI is being reloaded), + * then discard this NimbusStyle and read a new one from NimbusLookAndFeel + * using NimbusLookAndFeel.getStyle.

+ * + *

The primary API of interest in this class for 3rd party component authors + * are the three methods which retrieve painters: #getBackgroundPainter, + * #getForegroundPainter, and #getBorderPainter.

+ * + *

NimbusStyle allows you to specify custom states, or modify the order of + * states. Synth (and thus Nimbus) has the concept of a "state". For example, + * a JButton might be in the "MOUSE_OVER" state, or the "ENABLED" state, or the + * "DISABLED" state. These are all "standard" states which are defined in synth, + * and which apply to all synth Regions.

+ * + *

Sometimes, however, you need to have a custom state. For example, you + * want JButton to render differently if it's parent is a JToolbar. In Nimbus, + * you specify these custom states by including a special key in UIDefaults. + * The following UIDefaults entries define three states for this button:

+ * + *

+ *     JButton.States = Enabled, Disabled, Toolbar
+ *     JButton[Enabled].backgroundPainter = somePainter
+ *     JButton[Disabled].background = BLUE
+ *     JButton[Toolbar].backgroundPainter = someOtherPaint
+ * 
+ * + *

As you can see, the JButton.States entry lists the states + * that the JButton style will support. You then specify the settings for + * each state. If you do not specify the JButton.States entry, + * then the standard Synth states will be assumed. If you specify the entry + * but the list of states is empty or null, then the standard synth states + * will be assumed.

+ * + * @author Richard Bair + * @author Jasper Potts + */ +public final class NimbusStyle extends SynthStyle { + /* Keys and scales for large/small/mini components, based on Apples sizes */ + public static final String LARGE_KEY = "large"; + public static final String SMALL_KEY = "small"; + public static final String MINI_KEY = "mini"; + public static final double LARGE_SCALE = 1.15; + public static final double SMALL_SCALE = 0.857; + public static final double MINI_SCALE = 0.714; + + /** + * Special constant used for performance reasons during the get() method. + * If get() runs through all of the search locations and determines that + * there is no value, then NULL will be placed into the values map. This way + * on subsequent lookups it will simply extract NULL, see it, and return + * null rather than continuing the lookup procedure. + */ + private static final Object NULL = '\0'; + /** + *

The Color to return from getColorForState if it would otherwise have + * returned null.

+ * + *

Returning null from getColorForState is a very bad thing, as it causes + * the AWT peer for the component to install a SystemColor, which is not a + * UIResource. As a result, if null is returned from + * getColorForState, then thereafter the color is not updated for other + * states or on LAF changes or updates. This DEFAULT_COLOR is used to + * ensure that a ColorUIResource is always returned from + * getColorForState.

+ */ + private static final Color DEFAULT_COLOR = new ColorUIResource(Color.BLACK); + /** + * Simple Comparator for ordering the RuntimeStates according to their + * rank. + */ + private static final Comparator STATE_COMPARATOR = + new Comparator() { + @Override + public int compare(RuntimeState a, RuntimeState b) { + return a.state - b.state; + } + }; + /** + * The prefix for the component or region that this NimbusStyle + * represents. This prefix is used to lookup state in the UIManager. + * It should be something like Button or Slider.Thumb or "MyButton" or + * ComboBox."ComboBox.arrowButton" or "MyComboBox"."ComboBox.arrowButton" + */ + private String prefix; + /** + * The SynthPainter that will be returned from this NimbusStyle. The + * SynthPainter returned will be a SynthPainterImpl, which will in turn + * delegate back to this NimbusStyle for the proper Painter (not + * SynthPainter) to use for painting the foreground, background, or border. + */ + private SynthPainter painter; + /** + * Data structure containing all of the defaults, insets, states, and other + * values associated with this style. This instance refers to default + * values, and are used when no overrides are discovered in the client + * properties of a component. These values are lazily created on first + * access. + */ + private Values values; + + /** + * A temporary CacheKey used to perform lookups. This pattern avoids + * creating useless garbage keys, or concatenating strings, etc. + */ + private CacheKey tmpKey = new CacheKey("", 0); + + /** + * Some NimbusStyles are created for a specific component only. In Nimbus, + * this happens whenever the component has as a client property a + * UIDefaults which overrides (or supplements) those defaults found in + * UIManager. + */ + private JComponent component; + + /** + * Create a new NimbusStyle. Only the prefix must be supplied. At the + * appropriate time, installDefaults will be called. At that point, all of + * the state information will be pulled from UIManager and stored locally + * within this style. + * + * @param prefix Something like Button or Slider.Thumb or + * org.jdesktop.swingx.JXStatusBar or ComboBox."ComboBox.arrowButton" + * @param c an optional reference to a component that this NimbusStyle + * should be associated with. This is only used when the component + * has Nimbus overrides registered in its client properties and + * should be null otherwise. + */ + NimbusStyle(String prefix, JComponent c) { + this.component = c; + this.prefix = prefix; + this.painter = new SynthPainterImpl(this); + } + + /** + * @inheritDoc + * + * Overridden to cause this style to populate itself with data from + * UIDefaults, if necessary. + */ + @Override public void installDefaults(SynthContext ctx) { + validate(); + + //delegate to the superclass to install defaults such as background, + //foreground, font, and opaque onto the swing component. + super.installDefaults(ctx); + } + + static String parsePrefix(String key) { + if (key == null) return null; + boolean inquotes = false; + for (int i=0; i> compiledDefaults = + (Map>) + ctx.get("NimbusStyle.defaults"); + + if (compiledDefaults == null) { + // the entire UIDefaults tables are parsed and compiled into + // this map of maps. The key of the compiledDefaults is the + // prefix for each style, while the value is a map of + // keys->values for that prefix. + compiledDefaults = new HashMap>(); + + // get all the defaults from UIManager.getDefaults() and put them + // into the compiledDefaults + compileDefaults(compiledDefaults, UIManager.getDefaults()); + + // This second statement pulls defaults from the laf defaults + UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); + compileDefaults(compiledDefaults, lafDefaults); + + // if it has not already been done, add a listener to both + // UIManager.getDefaults() and UIManager.getLookAndFeelDefaults(). + PropertyChangeListener pcl = (PropertyChangeListener) + ctx.get("NimbusStyle.defaults.pcl"); + + // if pcl is null, then it has not yet been registered with + // the UIManager defaults for this app context + if (pcl == null) { + // create a PCL which will simply clear out the compiled + // defaults from the app context, causing it to be recomputed + // on subsequent passes + pcl = new DefaultsListener(); + // add the PCL to both defaults tables that we pay attention + // to, so that if the UIDefaults are updated, then the + // precompiled defaults will be cleared from the app context + // and recomputed on subsequent passes + UIManager.getDefaults().addPropertyChangeListener(pcl); + UIManager.getLookAndFeelDefaults().addPropertyChangeListener(pcl); + // save the PCL to the app context as a marker indicating + // that the PCL has been registered so we don't end up adding + // more than one listener to the UIDefaults tables. + ctx.put("NimbusStyle.defaults.pcl", pcl); + } + + // store the defaults for reuse + ctx.put("NimbusStyle.defaults", compiledDefaults); + } + + TreeMap defaults = compiledDefaults.get(prefix); + + // inspect the client properties for the key "Nimbus.Overrides". If the + // value is an instance of UIDefaults, then these defaults are used + // in place of, or in addition to, the defaults in UIManager. + if (component != null) { + Object o = component.getClientProperty("Nimbus.Overrides"); + if (o instanceof UIDefaults) { + Object i = component.getClientProperty( + "Nimbus.Overrides.InheritDefaults"); + boolean inherit = i instanceof Boolean ? (Boolean)i : true; + UIDefaults d = (UIDefaults)o; + TreeMap map = new TreeMap(); + for (Object obj : d.keySet()) { + if (obj instanceof String) { + String key = (String)obj; + if (key.startsWith(prefix)) { + map.put(key, d.get(key)); + } + } + } + if (inherit) { + defaults.putAll(map); + } else { + defaults = map; + } + } + } + + // Now that I've accumulated all the defaults pertaining to this + // style, call init which will read these defaults and configure + // the default "values". + init(values, defaults); + } + + /** + * Iterates over all the keys in the specified UIDefaults and compiles + * those keys into the comiledDefaults data structure. It relies on + * parsing the "prefix" out of the key. If the key is not a String or is + * null then it is ignored. In all other cases a prefix is parsed out + * (even if that prefix is the empty String or is a "fake" prefix. That + * is, suppose you had a key Foo~~MySpecial.KeyThing~~. In this case this + * is not a Nimbus formatted key, but we don't care, we treat it as if it + * is. This doesn't pose any harm, it will simply never be used). + * + * @param compiledDefaults + * @param d + */ + private void compileDefaults( + Map> compiledDefaults, + UIDefaults d) { + for (Object obj : new HashSet(d.keySet())) { + if (obj instanceof String) { + String key = (String)obj; + String kp = parsePrefix(key); + if (kp == null) continue; + TreeMap map = compiledDefaults.get(kp); + if (map == null) { + map = new TreeMap(); + compiledDefaults.put(kp, map); + } + map.put(key, d.get(key)); + } + } + } + + /** + * Initializes the given Values object with the defaults + * contained in the given TreeMap. + * + * @param v The Values object to be initialized + * @param myDefaults a map of UIDefaults to use in initializing the Values. + * This map must contain only keys associated with this Style. + */ + private void init(Values v, TreeMap myDefaults) { + //a list of the different types of states used by this style. This + //list may contain only "standard" states (those defined by Synth), + //or it may contain custom states, or it may contain only "standard" + //states but list them in a non-standard order. + List states = new ArrayList(); + //a map of state name to code + Map stateCodes = new HashMap(); + //This is a list of runtime "state" context objects. These contain + //the values associated with each state. + List runtimeStates = new ArrayList(); + + //determine whether there are any custom states, or custom state + //order. If so, then read all those custom states and define the + //"values" stateTypes to be a non-null array. + //Otherwise, let the "values" stateTypes be null to indicate that + //there are no custom states or custom state ordering + String statesString = (String)myDefaults.get(prefix + ".States"); + if (statesString != null) { + String s[] = statesString.split(","); + for (int i=0; i 0) { + v.stateTypes = states.toArray(new State[states.size()]); + } + + //assign codes for each of the state types + int code = 1; + for (State state : states) { + stateCodes.put(state.getName(), code); + code <<= 1; + } + } else { + //since there were no custom states defined, setup the list of + //standard synth states. Note that the "v.stateTypes" is not + //being set here, indicating that at runtime the state selection + //routines should use standard synth states instead of custom + //states. I do need to popuplate this temp list now though, so that + //the remainder of this method will function as expected. + states.add(State.Enabled); + states.add(State.MouseOver); + states.add(State.Pressed); + states.add(State.Disabled); + states.add(State.Focused); + states.add(State.Selected); + states.add(State.Default); + + //assign codes for the states + stateCodes.put("Enabled", ENABLED); + stateCodes.put("MouseOver", MOUSE_OVER); + stateCodes.put("Pressed", PRESSED); + stateCodes.put("Disabled", DISABLED); + stateCodes.put("Focused", FOCUSED); + stateCodes.put("Selected", SELECTED); + stateCodes.put("Default", DEFAULT); + } + + //Now iterate over all the keys in the defaults table + for (String key : myDefaults.keySet()) { + //The key is something like JButton.Enabled.backgroundPainter, + //or JButton.States, or JButton.background. + //Remove the "JButton." portion of the key + String temp = key.substring(prefix.length()); + //if there is a " or : then we skip it because it is a subregion + //of some kind + if (temp.indexOf('"') != -1 || temp.indexOf(':') != -1) continue; + //remove the separator + temp = temp.substring(1); + //At this point, temp may be any of the following: + //background + //[Enabled].background + //[Enabled+MouseOver].background + //property.foo + + //parse out the states and the property + String stateString = null; + String property = null; + int bracketIndex = temp.indexOf(']'); + if (bracketIndex < 0) { + //there is not a state string, so property = temp + property = temp; + } else { + stateString = temp.substring(0, bracketIndex); + property = temp.substring(bracketIndex + 2); + } + + //now that I have the state (if any) and the property, get the + //value for this property and install it where it belongs + if (stateString == null) { + //there was no state, just a property. Check for the custom + //"contentMargins" property (which is handled specially by + //Synth/Nimbus). Also check for the property being "States", + //in which case it is not a real property and should be ignored. + //otherwise, assume it is a property and install it on the + //values object + if ("contentMargins".equals(property)) { + v.contentMargins = (Insets)myDefaults.get(key); + } else if ("States".equals(property)) { + //ignore + } else { + v.defaults.put(property, myDefaults.get(key)); + } + } else { + //it is possible that the developer has a malformed UIDefaults + //entry, such that something was specified in the place of + //the State portion of the key but it wasn't a state. In this + //case, skip will be set to true + boolean skip = false; + //this variable keeps track of the int value associated with + //the state. See SynthState for details. + int componentState = 0; + //Multiple states may be specified in the string, such as + //Enabled+MouseOver + String[] stateParts = stateString.split("\\+"); + //For each state, we need to find the State object associated + //with it, or skip it if it cannot be found. + for (String s : stateParts) { + if (stateCodes.containsKey(s)) { + componentState |= stateCodes.get(s); + } else { + //Was not a state. Maybe it was a subregion or something + //skip it. + skip = true; + break; + } + } + + if (skip) continue; + + //find the RuntimeState for this State + RuntimeState rs = null; + for (RuntimeState s : runtimeStates) { + if (s.state == componentState) { + rs = s; + break; + } + } + + //couldn't find the runtime state, so create a new one + if (rs == null) { + rs = new RuntimeState(componentState, stateString); + runtimeStates.add(rs); + } + + //check for a couple special properties, such as for the + //painters. If these are found, then set the specially on + //the runtime state. Else, it is just a normal property, + //so put it in the UIDefaults associated with that runtime + //state + if ("backgroundPainter".equals(property)) { + rs.backgroundPainter = (Painter)myDefaults.get(key); + } else if ("foregroundPainter".equals(property)) { + rs.foregroundPainter = (Painter) myDefaults.get(key); + } else if ("borderPainter".equals(property)) { + rs.borderPainter = (Painter) myDefaults.get(key); + } else { + rs.defaults.put(property, myDefaults.get(key)); + } + } + } + + //now that I've collected all the runtime states, I'll sort them based + //on their integer "state" (see SynthState for how this works). + Collections.sort(runtimeStates, STATE_COMPARATOR); + + //finally, set the array of runtime states on the values object + v.states = runtimeStates.toArray(new RuntimeState[runtimeStates.size()]); + } + + /** + * @inheritDoc + * + * Overridden to cause this style to populate itself with data from + * UIDefaults, if necessary. + */ + @Override public Insets getInsets(SynthContext ctx, Insets in) { + if (in == null) { + in = new Insets(0, 0, 0, 0); + } + + Values v = getValues(ctx); + + if (v.contentMargins == null) { + in.bottom = in.top = in.left = in.right = 0; + return in; + } else { + in.bottom = v.contentMargins.bottom; + in.top = v.contentMargins.top; + in.left = v.contentMargins.left; + in.right = v.contentMargins.right; + // Account for scale + // The key "JComponent.sizeVariant" is used to match Apple's LAF + String scaleKey = (String)ctx.getComponent().getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if (LARGE_KEY.equals(scaleKey)){ + in.bottom *= LARGE_SCALE; + in.top *= LARGE_SCALE; + in.left *= LARGE_SCALE; + in.right *= LARGE_SCALE; + } else if (SMALL_KEY.equals(scaleKey)){ + in.bottom *= SMALL_SCALE; + in.top *= SMALL_SCALE; + in.left *= SMALL_SCALE; + in.right *= SMALL_SCALE; + } else if (MINI_KEY.equals(scaleKey)){ + in.bottom *= MINI_SCALE; + in.top *= MINI_SCALE; + in.left *= MINI_SCALE; + in.right *= MINI_SCALE; + } + } + return in; + } + } + + /** + * @inheritDoc + * + *

Overridden to cause this style to populate itself with data from + * UIDefaults, if necessary.

+ * + *

In addition, NimbusStyle handles ColorTypes slightly differently from + * Synth.

+ *
    + *
  • ColorType.BACKGROUND will equate to the color stored in UIDefaults + * named "background".
  • + *
  • ColorType.TEXT_BACKGROUND will equate to the color stored in + * UIDefaults named "textBackground".
  • + *
  • ColorType.FOREGROUND will equate to the color stored in UIDefaults + * named "textForeground".
  • + *
  • ColorType.TEXT_FOREGROUND will equate to the color stored in + * UIDefaults named "textForeground".
  • + *
+ */ + @Override protected Color getColorForState(SynthContext ctx, ColorType type) { + String key = null; + if (type == ColorType.BACKGROUND) { + key = "background"; + } else if (type == ColorType.FOREGROUND) { + //map FOREGROUND as TEXT_FOREGROUND + key = "textForeground"; + } else if (type == ColorType.TEXT_BACKGROUND) { + key = "textBackground"; + } else if (type == ColorType.TEXT_FOREGROUND) { + key = "textForeground"; + } else if (type == ColorType.FOCUS) { + key = "focus"; + } else if (type != null) { + key = type.toString(); + } else { + return DEFAULT_COLOR; + } + Color c = (Color) get(ctx, key); + //if all else fails, return a default color (which is a ColorUIResource) + if (c == null) c = DEFAULT_COLOR; + return c; + } + + /** + * @inheritDoc + * + * Overridden to cause this style to populate itself with data from + * UIDefaults, if necessary. If a value named "font" is not found in + * UIDefaults, then the "defaultFont" font in UIDefaults will be returned + * instead. + */ + @Override protected Font getFontForState(SynthContext ctx) { + Font f = (Font)get(ctx, "font"); + if (f == null) f = UIManager.getFont("defaultFont"); + + // Account for scale + // The key "JComponent.sizeVariant" is used to match Apple's LAF + String scaleKey = (String)ctx.getComponent().getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if (LARGE_KEY.equals(scaleKey)){ + f = f.deriveFont(Math.round(f.getSize2D()*LARGE_SCALE)); + } else if (SMALL_KEY.equals(scaleKey)){ + f = f.deriveFont(Math.round(f.getSize2D()*SMALL_SCALE)); + } else if (MINI_KEY.equals(scaleKey)){ + f = f.deriveFont(Math.round(f.getSize2D()*MINI_SCALE)); + } + } + return f; + } + + /** + * @inheritDoc + * + * Returns the SynthPainter for this style, which ends up delegating to + * the Painters installed in this style. + */ + @Override public SynthPainter getPainter(SynthContext ctx) { + return painter; + } + + /** + * @inheritDoc + * + * Overridden to cause this style to populate itself with data from + * UIDefaults, if necessary. If opacity is not specified in UI defaults, + * then it defaults to being non-opaque. + */ + @Override public boolean isOpaque(SynthContext ctx) { + // Force Table CellRenderers to be opaque + if ("Table.cellRenderer".equals(ctx.getComponent().getName())) { + return true; + } + Boolean opaque = (Boolean)get(ctx, "opaque"); + return opaque == null ? false : opaque; + } + + /** + * @inheritDoc + * + *

Overridden to cause this style to populate itself with data from + * UIDefaults, if necessary.

+ * + *

Properties in UIDefaults may be specified in a chained manner. For + * example: + *

+     * background
+     * Button.opacity
+     * Button.Enabled.foreground
+     * Button.Enabled+Selected.background
+     * 

+ * + *

In this example, suppose you were in the Enabled+Selected state and + * searched for "foreground". In this case, we first check for + * Button.Enabled+Selected.foreground, but no such color exists. We then + * fall back to the next valid state, in this case, + * Button.Enabled.foreground, and have a match. So we return it.

+ * + *

Again, if we were in the state Enabled and looked for "background", we + * wouldn't find it in Button.Enabled, or in Button, but would at the top + * level in UIManager. So we return that value.

+ * + *

One special note: the "key" passed to this method could be of the form + * "background" or "Button.background" where "Button" equals the prefix + * passed to the NimbusStyle constructor. In either case, it looks for + * "background".

+ * + * @param ctx + * @param key must not be null + */ + @Override public Object get(SynthContext ctx, Object key) { + Values v = getValues(ctx); + + // strip off the prefix, if there is one. + String fullKey = key.toString(); + String partialKey = fullKey.substring(fullKey.indexOf(".") + 1); + + Object obj = null; + int xstate = getExtendedState(ctx, v); + + // check the cache + tmpKey.init(partialKey, xstate); + obj = v.cache.get(tmpKey); + boolean wasInCache = obj != null; + if (!wasInCache){ + // Search exact matching states and then lesser matching states + RuntimeState s = null; + int[] lastIndex = new int[] {-1}; + while (obj == null && + (s = getNextState(v.states, lastIndex, xstate)) != null) { + obj = s.defaults.get(partialKey); + } + // Search Region Defaults + if (obj == null && v.defaults != null) { + obj = v.defaults.get(partialKey); + } + // return found object + // Search UIManager Defaults + if (obj == null) obj = UIManager.get(fullKey); + // Search Synth Defaults for InputMaps + if (obj == null && partialKey.equals("focusInputMap")) { + obj = super.get(ctx, fullKey); + } + // if all we got was a null, store this fact for later use + v.cache.put(new CacheKey(partialKey, xstate), + obj == null ? NULL : obj); + } + // return found object + return obj == NULL ? null : obj; + } + + /** + * Gets the appropriate background Painter, if there is one, for the state + * specified in the given SynthContext. This method does appropriate + * fallback searching, as described in #get. + * + * @param ctx The SynthContext. Must not be null. + * @return The background painter associated for the given state, or null if + * none could be found. + */ + public Painter getBackgroundPainter(SynthContext ctx) { + Values v = getValues(ctx); + int xstate = getExtendedState(ctx, v); + Painter p = null; + + // check the cache + tmpKey.init("backgroundPainter$$instance", xstate); + p = (Painter)v.cache.get(tmpKey); + if (p != null) return p; + + // not in cache, so lookup and store in cache + RuntimeState s = null; + int[] lastIndex = new int[] {-1}; + while ((s = getNextState(v.states, lastIndex, xstate)) != null) { + if (s.backgroundPainter != null) { + p = s.backgroundPainter; + break; + } + } + if (p == null) p = (Painter)get(ctx, "backgroundPainter"); + if (p != null) { + v.cache.put(new CacheKey("backgroundPainter$$instance", xstate), p); + } + return p; + } + + /** + * Gets the appropriate foreground Painter, if there is one, for the state + * specified in the given SynthContext. This method does appropriate + * fallback searching, as described in #get. + * + * @param ctx The SynthContext. Must not be null. + * @return The foreground painter associated for the given state, or null if + * none could be found. + */ + public Painter getForegroundPainter(SynthContext ctx) { + Values v = getValues(ctx); + int xstate = getExtendedState(ctx, v); + Painter p = null; + + // check the cache + tmpKey.init("foregroundPainter$$instance", xstate); + p = (Painter)v.cache.get(tmpKey); + if (p != null) return p; + + // not in cache, so lookup and store in cache + RuntimeState s = null; + int[] lastIndex = new int[] {-1}; + while ((s = getNextState(v.states, lastIndex, xstate)) != null) { + if (s.foregroundPainter != null) { + p = s.foregroundPainter; + break; + } + } + if (p == null) p = (Painter)get(ctx, "foregroundPainter"); + if (p != null) { + v.cache.put(new CacheKey("foregroundPainter$$instance", xstate), p); + } + return p; + } + + /** + * Gets the appropriate border Painter, if there is one, for the state + * specified in the given SynthContext. This method does appropriate + * fallback searching, as described in #get. + * + * @param ctx The SynthContext. Must not be null. + * @return The border painter associated for the given state, or null if + * none could be found. + */ + public Painter getBorderPainter(SynthContext ctx) { + Values v = getValues(ctx); + int xstate = getExtendedState(ctx, v); + Painter p = null; + + // check the cache + tmpKey.init("borderPainter$$instance", xstate); + p = (Painter)v.cache.get(tmpKey); + if (p != null) return p; + + // not in cache, so lookup and store in cache + RuntimeState s = null; + int[] lastIndex = new int[] {-1}; + while ((s = getNextState(v.states, lastIndex, xstate)) != null) { + if (s.borderPainter != null) { + p = s.borderPainter; + break; + } + } + if (p == null) p = (Painter)get(ctx, "borderPainter"); + if (p != null) { + v.cache.put(new CacheKey("borderPainter$$instance", xstate), p); + } + return p; + } + + /** + * Utility method which returns the proper Values based on the given + * SynthContext. Ensures that parsing of the values has occurred, or + * reoccurs as necessary. + * + * @param ctx The SynthContext + * @return a non-null values reference + */ + private Values getValues(SynthContext ctx) { + validate(); + return values; + } + + /** + * Simple utility method that searchs the given array of Strings for the + * given string. This method is only called from getExtendedState if + * the developer has specified a specific state for the component to be + * in (ie, has "wedged" the component in that state) by specifying + * they client property "Nimbus.State". + * + * @param names a non-null array of strings + * @param name the name to look for in the array + * @return true or false based on whether the given name is in the array + */ + private boolean contains(String[] names, String name) { + assert name != null; + for (int i=0; iGets the extended state for a given synth context. Nimbus supports the + * ability to define custom states. The algorithm used for choosing what + * style information to use for a given state requires a single integer + * bit string where each bit in the integer represents a different state + * that the component is in. This method uses the componentState as + * reported in the SynthContext, in addition to custom states, to determine + * what this extended state is.

+ * + *

In addition, this method checks the component in the given context + * for a client property called "Nimbus.State". If one exists, then it will + * decompose the String associated with that property to determine what + * state to return. In this way, the developer can force a component to be + * in a specific state, regardless of what the "real" state of the component + * is.

+ * + *

The string associated with "Nimbus.State" would be of the form: + *

Enabled+CustomState+MouseOver

+ * + * @param ctx + * @param v + * @return + */ + private int getExtendedState(SynthContext ctx, Values v) { + JComponent c = ctx.getComponent(); + int xstate = 0; + int mask = 1; + //check for the Nimbus.State client property + //Performance NOTE: getClientProperty ends up inside a synchronized + //block, so there is some potential for performance issues here, however + //I'm not certain that there is one on a modern VM. + Object property = c.getClientProperty("Nimbus.State"); + if (property != null) { + String stateNames = property.toString(); + String[] states = stateNames.split("\\+"); + if (v.stateTypes == null){ + // standard states only + for (String stateStr : states) { + State.StandardState s = State.getStandardState(stateStr); + if (s != null) xstate |= s.getState(); + } + } else { + // custom states + for (State s : v.stateTypes) { + if (contains(states, s.getName())) { + xstate |= mask; + } + mask <<= 1; + } + } + } else { + //if there are no custom states defined, then simply return the + //state that Synth reported + if (v.stateTypes == null) return ctx.getComponentState(); + + //there are custom states on this values, so I'll have to iterate + //over them all and return a custom extended state + int state = ctx.getComponentState(); + for (State s : v.stateTypes) { + if (s.isInState(c, state)) { + xstate |= mask; + } + mask <<= 1; + } + } + return xstate; + } + + /** + *

Gets the RuntimeState that most closely matches the state in the given + * context, but is less specific than the given "lastState". Essentially, + * this allows you to search for the next best state.

+ * + *

For example, if you had the following three states: + *

+     * Enabled
+     * Enabled+Pressed
+     * Disabled
+     * 
+ * And you wanted to find the state that best represented + * ENABLED+PRESSED+FOCUSED and lastState was null (or an + * empty array, or an array with a single int with index == -1), then + * Enabled+Pressed would be returned. If you then call this method again but + * pass the index of Enabled+Pressed as the "lastState", then + * Enabled would be returned. If you call this method a third time and pass + * the index of Enabled in as the lastState, then null would be + * returned.

+ * + *

The actual code path for determining the proper state is the same as + * in Synth.

+ * + * @param ctx + * @param lastState a 1 element array, allowing me to do pass-by-reference. + * @return + */ + private RuntimeState getNextState(RuntimeState[] states, + int[] lastState, + int xstate) { + // Use the StateInfo with the most bits that matches that of state. + // If there are none, then fallback to + // the StateInfo with a state of 0, indicating it'll match anything. + + // Consider if we have 3 StateInfos a, b and c with states: + // SELECTED, SELECTED | ENABLED, 0 + // + // Input Return Value + // ----- ------------ + // SELECTED a + // SELECTED | ENABLED b + // MOUSE_OVER c + // SELECTED | ENABLED | FOCUSED b + // ENABLED c + + if (states != null && states.length > 0) { + int bestCount = 0; + int bestIndex = -1; + int wildIndex = -1; + + //if xstate is 0, then search for the runtime state with component + //state of 0. That is, find the exact match and return it. + if (xstate == 0) { + for (int counter = states.length - 1; counter >= 0; counter--) { + if (states[counter].state == 0) { + lastState[0] = counter; + return states[counter]; + } + } + //an exact match couldn't be found, so there was no match. + lastState[0] = -1; + return null; + } + + //xstate is some value != 0 + + //determine from which index to start looking. If lastState[0] is -1 + //then we know to start from the end of the state array. Otherwise, + //we start at the lastIndex - 1. + int lastStateIndex = lastState == null || lastState[0] == -1 ? + states.length : lastState[0]; + + for (int counter = lastStateIndex - 1; counter >= 0; counter--) { + int oState = states[counter].state; + + if (oState == 0) { + if (wildIndex == -1) { + wildIndex = counter; + } + } else if ((xstate & oState) == oState) { + // This is key, we need to make sure all bits of the + // StateInfo match, otherwise a StateInfo with + // SELECTED | ENABLED would match ENABLED, which we + // don't want. + + // This comes from BigInteger.bitCnt + int bitCount = oState; + bitCount -= (0xaaaaaaaa & bitCount) >>> 1; + bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) & + 0x33333333); + bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f; + bitCount += bitCount >>> 8; + bitCount += bitCount >>> 16; + bitCount = bitCount & 0xff; + if (bitCount > bestCount) { + bestIndex = counter; + bestCount = bitCount; + } + } + } + if (bestIndex != -1) { + lastState[0] = bestIndex; + return states[bestIndex]; + } + if (wildIndex != -1) { + lastState[0] = wildIndex; + return states[wildIndex]; + } + } + lastState[0] = -1; + return null; + } + + /** + * Contains values such as the UIDefaults and painters asssociated with + * a state. Whereas State represents a distinct state that a + * component can be in (such as Enabled), this class represents the colors, + * fonts, painters, etc associated with some state for this + * style. + */ + private final class RuntimeState implements Cloneable { + int state; + Painter backgroundPainter; + Painter foregroundPainter; + Painter borderPainter; + String stateName; + UIDefaults defaults = new UIDefaults(10, .7f); + + private RuntimeState(int state, String stateName) { + this.state = state; + this.stateName = stateName; + } + + @Override + public String toString() { + return stateName; + } + + @Override + public RuntimeState clone() { + RuntimeState clone = new RuntimeState(state, stateName); + clone.backgroundPainter = backgroundPainter; + clone.foregroundPainter = foregroundPainter; + clone.borderPainter = borderPainter; + clone.defaults.putAll(defaults); + return clone; + } + } + + /** + * Essentially a struct of data for a style. A default instance of this + * class is used by NimbusStyle. Additional instances exist for each + * component that has overrides. + */ + private static final class Values { + /** + * The list of State types. A State represents a type of state, such + * as Enabled, Default, WindowFocused, etc. These can be custom states. + */ + State[] stateTypes = null; + /** + * The list of actual runtime state representations. These can represent things such + * as Enabled + Focused. Thus, they differ from States in that they contain + * several states together, and have associated properties, data, etc. + */ + RuntimeState[] states = null; + /** + * The content margins for this region. + */ + Insets contentMargins; + /** + * Defaults on the region/component level. + */ + UIDefaults defaults = new UIDefaults(10, .7f); + /** + * Simple cache. After a value has been looked up, it is stored + * in this cache for later retrieval. The key is a concatenation of + * the property being looked up, two dollar signs, and the extended + * state. So for example: + * + * foo.bar$$2353 + */ + Map cache = new HashMap(); + } + + /** + * This implementation presupposes that key is never null and that + * the two keys being checked for equality are never null + */ + private static final class CacheKey { + private String key; + private int xstate; + + CacheKey(Object key, int xstate) { + init(key, xstate); + } + + void init(Object key, int xstate) { + this.key = key.toString(); + this.xstate = xstate; + } + + @Override + public boolean equals(Object obj) { + final CacheKey other = (CacheKey) obj; + if (obj == null) return false; + if (this.xstate != other.xstate) return false; + if (!this.key.equals(other.key)) return false; + return true; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 29 * hash + this.key.hashCode(); + hash = 29 * hash + this.xstate; + return hash; + } + } + + /** + * This listener is used to listen to the UIDefaults tables and clear out + * the cached-precompiled map of defaults in that case. + */ + private static final class DefaultsListener implements PropertyChangeListener { + @Override + public void propertyChange(PropertyChangeEvent evt) { + AppContext.getAppContext().put("NimbusStyle.defaults", null); + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/OuterGlowEffect.java b/src/share/classes/javax/swing/plaf/nimbus/OuterGlowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..26f83509864c40f08598e8520662ac8df3f0d7d2 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/OuterGlowEffect.java @@ -0,0 +1,39 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.Color; + +/** + * InnerGlowEffect + * + * @author Created by Jasper Potts (Jun 21, 2007) + */ +class OuterGlowEffect extends DropShadowEffect { + OuterGlowEffect() { + distance = 0; + color = new Color(255, 255, 211); + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/PainterImpl.template b/src/share/classes/javax/swing/plaf/nimbus/PainterImpl.template new file mode 100644 index 0000000000000000000000000000000000000000..2afa0005b084d0f1106ad59f7ad26f3b531e0418 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/PainterImpl.template @@ -0,0 +1,87 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package ${PACKAGE}; + +import java.awt.*; +import java.awt.geom.*; +import java.awt.image.*; +import javax.swing.*; +import javax.swing.Painter; + + +public final class ${PAINTER_NAME} extends AbstractRegionPainter { + //package private integers representing the available states that + //this painter will paint. These are used when creating a new instance + //of ${PAINTER_NAME} to determine which region/state is being painted + //by that instance. +${STATIC_DECL} + + private int state; //refers to one of the static final ints above + private PaintContext ctx; + + //the following 4 variables are reused during the painting code of the layers + private Path2D path = new Path2D.Float(); + private Rectangle2D rect = new Rectangle2D.Float(0, 0, 0, 0); + private RoundRectangle2D roundRect = new RoundRectangle2D.Float(0, 0, 0, 0, 0, 0); + private Ellipse2D ellipse = new Ellipse2D.Float(0, 0, 0, 0); + + //All Colors used for painting are stored here. Ideally, only those colors being used + //by a particular instance of ${PAINTER_NAME} would be created. For the moment at least, + //however, all are created for each instance. +${COLORS_DECL} + + //Array of current component colors, updated in each paint call + private Object[] componentColors; + + public ${PAINTER_NAME}(PaintContext ctx, int state) { + super(); + this.state = state; + this.ctx = ctx; + } + + @Override + protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) { + //populate componentColors array with colors calculated in getExtendedCacheKeys call + componentColors = extendedCacheKeys; + //generate this entire method. Each state/bg/fg/border combo that has + //been painted gets its own KEY and paint method. + switch(state) { +${DO_PAINT_SWITCH_BODY} + } + } + +${GET_EXTENDED_CACHE_KEYS} + + @Override + protected final PaintContext getPaintContext() { + return ctx; + } + +${PAINTING_DECL} + +${SHAPES_DECL} + +${GRADIENTS_DECL} +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/ShadowEffect.java b/src/share/classes/javax/swing/plaf/nimbus/ShadowEffect.java new file mode 100644 index 0000000000000000000000000000000000000000..03a1e3d60acdf4184e64ba497549388fe501a208 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/ShadowEffect.java @@ -0,0 +1,103 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.Color; + +/** + * ShadowEffect - base class with all the standard properties for shadow effects + * + * @author Created by Jasper Potts (Jun 18, 2007) + */ +abstract class ShadowEffect extends Effect { + protected Color color = Color.BLACK; + /** Opacity a float 0-1 for percentage */ + protected float opacity = 0.75f; + /** Angle in degrees between 0-360 */ + protected int angle = 135; + /** Distance in pixels */ + protected int distance = 5; + /** The shadow spread between 0-100 % */ + protected int spread = 0; + /** Size in pixels */ + protected int size = 5; + + // ================================================================================================================= + // Bean methods + + Color getColor() { + return color; + } + + void setColor(Color color) { + Color old = getColor(); + this.color = color; + } + + float getOpacity() { + return opacity; + } + + void setOpacity(float opacity) { + float old = getOpacity(); + this.opacity = opacity; + } + + int getAngle() { + return angle; + } + + void setAngle(int angle) { + int old = getAngle(); + this.angle = angle; + } + + int getDistance() { + return distance; + } + + void setDistance(int distance) { + int old = getDistance(); + this.distance = distance; + } + + int getSpread() { + return spread; + } + + void setSpread(int spread) { + int old = getSpread(); + this.spread = spread; + } + + int getSize() { + return size; + } + + void setSize(int size) { + int old = getSize(); + this.size = size; + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/State.java b/src/share/classes/javax/swing/plaf/nimbus/State.java new file mode 100644 index 0000000000000000000000000000000000000000..92b408116b624da3db754b403e06ecbbdb526cce --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/State.java @@ -0,0 +1,213 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.util.HashMap; +import java.util.Map; +import javax.swing.JComponent; +import javax.swing.plaf.synth.SynthConstants; + +/** + *

Represents a built in, or custom, state in Nimbus.

+ * + *

Synth provides several built in states, which are: + *

    + *
  • Enabled
  • + *
  • Mouse Over
  • + *
  • Pressed
  • + *
  • Disabled
  • + *
  • Focused
  • + *
  • Selected
  • + *
  • Default
  • + *
+ * + *

However, there are many more states that could be described in a LookAndFeel, and it + * would be nice to style components differently based on these different states. + * For example, a progress bar could be "indeterminate". It would be very convenient + * to allow this to be defined as a "state".

+ * + *

This class, State, is intended to be used for such situations. + * Simply implement the abstract #isInState method. It returns true if the given + * JComponent is "in this state", false otherwise. This method will be called + * many times in performance sensitive loops. It must execute + * very quickly.

+ * + *

For example, the following might be an implementation of a custom + * "Indeterminate" state for JProgressBars:

+ * + *

+ *     public final class IndeterminateState extends State<JProgressBar> {
+ *         public IndeterminateState() {
+ *             super("Indeterminate");
+ *         }
+ *
+ *         @Override
+ *         protected boolean isInState(JProgressBar c) {
+ *             return c.isIndeterminate();
+ *         }
+ *     }
+ * 
+ */ +public abstract class State{ + static final Map standardStates = new HashMap(7); + static final State Enabled = new StandardState(SynthConstants.ENABLED); + static final State MouseOver = new StandardState(SynthConstants.MOUSE_OVER); + static final State Pressed = new StandardState(SynthConstants.PRESSED); + static final State Disabled = new StandardState(SynthConstants.DISABLED); + static final State Focused = new StandardState(SynthConstants.FOCUSED); + static final State Selected = new StandardState(SynthConstants.SELECTED); + static final State Default = new StandardState(SynthConstants.DEFAULT); + + private String name; + + /** + *

Create a new custom State. Specify the name for the state. The name should + * be unique within the states set for any one particular component. + * The name of the state should coincide with the name used in UIDefaults.

+ * + *

For example, the following would be correct:

+ *

+     *     defaults.put("Button.States", "Enabled, Foo, Disabled");
+     *     defaults.put("Button.Foo", new FooState("Foo"));
+     * 
+ * + * @param name a simple user friendly name for the state, such as "Indeterminate" + * or "EmbeddedPanel" or "Blurred". It is customary to use camel case, + * with the first letter capitalized. + */ + protected State(String name) { + this.name = name; + } + + @Override public String toString() { return name; } + + /** + *

This is the main entry point, called by NimbusStyle.

+ * + *

There are both custom states and standard states. Standard states + * correlate to the states defined in SynthConstants. When a UI delegate + * constructs a SynthContext, it specifies the state that the component is + * in according to the states defined in SynthConstants. Our NimbusStyle + * will then take this state, and query each State instance in the style + * asking whether isInState(c, s).

+ * + *

Now, only the standard states care about the "s" param. So we have + * this odd arrangement:

+ *
    + *
  • NimbusStyle calls State.isInState(c, s)
  • + *
  • State.isInState(c, s) simply delegates to State.isInState(c)
  • + *
  • EXCEPT, StandardState overrides State.isInState(c, s) and + * returns directly from that method after checking its state, and + * does not call isInState(c) (since it is not needed for standard states).
  • + *
+ */ + boolean isInState(T c, int s) { + return isInState(c); + } + + /** + *

Gets whether the specified JComponent is in the custom state represented + * by this class. This is an extremely performance sensitive loop. + * Please take proper precautions to ensure that it executes quickly.

+ * + *

Nimbus uses this method to help determine what state a JComponent is + * in. For example, a custom State could exist for JProgressBar such that + * it would return true when the progress bar is indeterminate. + * Such an implementation of this method would simply be:

+ * + *
 return c.isIndeterminate();
+ * + * @param c the JComponent to test. This will never be null. + * @return true if c is in the custom state represented by + * this State instance + */ + protected abstract boolean isInState(T c); + + String getName() { return name; } + + static boolean isStandardStateName(String name) { + return standardStates.containsKey(name); + } + + static StandardState getStandardState(String name) { + return standardStates.get(name); + } + + static final class StandardState extends State { + private int state; + + private StandardState(int state) { + super(toString(state)); + this.state = state; + standardStates.put(getName(), this); + } + + public int getState() { + return state; + } + + @Override + boolean isInState(JComponent c, int s) { + return (s & state) == state; + } + + @Override + protected boolean isInState(JComponent c) { + throw new AssertionError("This method should never be called"); + } + + private static String toString(int state) { + StringBuffer buffer = new StringBuffer(); + if ((state & SynthConstants.DEFAULT) == SynthConstants.DEFAULT) { + buffer.append("Default"); + } + if ((state & SynthConstants.DISABLED) == SynthConstants.DISABLED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("Disabled"); + } + if ((state & SynthConstants.ENABLED) == SynthConstants.ENABLED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("Enabled"); + } + if ((state & SynthConstants.FOCUSED) == SynthConstants.FOCUSED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("Focused"); + } + if ((state & SynthConstants.MOUSE_OVER) == SynthConstants.MOUSE_OVER) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("MouseOver"); + } + if ((state & SynthConstants.PRESSED) == SynthConstants.PRESSED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("Pressed"); + } + if ((state & SynthConstants.SELECTED) == SynthConstants.SELECTED) { + if (buffer.length() > 0) buffer.append("+"); + buffer.append("Selected"); + } + return buffer.toString(); + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/StateImpl.template b/src/share/classes/javax/swing/plaf/nimbus/StateImpl.template new file mode 100644 index 0000000000000000000000000000000000000000..74ddc9347e782c74e422ae5c1857c8da52cf384a --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/StateImpl.template @@ -0,0 +1,40 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package ${PACKAGE}; + +import java.awt.*; +import javax.swing.*; + + +class ${STATE_NAME} extends State { + ${STATE_NAME}() { + super("${STATE_KEY}"); + } + + @Override protected boolean isInState(JComponent c) { +${BODY} + } +} + diff --git a/src/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java b/src/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6abec9a13e08e9adb1841dbba88b47b3ab07ae86 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java @@ -0,0 +1,2802 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.image.BufferedImage; +import java.util.*; +import javax.swing.*; +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthPainter; +import javax.swing.plaf.synth.SynthConstants; + +import javax.swing.Painter; + + +class SynthPainterImpl extends SynthPainter { + private NimbusStyle style; + + SynthPainterImpl(NimbusStyle style) { + this.style = style; + } + + /** + * Paint the provided painter using the provided transform at the specified + * position and size. Handles if g is a non 2D Graphics by painting via a + * BufferedImage. + */ + private void paint(Painter p, SynthContext ctx, Graphics g, int x, int y, + int w, int h, AffineTransform transform) { + if (p != null) { + if (g instanceof Graphics2D){ + Graphics2D gfx = (Graphics2D)g; + if (transform!=null){ + gfx.transform(transform); + } + gfx.translate(x, y); + p.paint(gfx, ctx.getComponent(), w, h); + gfx.translate(-x, -y); + if (transform!=null){ + try { + gfx.transform(transform.createInverse()); + } catch (NoninvertibleTransformException e) { + // this should never happen as we are in control of all + // calls into this method and only ever pass in simple + // transforms of rotate, flip and translates + e.printStackTrace(); + } + } + } else { + // use image if we are printing to a Java 1.1 PrintGraphics as + // it is not a instance of Graphics2D + BufferedImage img = new BufferedImage(w,h, + BufferedImage.TYPE_INT_ARGB); + Graphics2D gfx = img.createGraphics(); + if (transform!=null){ + gfx.transform(transform); + } + p.paint(gfx, ctx.getComponent(), w, h); + gfx.dispose(); + g.drawImage(img,x,y,null); + img = null; + } + } + } + + private void paintBackground(SynthContext ctx, Graphics g, int x, int y, + int w, int h, AffineTransform transform) { + // if the background color of the component is 100% transparent + // then we should not paint any background graphics. This is a solution + // for there being no way of turning off Nimbus background painting as + // basic components are all non-opaque by default. + Component c = ctx.getComponent(); + Color bg = (c != null) ? c.getBackground() : null; + if (bg == null || bg.getAlpha() > 0){ + Painter backgroundPainter = style.getBackgroundPainter(ctx); + if (backgroundPainter != null) { + paint(backgroundPainter, ctx, g, x, y, w, h,transform); + } + } + } + + private void paintForeground(SynthContext ctx, Graphics g, int x, int y, + int w, int h, AffineTransform transform) { + Painter foregroundPainter = style.getForegroundPainter(ctx); + if (foregroundPainter != null) { + paint(foregroundPainter, ctx, g, x, y, w, h,transform); + } + } + + private void paintBorder(SynthContext ctx, Graphics g, int x, int y, int w, + int h, AffineTransform transform) { + Painter borderPainter = style.getBorderPainter(ctx); + if (borderPainter != null) { + paint(borderPainter, ctx, g, x, y, w, h,transform); + } + } + + private void paintBackground(SynthContext ctx, Graphics g, int x, int y, int w, int h, int orientation) { + Component c = ctx.getComponent(); + boolean ltr = c.getComponentOrientation().isLeftToRight(); + // Don't RTL flip JSpliders as they handle it internaly + if (ctx.getComponent() instanceof JSlider) ltr = true; + + if (orientation == SwingConstants.VERTICAL && ltr) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(ctx, g, y, x, h, w, transform); + } else if (orientation == SwingConstants.VERTICAL) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0,-(x+w)); + paintBackground(ctx, g, y, x, h, w, transform); + } else if (orientation == SwingConstants.HORIZONTAL && ltr) { + paintBackground(ctx, g, x, y, w, h, null); + } else { + //horizontal and right-to-left orientation + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBackground(ctx, g, 0, 0, w, h, transform); + } + } + + private void paintBorder(SynthContext ctx, Graphics g, int x, int y, int w, int h, int orientation) { + Component c = ctx.getComponent(); + boolean ltr = c.getComponentOrientation().isLeftToRight(); + if (orientation == SwingConstants.VERTICAL && ltr) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBorder(ctx, g, y, x, h, w, transform); + } else if (orientation == SwingConstants.VERTICAL) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintBorder(ctx, g, y, 0, h, w, transform); + } else if (orientation == SwingConstants.HORIZONTAL && ltr) { + paintBorder(ctx, g, x, y, w, h, null); + } else { + //horizontal and right-to-left orientation + paintBorder(ctx, g, x, y, w, h, null); + } + } + + private void paintForeground(SynthContext ctx, Graphics g, int x, int y, int w, int h, int orientation) { + Component c = ctx.getComponent(); + boolean ltr = c.getComponentOrientation().isLeftToRight(); + if (orientation == SwingConstants.VERTICAL && ltr) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintForeground(ctx, g, y, x, h, w, transform); + } else if (orientation == SwingConstants.VERTICAL) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintForeground(ctx, g, y, 0, h, w, transform); + } else if (orientation == SwingConstants.HORIZONTAL && ltr) { + paintForeground(ctx, g, x, y, w, h, null); + } else { + //horizontal and right-to-left orientation + paintForeground(ctx, g, x, y, w, h, null); + } + } + + /** + * Paints the background of an arrow button. Arrow buttons are created by + * some components, such as JScrollBar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintArrowButtonBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + if (context.getComponent().getComponentOrientation().isLeftToRight()){ + paintBackground(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBackground(context, g, 0, 0, w, h, transform); + } + } + + /** + * Paints the border of an arrow button. Arrow buttons are created by + * some components, such as JScrollBar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintArrowButtonBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the foreground of an arrow button. This method is responsible + * for drawing a graphical representation of a direction, typically + * an arrow. Arrow buttons are created by + * some components, such as JScrollBar + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param direction One of SwingConstants.NORTH, SwingConstants.SOUTH + * SwingConstants.EAST or SwingConstants.WEST + */ + public void paintArrowButtonForeground(SynthContext context, + Graphics g, int x, int y, + int w, int h, + int direction) { + //assume that the painter is arranged with the arrow pointing... LEFT? + String compName = context.getComponent().getName(); + boolean ltr = context.getComponent(). + getComponentOrientation().isLeftToRight(); + // The hard coding for spinners here needs to be replaced by a more + // general method for disabling rotation + if ("Spinner.nextButton".equals(compName) || + "Spinner.previousButton".equals(compName)) { + if (ltr){ + paintForeground(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(w, 0); + transform.scale(-1, 1); + paintForeground(context, g, x, y, w, h, transform); + } + } else if (direction == SwingConstants.WEST) { + paintForeground(context, g, x, y, w, h, null); + } else if (direction == SwingConstants.NORTH) { + if (ltr){ + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintForeground(context, g, y, 0, h, w, transform); + } else { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintForeground(context, g, y, 0, h, w, transform); + } + } else if (direction == SwingConstants.EAST) { + AffineTransform transform = new AffineTransform(); + transform.translate(w, 0); + transform.scale(-1, 1); + paintForeground(context, g, x, y, w, h, transform); + } else if (direction == SwingConstants.SOUTH) { + if (ltr){ + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(-90)); + transform.translate(-h, 0); + paintForeground(context, g, y, x, h, w, transform); + } else { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(-90)); + transform.translate(-(h+y), -(w+x)); + paintForeground(context, g, y, x, h, w, transform); + } + } + } + + /** + * Paints the background of a button. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintButtonBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a button. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintButtonBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a check box menu item. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintCheckBoxMenuItemBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a check box menu item. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintCheckBoxMenuItemBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a check box. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintCheckBoxBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a check box. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintCheckBoxBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a color chooser. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintColorChooserBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a color chooser. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintColorChooserBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a combo box. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintComboBoxBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + if (context.getComponent().getComponentOrientation().isLeftToRight()){ + paintBackground(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBackground(context, g, 0, 0, w, h, transform); + } + } + + /** + * Paints the border of a combo box. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintComboBoxBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a desktop icon. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintDesktopIconBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a desktop icon. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintDesktopIconBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a desktop pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintDesktopPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a desktop pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintDesktopPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of an editor pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintEditorPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of an editor pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintEditorPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a file chooser. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintFileChooserBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a file chooser. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintFileChooserBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a formatted text field. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintFormattedTextFieldBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + if (context.getComponent().getComponentOrientation().isLeftToRight()){ + paintBackground(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBackground(context, g, 0, 0, w, h, transform); + } + } + + /** + * Paints the border of a formatted text field. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintFormattedTextFieldBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + if (context.getComponent().getComponentOrientation().isLeftToRight()){ + paintBorder(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBorder(context, g, 0, 0, w, h, transform); + } + } + + /** + * Paints the background of an internal frame title pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintInternalFrameTitlePaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of an internal frame title pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintInternalFrameTitlePaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of an internal frame. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintInternalFrameBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of an internal frame. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintInternalFrameBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a label. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintLabelBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a label. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintLabelBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a list. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintListBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a list. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintListBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a menu bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintMenuBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a menu bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintMenuBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a menu item. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintMenuItemBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a menu item. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintMenuItemBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a menu. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintMenuBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a menu. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintMenuBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of an option pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintOptionPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of an option pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintOptionPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a panel. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintPanelBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a panel. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintPanelBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a password field. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintPasswordFieldBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a password field. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintPasswordFieldBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a popup menu. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintPopupMenuBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a popup menu. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintPopupMenuBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a progress bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintProgressBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a progress bar. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation one of JProgressBar.HORIZONTAL or + * JProgressBar.VERTICAL + * @since 1.6 + */ + public void paintProgressBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of a progress bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintProgressBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a progress bar. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation one of JProgressBar.HORIZONTAL or + * JProgressBar.VERTICAL + * @since 1.6 + */ + public void paintProgressBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the foreground of a progress bar. is responsible for + * providing an indication of the progress of the progress bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation one of JProgressBar.HORIZONTAL or + * JProgressBar.VERTICAL + */ + public void paintProgressBarForeground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintForeground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of a radio button menu item. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintRadioButtonMenuItemBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a radio button menu item. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintRadioButtonMenuItemBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a radio button. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintRadioButtonBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a radio button. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintRadioButtonBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a root pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintRootPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a root pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintRootPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a scrollbar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintScrollBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a scrollbar. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation Orientation of the JScrollBar, one of + * JScrollBar.HORIZONTAL or + * JScrollBar.VERTICAL + * @since 1.6 + */ + public void paintScrollBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of a scrollbar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintScrollBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a scrollbar. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation Orientation of the JScrollBar, one of + * JScrollBar.HORIZONTAL or + * JScrollBar.VERTICAL + * @since 1.6 + */ + public void paintScrollBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of the thumb of a scrollbar. The thumb provides + * a graphical indication as to how much of the Component is visible in a + * JScrollPane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation Orientation of the JScrollBar, one of + * JScrollBar.HORIZONTAL or + * JScrollBar.VERTICAL + */ + public void paintScrollBarThumbBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of the thumb of a scrollbar. The thumb provides + * a graphical indication as to how much of the Component is visible in a + * JScrollPane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation Orientation of the JScrollBar, one of + * JScrollBar.HORIZONTAL or + * JScrollBar.VERTICAL + */ + public void paintScrollBarThumbBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of the track of a scrollbar. The track contains + * the thumb. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintScrollBarTrackBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the track of a scrollbar. The track contains + * the thumb. This implementation invokes the method of the same name without + * the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation Orientation of the JScrollBar, one of + * JScrollBar.HORIZONTAL or + * JScrollBar.VERTICAL + * @since 1.6 + */ + public void paintScrollBarTrackBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of the track of a scrollbar. The track contains + * the thumb. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintScrollBarTrackBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the track of a scrollbar. The track contains + * the thumb. This implementation invokes the method of the same name without + * the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation Orientation of the JScrollBar, one of + * JScrollBar.HORIZONTAL or + * JScrollBar.VERTICAL + * @since 1.6 + */ + public void paintScrollBarTrackBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of a scroll pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintScrollPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a scroll pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintScrollPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a separator. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSeparatorBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a separator. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSeparator.HORIZONTAL or + * JSeparator.VERTICAL + * @since 1.6 + */ + public void paintSeparatorBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of a separator. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSeparatorBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a separator. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSeparator.HORIZONTAL or + * JSeparator.VERTICAL + * @since 1.6 + */ + public void paintSeparatorBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the foreground of a separator. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSeparator.HORIZONTAL or + * JSeparator.VERTICAL + */ + public void paintSeparatorForeground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintForeground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of a slider. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSliderBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a slider. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSlider.HORIZONTAL or + * JSlider.VERTICAL + * @since 1.6 + */ + public void paintSliderBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of a slider. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSliderBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a slider. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSlider.HORIZONTAL or + * JSlider.VERTICAL + * @since 1.6 + */ + public void paintSliderBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of the thumb of a slider. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSlider.HORIZONTAL or + * JSlider.VERTICAL + */ + public void paintSliderThumbBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + if (context.getComponent().getClientProperty( + "Slider.paintThumbArrowShape") == Boolean.TRUE){ + if (orientation == JSlider.HORIZONTAL){ + orientation = JSlider.VERTICAL; + } else { + orientation = JSlider.HORIZONTAL; + } + paintBackground(context, g, x, y, w, h, orientation); + } else { + paintBackground(context, g, x, y, w, h, orientation); + } + } + + /** + * Paints the border of the thumb of a slider. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSlider.HORIZONTAL or + * JSlider.VERTICAL + */ + public void paintSliderThumbBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of the track of a slider. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSliderTrackBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the track of a slider. This implementation invokes + * the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSlider.HORIZONTAL or + * JSlider.VERTICAL + * @since 1.6 + */ + public void paintSliderTrackBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of the track of a slider. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSliderTrackBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the track of a slider. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSlider.HORIZONTAL or + * JSlider.VERTICAL + * @since 1.6 + */ + public void paintSliderTrackBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of a spinner. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSpinnerBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a spinner. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSpinnerBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the divider of a split pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSplitPaneDividerBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the divider of a split pane. This implementation + * invokes the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + * @since 1.6 + */ + public void paintSplitPaneDividerBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + if (orientation == JSplitPane.HORIZONTAL_SPLIT) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(context, g, y, x, h, w, transform); + } else { + paintBackground(context, g, x, y, w, h, null); + } + } + + /** + * Paints the foreground of the divider of a split pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + */ + public void paintSplitPaneDividerForeground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintForeground(context, g, x, y, w, h, null); + } + + /** + * Paints the divider, when the user is dragging the divider, of a + * split pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + */ + public void paintSplitPaneDragDivider(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a split pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSplitPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a split pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintSplitPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTabbedPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTabbedPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the area behind the tabs of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTabbedPaneTabAreaBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the area behind the tabs of a tabbed pane. + * This implementation invokes the method of the same name without the + * orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JTabbedPane.TOP, + * JTabbedPane.LEFT, + * JTabbedPane.BOTTOM, or + * JTabbedPane.RIGHT + * @since 1.6 + */ + public void paintTabbedPaneTabAreaBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + if (orientation == JTabbedPane.LEFT) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(context, g, y, x, h, w, transform); + } else if (orientation == JTabbedPane.RIGHT) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintBackground(context, g, y, 0, h, w, transform); + } else if (orientation == JTabbedPane.BOTTOM) { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(1, -1); + transform.translate(0,-h); + paintBackground(context, g, 0, 0, w, h, transform); + } else { + paintBackground(context, g, x, y, w, h, null); + } + } + + /** + * Paints the border of the area behind the tabs of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTabbedPaneTabAreaBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the area behind the tabs of a tabbed pane. This + * implementation invokes the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JTabbedPane.TOP, + * JTabbedPane.LEFT, + * JTabbedPane.BOTTOM, or + * JTabbedPane.RIGHT + * @since 1.6 + */ + public void paintTabbedPaneTabAreaBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a tab of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param tabIndex Index of tab being painted. + */ + public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, + int x, int y, int w, int h, + int tabIndex) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a tab of a tabbed pane. This implementation + * invokes the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param tabIndex Index of tab being painted. + * @param orientation One of JTabbedPane.TOP, + * JTabbedPane.LEFT, + * JTabbedPane.BOTTOM, or + * JTabbedPane.RIGHT + * @since 1.6 + */ + public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, + int x, int y, int w, int h, + int tabIndex, int orientation) { + if (orientation == JTabbedPane.LEFT) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(context, g, y, x, h, w, transform); + } else if (orientation == JTabbedPane.RIGHT) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintBackground(context, g, y, 0, h, w, transform); + } else if (orientation == JTabbedPane.BOTTOM) { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(1, -1); + transform.translate(0,-h); + paintBackground(context, g, 0, 0, w, h, transform); + } else { + paintBackground(context, g, x, y, w, h, null); + } + } + + /** + * Paints the border of a tab of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param tabIndex Index of tab being painted. + */ + public void paintTabbedPaneTabBorder(SynthContext context, Graphics g, + int x, int y, int w, int h, + int tabIndex) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a tab of a tabbed pane. This implementation invokes + * the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param tabIndex Index of tab being painted. + * @param orientation One of JTabbedPane.TOP, + * JTabbedPane.LEFT, + * JTabbedPane.BOTTOM, or + * JTabbedPane.RIGHT + * @since 1.6 + */ + public void paintTabbedPaneTabBorder(SynthContext context, Graphics g, + int x, int y, int w, int h, + int tabIndex, int orientation) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the area that contains the content of the + * selected tab of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTabbedPaneContentBackground(SynthContext context, + Graphics g, int x, int y, int w, + int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the area that contains the content of the + * selected tab of a tabbed pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTabbedPaneContentBorder(SynthContext context, Graphics g, + int x, int y, int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the header of a table. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTableHeaderBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the header of a table. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTableHeaderBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a table. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTableBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a table. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTableBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a text area. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTextAreaBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a text area. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTextAreaBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a text pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTextPaneBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a text pane. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTextPaneBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a text field. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTextFieldBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + if (context.getComponent().getComponentOrientation().isLeftToRight()){ + paintBackground(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBackground(context, g, 0, 0, w, h, transform); + } + } + + /** + * Paints the border of a text field. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTextFieldBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + if (context.getComponent().getComponentOrientation().isLeftToRight()){ + paintBorder(context, g, x, y, w, h, null); + } else { + AffineTransform transform = new AffineTransform(); + transform.translate(x,y); + transform.scale(-1, 1); + transform.translate(-w,0); + paintBorder(context, g, 0, 0, w, h, transform); + } + } + + /** + * Paints the background of a toggle button. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToggleButtonBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a toggle button. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToggleButtonBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a tool bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a tool bar. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JToolBar.HORIZONTAL or + * JToolBar.VERTICAL + * @since 1.6 + */ + public void paintToolBarBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of a tool bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a tool bar. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JToolBar.HORIZONTAL or + * JToolBar.VERTICAL + * @since 1.6 + */ + public void paintToolBarBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of the tool bar's content area. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolBarContentBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the tool bar's content area. This implementation + * invokes the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JToolBar.HORIZONTAL or + * JToolBar.VERTICAL + * @since 1.6 + */ + public void paintToolBarContentBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of the content area of a tool bar. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolBarContentBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the content area of a tool bar. This implementation + * invokes the method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JToolBar.HORIZONTAL or + * JToolBar.VERTICAL + * @since 1.6 + */ + public void paintToolBarContentBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of the window containing the tool bar when it + * has been detached from its primary frame. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolBarDragWindowBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the window containing the tool bar when it + * has been detached from its primary frame. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JToolBar.HORIZONTAL or + * JToolBar.VERTICAL + * @since 1.6 + */ + public void paintToolBarDragWindowBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBackground(context, g, x, y, w, h, orientation); + } + + /** + * Paints the border of the window containing the tool bar when it + * has been detached from it's primary frame. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolBarDragWindowBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the window containing the tool bar when it + * has been detached from it's primary frame. This implementation invokes the + * method of the same name without the orientation. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + * @param orientation One of JToolBar.HORIZONTAL or + * JToolBar.VERTICAL + * @since 1.6 + */ + public void paintToolBarDragWindowBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h, int orientation) { + paintBorder(context, g, x, y, w, h, orientation); + } + + /** + * Paints the background of a tool tip. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolTipBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a tool tip. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintToolTipBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of a tree. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTreeBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a tree. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTreeBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the background of the row containing a cell in a tree. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTreeCellBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of the row containing a cell in a tree. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTreeCellBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } + + /** + * Paints the focus indicator for a cell in a tree when it has focus. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintTreeCellFocus(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + //TODO + } + + /** + * Paints the background of the viewport. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintViewportBackground(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBackground(context, g, x, y, w, h, null); + } + + /** + * Paints the border of a viewport. + * + * @param context SynthContext identifying the JComponent and + * Region to paint to + * @param g Graphics to paint to + * @param x X coordinate of the area to paint to + * @param y Y coordinate of the area to paint to + * @param w Width of the area to paint to + * @param h Height of the area to paint to + */ + public void paintViewportBorder(SynthContext context, + Graphics g, int x, int y, + int w, int h) { + paintBorder(context, g, x, y, w, h, null); + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/TableScrollPaneCorner.java b/src/share/classes/javax/swing/plaf/nimbus/TableScrollPaneCorner.java new file mode 100644 index 0000000000000000000000000000000000000000..367fbff9b3863c0d88ef12a7b6bdae4c6e6fd50e --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/TableScrollPaneCorner.java @@ -0,0 +1,68 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package javax.swing.plaf.nimbus; + +import javax.swing.Painter; + +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.plaf.UIResource; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Color; +import java.awt.image.BufferedImage; + +/** + * TableScrollPaneCorner - A simple component that paints itself using the table + * header background painter. It is used to fill the top right corner of + * scrollpane. + * + * @author Created by Jasper Potts (Jan 28, 2008) + */ +class TableScrollPaneCorner extends JComponent implements UIResource{ + + /** + * Paint the component using the Nimbus Table Header Background Painter + */ + @Override protected void paintComponent(Graphics g) { + Painter painter = (Painter) UIManager.get( + "TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter"); + if (painter != null){ + if (g instanceof Graphics2D){ + painter.paint((Graphics2D)g,this,getWidth()+1,getHeight()); + } else { + // paint using image to not Graphics2D to support + // Java 1.1 printing API + BufferedImage img = new BufferedImage(getWidth(),getHeight(), + BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D)img.getGraphics(); + painter.paint(g2,this,getWidth()+1,getHeight()); + g2.dispose(); + g.drawImage(img,0,0,null); + img = null; + } + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/ToolBarSeparatorPainter.java b/src/share/classes/javax/swing/plaf/nimbus/ToolBarSeparatorPainter.java new file mode 100644 index 0000000000000000000000000000000000000000..4ea45e16b029d5d67e5cfe76e86768de3e04014f --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/ToolBarSeparatorPainter.java @@ -0,0 +1,71 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.plaf.nimbus; + +import javax.swing.plaf.nimbus.AbstractRegionPainter.PaintContext.CacheMode; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import javax.swing.JComponent; + +/** + * A special painter implementation for tool bar separators in Nimbus. + * The designer tool doesn't have support for painters which render + * repeated patterns, but that's exactly what the toolbar separator design + * is for Nimbus. This custom painter is designed to handle this situation. + * When support is added to the design tool / code generator to deal with + * repeated patterns, then we can remove this class. + *

+ */ +final class ToolBarSeparatorPainter extends AbstractRegionPainter { + private static final int SPACE = 3; + private static final int INSET = 2; + + @Override + protected PaintContext getPaintContext() { + //the paint context returned will have a few dummy values. The + //implementation of doPaint doesn't bother with the "decode" methods + //but calculates where to paint the circles manually. As such, we + //only need to indicate in our PaintContext that we don't want this + //to ever be cached + return new PaintContext( + new Insets(1, 0, 1, 0), + new Dimension(38, 7), + false, CacheMode.NO_CACHING, 1, 1); + } + + @Override + protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) { + //it is assumed that in the normal orientation the separator renders + //horizontally. Other code rotates it as necessary for a vertical + //separator. + g.setColor(c.getForeground()); + int y = height / 2; + for (int i=INSET; i<=width-INSET; i+=SPACE) { + g.fillRect(i, y, 1, 1); + } + } +} diff --git a/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html b/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html new file mode 100644 index 0000000000000000000000000000000000000000..1e170c4d3209206a223a7320b111a0553eb6ef5b --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html @@ -0,0 +1,207 @@ + + + + + +

Primary Colors

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValuePreview
control
#d6d9df (214,217,223)
 
info
#f2f2bd (242,242,189)
 
nimbusAlertYellow
#ffdc23 (255,220,35)
 
nimbusBase
#33628c (51,98,140)
 
nimbusDisabledText
#8e8f91 (142,143,145)
 
nimbusFocus
#73a4d1 (115,164,209)
 
nimbusGreen
#b0b332 (176,179,50)
 
nimbusInfoBlue
#2f5cb4 (47,92,180)
 
nimbusLightBackground
#ffffff (255,255,255)
 
nimbusOrange
#bf6204 (191,98,4)
 
nimbusRed
#a92e22 (169,46,34)
 
nimbusSelectedText
#ffffff (255,255,255)
 
nimbusSelectionBackground
#39698a (57,105,138)
 
text
#000000 (0,0,0)
 
+ +

Secondary Colors

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValuePreview
activeCaption
#babec6 (186,190,198)
 
background
#d6d9df (214,217,223)
 
controlDkShadow
#a4abb8 (164,171,184)
 
controlHighlight
#e9ecf2 (233,236,242)
 
controlLHighlight
#f7f8fa (247,248,250)
 
controlShadow
#ccd3e0 (204,211,224)
 
controlText
#000000 (0,0,0)
 
desktop
#3d6079 (61,96,121)
 
inactiveCaption
#bdc1c8 (189,193,200)
 
infoText
#000000 (0,0,0)
 
menu
#edeff2 (237,239,242)
 
menuText
#000000 (0,0,0)
 
nimbusBlueGrey
#a9b0be (169,176,190)
 
nimbusBorder
#9297a1 (146,151,161)
 
nimbusSelection
#39698a (57,105,138)
 
scrollbar
#cdd0d5 (205,208,213)
 
textBackground
#39698a (57,105,138)
 
textForeground
#000000 (0,0,0)
 
textHighlight
#39698a (57,105,138)
 
textHighlightText
#ffffff (255,255,255)
 
textInactiveText
#8e8f91 (142,143,145)
 
+ + + diff --git a/src/share/classes/javax/swing/plaf/nimbus/package.html b/src/share/classes/javax/swing/plaf/nimbus/package.html new file mode 100644 index 0000000000000000000000000000000000000000..bd3a0f4f4f189de869cb7ae7a1ba20915dd99af4 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/package.html @@ -0,0 +1,102 @@ + + + + + + + + +Provides user interface objects built according to the cross-platform +Nimbus look and feel. + +

Nimbus uses instances of the {@link javax.swing.Painter} interface to paint +components. With each Swing component it associates a foreground and a +background {@code Painter}, and there may be several painters for different +component states. + +

Nimbus allows customizing many of its properties, including painters, by +altering the {@link UIDefaults} table. Here's an example: +

+    UIManager.put("ProgressBar.tileWidth", myTileWidth);
+    UIManager.put("ProgressBar[Enabled].backgroundPainter", myBgPainter);
+    UIManager.put("ProgressBar[Enabled].foregroundPainter", myFgPainter);
+
+ +

Per-component customization is also possible. When rendering a component, +Nimbus checks its client property named "Nimbus.Overrides". The value of this +property should be an instance of {@code UIDefaults}. Settings from that table +override the UIManager settings, but for that particular component instance +only. An optional client property, "Nimbus.Overrides.InheritDefaults" of type +Boolean, specifies whether the overriding settings should be merged with +default ones ({@code true}), or replace them ({@code false}). By default they +are merged: +

+    JProgressBar bar = new JProgressBar();
+    UIDefaults overrides = new UIDefaults();
+    overrides.put("ProgressBar.cycleTime", 330);
+    ...
+    bar.putClientProperty("Nimbus.Overrides", overrides);
+    bar.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
+
+ +

Colors in Nimbus are derived from a core set of +primary colors. There are also +secondary colors, which are +derived from primary ones, but serve themselves as base colors for other +derived colors. The derivation mechanism allows for runtime customization, +i.e. if a primary or secondary color is changed, all colors that are derived +from it are automatically updated. The method +{@link javax.swing.plaf.nimbus.NimbusLookAndFeel#getDerivedColor(java.lang.String, float, float, float, int, boolean)} +may be used to create a derived color. + +

These classes are designed to be used while the +corresponding LookAndFeel class has been +installed +(UIManager.setLookAndFeel(new XXXLookAndFeel())). +Using them while a different LookAndFeel is installed +may produce unexpected results, including exceptions. +Additionally, changing the LookAndFeel +maintained by the UIManager without updating the +corresponding ComponentUI of any +JComponents may also produce unexpected results, +such as the wrong colors showing up, and is generally not +encouraged. + +

Note: +Most of the Swing API is not thread safe. +For details, see +Threads and Swing, +a section in +The Java Tutorial. + +@since 1.7 +@serial exclude + + + diff --git a/src/share/classes/javax/swing/plaf/nimbus/skin.laf b/src/share/classes/javax/swing/plaf/nimbus/skin.laf new file mode 100644 index 0000000000000000000000000000000000000000..ac2867b59994b72eb11949129d577f21ca79a93c --- /dev/null +++ b/src/share/classes/javax/swing/plaf/nimbus/skin.laf @@ -0,0 +1,28332 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 7 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 6 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 5 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 4 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + 1.0 + 1.0 + NORMAL + false + false + + + + + + + + + + + 3 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + 1.0 + 1.0 + NORMAL + false + true + + + + + + + + + + + + diff --git a/src/share/classes/javax/swing/plaf/synth/SynthArrowButton.java b/src/share/classes/javax/swing/plaf/synth/SynthArrowButton.java index 33adfc5317050d3f142d32bba581e191a9e9462a..edfd89680a62922a9c10f83f421d167d8a17ffc8 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthArrowButton.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthArrowButton.java @@ -113,6 +113,31 @@ class SynthArrowButton extends JButton implements SwingConstants, UIResource { context.getStyle().getInt(context, "ArrowButton.size", 16); dim = new Dimension(size, size); } + + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + Container parent = context.getComponent().getParent(); + if (parent instanceof JComponent && !(parent instanceof JComboBox)) { + Object scaleKey = ((JComponent)parent). + getClientProperty("JComponent.sizeVariant"); + if (scaleKey != null){ + if ("large".equals(scaleKey)){ + dim = new Dimension( + (int)(dim.width * 1.15), + (int)(dim.height * 1.15)); + } else if ("small".equals(scaleKey)){ + dim = new Dimension( + (int)(dim.width * 0.857), + (int)(dim.height * 0.857)); + } else if ("mini".equals(scaleKey)){ + dim = new Dimension( + (int)(dim.width * 0.714), + (int)(dim.height * 0.714)); + } + } + } + context.dispose(); return dim; } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java b/src/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java index 6b8d4bbc999df766275bc82104ebe8a2dd9b6b1b..7687a0d7bcbcbc66a4c6ce2ec4ecf3c1bb9352d8 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java @@ -29,16 +29,11 @@ import java.awt.*; import java.awt.event.*; import java.lang.reflect.*; import javax.swing.*; -import javax.accessibility.*; -import javax.swing.FocusManager; import javax.swing.plaf.*; -import javax.swing.border.*; -import javax.swing.text.*; import javax.swing.event.*; import javax.swing.plaf.basic.*; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import sun.awt.AppContext; import sun.swing.plaf.synth.SynthUI; /** @@ -51,11 +46,93 @@ class SynthComboBoxUI extends BasicComboBoxUI implements private SynthStyle style; private boolean useListColors; + /** + * Used to adjust the location and size of the popup. Very useful for + * situations such as we find in Nimbus where part of the border is used + * to paint the focus. In such cases, the border is empty space, and not + * part of the "visual" border, and in these cases, you'd like the popup + * to be adjusted such that it looks as if it were next to the visual border. + * You may want to use negative insets to get the right look. + */ + Insets popupInsets; + + /** + * This flag may be set via UIDefaults. By default, it is false, to + * preserve backwards compatibility. If true, then the combo will + * "act as a button" when it is not editable. + */ + private boolean buttonWhenNotEditable; + + /** + * A flag to indicate that the combo box and combo box button should + * remain in the PRESSED state while the combo popup is visible. + */ + private boolean pressedWhenPopupVisible; + + /** + * When buttonWhenNotEditable is true, this field is used to help make + * the combo box appear and function as a button when the combo box is + * not editable. In such a state, you can click anywhere on the button + * to get it to open the popup. Also, anywhere you hover over the combo + * will cause the entire combo to go into "rollover" state, and anywhere + * you press will go into "pressed" state. This also keeps in sync the + * state of the combo and the arrowButton. + */ + private ButtonHandler buttonHandler; + + /** + * Handler for repainting combo when editor component gains/looses focus + */ + private EditorFocusHandler editorFocusHandler; + + /** + * If true, then the cell renderer will be forced to be non-opaque when + * used for rendering the selected item in the combo box (not in the list), + * and forced to opaque after rendering the selected value. + */ + private boolean forceOpaque = false; + + /** + * NOTE: This serves the same purpose as the same field in BasicComboBoxUI. + * It is here because I could not give the padding field in + * BasicComboBoxUI protected access in an update release. + */ + private Insets padding; + public static ComponentUI createUI(JComponent c) { return new SynthComboBoxUI(); } + /** + * @inheritDoc + * + * Overridden to ensure that ButtonHandler is created prior to any of + * the other installXXX methods, since several of them reference + * buttonHandler. + */ + @Override + public void installUI(JComponent c) { + buttonHandler = new ButtonHandler(); + super.installUI(c); + } + + @Override protected void installDefaults() { + //NOTE: This next line of code was added because, since squareButton in + //BasicComboBoxUI is private, I need to have some way of reading it from UIManager. + //This is an incomplete solution (since it implies that squareButons, + //once set, cannot be reset per state. Probably ok, but not always ok). + //This line of code should be removed at the same time that squareButton + //is made protected in the super class. + super.installDefaults(); + + //This is here instead of in updateStyle because the value for padding + //needs to remain consistent with the value for padding in + //BasicComboBoxUI. I wouldn't have this value here at all if not + //for the fact that I cannot make "padding" protected in any way + //for an update release. This *should* be fixed in Java 7 + padding = UIManager.getInsets("ComboBox.padding"); + updateStyle(comboBox); } @@ -65,12 +142,20 @@ class SynthComboBoxUI extends BasicComboBoxUI implements style = SynthLookAndFeel.updateStyle(context, this); if (style != oldStyle) { + popupInsets = (Insets)style.get(context, "ComboBox.popupInsets"); useListColors = style.getBoolean(context, - "ComboBox.rendererUseListColors", true); + "ComboBox.rendererUseListColors", true); + buttonWhenNotEditable = style.getBoolean(context, + "ComboBox.buttonWhenNotEditable", false); + pressedWhenPopupVisible = style.getBoolean(context, + "ComboBox.pressedWhenPopupVisible", false); + if (oldStyle != null) { uninstallKeyboardActions(); installKeyboardActions(); } + forceOpaque = style.getBoolean(context, + "ComboBox.forceOpaque", false); } context.dispose(); @@ -79,11 +164,24 @@ class SynthComboBoxUI extends BasicComboBoxUI implements } } + @Override protected void installListeners() { comboBox.addPropertyChangeListener(this); + comboBox.addMouseListener(buttonHandler); + editorFocusHandler = new EditorFocusHandler(comboBox); super.installListeners(); } + @Override + public void uninstallUI(JComponent c) { + if (popup instanceof SynthComboPopup) { + ((SynthComboPopup)popup).removePopupMenuListener(buttonHandler); + } + super.uninstallUI(c); + buttonHandler = null; + } + + @Override protected void uninstallDefaults() { SynthContext context = getContext(comboBox, ENABLED); @@ -92,11 +190,17 @@ class SynthComboBoxUI extends BasicComboBoxUI implements style = null; } + @Override protected void uninstallListeners() { + editorFocusHandler.unregister(); comboBox.removePropertyChangeListener(this); + comboBox.removeMouseListener(buttonHandler); + buttonHandler.pressed = false; + buttonHandler.over = false; super.uninstallListeners(); } + @Override public SynthContext getContext(JComponent c) { return getContext(c, getComponentState(c)); } @@ -111,18 +215,56 @@ class SynthComboBoxUI extends BasicComboBoxUI implements } private int getComponentState(JComponent c) { - return SynthLookAndFeel.getComponentState(c); + // currently we have a broken situation where if a developer + // takes the border from a JComboBox and sets it on a JTextField + // then the codepath will eventually lead back to this method + // but pass in a JTextField instead of JComboBox! In case this + // happens, we just return the normal synth state for the component + // instead of doing anything special + if (!(c instanceof JComboBox)) return SynthLookAndFeel.getComponentState(c); + + JComboBox box = (JComboBox)c; + if (shouldActLikeButton()) { + int state = ENABLED; + if ((!c.isEnabled())) { + state = DISABLED; + } + if (buttonHandler.isPressed()) { + state |= PRESSED; + } + if (buttonHandler.isRollover()) { + state |= MOUSE_OVER; + } + if (box.isFocusOwner()) { + state |= FOCUSED; + } + return state; + } else { + // for editable combos the editor component has the focus not the + // combo box its self, so we should make the combo paint focused + // when its editor has focus + int basicState = SynthLookAndFeel.getComponentState(c); + if (box.isEditable() && + box.getEditor().getEditorComponent().isFocusOwner()) { + basicState |= FOCUSED; + } + return basicState; + } } + @Override protected ComboPopup createPopup() { - SynthComboPopup popup = new SynthComboPopup( comboBox ); - return popup; + SynthComboPopup p = new SynthComboPopup(comboBox); + p.addPopupMenuListener(buttonHandler); + return p; } + @Override protected ListCellRenderer createRenderer() { return new SynthComboBoxRenderer(); } + @Override protected ComboBoxEditor createEditor() { return new SynthComboBoxEditor(); } @@ -131,22 +273,25 @@ class SynthComboBoxUI extends BasicComboBoxUI implements // end UI Initialization //====================== - + @Override public void propertyChange(PropertyChangeEvent e) { if (SynthLookAndFeel.shouldUpdateStyle(e)) { updateStyle(comboBox); } } + @Override protected JButton createArrowButton() { SynthArrowButton button = new SynthArrowButton(SwingConstants.SOUTH); button.setName("ComboBox.arrowButton"); + button.setModel(buttonHandler); return button; } //================================= // begin ComponentUI Implementation + @Override public void update(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -157,6 +302,7 @@ class SynthComboBoxUI extends BasicComboBoxUI implements context.dispose(); } + @Override public void paint(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -172,33 +318,23 @@ class SynthComboBoxUI extends BasicComboBoxUI implements } } + @Override public void paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { context.getPainter().paintComboBoxBorder(context, g, x, y, w, h); } - /** * Paints the currently selected item. */ + @Override public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) { ListCellRenderer renderer = comboBox.getRenderer(); Component c; - if ( hasFocus && !isPopupVisible(comboBox) ) { - c = renderer.getListCellRendererComponent( listBox, - comboBox.getSelectedItem(), - -1, - false, - false ); - } - else { - c = renderer.getListCellRendererComponent( listBox, - comboBox.getSelectedItem(), - -1, - false, - false ); - } + c = renderer.getListCellRendererComponent( + listBox, comboBox.getSelectedItem(), -1, false, false ); + // Fix for 4238829: should lay out the JPanel. boolean shouldValidate = false; if (c instanceof JPanel) { @@ -207,36 +343,88 @@ class SynthComboBoxUI extends BasicComboBoxUI implements if (c instanceof UIResource) { c.setName("ComboBox.renderer"); - currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y, - bounds.width,bounds.height, shouldValidate); } - else { - currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y, - bounds.width,bounds.height, shouldValidate); + + boolean force = forceOpaque && c instanceof JComponent; + if (force) { + ((JComponent)c).setOpaque(false); + } + + int x = bounds.x, y = bounds.y, w = bounds.width, h = bounds.height; + if (padding != null) { + x = bounds.x + padding.left; + y = bounds.y + padding.top; + w = bounds.width - (padding.left + padding.right); + h = bounds.height - (padding.top + padding.bottom); + } + + currentValuePane.paintComponent(g, c, comboBox, x, y, w, h, shouldValidate); + + if (force) { + ((JComponent)c).setOpaque(true); } } + /** + * @return true if this combo box should act as one big button. Typically + * only happens when buttonWhenNotEditable is true, and comboBox.isEditable + * is false. + */ + private boolean shouldActLikeButton() { + return buttonWhenNotEditable && !comboBox.isEditable(); + } + + /** + * Return the default size of an empty display area of the combo box using + * the current renderer and font. + * + * This method was overridden to use SynthComboBoxRenderer instead of + * DefaultListCellRenderer as the default renderer when calculating the + * size of the combo box. This is used in the case of the combo not having + * any data. + * + * @return the size of an empty display area + * @see #getDisplaySize + */ + @Override + protected Dimension getDefaultSize() { + SynthComboBoxRenderer r = new SynthComboBoxRenderer(); + Dimension d = getSizeForComponent(r.getListCellRendererComponent(listBox, " ", -1, false, false)); + return new Dimension(d.width, d.height); + } + + /** + * This has been refactored out in hopes that it may be investigated and + * simplified for the next major release. adding/removing + * the component to the currentValuePane and changing the font may be + * redundant operations. + * + * NOTE: This method was copied in its entirety from BasicComboBoxUI. Might + * want to make it protected in BasicComboBoxUI in Java 7 + */ + private Dimension getSizeForComponent(Component comp) { + currentValuePane.add(comp); + comp.setFont(comboBox.getFont()); + Dimension d = comp.getPreferredSize(); + currentValuePane.remove(comp); + return d; + } + /** * From BasicComboBoxRenderer v 1.18. + * + * Be aware that SynthFileChooserUIImpl relies on the fact that the default + * renderer installed on a Synth combo box is a JLabel. If this is changed, + * then an assert will fail in SynthFileChooserUIImpl */ private class SynthComboBoxRenderer extends JLabel implements ListCellRenderer, UIResource { public SynthComboBoxRenderer() { super(); + setName("ComboBox.renderer"); setText(" "); } - public String getName() { - // As SynthComboBoxRenderer's are asked for a size BEFORE they - // are parented getName is overriden to force the name to be - // ComboBox.renderer if it isn't set. If we didn't do this the - // wrong style could be used for size calculations. - String name = super.getName(); - if (name == null) { - return "ComboBox.renderer"; - } - return name; - } - + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setName("ComboBox.listRenderer"); @@ -250,8 +438,7 @@ class SynthComboBoxUI extends BasicComboBoxUI implements SynthLabelUI.class), isSelected, cellHasFocus, list.isEnabled(), false); } - } - else { + } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } @@ -261,8 +448,7 @@ class SynthComboBoxUI extends BasicComboBoxUI implements if (value instanceof Icon) { setIcon((Icon)value); setText(""); - } - else { + } else { String text = (value == null) ? " " : value.toString(); if ("".equals(text)) { @@ -276,12 +462,15 @@ class SynthComboBoxUI extends BasicComboBoxUI implements // especially needed for GTK comboboxes, where the // ListCellRenderer's state determines the visual state // of the combobox. - setEnabled(comboBox.isEnabled()); - setComponentOrientation(comboBox.getComponentOrientation()); + if (comboBox != null){ + setEnabled(comboBox.isEnabled()); + setComponentOrientation(comboBox.getComponentOrientation()); + } return this; } + @Override public void paint(Graphics g) { super.paint(g); SynthLookAndFeel.resetSelectedUI(); @@ -302,6 +491,7 @@ class SynthComboBoxUI extends BasicComboBoxUI implements editor.setName("ComboBox.textField"); } + @Override public Component getEditorComponent() { return editor; } @@ -311,6 +501,7 @@ class SynthComboBoxUI extends BasicComboBoxUI implements * * @param anObject the displayed value of the editor */ + @Override public void setItem(Object anObject) { String text; @@ -326,6 +517,7 @@ class SynthComboBoxUI extends BasicComboBoxUI implements } } + @Override public Object getItem() { Object newValue = editor.getText(); @@ -348,17 +540,261 @@ class SynthComboBoxUI extends BasicComboBoxUI implements return newValue; } + @Override public void selectAll() { editor.selectAll(); editor.requestFocus(); } + @Override public void addActionListener(ActionListener l) { editor.addActionListener(l); } + @Override public void removeActionListener(ActionListener l) { editor.removeActionListener(l); } } + + /** + * Handles all the logic for treating the combo as a button when it is + * not editable, and when shouldActLikeButton() is true. This class is a + * special ButtonModel, and installed on the arrowButton when appropriate. + * It also is installed as a mouse listener and mouse motion listener on + * the combo box. In this way, the state between the button and combo + * are in sync. Whenever one is "over" both are. Whenever one is pressed, + * both are. + */ + private final class ButtonHandler extends DefaultButtonModel + implements MouseListener, PopupMenuListener { + /** + * Indicates that the mouse is over the combo or the arrow button. + * This field only has meaning if buttonWhenNotEnabled is true. + */ + private boolean over; + /** + * Indicates that the combo or arrow button has been pressed. This + * field only has meaning if buttonWhenNotEnabled is true. + */ + private boolean pressed; + + //------------------------------------------------------------------ + // State Methods + //------------------------------------------------------------------ + + /** + *

Updates the internal "pressed" state. If shouldActLikeButton() + * is true, and if this method call will change the internal state, + * then the combo and button will be repainted.

+ * + *

Note that this method is called either when a press event + * occurs on the combo box, or on the arrow button.

+ */ + private void updatePressed(boolean p) { + this.pressed = p && isEnabled(); + if (shouldActLikeButton()) { + comboBox.repaint(); + } + } + + /** + *

Updates the internal "over" state. If shouldActLikeButton() + * is true, and if this method call will change the internal state, + * then the combo and button will be repainted.

+ * + *

Note that this method is called either when a mouseover/mouseoff event + * occurs on the combo box, or on the arrow button.

+ */ + private void updateOver(boolean o) { + boolean old = isRollover(); + this.over = o && isEnabled(); + boolean newo = isRollover(); + if (shouldActLikeButton() && old != newo) { + comboBox.repaint(); + } + } + + //------------------------------------------------------------------ + // DefaultButtonModel Methods + //------------------------------------------------------------------ + + /** + * {@inheritDoc} + * + * Ensures that isPressed() will return true if the combo is pressed, + * or the arrowButton is pressed, or if the combo popup is + * visible. This is the case because a combo box looks pressed when + * the popup is visible, and so should the arrow button. + */ + @Override + public boolean isPressed() { + boolean b = shouldActLikeButton() ? pressed : super.isPressed(); + return b || (pressedWhenPopupVisible && comboBox.isPopupVisible()); + } + + /** + * {@inheritDoc} + * + * Ensures that the armed state is in sync with the pressed state + * if shouldActLikeButton is true. Without this method, the arrow + * button will not look pressed when the popup is open, regardless + * of the result of isPressed() alone. + */ + @Override + public boolean isArmed() { + boolean b = shouldActLikeButton() || + (pressedWhenPopupVisible && comboBox.isPopupVisible()); + return b ? isPressed() : super.isArmed(); + } + + /** + * {@inheritDoc} + * + * Ensures that isRollover() will return true if the combo is + * rolled over, or the arrowButton is rolled over. + */ + @Override + public boolean isRollover() { + return shouldActLikeButton() ? over : super.isRollover(); + } + + /** + * {@inheritDoc} + * + * Forwards pressed states to the internal "pressed" field + */ + @Override + public void setPressed(boolean b) { + super.setPressed(b); + updatePressed(b); + } + + /** + * {@inheritDoc} + * + * Forwards rollover states to the internal "over" field + */ + @Override + public void setRollover(boolean b) { + super.setRollover(b); + updateOver(b); + } + + //------------------------------------------------------------------ + // MouseListener/MouseMotionListener Methods + //------------------------------------------------------------------ + + @Override + public void mouseEntered(MouseEvent mouseEvent) { + updateOver(true); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) { + updateOver(false); + } + + @Override + public void mousePressed(MouseEvent mouseEvent) { + updatePressed(true); + } + + @Override + public void mouseReleased(MouseEvent mouseEvent) { + updatePressed(false); + } + + @Override + public void mouseClicked(MouseEvent e) {} + + //------------------------------------------------------------------ + // PopupMenuListener Methods + //------------------------------------------------------------------ + + /** + * @inheritDoc + * + * Ensures that the combo box is repainted when the popup is closed. + * This avoids a bug where clicking off the combo wasn't causing a repaint, + * and thus the combo box still looked pressed even when it was not. + * + * This bug was only noticed when acting as a button, but may be generally + * present. If so, remove the if() block + */ + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + if (shouldActLikeButton() || pressedWhenPopupVisible) { + comboBox.repaint(); + } + } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} + } + + /** + * Handler for repainting combo when editor component gains/looses focus + */ + private static class EditorFocusHandler implements FocusListener, + PropertyChangeListener { + private JComboBox comboBox; + private ComboBoxEditor editor = null; + private Component editorComponent = null; + + private EditorFocusHandler(JComboBox comboBox) { + this.comboBox = comboBox; + editor = comboBox.getEditor(); + if (editor != null){ + editorComponent = editor.getEditorComponent(); + if (editorComponent != null){ + editorComponent.addFocusListener(this); + } + } + comboBox.addPropertyChangeListener("editor",this); + } + + public void unregister(){ + comboBox.removePropertyChangeListener(this); + if (editorComponent!=null){ + editorComponent.removeFocusListener(this); + } + } + + /** Invoked when a component gains the keyboard focus. */ + public void focusGained(FocusEvent e) { + // repaint whole combo on focus gain + comboBox.repaint(); + } + + /** Invoked when a component loses the keyboard focus. */ + public void focusLost(FocusEvent e) { + // repaint whole combo on focus loss + comboBox.repaint(); + } + + /** + * Called when the combos editor changes + * + * @param evt A PropertyChangeEvent object describing the event source and + * the property that has changed. + */ + public void propertyChange(PropertyChangeEvent evt) { + ComboBoxEditor newEditor = comboBox.getEditor(); + if (editor != newEditor){ + if (editorComponent!=null){ + editorComponent.removeFocusListener(this); + } + editor = newEditor; + if (editor != null){ + editorComponent = editor.getEditorComponent(); + if (editorComponent != null){ + editorComponent.addFocusListener(this); + } + } + } + } + } } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java b/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java index 178981fd8fcf92edea97b622ab25f790aaf6d2dd..976ec0adc6607476ce2b297e71df99de3c58400e 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java @@ -138,9 +138,9 @@ public class SynthLookAndFeel extends BasicLookAndFeel { } } else { - selectedUIState = SynthConstants.FOCUSED; if (enabled) { selectedUIState |= SynthConstants.ENABLED; + selectedUIState = SynthConstants.FOCUSED; } else { selectedUIState |= SynthConstants.DISABLED; @@ -251,6 +251,26 @@ public class SynthLookAndFeel extends BasicLookAndFeel { ((SynthLookAndFeel)laf). shouldUpdateStyleOnAncestorChanged()); } + // Note: The following two nimbus based overrides should be refactored + // to be in the Nimbus LAF. Due to constraints in an update release, + // we couldn't actually provide the public API necessary to allow + // NimbusLookAndFeel (a subclass of SynthLookAndFeel) to provide its + // own rules for shouldUpdateStyle. + else if ("Nimbus.Overrides" == eName) { + // Always update when the Nimbus.Overrides client property has + // been changed + return true; + } + else if ("Nimbus.Overrides.InheritDefaults" == eName) { + // Always update when the Nimbus.Overrides.InheritDefaults + // client property has changed + return true; + } + else if ("JComponent.sizeVariant" == eName) { + // Always update when the JComponent.sizeVariant + // client property has changed + return true; + } return false; } @@ -622,6 +642,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { /** * Called by UIManager when this look and feel is installed. */ + @Override public void initialize() { super.initialize(); DefaultLookup.setDefaultLookup(new SynthDefaultLookup()); @@ -633,6 +654,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { /** * Called by UIManager when this look and feel is uninstalled. */ + @Override public void uninitialize() { KeyboardFocusManager.getCurrentKeyboardFocusManager(). removePropertyChangeListener(_handler); @@ -647,6 +669,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { * * @return Defaults table. */ + @Override public UIDefaults getDefaults() { UIDefaults table = new UIDefaults(60, 0.75f); @@ -704,6 +727,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { * * @return true. */ + @Override public boolean isSupportedLookAndFeel() { return true; } @@ -713,6 +737,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { * * @return false */ + @Override public boolean isNativeLookAndFeel() { return false; } @@ -722,6 +747,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { * * @return textual description of synth. */ + @Override public String getDescription() { return "Synth look and feel"; } @@ -731,6 +757,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { * * @return a short string identifying this look and feel. */ + @Override public String getName() { return "Synth look and feel"; } @@ -740,6 +767,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { * * @return a short string identifying this look and feel. */ + @Override public String getID() { return "Synth"; } @@ -805,6 +833,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { tk.addPropertyChangeListener(key, this); } + @Override public void propertyChange(PropertyChangeEvent pce) { UIDefaults defaults = UIManager.getLookAndFeelDefaults(); if (defaults.getBoolean("Synth.doNotSetTextAA")) { @@ -873,6 +902,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { if (!isUpdatePending()) { setUpdatePending(true); Runnable uiUpdater = new Runnable() { + @Override public void run() { updateAllUIs(); setUpdatePending(false); @@ -889,6 +919,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel { } private class Handler implements PropertyChangeListener { + @Override public void propertyChange(PropertyChangeEvent evt) { String propertyName = evt.getPropertyName(); Object newValue = evt.getNewValue(); diff --git a/src/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java b/src/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java index 93c66c376dc7814c0eb8fe80e5e81565f9784d97..c6a75375bf7a7fdc2273aef9cde93c52e3b323d0 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java @@ -27,14 +27,11 @@ package javax.swing.plaf.synth; import java.awt.*; import java.awt.geom.AffineTransform; -import java.awt.event.*; import javax.swing.*; -import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.BasicProgressBarUI; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import java.io.Serializable; import sun.swing.plaf.synth.SynthUI; import sun.swing.SwingUtilities2; @@ -46,24 +43,29 @@ import sun.swing.SwingUtilities2; class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, PropertyChangeListener { private SynthStyle style; - private int progressPadding; + private boolean rotateText; // added for Nimbus LAF private boolean paintOutsideClip; + private boolean tileWhenIndeterminate; //whether to tile indeterminate painting + private int tileWidth; //the width of each tile public static ComponentUI createUI(JComponent x) { return new SynthProgressBarUI(); } + @Override protected void installListeners() { super.installListeners(); progressBar.addPropertyChangeListener(this); } + @Override protected void uninstallListeners() { super.uninstallListeners(); progressBar.removePropertyChangeListener(this); } + @Override protected void installDefaults() { updateStyle(progressBar); } @@ -72,17 +74,34 @@ class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, SynthContext context = getContext(c, ENABLED); SynthStyle oldStyle = style; style = SynthLookAndFeel.updateStyle(context, this); - if (style != oldStyle) { - setCellLength(style.getInt(context, "ProgressBar.cellLength", 1)); - setCellSpacing(style.getInt(context, "ProgressBar.cellSpacing", 0)); - progressPadding = style.getInt(context, - "ProgressBar.progressPadding", 0); - paintOutsideClip = style.getBoolean(context, - "ProgressBar.paintOutsideClip", false); + setCellLength(style.getInt(context, "ProgressBar.cellLength", 1)); + setCellSpacing(style.getInt(context, "ProgressBar.cellSpacing", 0)); + progressPadding = style.getInt(context, + "ProgressBar.progressPadding", 0); + paintOutsideClip = style.getBoolean(context, + "ProgressBar.paintOutsideClip", false); + rotateText = style.getBoolean(context, + "ProgressBar.rotateText", false); + tileWhenIndeterminate = style.getBoolean(context, "ProgressBar.tileWhenIndeterminate", false); + tileWidth = style.getInt(context, "ProgressBar.tileWidth", 15); + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + String scaleKey = (String)progressBar.getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if ("large".equals(scaleKey)){ + tileWidth *= 1.15; + } else if ("small".equals(scaleKey)){ + tileWidth *= 0.857; + } else if ("mini".equals(scaleKey)){ + tileWidth *= 0.784; + } } context.dispose(); } + @Override protected void uninstallDefaults() { SynthContext context = getContext(progressBar, ENABLED); @@ -108,6 +127,7 @@ class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, return SynthLookAndFeel.getComponentState(c); } + @Override public int getBaseline(JComponent c, int width, int height) { super.getBaseline(c, width, height); if (progressBar.isStringPainted() && @@ -122,6 +142,16 @@ class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, return -1; } + @Override + protected Rectangle getBox(Rectangle r) { + if (tileWhenIndeterminate) { + return SwingUtilities.calculateInnerArea(progressBar, r); + } else { + return super.getBox(r); + } + } + + @Override protected void setAnimationIndex(int newValue) { if (paintOutsideClip) { if (getAnimationIndex() == newValue) { @@ -134,6 +164,7 @@ class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, } } + @Override public void update(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -145,6 +176,7 @@ class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, context.dispose(); } + @Override public void paint(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -196,44 +228,98 @@ class SynthProgressBarUI extends BasicProgressBarUI implements SynthUI, width = boxRect.width - progressPadding - progressPadding; height = boxRect.height - progressPadding - progressPadding; } - context.getPainter().paintProgressBarForeground(context, g, - x, y, width, height, pBar.getOrientation()); - if (pBar.isStringPainted() && !pBar.isIndeterminate()) { + //if tiling and indeterminate, then paint the progress bar foreground a + //bit wider than it should be. Shift as needed to ensure that there is + //an animated effect + if (tileWhenIndeterminate && pBar.isIndeterminate()) { + double percentComplete = (double)getAnimationIndex() / (double)getFrameCount(); + int offset = (int)(percentComplete * tileWidth); + Shape clip = g.getClip(); + g.clipRect(x, y, width, height); + if (pBar.getOrientation() == JProgressBar.HORIZONTAL) { + //paint each tile horizontally + for (int i=x-tileWidth+offset; i<=width; i+=tileWidth) { + context.getPainter().paintProgressBarForeground( + context, g, i, y, tileWidth, height, pBar.getOrientation()); + } + } else { //JProgressBar.VERTICAL + //paint each tile vertically + for (int i=y-offset; i size.height) { + size.height = stringHeight; + } + + // adjust the width if necessary to make room for the string + int stringWidth = SwingUtilities2.stringWidth( + progressBar, fontSizer, progString); + if (stringWidth > size.width) { + size.width = stringWidth; + } + } } else { size = new Dimension(getPreferredInnerVertical()); - } - // Ensure that the progress string will fit. - if (progressBar.isStringPainted()) { - String progString = progressBar.getString(); - int stringHeight = fontSizer.getHeight() + - fontSizer.getDescent(); - if (stringHeight > size.height) { - size.height = stringHeight; + if (progressBar.isStringPainted()) { + // make sure the width is big enough for the string + if (stringHeight > size.width) { + size.width = stringHeight; + } + + // make sure the height is big enough for the string + int stringWidth = SwingUtilities2.stringWidth( + progressBar, fontSizer, progString); + if (stringWidth > size.height) { + size.height = stringWidth; + } } - // This is also for completeness. - int stringWidth = SwingUtilities2.stringWidth( - progressBar, fontSizer, progString); - if (stringWidth > size.width) { - size.width = stringWidth; + } + + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + String scaleKey = (String)progressBar.getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if ("large".equals(scaleKey)){ + size.width *= 1.15f; + size.height *= 1.15f; + } else if ("small".equals(scaleKey)){ + size.width *= 0.90f; + size.height *= 0.90f; + } else if ("mini".equals(scaleKey)){ + size.width *= 0.784f; + size.height *= 0.784f; } } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java b/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java index 603810cdafbf53d52c9cd14459d02ac85155d3c3..6a4b2d7da83255b26977214d60fddc1f4f9b3031 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java @@ -26,12 +26,8 @@ package javax.swing.plaf.synth; import java.awt.*; -import java.awt.event.*; - import java.beans.*; - import javax.swing.*; -import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import sun.swing.plaf.synth.SynthUI; @@ -52,12 +48,23 @@ class SynthScrollBarUI extends BasicScrollBarUI implements private boolean validMinimumThumbSize; private int scrollBarWidth; + //These two variables should be removed when the corrosponding ones in BasicScrollBarUI are made protected + private int incrGap; + private int decrGap; public static ComponentUI createUI(JComponent c) { return new SynthScrollBarUI(); } protected void installDefaults() { + //NOTE: This next line of code was added because, since incrGap and decrGap in + //BasicScrollBarUI are private, I need to have some way of updating them. + //This is an incomplete solution (since it implies that the incrGap and decrGap + //are set once, and not reset per state. Probably ok, but not always ok). + //This line of code should be removed at the same time that incrGap and + //decrGap are removed and made protected in the super class. + super.installDefaults(); + trackHighlight = NO_HIGHLIGHT; if (scrollbar.getLayout() == null || (scrollbar.getLayout() instanceof UIResource)) { @@ -89,6 +96,31 @@ class SynthScrollBarUI extends BasicScrollBarUI implements if (maximumThumbSize == null) { maximumThumbSize = new Dimension(4096, 4097); } + + incrGap = style.getInt(context, "ScrollBar.incrementButtonGap", 0); + decrGap = style.getInt(context, "ScrollBar.decrementButtonGap", 0); + + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + String scaleKey = (String)scrollbar.getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if ("large".equals(scaleKey)){ + scrollBarWidth *= 1.15; + incrGap *= 1.15; + decrGap *= 1.15; + } else if ("small".equals(scaleKey)){ + scrollBarWidth *= 0.857; + incrGap *= 0.857; + decrGap *= 0.857; + } else if ("mini".equals(scaleKey)){ + scrollBarWidth *= 0.714; + incrGap *= 0.714; + decrGap *= 0.714; + } + } + if (oldStyle != null) { uninstallKeyboardActions(); installKeyboardActions(); @@ -274,18 +306,56 @@ class SynthScrollBarUI extends BasicScrollBarUI implements } } return minimumThumbSize; - } - protected JButton createDecreaseButton(int orientation) { - SynthArrowButton synthArrowButton = new SynthArrowButton(orientation); + SynthArrowButton synthArrowButton = new SynthArrowButton(orientation) { + @Override + public boolean contains(int x, int y) { + if (decrGap < 0) { //there is an overlap between the track and button + int width = getWidth(); + int height = getHeight(); + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + //adjust the height by decrGap + //Note: decrGap is negative! + height += decrGap; + } else { + //adjust the width by decrGap + //Note: decrGap is negative! + width += decrGap; + } + return (x >= 0) && (x < width) && (y >= 0) && (y < height); + } + return super.contains(x, y); + } + }; synthArrowButton.setName("ScrollBar.button"); return synthArrowButton; } protected JButton createIncreaseButton(int orientation) { - SynthArrowButton synthArrowButton = new SynthArrowButton(orientation); + SynthArrowButton synthArrowButton = new SynthArrowButton(orientation) { + @Override + public boolean contains(int x, int y) { + if (incrGap < 0) { //there is an overlap between the track and button + int width = getWidth(); + int height = getHeight(); + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + //adjust the height and y by incrGap + //Note: incrGap is negative! + height += incrGap; + y += incrGap; + } else { + //adjust the width and x by incrGap + //Note: incrGap is negative! + width += incrGap; + x += incrGap; + } + return (x >= 0) && (x < width) && (y >= 0) && (y < height); + } + return super.contains(x, y); + } + }; synthArrowButton.setName("ScrollBar.button"); return synthArrowButton; } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java b/src/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java index 62f732c9d81a6d0583066e7805a189a1686abcaf..1dfdad63cd89aa83acec564e4a324dc5b7a5e768 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java @@ -26,7 +26,7 @@ package javax.swing.plaf.synth; import javax.swing.*; -import javax.swing.event.*; +import javax.swing.text.JTextComponent; import javax.swing.border.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; @@ -35,7 +35,11 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; import java.awt.*; -import java.awt.event.*; +import java.awt.event.ContainerListener; +import java.awt.event.ContainerEvent; +import java.awt.event.FocusListener; +import java.awt.event.FocusEvent; + import sun.swing.plaf.synth.SynthUI; @@ -47,11 +51,14 @@ import sun.swing.plaf.synth.SynthUI; class SynthScrollPaneUI extends BasicScrollPaneUI implements PropertyChangeListener, SynthUI { private SynthStyle style; + private boolean viewportViewHasFocus = false; + private ViewportViewFocusHandler viewportViewFocusHandler; public static ComponentUI createUI(JComponent x) { return new SynthScrollPaneUI(); } + @Override public void update(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -62,6 +69,7 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements context.dispose(); } + @Override public void paint(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -83,6 +91,7 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements context.getPainter().paintScrollPaneBorder(context, g, x, y, w, h); } + @Override protected void installDefaults(JScrollPane scrollpane) { updateStyle(scrollpane); } @@ -106,11 +115,21 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements } + @Override protected void installListeners(JScrollPane c) { super.installListeners(c); c.addPropertyChangeListener(this); + if (UIManager.getBoolean("ScrollPane.useChildTextComponentFocus")){ + viewportViewFocusHandler = new ViewportViewFocusHandler(); + c.getViewport().addContainerListener(viewportViewFocusHandler); + Component view = c.getViewport().getView(); + if (view instanceof JTextComponent) { + view.addFocusListener(viewportViewFocusHandler); + } + } } + @Override protected void uninstallDefaults(JScrollPane c) { SynthContext context = getContext(c, ENABLED); @@ -123,9 +142,18 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements } + @Override protected void uninstallListeners(JComponent c) { super.uninstallListeners(c); c.removePropertyChangeListener(this); + if (viewportViewFocusHandler != null) { + JViewport viewport = ((JScrollPane) c).getViewport(); + viewport.removeContainerListener(viewportViewFocusHandler); + if (viewport.getView()!= null) { + viewport.getView().removeFocusListener(viewportViewFocusHandler); + } + viewportViewFocusHandler = null; + } } @@ -145,7 +173,11 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements private int getComponentState(JComponent c) { - return SynthLookAndFeel.getComponentState(c); + int baseState = SynthLookAndFeel.getComponentState(c); + if (viewportViewFocusHandler!=null && viewportViewHasFocus){ + baseState = baseState | FOCUSED; + } + return baseState; } public void propertyChange(PropertyChangeEvent e) { @@ -167,6 +199,7 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements } } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { JComponent jc = (JComponent)c; @@ -182,6 +215,7 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements context.dispose(); } + @Override public Insets getBorderInsets(Component c, Insets insets) { if (insets == null) { return new Insets(this.insets.top, this.insets.left, @@ -194,8 +228,39 @@ class SynthScrollPaneUI extends BasicScrollPaneUI implements return insets; } + @Override public boolean isBorderOpaque() { return false; } } + + /** + * Handle keeping track of the viewport's view's focus + */ + private class ViewportViewFocusHandler implements ContainerListener, + FocusListener{ + public void componentAdded(ContainerEvent e) { + if (e.getChild() instanceof JTextComponent) { + e.getChild().addFocusListener(this); + viewportViewHasFocus = e.getChild().isFocusOwner(); + scrollpane.repaint(); + } + } + + public void componentRemoved(ContainerEvent e) { + if (e.getChild() instanceof JTextComponent) { + e.getChild().removeFocusListener(this); + } + } + + public void focusGained(FocusEvent e) { + viewportViewHasFocus = true; + scrollpane.repaint(); + } + + public void focusLost(FocusEvent e) { + viewportViewHasFocus = false; + scrollpane.repaint(); + } + } } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java b/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java index 58fb5370977d7f8d64a761120be15aff33e9771e..78d0bb1aaed9707cb68c1a0398c2ff4bd338a852 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java @@ -53,6 +53,20 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, protected Rectangle valueRect = new Rectangle(); protected boolean paintValue; + /** + * When a JSlider is used as a renderer in a JTable, its layout is not + * being recomputed even though the size is changing. Even though there + * is a ComponentListener installed, it is not being notified. As such, + * at times when being asked to paint the layout should first be redone. + * At the end of the layout method we set this lastSize variable, which + * represents the size of the slider the last time it was layed out. + * + * In the paint method we then check to see that this is accurate, that + * the slider has not changed sizes since being last layed out. If necessary + * we recompute the layout. + */ + private Dimension lastSize = null; + private int trackHeight; private int trackBorder; private int thumbWidth; @@ -63,7 +77,8 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, private SynthStyle sliderThumbStyle; /** Used to determine the color to paint the thumb. */ - private transient boolean thumbActive; + private transient boolean thumbActive; //happens on rollover, and when pressed + private transient boolean thumbPressed; //happens when mouse was depressed while over thumb /////////////////////////////////////////////////// // ComponentUI Interface Implementation methods @@ -119,6 +134,24 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, thumbHeight = style.getInt(context, "Slider.thumbHeight", 14); + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + String scaleKey = (String)slider.getClientProperty( + "JComponent.sizeVariant"); + if (scaleKey != null){ + if ("large".equals(scaleKey)){ + thumbWidth *= 1.15; + thumbHeight *= 1.15; + } else if ("small".equals(scaleKey)){ + thumbWidth *= 0.857; + thumbHeight *= 0.857; + } else if ("mini".equals(scaleKey)){ + thumbWidth *= 0.784; + thumbHeight *= 0.784; + } + } + trackBorder = style.getInt(context, "Slider.trackBorder", 1); @@ -152,6 +185,11 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, setThumbActive(thumbRect.contains(x, y)); } + private void updateThumbState(int x, int y, boolean pressed) { + updateThumbState(x, y); + setThumbPressed(pressed); + } + private void setThumbActive(boolean active) { if (thumbActive != active) { thumbActive = active; @@ -159,6 +197,13 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, } } + private void setThumbPressed(boolean pressed) { + if (thumbPressed != pressed) { + thumbPressed = pressed; + slider.repaint(thumbRect); + } + } + public int getBaseline(JComponent c, int width, int height) { if (c == null) { throw new NullPointerException("Component must be non-null"); @@ -418,6 +463,7 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, } } context.dispose(); + lastSize = slider.getSize(); } /** @@ -667,7 +713,9 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, private int getComponentState(JComponent c, Region region) { if (region == Region.SLIDER_THUMB && thumbActive &&c.isEnabled()) { - return MOUSE_OVER; + int state = thumbPressed ? PRESSED : MOUSE_OVER; + if (c.isFocusOwner()) state |= FOCUSED; + return state; } return SynthLookAndFeel.getComponentState(c); } @@ -693,6 +741,10 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, recalculateIfOrientationChanged(); Rectangle clip = g.getClipBounds(); + if (lastSize == null || !lastSize.equals(slider.getSize())) { + calculateGeometry(); + } + if (paintValue) { FontMetrics fm = SwingUtilities2.getFontMetrics(slider, g); int labelWidth = context.getStyle().getGraphicsUtils(context). @@ -781,9 +833,14 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, setThumbActive(false); } + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + setThumbPressed(thumbRect.contains(e.getX(), e.getY())); + } + public void mouseReleased(MouseEvent e) { super.mouseReleased(e); - updateThumbState(e.getX(), e.getY()); + updateThumbState(e.getX(), e.getY(), false); } public void mouseDragged(MouseEvent e) { @@ -814,6 +871,7 @@ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, if (drawInverted()) { trackBottom = vMax; + trackTop = trackTop + halfThumbHeight; } else { trackTop = vMax; } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java b/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java index c794999ffbe84dd21b99883c907e91c570988328..d0dd44b8963806cc42b160f43df7dd62ed4bbcb5 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java @@ -26,17 +26,12 @@ package javax.swing.plaf.synth; import java.awt.*; import java.awt.event.*; -import java.text.ParseException; import javax.swing.*; -import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.BasicSpinnerUI; -import javax.swing.text.*; import java.beans.*; -import java.text.*; -import java.util.*; import sun.swing.plaf.synth.SynthUI; /** @@ -48,7 +43,16 @@ import sun.swing.plaf.synth.SynthUI; class SynthSpinnerUI extends BasicSpinnerUI implements PropertyChangeListener, SynthUI { private SynthStyle style; - + /** + * A FocusListener implementation which causes the entire spinner to be + * repainted whenever the editor component (typically a text field) becomes + * focused, or loses focus. This is necessary because since SynthSpinnerUI + * is composed of an editor and two buttons, it is necessary that all three + * components indicate that they are "focused" so that they can be drawn + * appropriately. The repaint is used to ensure that the buttons are drawn + * in the new focused or unfocused state, mirroring that of the editor. + */ + private EditorFocusHandler editorFocusHandler = new EditorFocusHandler(); /** * Returns a new instance of SynthSpinnerUI. @@ -61,9 +65,17 @@ class SynthSpinnerUI extends BasicSpinnerUI implements PropertyChangeListener, return new SynthSpinnerUI(); } + @Override protected void installListeners() { super.installListeners(); spinner.addPropertyChangeListener(this); + JComponent editor = spinner.getEditor(); + if (editor instanceof JSpinner.DefaultEditor) { + JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); + if (tf != null) { + tf.addFocusListener(editorFocusHandler); + } + } } /** @@ -74,9 +86,17 @@ class SynthSpinnerUI extends BasicSpinnerUI implements PropertyChangeListener, * * @see #installListeners */ + @Override protected void uninstallListeners() { super.uninstallListeners(); spinner.removePropertyChangeListener(this); + JComponent editor = spinner.getEditor(); + if (editor instanceof JSpinner.DefaultEditor) { + JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); + if (tf != null) { + tf.removeFocusListener(editorFocusHandler); + } + } } /** @@ -233,6 +253,18 @@ class SynthSpinnerUI extends BasicSpinnerUI implements PropertyChangeListener, protected void replaceEditor(JComponent oldEditor, JComponent newEditor) { spinner.remove(oldEditor); spinner.add(newEditor, "Editor"); + if (oldEditor instanceof JSpinner.DefaultEditor) { + JTextField tf = ((JSpinner.DefaultEditor)oldEditor).getTextField(); + if (tf != null) { + tf.removeFocusListener(editorFocusHandler); + } + } + if (newEditor instanceof JSpinner.DefaultEditor) { + JTextField tf = ((JSpinner.DefaultEditor)newEditor).getTextField(); + if (tf != null) { + tf.addFocusListener(editorFocusHandler); + } + } } private void updateEditorAlignment(JComponent editor) { @@ -240,10 +272,14 @@ class SynthSpinnerUI extends BasicSpinnerUI implements PropertyChangeListener, SynthContext context = getContext(spinner); Integer alignment = (Integer)context.getStyle().get( context, "Spinner.editorAlignment"); + JTextField text = ((JSpinner.DefaultEditor)editor).getTextField(); if (alignment != null) { - JTextField text = ((JSpinner.DefaultEditor)editor).getTextField(); text.setHorizontalAlignment(alignment); + } + // copy across the sizeVariant property to the editor + text.putClientProperty("JComponent.sizeVariant", + spinner.getClientProperty("JComponent.sizeVariant")); } } @@ -404,4 +440,38 @@ class SynthSpinnerUI extends BasicSpinnerUI implements PropertyChangeListener, } } } + + /** Listen to editor text field focus changes and repaint whole spinner */ + private class EditorFocusHandler implements FocusListener{ + /** Invoked when a editor text field gains the keyboard focus. */ + public void focusGained(FocusEvent e) { + spinner.repaint(); + } + + /** Invoked when a editor text field loses the keyboard focus. */ + public void focusLost(FocusEvent e) { + spinner.repaint(); + } + } + + /** Override the arrowbuttons focus handling to follow the text fields focus */ + private class SpinnerArrowButton extends SynthArrowButton{ + public SpinnerArrowButton(int direction) { + super(direction); + } + + @Override + public boolean isFocusOwner() { + if (spinner == null){ + return super.isFocusOwner(); + } else if (spinner.getEditor() instanceof JSpinner.DefaultEditor){ + return ((JSpinner.DefaultEditor)spinner.getEditor()) + .getTextField().isFocusOwner(); + } else if (spinner.getEditor()!= null) { + return spinner.getEditor().isFocusOwner(); + } else { + return super.isFocusOwner(); + } + } + } } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthStyle.java b/src/share/classes/javax/swing/plaf/synth/SynthStyle.java index d595ef6e84866059daa44ea7dccf03602f5239c0..52e9ef11b080880255bda7627d87b2a73cb474a1 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthStyle.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthStyle.java @@ -32,6 +32,7 @@ import javax.swing.plaf.basic.BasicLookAndFeel; import javax.swing.text.DefaultEditorKit; import java.util.HashMap; import java.util.Map; +import javax.swing.text.JTextComponent; import sun.swing.plaf.synth.SynthUI; /** @@ -758,28 +759,48 @@ public abstract class SynthStyle { public Color getColor(SynthContext context, ColorType type) { JComponent c = context.getComponent(); Region id = context.getRegion(); - int cs = context.getComponentState(); - // For the enabled state, prefer the widget's colors - if (!id.isSubregion() && cs == SynthConstants.ENABLED) { + + if ((context.getComponentState() & SynthConstants.DISABLED) != 0) { + //This component is disabled, so return the disabled color. + //In some cases this means ignoring the color specified by the + //developer on the component. In other cases it means using a + //specified disabledTextColor, such as on JTextComponents. + //For example, JLabel doesn't specify a disabled color that the + //developer can set, yet it should have a disabled color to the + //text when the label is disabled. This code allows for that. + if (c instanceof JTextComponent) { + JTextComponent txt = (JTextComponent)c; + Color disabledColor = txt.getDisabledTextColor(); + if (disabledColor == null || disabledColor instanceof UIResource) { + return getColorForState(context, type); + } + } else if (c instanceof JLabel && + (type == ColorType.FOREGROUND || + type == ColorType.TEXT_FOREGROUND)) { + return getColorForState(context, type); + } + } + + // If the developer has specified a color, prefer it. Otherwise, get + // the color for the state. + Color color = null; + if (!id.isSubregion()) { if (type == ColorType.BACKGROUND) { - return c.getBackground(); + color = c.getBackground(); } else if (type == ColorType.FOREGROUND) { - return c.getForeground(); + color = c.getForeground(); } else if (type == ColorType.TEXT_FOREGROUND) { - // If getForeground returns a non-UIResource it means the - // developer has explicitly set the foreground, use it over - // that of TEXT_FOREGROUND as that is typically the expected - // behavior. - Color color = c.getForeground(); - if (!(color instanceof UIResource)) { - return color; - } + color = c.getForeground(); } } - // Then use what we've locally defined - Color color = getColorForState(context, type); + + if (color == null || color instanceof UIResource) { + // Then use what we've locally defined + color = getColorForState(context, type); + } + if (color == null) { // No color, fallback to that of the widget. if (type == ColorType.BACKGROUND || diff --git a/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java b/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java index ac91419f11504cb06e977726034529146fc44bfd..cef94e151d1877bcd25123a5fd35778270120fde 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java @@ -26,7 +26,6 @@ package javax.swing.plaf.synth; import javax.swing.*; -import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import javax.swing.text.View; @@ -35,8 +34,6 @@ import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import java.util.Vector; -import java.util.Hashtable; import sun.swing.plaf.synth.SynthUI; import sun.swing.SwingUtilities2; @@ -50,6 +47,40 @@ import sun.swing.SwingUtilities2; * insets for the selected tab. */ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyChangeListener { + /** + *

If non-zero, tabOverlap indicates the amount that the tab bounds + * should be altered such that they would overlap with a tab on either the + * leading or trailing end of a run (ie: in TOP, this would be on the left + * or right).

+ + *

A positive overlap indicates that tabs should overlap right/down, + * while a negative overlap indicates tha tabs should overlap left/up.

+ * + *

When tabOverlap is specified, it both changes the x position and width + * of the tab if in TOP or BOTTOM placement, and changes the y position and + * height if in LEFT or RIGHT placement.

+ * + *

This is done for the following reason. Consider a run of 10 tabs. + * There are 9 gaps between these tabs. If you specified a tabOverlap of + * "-1", then each of the tabs "x" values will be shifted left. This leaves + * 9 pixels of space to the right of the right-most tab unpainted. So, each + * tab's width is also extended by 1 pixel to make up the difference.

+ * + *

This property respects the RTL component orientation.

+ */ + private int tabOverlap = 0; + + /** + * When a tabbed pane has multiple rows of tabs, this indicates whether + * the tabs in the upper row(s) should extend to the base of the tab area, + * or whether they should remain at their normal tab height. This does not + * affect the bounds of the tabs, only the bounds of area painted by the + * tabs. The text position does not change. The result is that the bottom + * border of the upper row of tabs becomes fully obscured by the lower tabs, + * resulting in a cleaner look. + */ + private boolean extendTabsToBase = false; + private SynthContext tabAreaContext; private SynthContext tabContext; private SynthContext tabContentContext; @@ -64,6 +95,14 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh private Rectangle tabAreaBounds = new Rectangle(); + //added for the Nimbus look and feel, where the tab area is painted differently depending on the + //state for the selected tab + private boolean tabAreaStatesMatchSelectedTab = false; + //added for the Nimbus LAF to ensure that the labels don't move whether the tab is selected or not + private boolean nudgeSelectedLabel = true; + + private boolean selectedTabIsPressed = false; + public static ComponentUI createUI(JComponent c) { return new SynthTabbedPaneUI(); } @@ -90,12 +129,19 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh if (style != oldStyle) { tabRunOverlay = style.getInt(context, "TabbedPane.tabRunOverlay", 0); + tabOverlap = style.getInt(context, "TabbedPane.tabOverlap", 0); + extendTabsToBase = style.getBoolean(context, + "TabbedPane.extendTabsToBase", false); textIconGap = style.getInt(context, "TabbedPane.textIconGap", 0); selectedTabPadInsets = (Insets)style.get(context, "TabbedPane.selectedTabPadInsets"); if (selectedTabPadInsets == null) { selectedTabPadInsets = new Insets(0, 0, 0, 0); } + tabAreaStatesMatchSelectedTab = style.getBoolean(context, + "TabbedPane.tabAreaStatesMatchSelectedTab", false); + nudgeSelectedLabel = style.getBoolean(context, + "TabbedPane.nudgeSelectedLabel", true); if (oldStyle != null) { uninstallKeyboardActions(); installKeyboardActions(); @@ -199,6 +245,14 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh } protected JButton createScrollButton(int direction) { + // added for Nimbus LAF so that it can use the basic arrow buttons + // UIManager is queried directly here because this is called before + // updateStyle is called so the style can not be queried directly + if (UIManager.getBoolean("TabbedPane.useBasicArrows")) { + JButton btn = super.createScrollButton(direction); + btn.setBorder(BorderFactory.createEmptyBorder()); + return btn; + } return new SynthScrollableTabButton(direction); } @@ -208,6 +262,75 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh } } + /** + * @inheritDoc + * + * Overridden to keep track of whether the selected tab is also pressed. + */ + @Override + protected MouseListener createMouseListener() { + final MouseListener delegate = super.createMouseListener(); + final MouseMotionListener delegate2 = (MouseMotionListener)delegate; + return new MouseListener() { + public void mouseClicked(MouseEvent e) { delegate.mouseClicked(e); } + public void mouseEntered(MouseEvent e) { delegate.mouseEntered(e); } + public void mouseExited(MouseEvent e) { delegate.mouseExited(e); } + + public void mousePressed(MouseEvent e) { + if (!tabPane.isEnabled()) { + return; + } + + int tabIndex = tabForCoordinate(tabPane, e.getX(), e.getY()); + if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex)) { + if (tabIndex == tabPane.getSelectedIndex()) { + // Clicking on selected tab + selectedTabIsPressed = true; + //TODO need to just repaint the tab area! + tabPane.repaint(); + } + } + + //forward the event (this will set the selected index, or none at all + delegate.mousePressed(e); + } + + public void mouseReleased(MouseEvent e) { + if (selectedTabIsPressed) { + selectedTabIsPressed = false; + //TODO need to just repaint the tab area! + tabPane.repaint(); + } + //forward the event + delegate.mouseReleased(e); + + //hack: The super method *should* be setting the mouse-over property correctly + //here, but it doesn't. That is, when the mouse is released, whatever tab is below the + //released mouse should be in rollover state. But, if you select a tab and don't + //move the mouse, this doesn't happen. Hence, forwarding the event. + delegate2.mouseMoved(e); + } + }; + } + + @Override + protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) { + if (nudgeSelectedLabel) { + return super.getTabLabelShiftX(tabPlacement, tabIndex, isSelected); + } else { + return 0; + } + } + + @Override + protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) { + if (nudgeSelectedLabel) { + return super.getTabLabelShiftY(tabPlacement, tabIndex, isSelected); + } else { + return 0; + } + } + public void update(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -321,6 +444,20 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh Rectangle tabAreaBounds) { Rectangle clipRect = g.getClipBounds(); + //if the tab area's states should match that of the selected tab, then + //first update the selected tab's states, then set the state + //for the tab area to match + //otherwise, restore the tab area's state to ENABLED (which is the + //only supported state otherwise). + if (tabAreaStatesMatchSelectedTab && selectedIndex >= 0) { + updateTabContext(selectedIndex, true, selectedTabIsPressed, + (getRolloverTab() == selectedIndex), + (getFocusIndex() == selectedIndex)); + ss.setComponentState(tabContext.getComponentState()); + } else { + ss.setComponentState(SynthConstants.ENABLED); + } + // Paint the tab area. SynthLookAndFeel.updateSubregion(ss, g, tabAreaBounds); ss.getPainter().paintTabbedPaneTabAreaBackground(ss, g, @@ -362,17 +499,22 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh Rectangle r = null; - if ((oldRolloverTab >= 0) && (oldRolloverTab < tabPane.getTabCount())) { - r = getTabBounds(tabPane, oldRolloverTab); - if (r != null) { - tabPane.repaint(r); + if (oldRolloverTab != index && tabAreaStatesMatchSelectedTab) { + //TODO need to just repaint the tab area! + tabPane.repaint(); + } else { + if ((oldRolloverTab >= 0) && (oldRolloverTab < tabPane.getTabCount())) { + r = getTabBounds(tabPane, oldRolloverTab); + if (r != null) { + tabPane.repaint(r); + } } - } - if (index >= 0) { - r = getTabBounds(tabPane, index); - if (r != null) { - tabPane.repaint(r); + if (index >= 0) { + r = getTabBounds(tabPane, index); + if (r != null) { + tabPane.repaint(r); + } } } } @@ -383,18 +525,51 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh Rectangle tabRect = rects[tabIndex]; int selectedIndex = tabPane.getSelectedIndex(); boolean isSelected = selectedIndex == tabIndex; - updateTabContext(tabIndex, isSelected, - (getRolloverTab() == tabIndex), - (getFocusIndex() == tabIndex)); + updateTabContext(tabIndex, isSelected, isSelected && selectedTabIsPressed, + (getRolloverTab() == tabIndex), + (getFocusIndex() == tabIndex)); SynthLookAndFeel.updateSubregion(ss, g, tabRect); - tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, - g, tabRect.x, tabRect.y, tabRect.width, - tabRect.height, tabIndex, - tabPane.getTabPlacement()); + int x = tabRect.x; + int y = tabRect.y; + int height = tabRect.height; + int width = tabRect.width; + int placement = tabPane.getTabPlacement(); + if (extendTabsToBase && runCount > 1) { + //paint this tab such that its edge closest to the base is equal to + //edge of the selected tab closest to the base. In terms of the TOP + //tab placement, this will cause the bottom of each tab to be + //painted even with the bottom of the selected tab. This is because + //in each tab placement (TOP, LEFT, BOTTOM, RIGHT) the selected tab + //is closest to the base. + if (selectedIndex >= 0) { + Rectangle r = rects[selectedIndex]; + switch (placement) { + case TOP: + int bottomY = r.y + r.height; + height = bottomY - tabRect.y; + break; + case LEFT: + int rightX = r.x + r.width; + width = rightX - tabRect.x; + break; + case BOTTOM: + int topY = r.y; + height = (tabRect.y + tabRect.height) - topY; + y = topY; + break; + case RIGHT: + int leftX = r.x; + width = (tabRect.x + tabRect.width) - leftX; + x = leftX; + break; + } + } + } + tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, + x, y, width, height, tabIndex, placement); tabContext.getPainter().paintTabbedPaneTabBorder(tabContext, g, - tabRect.x, tabRect.y, tabRect.width, tabRect.height, - tabIndex, tabPane.getTabPlacement()); + x, y, width, height, tabIndex, placement); if (tabPane.getTabComponentAt(tabIndex) == null) { String title = tabPane.getTitleAt(tabIndex); @@ -561,7 +736,7 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh } protected Insets getTabInsets(int tabPlacement, int tabIndex) { - updateTabContext(tabIndex, false, false, + updateTabContext(tabIndex, false, false, false, (getFocusIndex() == tabIndex)); return tabInsets; } @@ -575,7 +750,7 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh } private void updateTabContext(int index, boolean selected, - boolean isMouseOver, boolean hasFocus) { + boolean isMouseDown, boolean isMouseOver, boolean hasFocus) { int state = 0; if (!tabPane.isEnabled() || !tabPane.isEnabledAt(index)) { state |= SynthConstants.DISABLED; @@ -599,9 +774,68 @@ class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyCh if (hasFocus && tabPane.hasFocus()) { state |= SynthConstants.FOCUSED; // individual tab has focus } + if (isMouseDown) { + state |= SynthConstants.PRESSED; + } + tabContext.setComponentState(state); } + /** + * @inheritDoc + * + * Overridden to create a TabbedPaneLayout subclass which takes into + * account tabOverlap. + */ + @Override protected LayoutManager createLayoutManager() { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { + return super.createLayoutManager(); + } else { /* WRAP_TAB_LAYOUT */ + return new TabbedPaneLayout() { + @Override + public void calculateLayoutInfo() { + super.calculateLayoutInfo(); + //shift all the tabs, if necessary + if (tabOverlap != 0) { + int tabCount = tabPane.getTabCount(); + //left-to-right/right-to-left only affects layout + //when placement is TOP or BOTTOM + boolean ltr = tabPane.getComponentOrientation().isLeftToRight(); + for (int i = runCount - 1; i >= 0; i--) { + int start = tabRuns[i]; + int next = tabRuns[(i == runCount - 1)? 0 : i + 1]; + int end = (next != 0? next - 1: tabCount - 1); + for (int j = start+1; j <= end; j++) { + // xshift and yshift represent the amount & + // direction to shift the tab in their + // respective axis. + int xshift = 0; + int yshift = 0; + // configure xshift and y shift based on tab + // position and ltr/rtl + switch (tabPane.getTabPlacement()) { + case JTabbedPane.TOP: + case JTabbedPane.BOTTOM: + xshift = ltr ? tabOverlap : -tabOverlap; + break; + case JTabbedPane.LEFT: + case JTabbedPane.RIGHT: + yshift = tabOverlap; + break; + default: //do nothing + } + rects[j].x += xshift; + rects[j].y += yshift; + rects[j].width += Math.abs(xshift); + rects[j].height += Math.abs(yshift); + } + } + } + } + }; + } + } + private class SynthScrollableTabButton extends SynthArrowButton implements UIResource { public SynthScrollableTabButton(int direction) { diff --git a/src/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java b/src/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java index 20d3c01f34834c26704ba622741c36fecea96564..b37d9f1262d32d6eddbfc736f70cb8875a6f69a1 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java @@ -33,6 +33,7 @@ import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import javax.swing.table.*; +import sun.swing.DefaultLookup; import sun.swing.plaf.synth.*; import sun.swing.table.*; @@ -160,6 +161,7 @@ class SynthTableHeaderUI extends BasicTableHeaderUI implements private class HeaderRenderer extends DefaultTableCellHeaderRenderer { HeaderRenderer() { setHorizontalAlignment(JLabel.LEADING); + setName("TableHeader.renderer"); } @Override @@ -178,24 +180,40 @@ class SynthTableHeaderUI extends BasicTableHeaderUI implements SynthLookAndFeel.resetSelectedUI(); } + //stuff a variable into the client property of this renderer indicating the sort order, + //so that different rendering can be done for the header based on sorted state. + RowSorter rs = table == null ? null : table.getRowSorter(); + java.util.List sortKeys = rs == null ? null : rs.getSortKeys(); + if (sortKeys != null && sortKeys.size() > 0 && sortKeys.get(0).getColumn() == + table.convertColumnIndexToModel(column)) { + switch(sortKeys.get(0).getSortOrder()) { + case ASCENDING: + putClientProperty("Table.sortOrder", "ASCENDING"); + break; + case DESCENDING: + putClientProperty("Table.sortOrder", "DESCENDING"); + break; + case UNSORTED: + putClientProperty("Table.sortOrder", "UNSORTED"); + break; + default: + throw new AssertionError("Cannot happen"); + } + } else { + putClientProperty("Table.sortOrder", "UNSORTED"); + } + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); return this; } + @Override public void setBorder(Border border) { if (border instanceof SynthBorder) { super.setBorder(border); } } - - public String getName() { - String name = super.getName(); - if (name == null) { - return "TableHeader.renderer"; - } - return name; - } } } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java b/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java index be90ac5198b45c22b6acf63f254f4800a8a41135..1b8cf9894465b4c8f915973d8176c014cb96d407 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java @@ -27,6 +27,7 @@ package javax.swing.plaf.synth; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; @@ -70,6 +71,7 @@ class SynthTableUI extends BasicTableUI implements SynthUI, private boolean useTableColors; private boolean useUIBorder; + private Color alternateColor; //the background color to use for cells for alternate cells // TableCellRenderer installed on the JTable at the time we're installed, // cached so that we can reinstall them at uninstallUI time. @@ -161,6 +163,21 @@ class SynthTableUI extends BasicTableUI implements SynthUI, if (rowHeight != null) { LookAndFeel.installProperty(table, "rowHeight", rowHeight); } + boolean showGrid = style.getBoolean(context, "Table.showGrid", true); + if (!showGrid) { + table.setShowGrid(false); + } + Dimension d = table.getIntercellSpacing(); +// if (d == null || d instanceof UIResource) { + if (d != null) { + d = (Dimension)style.get(context, "Table.intercellSpacing"); + } + alternateColor = (Color)style.get(context, "Table.alternateRowColor"); + if (d != null) { + table.setIntercellSpacing(d); + } + + if (oldStyle != null) { uninstallKeyboardActions(); installKeyboardActions(); @@ -617,6 +634,14 @@ class SynthTableUI extends BasicTableUI implements SynthUI, else { TableCellRenderer renderer = table.getCellRenderer(row, column); Component component = table.prepareRenderer(renderer, row, column); + Color b = component.getBackground(); + if ((b == null || b instanceof UIResource + || component instanceof SynthBooleanTableCellRenderer) + && !table.isCellSelected(row, column)) { + if (alternateColor != null && row % 2 == 0) { + component.setBackground(alternateColor); + } + } rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true); } @@ -634,16 +659,8 @@ class SynthTableUI extends BasicTableUI implements SynthUI, private boolean isRowSelected; public SynthBooleanTableCellRenderer() { - super(); setHorizontalAlignment(JLabel.CENTER); - } - - public String getName() { - String name = super.getName(); - if (name == null) { - return "Table.cellRenderer"; - } - return name; + setName("Table.cellRenderer"); } public Component getTableCellRendererComponent( @@ -652,17 +669,24 @@ class SynthTableUI extends BasicTableUI implements SynthUI, isRowSelected = isSelected; if (isSelected) { - setForeground(table.getSelectionForeground()); - setBackground(table.getSelectionBackground()); + setForeground(unwrap(table.getSelectionForeground())); + setBackground(unwrap(table.getSelectionBackground())); } else { - setForeground(table.getForeground()); - setBackground(table.getBackground()); + setForeground(unwrap(table.getForeground())); + setBackground(unwrap(table.getBackground())); } setSelected((value != null && ((Boolean)value).booleanValue())); return this; } + private Color unwrap(Color c) { + if (c instanceof UIResource) { + return new Color(c.getRGB()); + } + return c; + } + public boolean isOpaque() { return isRowSelected ? true : super.isOpaque(); } @@ -732,7 +756,7 @@ class SynthTableUI extends BasicTableUI implements SynthUI, } else if (columnClass == Icon.class || columnClass == ImageIcon.class) { setHorizontalAlignment(JLabel.CENTER); - setIcon((Icon)value); + setIcon((value instanceof Icon) ? (Icon)value : null); setText(""); } else if (columnClass == Date.class) { diff --git a/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java b/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java index 3a650d2abebdf9bb7f8e256e2552ee5f812dfe52..01947655afe352fd185b3a2325e170b908f86318 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java @@ -27,10 +27,11 @@ package javax.swing.plaf.synth; import javax.swing.*; import javax.swing.text.*; -import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.BasicTextAreaUI; import java.awt.*; +import java.awt.event.FocusListener; +import java.awt.event.FocusEvent; import java.beans.PropertyChangeEvent; import sun.swing.plaf.synth.SynthUI; @@ -50,7 +51,7 @@ import sun.swing.plaf.synth.SynthUI; * * @author Shannon Hickey */ -class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { +class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI, FocusListener { private SynthStyle style; /** @@ -63,16 +64,26 @@ class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { return new SynthTextAreaUI(); } + public void focusGained(FocusEvent e) { + getComponent().repaint(); + } + + public void focusLost(FocusEvent e) { + getComponent().repaint(); + } + protected void installDefaults() { // Installs the text cursor on the component super.installDefaults(); updateStyle(getComponent()); + getComponent().addFocusListener(this); } protected void uninstallDefaults() { SynthContext context = getContext(getComponent(), ENABLED); getComponent().putClientProperty("caretAspectRatio", null); + getComponent().removeFocusListener(this); style.uninstallDefaults(context); context.dispose(); diff --git a/src/share/classes/javax/swing/plaf/synth/SynthToggleButtonUI.java b/src/share/classes/javax/swing/plaf/synth/SynthToggleButtonUI.java index 74b9f7cca67a9405c9c3a468e8cfc8d29a0e5518..d4b22baaf2b3042660a66b3b21384a541ddb12e6 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthToggleButtonUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthToggleButtonUI.java @@ -25,12 +25,10 @@ package javax.swing.plaf.synth; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.border.*; -import javax.swing.plaf.*; -import javax.swing.text.View; +import java.awt.Graphics; +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; /** * Synth's ToggleButtonUI. @@ -45,15 +43,21 @@ class SynthToggleButtonUI extends SynthButtonUI { return new SynthToggleButtonUI(); } + @Override protected String getPropertyPrefix() { return "ToggleButton."; } + @Override void paintBackground(SynthContext context, Graphics g, JComponent c) { - context.getPainter().paintToggleButtonBackground(context, g, 0, 0, - c.getWidth(), c.getHeight()); + if (((AbstractButton) c).isContentAreaFilled()) { + int x = 0, y = 0, w = c.getWidth(), h = c.getHeight(); + SynthPainter painter = context.getPainter(); + painter.paintToggleButtonBackground(context, g, x, y, w, h); + } } + @Override public void paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { context.getPainter().paintToggleButtonBorder(context, g, x, y, w, h); diff --git a/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java b/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java index 60aa951c9f395886121ab610b3c1df9df67c753d..c49536c34e745bc73e76a926f46871ae84dcd18d 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java @@ -25,18 +25,24 @@ package javax.swing.plaf.synth; -import javax.swing.*; -import javax.swing.event.*; -import java.awt.*; -import java.awt.event.*; - -import java.beans.*; - -import javax.swing.border.*; -import javax.swing.plaf.*; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.Box; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JSeparator; +import javax.swing.JToolBar; +import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToolBarUI; -import sun.swing.plaf.synth.*; - +import sun.swing.plaf.synth.SynthIcon; +import sun.swing.plaf.synth.SynthUI; /** * A Synth L&F implementation of ToolBarUI. This implementation @@ -57,23 +63,35 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, return new SynthToolBarUI(); } + @Override protected void installDefaults() { toolBar.setLayout(createLayout()); updateStyle(toolBar); } + @Override protected void installListeners() { super.installListeners(); toolBar.addPropertyChangeListener(this); } + @Override protected void uninstallListeners() { super.uninstallListeners(); toolBar.removePropertyChangeListener(this); } private void updateStyle(JToolBar c) { - SynthContext context = getContext(c, ENABLED); + SynthContext context = getContext( + c, Region.TOOL_BAR_CONTENT, null, ENABLED); + contentStyle = SynthLookAndFeel.updateStyle(context, this); + context.dispose(); + + context = getContext(c, Region.TOOL_BAR_DRAG_WINDOW, null, ENABLED); + dragWindowStyle = SynthLookAndFeel.updateStyle(context, this); + context.dispose(); + + context = getContext(c, ENABLED); SynthStyle oldStyle = style; style = SynthLookAndFeel.updateStyle(context, this); @@ -86,16 +104,9 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, } } context.dispose(); - - context = getContext(c, Region.TOOL_BAR_CONTENT, ENABLED); - contentStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); - - context = getContext(c, Region.TOOL_BAR_DRAG_WINDOW, ENABLED); - dragWindowStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } + @Override protected void uninstallDefaults() { SynthContext context = getContext(toolBar, ENABLED); @@ -105,12 +116,14 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, handleIcon = null; - context = getContext(toolBar, Region.TOOL_BAR_CONTENT, ENABLED); + context = getContext(toolBar, Region.TOOL_BAR_CONTENT, + contentStyle, ENABLED); contentStyle.uninstallDefaults(context); context.dispose(); contentStyle = null; - context = getContext(toolBar, Region.TOOL_BAR_DRAG_WINDOW, ENABLED); + context = getContext(toolBar, Region.TOOL_BAR_DRAG_WINDOW, + dragWindowStyle, ENABLED); dragWindowStyle.uninstallDefaults(context); context.dispose(); dragWindowStyle = null; @@ -118,11 +131,11 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, toolBar.setLayout(null); } - protected void installComponents() { - } + @Override + protected void installComponents() {} - protected void uninstallComponents() { - } + @Override + protected void uninstallComponents() {} protected LayoutManager createLayout() { return new SynthToolBarLayoutManager(); @@ -137,13 +150,15 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, SynthLookAndFeel.getRegion(c), style, state); } - private SynthContext getContext(JComponent c, Region region) { - return getContext(c, region, getComponentState(c, region)); + private SynthContext getContext(JComponent c, Region region, SynthStyle style) { + return SynthContext.getContext(SynthContext.class, c, region, + style, getComponentState(c, region)); } - private SynthContext getContext(JComponent c, Region region, int state) { + private SynthContext getContext(JComponent c, Region region, + SynthStyle style, int state) { return SynthContext.getContext(SynthContext.class, c, region, - dragWindowStyle, state); + style, state); } private Region getRegion(JComponent c) { @@ -158,6 +173,7 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, return SynthLookAndFeel.getComponentState(c); } + @Override public void update(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -169,6 +185,7 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, context.dispose(); } + @Override public void paint(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -183,12 +200,15 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, } // Overloaded to do nothing so we can share listeners. + @Override protected void setBorderToNonRollover(Component c) {} // Overloaded to do nothing so we can share listeners. + @Override protected void setBorderToRollover(Component c) {} // Overloaded to do nothing so we can share listeners. + @Override protected void setBorderToNormal(Component c) {} protected void paint(SynthContext context, Graphics g) { @@ -201,7 +221,8 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, SynthIcon.getIconHeight(handleIcon, context)); } - SynthContext subcontext = getContext(toolBar, Region.TOOL_BAR_CONTENT); + SynthContext subcontext = getContext( + toolBar, Region.TOOL_BAR_CONTENT, contentStyle); paintContent(subcontext, g, contentRect); subcontext.dispose(); } @@ -217,12 +238,14 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, toolBar.getOrientation()); } + @Override protected void paintDragWindow(Graphics g) { int w = dragWindow.getWidth(); int h = dragWindow.getHeight(); - SynthContext context = getContext(toolBar,Region.TOOL_BAR_DRAG_WINDOW); - SynthLookAndFeel.updateSubregion(context, g, new Rectangle( - 0, 0, w, h)); + SynthContext context = getContext( + toolBar, Region.TOOL_BAR_DRAG_WINDOW, dragWindowStyle); + SynthLookAndFeel.updateSubregion( + context, g, new Rectangle(0, 0, w, h)); context.getPainter().paintToolBarDragWindowBackground(context, g, 0, 0, w, h, dragWindow.getOrientation()); @@ -319,6 +342,19 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, Component c; Dimension d; + + // JToolBar by default uses a somewhat modified BoxLayout as + // its layout manager. For compatibility reasons, we want to + // support Box "glue" as a way to move things around on the + // toolbar. "glue" is represented in BoxLayout as a Box.Filler + // with a minimum and preferred size of (0,0). + // So what we do here is find the number of such glue fillers + // and figure out how much space should be allocated to them. + int glueCount = 0; + for (int i=0; i 0) { + int minWidth = minimumLayoutSize(parent).width; + extraSpacePerGlue = (tb.getWidth() - minWidth) / glueCount; + if (extraSpacePerGlue < 0) extraSpacePerGlue = 0; + } + for (int i = 0; i < tb.getComponentCount(); i++) { c = tb.getComponent(i); d = c.getPreferredSize(); @@ -352,6 +398,9 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, y = baseY + (baseH / 2) - (d.height / 2); h = d.height; } + //if the component is a "glue" component then add to its + //width the extraSpacePerGlue it is due + if (isGlue(c)) d.width += extraSpacePerGlue; c.setBounds(ltr ? x : x - d.width, y, d.width, h); x = ltr ? x + d.width : x - d.width; } @@ -369,6 +418,16 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, int baseW = tb.getWidth() - insets.left - insets.right; int y = handleHeight + insets.top; + // we need to get the minimum height for laying things out + // so that we can calculate how much empty space needs to + // be distributed among the "glue", if any + int extraSpacePerGlue = 0; + if (glueCount > 0) { + int minHeight = minimumLayoutSize(parent).height; + extraSpacePerGlue = (tb.getHeight() - minHeight) / glueCount; + if (extraSpacePerGlue < 0) extraSpacePerGlue = 0; + } + for (int i = 0; i < tb.getComponentCount(); i++) { c = tb.getComponent(i); d = c.getPreferredSize(); @@ -382,11 +441,25 @@ class SynthToolBarUI extends BasicToolBarUI implements PropertyChangeListener, x = baseX + (baseW / 2) - (d.width / 2); w = d.width; } + //if the component is a "glue" component then add to its + //height the extraSpacePerGlue it is due + if (isGlue(c)) d.height += extraSpacePerGlue; c.setBounds(x, y, w, d.height); y += d.height; } } context.dispose(); } + + private boolean isGlue(Component c) { + if (c instanceof Box.Filler) { + Box.Filler f = (Box.Filler)c; + Dimension min = f.getMinimumSize(); + Dimension pref = f.getPreferredSize(); + return min.width == 0 && min.height == 0 && + pref.width == 0 && pref.height == 0; + } + return false; + } } } diff --git a/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java b/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java index 5603c2035ae6ea55ae48bc10b4d53ea53052324e..47011a865d33dca0f63fb6a80e1d1e9c9df14293 100644 --- a/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java +++ b/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java @@ -24,20 +24,31 @@ */ package javax.swing.plaf.synth; -import javax.swing.*; -import javax.swing.event.*; -import java.awt.*; -import java.awt.event.*; -import java.awt.datatransfer.*; -import java.awt.dnd.*; -import java.beans.*; -import java.io.*; -import java.util.*; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.*; -import javax.swing.tree.*; -import javax.swing.text.Position; -import sun.swing.plaf.synth.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Enumeration; +import javax.swing.DefaultCellEditor; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.LookAndFeel; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicTreeUI; +import javax.swing.tree.DefaultTreeCellEditor; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import sun.swing.plaf.synth.SynthIcon; +import sun.swing.plaf.synth.SynthUI; /** * Skinnable TreeUI. @@ -72,10 +83,12 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, expandedIconWrapper = new ExpandedIconWrapper(); } + @Override public Icon getExpandedIcon() { return expandedIconWrapper; } + @Override protected void installDefaults() { updateStyle(tree); } @@ -135,11 +148,13 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, context.dispose(); } + @Override protected void installListeners() { super.installListeners(); tree.addPropertyChangeListener(this); } + @Override public SynthContext getContext(JComponent c) { return getContext(c, getComponentState(c)); } @@ -172,6 +187,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, return ENABLED | SELECTED; } + @Override protected TreeCellEditor createDefaultCellEditor() { TreeCellRenderer renderer = tree.getCellRenderer(); DefaultTreeCellEditor editor; @@ -186,10 +202,12 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, return editor; } + @Override protected TreeCellRenderer createDefaultCellRenderer() { return new SynthTreeCellRenderer(); } + @Override protected void uninstallDefaults() { SynthContext context = getContext(tree, ENABLED); @@ -208,11 +226,13 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } } + @Override protected void uninstallListeners() { super.uninstallListeners(); tree.removePropertyChangeListener(this); } + @Override public void update(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -228,6 +248,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, context.getPainter().paintTreeBorder(context, g, x, y, w, h); } + @Override public void paint(Graphics g, JComponent c) { SynthContext context = getContext(c); @@ -481,6 +502,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } } + @Override protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds, TreePath path, int row, @@ -494,12 +516,14 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } } + @Override protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left, int right) { paintContext.getStyle().getGraphicsUtils(paintContext).drawLine( paintContext, "Tree.horizontalLine", g, left, y, right, y, linesStyle); } + @Override protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) { @@ -508,6 +532,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } } + @Override protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, int bottom) { paintContext.getStyle().getGraphicsUtils(paintContext).drawLine( @@ -528,12 +553,17 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, && dropLocation.getChildIndex() == -1 && path == dropLocation.getPath(); + int state = ENABLED; if (selected || isDrop) { - cellContext.setComponentState(ENABLED | SELECTED); + state |= SELECTED; } - else { - cellContext.setComponentState(ENABLED); + + if (tree.isFocusOwner() && row == leadRow) { + state |= FOCUSED; } + + cellContext.setComponentState(state); + if (dtcr != null && (dtcr.getBorderSelectionColor() instanceof UIResource)) { dtcr.setBorderSelectionColor(style.getColor( @@ -574,6 +604,28 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, : x - (int)Math.floor(iconWidth / 2.0); } + /** + * @inheritDoc + */ + @Override + protected void paintExpandControl(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) { + //modify the paintContext's state to match the state for the row + //this is a hack in that it requires knowledge of the subsequent + //method calls. The point is, the context used in drawCentered + //should reflect the state of the row, not of the tree. + boolean isSelected = tree.getSelectionModel().isPathSelected(path); + int state = paintContext.getComponentState(); + if (isSelected) { + paintContext.setComponentState(state | SynthConstants.SELECTED); + } + super.paintExpandControl(g, clipBounds, insets, bounds, path, row, + isExpanded, hasBeenExpanded, isLeaf); + paintContext.setComponentState(state); + } + + @Override protected void drawCentered(Component c, Graphics graphics, Icon icon, int x, int y) { int w = SynthIcon.getIconWidth(icon, paintContext); @@ -618,6 +670,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } } + @Override protected int getRowX(int row, int depth) { return super.getRowX(row, depth) + padding; } @@ -627,9 +680,13 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, implements UIResource { SynthTreeCellRenderer() { } + + @Override public String getName() { return "Tree.cellRenderer"; } + + @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, @@ -646,6 +703,8 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); } + + @Override public void paint(Graphics g) { paintComponent(g); if (hasFocus) { @@ -692,8 +751,10 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, setBorderSelectionColor(null); } + @Override protected TreeCellEditor createTreeCellEditor() { JTextField tf = new JTextField() { + @Override public String getName() { return "Tree.cellEditor"; } @@ -706,7 +767,6 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } } - // // BasicTreeUI directly uses expandIcon outside of the Synth methods. // To get the correct context we return an instance of this that fetches diff --git a/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java b/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java index a1ac5fe5bac5f580f4b06f6a933107352b9eef47..c203178ce3ae1a13a9c8793e5530a9baf5c43c6a 100644 --- a/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java +++ b/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java @@ -26,7 +26,6 @@ package javax.swing.table; import javax.swing.*; -import javax.swing.table.TableCellRenderer; import javax.swing.border.*; import java.awt.Component; @@ -34,6 +33,7 @@ import java.awt.Color; import java.awt.Rectangle; import java.io.Serializable; +import sun.swing.DefaultLookup; /** @@ -92,8 +92,9 @@ public class DefaultTableCellRenderer extends JLabel * getTableCellRendererComponent method and set the border * of the returned component directly. */ - protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); + private static final Border DEFAULT_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); + protected static Border noFocusBorder = DEFAULT_NO_FOCUS_BORDER; // We need a place to store the color the JLabel should be returned // to after its foreground and background colors have been set @@ -109,12 +110,18 @@ public class DefaultTableCellRenderer extends JLabel super(); setOpaque(true); setBorder(getNoFocusBorder()); + setName("Table.cellRenderer"); } - private static Border getNoFocusBorder() { + private Border getNoFocusBorder() { + Border border = DefaultLookup.getBorder(this, ui, "Table.cellNoFocusBorder"); if (System.getSecurityManager() != null) { + if (border != null) return border; return SAFE_NO_FOCUS_BORDER; } else { + if (noFocusBorder == null || noFocusBorder == DEFAULT_NO_FOCUS_BORDER) { + return border; + } return noFocusBorder; } } @@ -190,8 +197,8 @@ public class DefaultTableCellRenderer extends JLabel && dropLocation.getRow() == row && dropLocation.getColumn() == column) { - fg = UIManager.getColor("Table.dropCellForeground"); - bg = UIManager.getColor("Table.dropCellBackground"); + fg = DefaultLookup.getColor(this, ui, "Table.dropCellForeground"); + bg = DefaultLookup.getColor(this, ui, "Table.dropCellBackground"); isSelected = true; } @@ -202,12 +209,18 @@ public class DefaultTableCellRenderer extends JLabel super.setBackground(bg == null ? table.getSelectionBackground() : bg); } else { + Color background = unselectedBackground != null + ? unselectedBackground + : table.getBackground(); + if (background == null || background instanceof javax.swing.plaf.UIResource) { + Color alternateColor = DefaultLookup.getColor(this, ui, "Table.alternateRowColor"); + if (alternateColor != null && row % 2 == 0) + background = alternateColor; + } super.setForeground(unselectedForeground != null ? unselectedForeground : table.getForeground()); - super.setBackground(unselectedBackground != null - ? unselectedBackground - : table.getBackground()); + super.setBackground(background); } setFont(table.getFont()); @@ -215,20 +228,20 @@ public class DefaultTableCellRenderer extends JLabel if (hasFocus) { Border border = null; if (isSelected) { - border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder"); + border = DefaultLookup.getBorder(this, ui, "Table.focusSelectedCellHighlightBorder"); } if (border == null) { - border = UIManager.getBorder("Table.focusCellHighlightBorder"); + border = DefaultLookup.getBorder(this, ui, "Table.focusCellHighlightBorder"); } setBorder(border); if (!isSelected && table.isCellEditable(row, column)) { Color col; - col = UIManager.getColor("Table.focusCellForeground"); + col = DefaultLookup.getColor(this, ui, "Table.focusCellForeground"); if (col != null) { super.setForeground(col); } - col = UIManager.getColor("Table.focusCellBackground"); + col = DefaultLookup.getColor(this, ui, "Table.focusCellBackground"); if (col != null) { super.setBackground(col); } @@ -261,6 +274,7 @@ public class DefaultTableCellRenderer extends JLabel if (p != null) { p = p.getParent(); } + // p should now be the JTable. boolean colorMatch = (back != null) && (p != null) && back.equals(p.getBackground()) && diff --git a/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java b/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java index 6363ae995981d09b38de3980d199ecfc810526a4..dd7a1ca9b213e97b24e5c004082f100ebdfdf8b7 100644 --- a/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java +++ b/src/share/classes/javax/swing/tree/DefaultTreeCellRenderer.java @@ -25,16 +25,24 @@ package javax.swing.tree; -import javax.swing.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicGraphicsUtils; -import java.awt.*; -import java.awt.event.*; -import java.beans.*; -import java.io.*; -import java.util.*; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JTree; +import javax.swing.LookAndFeel; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import sun.swing.DefaultLookup; /** * Displays an entry in a tree. @@ -148,6 +156,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer protected Color borderSelectionColor; private boolean isDropCell; + private boolean fillBackground = true; /** * Set to true after the constructor has run. @@ -177,41 +186,48 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer // null. As such, if the value is null, this does not reset the // value. if (!inited || (getLeafIcon() instanceof UIResource)) { - setLeafIcon(UIManager.getIcon("Tree.leafIcon")); + setLeafIcon(DefaultLookup.getIcon(this, ui, "Tree.leafIcon")); } if (!inited || (getClosedIcon() instanceof UIResource)) { - setClosedIcon(UIManager.getIcon("Tree.closedIcon")); + setClosedIcon(DefaultLookup.getIcon(this, ui, "Tree.closedIcon")); } if (!inited || (getOpenIcon() instanceof UIManager)) { - setOpenIcon(UIManager.getIcon("Tree.openIcon")); + setOpenIcon(DefaultLookup.getIcon(this, ui, "Tree.openIcon")); } if (!inited || (getTextSelectionColor() instanceof UIResource)) { setTextSelectionColor( - UIManager.getColor("Tree.selectionForeground")); + DefaultLookup.getColor(this, ui, "Tree.selectionForeground")); } if (!inited || (getTextNonSelectionColor() instanceof UIResource)) { setTextNonSelectionColor( - UIManager.getColor("Tree.textForeground")); + DefaultLookup.getColor(this, ui, "Tree.textForeground")); } if (!inited || (getBackgroundSelectionColor() instanceof UIResource)) { setBackgroundSelectionColor( - UIManager.getColor("Tree.selectionBackground")); + DefaultLookup.getColor(this, ui, "Tree.selectionBackground")); } if (!inited || (getBackgroundNonSelectionColor() instanceof UIResource)) { setBackgroundNonSelectionColor( - UIManager.getColor("Tree.textBackground")); + DefaultLookup.getColor(this, ui, "Tree.textBackground")); } if (!inited || (getBorderSelectionColor() instanceof UIResource)) { setBorderSelectionColor( - UIManager.getColor("Tree.selectionBorderColor")); + DefaultLookup.getColor(this, ui, "Tree.selectionBorderColor")); } - Object value = UIManager.get("Tree.drawsFocusBorderAroundIcon"); - drawsFocusBorderAroundIcon = (value != null && ((Boolean)value). - booleanValue()); - value = UIManager.get("Tree.drawDashedFocusIndicator"); - drawDashedFocusIndicator = (value != null && ((Boolean)value). - booleanValue()); + drawsFocusBorderAroundIcon = DefaultLookup.getBoolean( + this, ui, "Tree.drawsFocusBorderAroundIcon", false); + drawDashedFocusIndicator = DefaultLookup.getBoolean( + this, ui, "Tree.drawDashedFocusIndicator", false); + + fillBackground = DefaultLookup.getBoolean(this, ui, "Tree.rendererFillBackground", true); + Insets margins = DefaultLookup.getInsets(this, ui, "Tree.rendererMargins"); + if (margins != null) { + setBorder(new EmptyBorder(margins.top, margins.left, + margins.bottom, margins.right)); + } + + setName("Tree.cellRenderer"); } @@ -220,7 +236,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer * represent non-leaf nodes that are expanded. */ public Icon getDefaultOpenIcon() { - return UIManager.getIcon("Tree.openIcon"); + return DefaultLookup.getIcon(this, ui, "Tree.openIcon"); } /** @@ -228,7 +244,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer * represent non-leaf nodes that are not expanded. */ public Icon getDefaultClosedIcon() { - return UIManager.getIcon("Tree.closedIcon"); + return DefaultLookup.getIcon(this, ui, "Tree.closedIcon"); } /** @@ -236,7 +252,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer * represent leaf nodes. */ public Icon getDefaultLeafIcon() { - return UIManager.getIcon("Tree.leafIcon"); + return DefaultLookup.getIcon(this, ui, "Tree.leafIcon"); } /** @@ -425,7 +441,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer && dropLocation.getChildIndex() == -1 && tree.getRowForPath(dropLocation.getPath()) == row) { - Color col = UIManager.getColor("Tree.dropCellForeground"); + Color col = DefaultLookup.getColor(this, ui, "Tree.dropCellForeground"); if (col != null) { fg = col; } else { @@ -441,26 +457,24 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer setForeground(fg); - // There needs to be a way to specify disabled icons. + Icon icon = null; + if (leaf) { + icon = getLeafIcon(); + } else if (expanded) { + icon = getOpenIcon(); + } else { + icon = getClosedIcon(); + } + if (!tree.isEnabled()) { setEnabled(false); - if (leaf) { - setDisabledIcon(getLeafIcon()); - } else if (expanded) { - setDisabledIcon(getOpenIcon()); - } else { - setDisabledIcon(getClosedIcon()); - } - } - else { + LookAndFeel laf = UIManager.getLookAndFeel(); + Icon disabledIcon = laf.getDisabledIcon(tree, icon); + if (disabledIcon != null) icon = disabledIcon; + setDisabledIcon(icon); + } else { setEnabled(true); - if (leaf) { - setIcon(getLeafIcon()); - } else if (expanded) { - setIcon(getOpenIcon()); - } else { - setIcon(getClosedIcon()); - } + setIcon(icon); } setComponentOrientation(tree.getComponentOrientation()); @@ -476,7 +490,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer Color bColor; if (isDropCell) { - bColor = UIManager.getColor("Tree.dropCellBackground"); + bColor = DefaultLookup.getColor(this, ui, "Tree.dropCellBackground"); if (bColor == null) { bColor = getBackgroundSelectionColor(); } @@ -490,9 +504,7 @@ public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer } int imageOffset = -1; - if(bColor != null) { - Icon currentI = getIcon(); - + if (bColor != null && fillBackground) { imageOffset = getLabelStart(); g.setColor(bColor); if(getComponentOrientation().isLeftToRight()) { diff --git a/src/share/classes/sun/swing/DefaultLookup.java b/src/share/classes/sun/swing/DefaultLookup.java index af46f955f9f91fa9ce69b862e729996fcdd84b56..c5dccc5e13b873375639c2b875c6d8ea1220eb1a 100644 --- a/src/share/classes/sun/swing/DefaultLookup.java +++ b/src/share/classes/sun/swing/DefaultLookup.java @@ -27,6 +27,7 @@ package sun.swing; import java.awt.Color; import java.awt.Insets; import javax.swing.*; +import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import sun.awt.AppContext; @@ -137,6 +138,10 @@ public class DefaultLookup { return ((Number)iValue).intValue(); } + public static int getInt(JComponent c, ComponentUI ui, String key) { + return getInt(c, ui, key, -1); + } + public static Insets getInsets(JComponent c, ComponentUI ui, String key, Insets defaultValue) { Object iValue = get(c, ui, key); @@ -147,6 +152,10 @@ public class DefaultLookup { return (Insets)iValue; } + public static Insets getInsets(JComponent c, ComponentUI ui, String key) { + return getInsets(c, ui, key, null); + } + public static boolean getBoolean(JComponent c, ComponentUI ui, String key, boolean defaultValue) { Object iValue = get(c, ui, key); @@ -157,6 +166,10 @@ public class DefaultLookup { return ((Boolean)iValue).booleanValue(); } + public static boolean getBoolean(JComponent c, ComponentUI ui, String key) { + return getBoolean(c, ui, key, false); + } + public static Color getColor(JComponent c, ComponentUI ui, String key, Color defaultValue) { Object iValue = get(c, ui, key); @@ -167,7 +180,35 @@ public class DefaultLookup { return (Color)iValue; } + public static Color getColor(JComponent c, ComponentUI ui, String key) { + return getColor(c, ui, key, null); + } + + public static Icon getIcon(JComponent c, ComponentUI ui, String key, + Icon defaultValue) { + Object iValue = get(c, ui, key); + if (iValue == null || !(iValue instanceof Icon)) { + return defaultValue; + } + return (Icon)iValue; + } + + public static Icon getIcon(JComponent c, ComponentUI ui, String key) { + return getIcon(c, ui, key, null); + } + + public static Border getBorder(JComponent c, ComponentUI ui, String key, + Border defaultValue) { + Object iValue = get(c, ui, key); + if (iValue == null || !(iValue instanceof Border)) { + return defaultValue; + } + return (Border)iValue; + } + public static Border getBorder(JComponent c, ComponentUI ui, String key) { + return getBorder(c, ui, key, null); + } public Object getDefault(JComponent c, ComponentUI ui, String key) { // basic diff --git a/src/share/classes/sun/swing/FilePane.java b/src/share/classes/sun/swing/FilePane.java index 71112b319d8c328c91236bc719ce0a0638565faa..eae3d5a0d602be71b2d79ed0a1fd84001d43adf8 100644 --- a/src/share/classes/sun/swing/FilePane.java +++ b/src/share/classes/sun/swing/FilePane.java @@ -265,6 +265,7 @@ public class FilePane extends JPanel implements PropertyChangeListener { private Color listViewBackground; private boolean listViewWindowsStyle; private boolean readOnly; + private boolean fullRowSelection = false; private ListSelectionModel listSelectionModel; private JList list; @@ -448,6 +449,7 @@ public class FilePane extends JPanel implements PropertyChangeListener { kiloByteString = UIManager.getString("FileChooser.fileSizeKiloBytes", l); megaByteString = UIManager.getString("FileChooser.fileSizeMegaBytes", l); gigaByteString = UIManager.getString("FileChooser.fileSizeGigaBytes", l); + fullRowSelection = UIManager.getBoolean("FileView.fullRowSelection"); renameErrorTitleText = UIManager.getString("FileChooser.renameErrorTitleText", l); renameErrorText = UIManager.getString("FileChooser.renameErrorText", l); @@ -991,6 +993,7 @@ public class FilePane extends JPanel implements PropertyChangeListener { public DetailsTableCellEditor(JTextField tf) { super(tf); this.tf = tf; + tf.setName("Table.editor"); tf.addFocusListener(editorFocusListener); } @@ -1018,7 +1021,8 @@ public class FilePane extends JPanel implements PropertyChangeListener { } public void setBounds(int x, int y, int width, int height) { - if (getHorizontalAlignment() == SwingConstants.LEADING) { + if (getHorizontalAlignment() == SwingConstants.LEADING && + !fullRowSelection) { // Restrict width to actual text width = Math.min(width, this.getPreferredSize().width+4); } else { @@ -1039,9 +1043,9 @@ public class FilePane extends JPanel implements PropertyChangeListener { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - if (table.convertColumnIndexToModel(column) != COLUMN_FILENAME || - (listViewWindowsStyle && !table.isFocusOwner())) { - + if ((table.convertColumnIndexToModel(column) != COLUMN_FILENAME || + (listViewWindowsStyle && !table.isFocusOwner())) && + !fullRowSelection) { isSelected = false; } @@ -1338,6 +1342,7 @@ public class FilePane extends JPanel implements PropertyChangeListener { Rectangle r = list.getCellBounds(index, index); if (editCell == null) { editCell = new JTextField(); + editCell.setName("Tree.cellEditor"); editCell.addActionListener(new EditActionListener()); editCell.addFocusListener(editorFocusListener); editCell.setNextFocusableComponent(list); @@ -1797,10 +1802,11 @@ public class FilePane extends JPanel implements PropertyChangeListener { Point p = evt.getPoint(); index = table.rowAtPoint(p); - if (SwingUtilities2.pointOutsidePrefSize(table, - index, - table.columnAtPoint(p), p)) { + boolean pointOutsidePrefSize = + SwingUtilities2.pointOutsidePrefSize( + table, index, table.columnAtPoint(p), p); + if (pointOutsidePrefSize && !fullRowSelection) { return; } diff --git a/src/share/classes/sun/swing/plaf/GTKKeybindings.java b/src/share/classes/sun/swing/plaf/GTKKeybindings.java new file mode 100644 index 0000000000000000000000000000000000000000..3701d86ccd51a4da155b9537302e1563b182e1c3 --- /dev/null +++ b/src/share/classes/sun/swing/plaf/GTKKeybindings.java @@ -0,0 +1,736 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.swing.plaf; + +import javax.swing.JTextField; +import javax.swing.UIDefaults; +import javax.swing.text.DefaultEditorKit; + +/** + * GTKKeybindings - The standard set of keymaps for the GTK Platform + * + * @author Jasper Potts + */ +public class GTKKeybindings { + + /** + * Install all GTK keybindings into the provided UIDefaults table + * + * @param table The UiDefaults table to install into + */ + public static void installKeybindings(UIDefaults table) { + Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", DefaultEditorKit.copyAction, + "ctrl V", DefaultEditorKit.pasteAction, + "ctrl X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction, + "ctrl LEFT", DefaultEditorKit.previousWordAction, + "ctrl KP_LEFT", DefaultEditorKit.previousWordAction, + "ctrl RIGHT", DefaultEditorKit.nextWordAction, + "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction, + "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl A", DefaultEditorKit.selectAllAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "ctrl DELETE", DefaultEditorKit.deleteNextWordAction, + "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "ENTER", JTextField.notifyAction, + "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/, + "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ + }); + Object passwordInputMap = new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", DefaultEditorKit.copyAction, + "ctrl V", DefaultEditorKit.pasteAction, + "ctrl X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction, + "ctrl LEFT", DefaultEditorKit.beginLineAction, + "ctrl KP_LEFT", DefaultEditorKit.beginLineAction, + "ctrl RIGHT", DefaultEditorKit.endLineAction, + "ctrl KP_RIGHT", DefaultEditorKit.endLineAction, + "ctrl shift LEFT", DefaultEditorKit.selectionBeginLineAction, + "ctrl shift KP_LEFT", DefaultEditorKit.selectionBeginLineAction, + "ctrl shift RIGHT", DefaultEditorKit.selectionEndLineAction, + "ctrl shift KP_RIGHT", DefaultEditorKit.selectionEndLineAction, + "ctrl A", DefaultEditorKit.selectAllAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "ENTER", JTextField.notifyAction, + "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/, + "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ + }); + Object multilineInputMap = new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", DefaultEditorKit.copyAction, + "ctrl V", DefaultEditorKit.pasteAction, + "ctrl X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction, + "ctrl LEFT", DefaultEditorKit.previousWordAction, + "ctrl KP_LEFT", DefaultEditorKit.previousWordAction, + "ctrl RIGHT", DefaultEditorKit.nextWordAction, + "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction, + "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl A", DefaultEditorKit.selectAllAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + + "UP", DefaultEditorKit.upAction, + "KP_UP", DefaultEditorKit.upAction, + "DOWN", DefaultEditorKit.downAction, + "KP_DOWN", DefaultEditorKit.downAction, + "PAGE_UP", DefaultEditorKit.pageUpAction, + "PAGE_DOWN", DefaultEditorKit.pageDownAction, + "shift PAGE_UP", "selection-page-up", + "shift PAGE_DOWN", "selection-page-down", + "ctrl shift PAGE_UP", "selection-page-left", + "ctrl shift PAGE_DOWN", "selection-page-right", + "shift UP", DefaultEditorKit.selectionUpAction, + "shift KP_UP", DefaultEditorKit.selectionUpAction, + "shift DOWN", DefaultEditorKit.selectionDownAction, + "shift KP_DOWN", DefaultEditorKit.selectionDownAction, + "ENTER", DefaultEditorKit.insertBreakAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "ctrl DELETE", DefaultEditorKit.deleteNextWordAction, + "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "TAB", DefaultEditorKit.insertTabAction, + "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/, + "ctrl HOME", DefaultEditorKit.beginAction, + "ctrl END", DefaultEditorKit.endAction, + "ctrl shift HOME", DefaultEditorKit.selectionBeginAction, + "ctrl shift END", DefaultEditorKit.selectionEndAction, + "ctrl T", "next-link-action", + "ctrl shift T", "previous-link-action", + "ctrl SPACE", "activate-link-action", + "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ + }); + + Object[] defaults = new Object[]{ + "Button.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released", + "ENTER", "pressed", + "released ENTER", "released" + }), + "CheckBox.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released" + }), + "ComboBox.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ESCAPE", "hidePopup", + "PAGE_UP", "pageUpPassThrough", + "PAGE_DOWN", "pageDownPassThrough", + "HOME", "homePassThrough", + "END", "endPassThrough", + "DOWN", "selectNext", + "KP_DOWN", "selectNext", + "alt DOWN", "togglePopup", + "alt KP_DOWN", "togglePopup", + "alt UP", "togglePopup", + "alt KP_UP", "togglePopup", + "SPACE", "spacePopup", + "ENTER", "enterPressed", + "UP", "selectPrevious", + "KP_UP", "selectPrevious" + + }), + "EditorPane.focusInputMap", multilineInputMap, + "FileChooser.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ESCAPE", "cancelSelection", + "F2", "editFileName", + "F5", "refresh", + "BACK_SPACE", "Go Up", + "ENTER", "approveSelection", + "ctrl ENTER", "approveSelection" + }), + "FormattedTextField.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", DefaultEditorKit.copyAction, + "ctrl V", DefaultEditorKit.pasteAction, + "ctrl X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction, + "ctrl LEFT", DefaultEditorKit.previousWordAction, + "ctrl KP_LEFT", DefaultEditorKit.previousWordAction, + "ctrl RIGHT", DefaultEditorKit.nextWordAction, + "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction, + "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl A", DefaultEditorKit.selectAllAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "ctrl DELETE", DefaultEditorKit.deleteNextWordAction, + "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "ENTER", JTextField.notifyAction, + "ctrl BACK_SLASH", "unselect", + "control shift O", "toggle-componentOrientation", + "ESCAPE", "reset-field-edit", + "UP", "increment", + "KP_UP", "increment", + "DOWN", "decrement", + "KP_DOWN", "decrement", + }), + "InternalFrame.windowBindings", + new Object[]{ + "shift ESCAPE", "showSystemMenu", + "ctrl SPACE", "showSystemMenu", + "ESCAPE", "hideSystemMenu" + }, + "List.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", "copy", + "ctrl V", "paste", + "ctrl X", "cut", + "COPY", "copy", + "PASTE", "paste", + "CUT", "cut", + "control INSERT", "copy", + "shift INSERT", "paste", + "shift DELETE", "cut", + "UP", "selectPreviousRow", + "KP_UP", "selectPreviousRow", + "shift UP", "selectPreviousRowExtendSelection", + "shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl shift UP", "selectPreviousRowExtendSelection", + "ctrl shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "DOWN", "selectNextRow", + "KP_DOWN", "selectNextRow", + "shift DOWN", "selectNextRowExtendSelection", + "shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl shift DOWN", "selectNextRowExtendSelection", + "ctrl shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl DOWN", "selectNextRowChangeLead", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "LEFT", "selectPreviousColumn", + "KP_LEFT", "selectPreviousColumn", + "shift LEFT", "selectPreviousColumnExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "RIGHT", "selectNextColumn", + "KP_RIGHT", "selectNextColumn", + "shift RIGHT", "selectNextColumnExtendSelection", + "shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl shift RIGHT", "selectNextColumnExtendSelection", + "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl RIGHT", "selectNextColumnChangeLead", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "HOME", "selectFirstRow", + "shift HOME", "selectFirstRowExtendSelection", + "ctrl shift HOME", "selectFirstRowExtendSelection", + "ctrl HOME", "selectFirstRowChangeLead", + "END", "selectLastRow", + "shift END", "selectLastRowExtendSelection", + "ctrl shift END", "selectLastRowExtendSelection", + "ctrl END", "selectLastRowChangeLead", + "PAGE_UP", "scrollUp", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_UP", "scrollUpExtendSelection", + "ctrl PAGE_UP", "scrollUpChangeLead", + "PAGE_DOWN", "scrollDown", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl PAGE_DOWN", "scrollDownChangeLead", + "ctrl A", "selectAll", + "ctrl SLASH", "selectAll", + "ctrl BACK_SLASH", "clearSelection", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "ctrl shift SPACE", "moveSelectionTo" + }), + "List.focusInputMap.RightToLeft", + new UIDefaults.LazyInputMap(new Object[]{ + "LEFT", "selectNextColumn", + "KP_LEFT", "selectNextColumn", + "shift LEFT", "selectNextColumnExtendSelection", + "shift KP_LEFT", "selectNextColumnExtendSelection", + "ctrl shift LEFT", "selectNextColumnExtendSelection", + "ctrl shift KP_LEFT", "selectNextColumnExtendSelection", + "ctrl LEFT", "selectNextColumnChangeLead", + "ctrl KP_LEFT", "selectNextColumnChangeLead", + "RIGHT", "selectPreviousColumn", + "KP_RIGHT", "selectPreviousColumn", + "shift RIGHT", "selectPreviousColumnExtendSelection", + "shift KP_RIGHT", "selectPreviousColumnExtendSelection", + "ctrl shift RIGHT", "selectPreviousColumnExtendSelection", + "ctrl shift KP_RIGHT", "selectPreviousColumnExtendSelection", + "ctrl RIGHT", "selectPreviousColumnChangeLead", + "ctrl KP_RIGHT", "selectPreviousColumnChangeLead", + }), + "MenuBar.windowBindings", new Object[]{ + "F10", "takeFocus" + }, + "OptionPane.windowBindings", new Object[]{ + "ESCAPE", "close" + }, + "PasswordField.focusInputMap", passwordInputMap, + "PopupMenu.selectedWindowInputMapBindings", + new Object[]{ + "ESCAPE", "cancel", + "DOWN", "selectNext", + "KP_DOWN", "selectNext", + "UP", "selectPrevious", + "KP_UP", "selectPrevious", + "LEFT", "selectParent", + "KP_LEFT", "selectParent", + "RIGHT", "selectChild", + "KP_RIGHT", "selectChild", + "ENTER", "return", + "SPACE", "return" + }, + "PopupMenu.selectedWindowInputMapBindings.RightToLeft", + new Object[]{ + "LEFT", "selectChild", + "KP_LEFT", "selectChild", + "RIGHT", "selectParent", + "KP_RIGHT", "selectParent", + }, + "RadioButton.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released", + "RETURN", "pressed" + }), + // These bindings are only enabled when there is a default + // button set on the rootpane. + "RootPane.defaultButtonWindowKeyBindings", new Object[]{ + "ENTER", "press", + "released ENTER", "release", + "ctrl ENTER", "press", + "ctrl released ENTER", "release" + }, + "ScrollBar.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "positiveUnitIncrement", + "KP_RIGHT", "positiveUnitIncrement", + "DOWN", "positiveUnitIncrement", + "KP_DOWN", "positiveUnitIncrement", + "PAGE_DOWN", "positiveBlockIncrement", + "LEFT", "negativeUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", + "UP", "negativeUnitIncrement", + "KP_UP", "negativeUnitIncrement", + "PAGE_UP", "negativeBlockIncrement", + "HOME", "minScroll", + "END", "maxScroll" + }), + "ScrollBar.ancestorInputMap.RightToLeft", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "negativeUnitIncrement", + "KP_RIGHT", "negativeUnitIncrement", + "LEFT", "positiveUnitIncrement", + "KP_LEFT", "positiveUnitIncrement", + }), + "ScrollPane.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "unitScrollRight", + "KP_RIGHT", "unitScrollRight", + "DOWN", "unitScrollDown", + "KP_DOWN", "unitScrollDown", + "LEFT", "unitScrollLeft", + "KP_LEFT", "unitScrollLeft", + "UP", "unitScrollUp", + "KP_UP", "unitScrollUp", + "PAGE_UP", "scrollUp", + "PAGE_DOWN", "scrollDown", + "ctrl PAGE_UP", "scrollLeft", + "ctrl PAGE_DOWN", "scrollRight", + "ctrl HOME", "scrollHome", + "ctrl END", "scrollEnd" + }), + "ScrollPane.ancestorInputMap.RightToLeft", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl PAGE_UP", "scrollRight", + "ctrl PAGE_DOWN", "scrollLeft", + }), + "Slider.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "positiveUnitIncrement", + "KP_RIGHT", "positiveUnitIncrement", + "DOWN", "negativeUnitIncrement", + "KP_DOWN", "negativeUnitIncrement", + "PAGE_DOWN", "negativeBlockIncrement", + "LEFT", "negativeUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", + "UP", "positiveUnitIncrement", + "KP_UP", "positiveUnitIncrement", + "PAGE_UP", "positiveBlockIncrement", + "HOME", "minScroll", + "END", "maxScroll" + }), + "Slider.focusInputMap.RightToLeft", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "negativeUnitIncrement", + "KP_RIGHT", "negativeUnitIncrement", + "LEFT", "positiveUnitIncrement", + "KP_LEFT", "positiveUnitIncrement", + }), + "Spinner.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "UP", "increment", + "KP_UP", "increment", + "DOWN", "decrement", + "KP_DOWN", "decrement", + }), + "SplitPane.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "UP", "negativeIncrement", + "DOWN", "positiveIncrement", + "LEFT", "negativeIncrement", + "RIGHT", "positiveIncrement", + "KP_UP", "negativeIncrement", + "KP_DOWN", "positiveIncrement", + "KP_LEFT", "negativeIncrement", + "KP_RIGHT", "positiveIncrement", + "HOME", "selectMin", + "END", "selectMax", + "F8", "startResize", + "F6", "toggleFocus", + "ctrl TAB", "focusOutForward", + "ctrl shift TAB", "focusOutBackward" + }), + "TabbedPane.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "navigateRight", + "KP_RIGHT", "navigateRight", + "LEFT", "navigateLeft", + "KP_LEFT", "navigateLeft", + "UP", "navigateUp", + "KP_UP", "navigateUp", + "DOWN", "navigateDown", + "KP_DOWN", "navigateDown", + "ctrl DOWN", "requestFocusForVisibleComponent", + "ctrl KP_DOWN", "requestFocusForVisibleComponent", + "SPACE", "selectTabWithFocus" + }), + "TabbedPane.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl TAB", "navigateNext", + "ctrl shift TAB", "navigatePrevious", + "ctrl PAGE_DOWN", "navigatePageDown", + "ctrl PAGE_UP", "navigatePageUp", + "ctrl UP", "requestFocus", + "ctrl KP_UP", "requestFocus", + }), + "TableHeader.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "toggleSortOrder", + "LEFT", "selectColumnToLeft", + "KP_LEFT", "selectColumnToLeft", + "RIGHT", "selectColumnToRight", + "KP_RIGHT", "selectColumnToRight", + "alt LEFT", "moveColumnLeft", + "alt KP_LEFT", "moveColumnLeft", + "alt RIGHT", "moveColumnRight", + "alt KP_RIGHT", "moveColumnRight", + "alt shift LEFT", "resizeLeft", + "alt shift KP_LEFT", "resizeLeft", + "alt shift RIGHT", "resizeRight", + "alt shift KP_RIGHT", "resizeRight", + "ESCAPE", "focusTable", + }), + "Table.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", "copy", + "ctrl V", "paste", + "ctrl X", "cut", + "COPY", "copy", + "PASTE", "paste", + "CUT", "cut", + "control INSERT", "copy", + "shift INSERT", "paste", + "shift DELETE", "cut", + "RIGHT", "selectNextColumn", + "KP_RIGHT", "selectNextColumn", + "shift RIGHT", "selectNextColumnExtendSelection", + "shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl shift RIGHT", "selectNextColumnExtendSelection", + "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl RIGHT", "selectNextColumnChangeLead", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "LEFT", "selectPreviousColumn", + "KP_LEFT", "selectPreviousColumn", + "shift LEFT", "selectPreviousColumnExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "DOWN", "selectNextRow", + "KP_DOWN", "selectNextRow", + "shift DOWN", "selectNextRowExtendSelection", + "shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl shift DOWN", "selectNextRowExtendSelection", + "ctrl shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl DOWN", "selectNextRowChangeLead", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "UP", "selectPreviousRow", + "KP_UP", "selectPreviousRow", + "shift UP", "selectPreviousRowExtendSelection", + "shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl shift UP", "selectPreviousRowExtendSelection", + "ctrl shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "HOME", "selectFirstColumn", + "shift HOME", "selectFirstColumnExtendSelection", + "ctrl shift HOME", "selectFirstRowExtendSelection", + "ctrl HOME", "selectFirstRow", + "END", "selectLastColumn", + "shift END", "selectLastColumnExtendSelection", + "ctrl shift END", "selectLastRowExtendSelection", + "ctrl END", "selectLastRow", + "PAGE_UP", "scrollUpChangeSelection", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_UP", "scrollLeftExtendSelection", + "ctrl PAGE_UP", "scrollLeftChangeSelection", + "PAGE_DOWN", "scrollDownChangeSelection", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl shift PAGE_DOWN", "scrollRightExtendSelection", + "ctrl PAGE_DOWN", "scrollRightChangeSelection", + "TAB", "selectNextColumnCell", + "shift TAB", "selectPreviousColumnCell", + "ENTER", "selectNextRowCell", + "shift ENTER", "selectPreviousRowCell", + "ctrl A", "selectAll", + "ctrl SLASH", "selectAll", + "ctrl BACK_SLASH", "clearSelection", + "ESCAPE", "cancel", + "F2", "startEditing", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "ctrl shift SPACE", "moveSelectionTo", + "F8", "focusHeader" + }), + "Table.ancestorInputMap.RightToLeft", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "selectPreviousColumn", + "KP_RIGHT", "selectPreviousColumn", + "shift RIGHT", "selectPreviousColumnExtendSelection", + "shift KP_RIGHT", "selectPreviousColumnExtendSelection", + "ctrl shift RIGHT", "selectPreviousColumnExtendSelection", + "ctrl shift KP_RIGHT", "selectPreviousColumnExtendSelection", + "shift RIGHT", "selectPreviousColumnChangeLead", + "shift KP_RIGHT", "selectPreviousColumnChangeLead", + "LEFT", "selectNextColumn", + "KP_LEFT", "selectNextColumn", + "shift LEFT", "selectNextColumnExtendSelection", + "shift KP_LEFT", "selectNextColumnExtendSelection", + "ctrl shift LEFT", "selectNextColumnExtendSelection", + "ctrl shift KP_LEFT", "selectNextColumnExtendSelection", + "ctrl LEFT", "selectNextColumnChangeLead", + "ctrl KP_LEFT", "selectNextColumnChangeLead", + "ctrl PAGE_UP", "scrollRightChangeSelection", + "ctrl PAGE_DOWN", "scrollLeftChangeSelection", + "ctrl shift PAGE_UP", "scrollRightExtendSelection", + "ctrl shift PAGE_DOWN", "scrollLeftExtendSelection", + }), + "TextArea.focusInputMap", multilineInputMap, + "TextField.focusInputMap", fieldInputMap, + "TextPane.focusInputMap", multilineInputMap, + "ToggleButton.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released" + }), + "ToolBar.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "UP", "navigateUp", + "KP_UP", "navigateUp", + "DOWN", "navigateDown", + "KP_DOWN", "navigateDown", + "LEFT", "navigateLeft", + "KP_LEFT", "navigateLeft", + "RIGHT", "navigateRight", + "KP_RIGHT", "navigateRight" + }), + "Tree.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", "copy", + "ctrl V", "paste", + "ctrl X", "cut", + "COPY", "copy", + "PASTE", "paste", + "CUT", "cut", + "control INSERT", "copy", + "shift INSERT", "paste", + "shift DELETE", "cut", + "UP", "selectPrevious", + "KP_UP", "selectPrevious", + "shift UP", "selectPreviousExtendSelection", + "shift KP_UP", "selectPreviousExtendSelection", + "ctrl shift UP", "selectPreviousExtendSelection", + "ctrl shift KP_UP", "selectPreviousExtendSelection", + "ctrl UP", "selectPreviousChangeLead", + "ctrl KP_UP", "selectPreviousChangeLead", + "DOWN", "selectNext", + "KP_DOWN", "selectNext", + "shift DOWN", "selectNextExtendSelection", + "shift KP_DOWN", "selectNextExtendSelection", + "ctrl shift DOWN", "selectNextExtendSelection", + "ctrl shift KP_DOWN", "selectNextExtendSelection", + "ctrl DOWN", "selectNextChangeLead", + "ctrl KP_DOWN", "selectNextChangeLead", + "RIGHT", "selectChild", + "KP_RIGHT", "selectChild", + "LEFT", "selectParent", + "KP_LEFT", "selectParent", + "typed +", "expand", + "typed -", "collapse", + "BACK_SPACE", "moveSelectionToParent", + "PAGE_UP", "scrollUpChangeSelection", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_UP", "scrollUpExtendSelection", + "ctrl PAGE_UP", "scrollUpChangeLead", + "PAGE_DOWN", "scrollDownChangeSelection", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl PAGE_DOWN", "scrollDownChangeLead", + "HOME", "selectFirst", + "shift HOME", "selectFirstExtendSelection", + "ctrl shift HOME", "selectFirstExtendSelection", + "ctrl HOME", "selectFirstChangeLead", + "END", "selectLast", + "shift END", "selectLastExtendSelection", + "ctrl shift END", "selectLastExtendSelection", + "ctrl END", "selectLastChangeLead", + "F2", "startEditing", + "ctrl A", "selectAll", + "ctrl SLASH", "selectAll", + "ctrl BACK_SLASH", "clearSelection", + "ctrl LEFT", "scrollLeft", + "ctrl KP_LEFT", "scrollLeft", + "ctrl RIGHT", "scrollRight", + "ctrl KP_RIGHT", "scrollRight", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "ctrl shift SPACE", "moveSelectionTo" + }), + "Tree.focusInputMap.RightToLeft", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "selectParent", + "KP_RIGHT", "selectParent", + "LEFT", "selectChild", + "KP_LEFT", "selectChild", + }), + "Tree.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ESCAPE", "cancel" + }), + }; + table.putDefaults(defaults); + } +} diff --git a/src/share/classes/sun/swing/plaf/WindowsKeybindings.java b/src/share/classes/sun/swing/plaf/WindowsKeybindings.java new file mode 100644 index 0000000000000000000000000000000000000000..48f93e78762dcdac42f526623b55c455ef728c96 --- /dev/null +++ b/src/share/classes/sun/swing/plaf/WindowsKeybindings.java @@ -0,0 +1,643 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.swing.plaf; + +import javax.swing.JTextField; +import javax.swing.UIDefaults; +import javax.swing.text.DefaultEditorKit; + +/** + * WindowsKeybindings - The standard set of keymaps for the Windows Platform + * + * @author Jasper Potts + */ +public class WindowsKeybindings { + + /** + * Install all Windows keybindings into the provided UIDefaults table + * + * @param table The UiDefaults table to install into + */ + public static void installKeybindings(UIDefaults table) { + // *** Text + Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[]{ + "control C", DefaultEditorKit.copyAction, + "control V", DefaultEditorKit.pasteAction, + "control X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "control A", DefaultEditorKit.selectAllAction, + "control BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "control LEFT", DefaultEditorKit.previousWordAction, + "control RIGHT", DefaultEditorKit.nextWordAction, + "control shift LEFT", DefaultEditorKit.selectionPreviousWordAction, + "control shift RIGHT", DefaultEditorKit.selectionNextWordAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "ctrl DELETE", DefaultEditorKit.deleteNextWordAction, + "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "ENTER", JTextField.notifyAction, + "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ + }); + Object passwordInputMap = new UIDefaults.LazyInputMap(new Object[]{ + "control C", DefaultEditorKit.copyAction, + "control V", DefaultEditorKit.pasteAction, + "control X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "control A", DefaultEditorKit.selectAllAction, + "control BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "control LEFT", DefaultEditorKit.beginLineAction, + "control RIGHT", DefaultEditorKit.endLineAction, + "control shift LEFT", DefaultEditorKit.selectionBeginLineAction, + "control shift RIGHT", DefaultEditorKit.selectionEndLineAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "ENTER", JTextField.notifyAction, + "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ + }); + Object multilineInputMap = new UIDefaults.LazyInputMap(new Object[]{ + "control C", DefaultEditorKit.copyAction, + "control V", DefaultEditorKit.pasteAction, + "control X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "control LEFT", DefaultEditorKit.previousWordAction, + "control RIGHT", DefaultEditorKit.nextWordAction, + "control shift LEFT", DefaultEditorKit.selectionPreviousWordAction, + "control shift RIGHT", DefaultEditorKit.selectionNextWordAction, + "control A", DefaultEditorKit.selectAllAction, + "control BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "control HOME", DefaultEditorKit.beginAction, + "control END", DefaultEditorKit.endAction, + "control shift HOME", DefaultEditorKit.selectionBeginAction, + "control shift END", DefaultEditorKit.selectionEndAction, + "UP", DefaultEditorKit.upAction, + "DOWN", DefaultEditorKit.downAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "ctrl DELETE", DefaultEditorKit.deleteNextWordAction, + "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "PAGE_UP", DefaultEditorKit.pageUpAction, + "PAGE_DOWN", DefaultEditorKit.pageDownAction, + "shift PAGE_UP", "selection-page-up", + "shift PAGE_DOWN", "selection-page-down", + "ctrl shift PAGE_UP", "selection-page-left", + "ctrl shift PAGE_DOWN", "selection-page-right", + "shift UP", DefaultEditorKit.selectionUpAction, + "shift DOWN", DefaultEditorKit.selectionDownAction, + "ENTER", DefaultEditorKit.insertBreakAction, + "TAB", DefaultEditorKit.insertTabAction, + "control T", "next-link-action", + "control shift T", "previous-link-action", + "control SPACE", "activate-link-action", + "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ + }); + Object[] defaults = { + "TextField.focusInputMap", fieldInputMap, + "PasswordField.focusInputMap", passwordInputMap, + "TextArea.focusInputMap", multilineInputMap, + "TextPane.focusInputMap", multilineInputMap, + "EditorPane.focusInputMap", multilineInputMap, + "Button.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released" + }), + "CheckBox.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released" + }), + "ComboBox.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[]{ + "ESCAPE", "hidePopup", + "PAGE_UP", "pageUpPassThrough", + "PAGE_DOWN", "pageDownPassThrough", + "HOME", "homePassThrough", + "END", "endPassThrough", + "DOWN", "selectNext2", + "KP_DOWN", "selectNext2", + "UP", "selectPrevious2", + "KP_UP", "selectPrevious2", + "ENTER", "enterPressed", + "F4", "togglePopup", + "alt DOWN", "togglePopup", + "alt KP_DOWN", "togglePopup", + "alt UP", "togglePopup", + "alt KP_UP", "togglePopup" + }), + "Desktop.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl F5", "restore", + "ctrl F4", "close", + "ctrl F7", "move", + "ctrl F8", "resize", + "RIGHT", "right", + "KP_RIGHT", "right", + "LEFT", "left", + "KP_LEFT", "left", + "UP", "up", + "KP_UP", "up", + "DOWN", "down", + "KP_DOWN", "down", + "ESCAPE", "escape", + "ctrl F9", "minimize", + "ctrl F10", "maximize", + "ctrl F6", "selectNextFrame", + "ctrl TAB", "selectNextFrame", + "ctrl alt F6", "selectNextFrame", + "shift ctrl alt F6", "selectPreviousFrame", + "ctrl F12", "navigateNext", + "shift ctrl F12", "navigatePrevious" + }), + "FileChooser.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ESCAPE", "cancelSelection", + "F2", "editFileName", + "F5", "refresh", + "BACK_SPACE", "Go Up", + "ENTER", "approveSelection", + "ctrl ENTER", "approveSelection" + }), + "InternalFrame.windowBindings", new Object[]{ + "shift ESCAPE", "showSystemMenu", + "ctrl SPACE", "showSystemMenu", + "ESCAPE", "hideSystemMenu" + }, + "List.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", "copy", + "ctrl V", "paste", + "ctrl X", "cut", + "COPY", "copy", + "PASTE", "paste", + "CUT", "cut", + "control INSERT", "copy", + "shift INSERT", "paste", + "shift DELETE", "cut", + "UP", "selectPreviousRow", + "KP_UP", "selectPreviousRow", + "shift UP", "selectPreviousRowExtendSelection", + "shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl shift UP", "selectPreviousRowExtendSelection", + "ctrl shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "DOWN", "selectNextRow", + "KP_DOWN", "selectNextRow", + "shift DOWN", "selectNextRowExtendSelection", + "shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl shift DOWN", "selectNextRowExtendSelection", + "ctrl shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl DOWN", "selectNextRowChangeLead", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "LEFT", "selectPreviousColumn", + "KP_LEFT", "selectPreviousColumn", + "shift LEFT", "selectPreviousColumnExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "RIGHT", "selectNextColumn", + "KP_RIGHT", "selectNextColumn", + "shift RIGHT", "selectNextColumnExtendSelection", + "shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl shift RIGHT", "selectNextColumnExtendSelection", + "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl RIGHT", "selectNextColumnChangeLead", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "HOME", "selectFirstRow", + "shift HOME", "selectFirstRowExtendSelection", + "ctrl shift HOME", "selectFirstRowExtendSelection", + "ctrl HOME", "selectFirstRowChangeLead", + "END", "selectLastRow", + "shift END", "selectLastRowExtendSelection", + "ctrl shift END", "selectLastRowExtendSelection", + "ctrl END", "selectLastRowChangeLead", + "PAGE_UP", "scrollUp", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_UP", "scrollUpExtendSelection", + "ctrl PAGE_UP", "scrollUpChangeLead", + "PAGE_DOWN", "scrollDown", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl PAGE_DOWN", "scrollDownChangeLead", + "ctrl A", "selectAll", + "ctrl SLASH", "selectAll", + "ctrl BACK_SLASH", "clearSelection", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "ctrl shift SPACE", "moveSelectionTo" + }), + "MenuBar.windowBindings", new Object[]{ + "F10", "takeFocus" + }, + "RadioButton.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released" + }), + "OptionPane.windowBindings", new Object[]{ + "ESCAPE", "close" + }, + "FormattedTextField.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", DefaultEditorKit.copyAction, + "ctrl V", DefaultEditorKit.pasteAction, + "ctrl X", DefaultEditorKit.cutAction, + "COPY", DefaultEditorKit.copyAction, + "PASTE", DefaultEditorKit.pasteAction, + "CUT", DefaultEditorKit.cutAction, + "control INSERT", DefaultEditorKit.copyAction, + "shift INSERT", DefaultEditorKit.pasteAction, + "shift DELETE", DefaultEditorKit.cutAction, + "shift LEFT", DefaultEditorKit.selectionBackwardAction, + "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction, + "shift RIGHT", DefaultEditorKit.selectionForwardAction, + "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction, + "ctrl LEFT", DefaultEditorKit.previousWordAction, + "ctrl KP_LEFT", DefaultEditorKit.previousWordAction, + "ctrl RIGHT", DefaultEditorKit.nextWordAction, + "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction, + "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction, + "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction, + "ctrl A", DefaultEditorKit.selectAllAction, + "HOME", DefaultEditorKit.beginLineAction, + "END", DefaultEditorKit.endLineAction, + "shift HOME", DefaultEditorKit.selectionBeginLineAction, + "shift END", DefaultEditorKit.selectionEndLineAction, + "BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction, + "ctrl H", DefaultEditorKit.deletePrevCharAction, + "DELETE", DefaultEditorKit.deleteNextCharAction, + "ctrl DELETE", DefaultEditorKit.deleteNextWordAction, + "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction, + "RIGHT", DefaultEditorKit.forwardAction, + "LEFT", DefaultEditorKit.backwardAction, + "KP_RIGHT", DefaultEditorKit.forwardAction, + "KP_LEFT", DefaultEditorKit.backwardAction, + "ENTER", JTextField.notifyAction, + "ctrl BACK_SLASH", "unselect", + "control shift O", "toggle-componentOrientation", + "ESCAPE", "reset-field-edit", + "UP", "increment", + "KP_UP", "increment", + "DOWN", "decrement", + "KP_DOWN", "decrement", + }), + // These bindings are only enabled when there is a default + // button set on the rootpane. + "RootPane.defaultButtonWindowKeyBindings", new Object[]{ + "ENTER", "press", + "released ENTER", "release", + "ctrl ENTER", "press", + "ctrl released ENTER", "release" + }, + "ScrollBar.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "positiveUnitIncrement", + "KP_RIGHT", "positiveUnitIncrement", + "DOWN", "positiveUnitIncrement", + "KP_DOWN", "positiveUnitIncrement", + "PAGE_DOWN", "positiveBlockIncrement", + "ctrl PAGE_DOWN", "positiveBlockIncrement", + "LEFT", "negativeUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", + "UP", "negativeUnitIncrement", + "KP_UP", "negativeUnitIncrement", + "PAGE_UP", "negativeBlockIncrement", + "ctrl PAGE_UP", "negativeBlockIncrement", + "HOME", "minScroll", + "END", "maxScroll" + }), + "ScrollPane.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "unitScrollRight", + "KP_RIGHT", "unitScrollRight", + "DOWN", "unitScrollDown", + "KP_DOWN", "unitScrollDown", + "LEFT", "unitScrollLeft", + "KP_LEFT", "unitScrollLeft", + "UP", "unitScrollUp", + "KP_UP", "unitScrollUp", + "PAGE_UP", "scrollUp", + "PAGE_DOWN", "scrollDown", + "ctrl PAGE_UP", "scrollLeft", + "ctrl PAGE_DOWN", "scrollRight", + "ctrl HOME", "scrollHome", + "ctrl END", "scrollEnd" + }), + "Slider.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "positiveUnitIncrement", + "KP_RIGHT", "positiveUnitIncrement", + "DOWN", "negativeUnitIncrement", + "KP_DOWN", "negativeUnitIncrement", + "PAGE_DOWN", "negativeBlockIncrement", + "LEFT", "negativeUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", + "UP", "positiveUnitIncrement", + "KP_UP", "positiveUnitIncrement", + "PAGE_UP", "positiveBlockIncrement", + "HOME", "minScroll", + "END", "maxScroll" + }), + "Spinner.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "UP", "increment", + "KP_UP", "increment", + "DOWN", "decrement", + "KP_DOWN", "decrement", + }), + "SplitPane.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "UP", "negativeIncrement", + "DOWN", "positiveIncrement", + "LEFT", "negativeIncrement", + "RIGHT", "positiveIncrement", + "KP_UP", "negativeIncrement", + "KP_DOWN", "positiveIncrement", + "KP_LEFT", "negativeIncrement", + "KP_RIGHT", "positiveIncrement", + "HOME", "selectMin", + "END", "selectMax", + "F8", "startResize", + "F6", "toggleFocus", + "ctrl TAB", "focusOutForward", + "ctrl shift TAB", "focusOutBackward" + }), + "TabbedPane.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "RIGHT", "navigateRight", + "KP_RIGHT", "navigateRight", + "LEFT", "navigateLeft", + "KP_LEFT", "navigateLeft", + "UP", "navigateUp", + "KP_UP", "navigateUp", + "DOWN", "navigateDown", + "KP_DOWN", "navigateDown", + "ctrl DOWN", "requestFocusForVisibleComponent", + "ctrl KP_DOWN", "requestFocusForVisibleComponent", + }), + "TabbedPane.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl TAB", "navigateNext", + "ctrl shift TAB", "navigatePrevious", + "ctrl PAGE_DOWN", "navigatePageDown", + "ctrl PAGE_UP", "navigatePageUp", + "ctrl UP", "requestFocus", + "ctrl KP_UP", "requestFocus", + }), + "TableHeader.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "toggleSortOrder", + "LEFT", "selectColumnToLeft", + "KP_LEFT", "selectColumnToLeft", + "RIGHT", "selectColumnToRight", + "KP_RIGHT", "selectColumnToRight", + "alt LEFT", "moveColumnLeft", + "alt KP_LEFT", "moveColumnLeft", + "alt RIGHT", "moveColumnRight", + "alt KP_RIGHT", "moveColumnRight", + "alt shift LEFT", "resizeLeft", + "alt shift KP_LEFT", "resizeLeft", + "alt shift RIGHT", "resizeRight", + "alt shift KP_RIGHT", "resizeRight", + "ESCAPE", "focusTable", + }), + "Table.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ctrl C", "copy", + "ctrl V", "paste", + "ctrl X", "cut", + "COPY", "copy", + "PASTE", "paste", + "CUT", "cut", + "control INSERT", "copy", + "shift INSERT", "paste", + "shift DELETE", "cut", + "RIGHT", "selectNextColumn", + "KP_RIGHT", "selectNextColumn", + "shift RIGHT", "selectNextColumnExtendSelection", + "shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl shift RIGHT", "selectNextColumnExtendSelection", + "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection", + "ctrl RIGHT", "selectNextColumnChangeLead", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "LEFT", "selectPreviousColumn", + "KP_LEFT", "selectPreviousColumn", + "shift LEFT", "selectPreviousColumnExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift LEFT", "selectPreviousColumnExtendSelection", + "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "DOWN", "selectNextRow", + "KP_DOWN", "selectNextRow", + "shift DOWN", "selectNextRowExtendSelection", + "shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl shift DOWN", "selectNextRowExtendSelection", + "ctrl shift KP_DOWN", "selectNextRowExtendSelection", + "ctrl DOWN", "selectNextRowChangeLead", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "UP", "selectPreviousRow", + "KP_UP", "selectPreviousRow", + "shift UP", "selectPreviousRowExtendSelection", + "shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl shift UP", "selectPreviousRowExtendSelection", + "ctrl shift KP_UP", "selectPreviousRowExtendSelection", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "HOME", "selectFirstColumn", + "shift HOME", "selectFirstColumnExtendSelection", + "ctrl shift HOME", "selectFirstRowExtendSelection", + "ctrl HOME", "selectFirstRow", + "END", "selectLastColumn", + "shift END", "selectLastColumnExtendSelection", + "ctrl shift END", "selectLastRowExtendSelection", + "ctrl END", "selectLastRow", + "PAGE_UP", "scrollUpChangeSelection", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_UP", "scrollLeftExtendSelection", + "ctrl PAGE_UP", "scrollLeftChangeSelection", + "PAGE_DOWN", "scrollDownChangeSelection", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl shift PAGE_DOWN", "scrollRightExtendSelection", + "ctrl PAGE_DOWN", "scrollRightChangeSelection", + "TAB", "selectNextColumnCell", + "shift TAB", "selectPreviousColumnCell", + "ENTER", "selectNextRowCell", + "shift ENTER", "selectPreviousRowCell", + "ctrl A", "selectAll", + "ctrl SLASH", "selectAll", + "ctrl BACK_SLASH", "clearSelection", + "ESCAPE", "cancel", + "F2", "startEditing", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "ctrl shift SPACE", "moveSelectionTo", + "F8", "focusHeader" + }), + "ToggleButton.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "SPACE", "pressed", + "released SPACE", "released" + }), + "ToolBar.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "UP", "navigateUp", + "KP_UP", "navigateUp", + "DOWN", "navigateDown", + "KP_DOWN", "navigateDown", + "LEFT", "navigateLeft", + "KP_LEFT", "navigateLeft", + "RIGHT", "navigateRight", + "KP_RIGHT", "navigateRight" + }), + "Tree.focusInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ADD", "expand", + "SUBTRACT", "collapse", + "ctrl C", "copy", + "ctrl V", "paste", + "ctrl X", "cut", + "COPY", "copy", + "PASTE", "paste", + "CUT", "cut", + "control INSERT", "copy", + "shift INSERT", "paste", + "shift DELETE", "cut", + "UP", "selectPrevious", + "KP_UP", "selectPrevious", + "shift UP", "selectPreviousExtendSelection", + "shift KP_UP", "selectPreviousExtendSelection", + "ctrl shift UP", "selectPreviousExtendSelection", + "ctrl shift KP_UP", "selectPreviousExtendSelection", + "ctrl UP", "selectPreviousChangeLead", + "ctrl KP_UP", "selectPreviousChangeLead", + "DOWN", "selectNext", + "KP_DOWN", "selectNext", + "shift DOWN", "selectNextExtendSelection", + "shift KP_DOWN", "selectNextExtendSelection", + "ctrl shift DOWN", "selectNextExtendSelection", + "ctrl shift KP_DOWN", "selectNextExtendSelection", + "ctrl DOWN", "selectNextChangeLead", + "ctrl KP_DOWN", "selectNextChangeLead", + "RIGHT", "selectChild", + "KP_RIGHT", "selectChild", + "LEFT", "selectParent", + "KP_LEFT", "selectParent", + "PAGE_UP", "scrollUpChangeSelection", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_UP", "scrollUpExtendSelection", + "ctrl PAGE_UP", "scrollUpChangeLead", + "PAGE_DOWN", "scrollDownChangeSelection", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl shift PAGE_DOWN", "scrollDownExtendSelection", + "ctrl PAGE_DOWN", "scrollDownChangeLead", + "HOME", "selectFirst", + "shift HOME", "selectFirstExtendSelection", + "ctrl shift HOME", "selectFirstExtendSelection", + "ctrl HOME", "selectFirstChangeLead", + "END", "selectLast", + "shift END", "selectLastExtendSelection", + "ctrl shift END", "selectLastExtendSelection", + "ctrl END", "selectLastChangeLead", + "F2", "startEditing", + "ctrl A", "selectAll", + "ctrl SLASH", "selectAll", + "ctrl BACK_SLASH", "clearSelection", + "ctrl LEFT", "scrollLeft", + "ctrl KP_LEFT", "scrollLeft", + "ctrl RIGHT", "scrollRight", + "ctrl KP_RIGHT", "scrollRight", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "ctrl shift SPACE", "moveSelectionTo" + }), + "Tree.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[]{ + "ESCAPE", "cancel" + }), + }; + table.putDefaults(defaults); + } + +} diff --git a/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java b/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java index 84d522106ccd90b134d82b2ce4a15220cfd4b170..dde00682cceec6aebc0a94455ee058c6e625232e 100644 --- a/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java +++ b/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java @@ -183,14 +183,7 @@ public abstract class SynthFileChooserUI extends BasicFileChooserUI implements } } - ActionMap createActionMap() { - ActionMap map = new ActionMapUIResource(); - map.put("approveSelection", getApproveSelectionAction()); - map.put("cancelSelection", getCancelSelectionAction()); - map.put("Go Up", getChangeToParentDirectoryAction()); - map.put("fileNameCompletion", getFileNameCompletionAction()); - return map; - } + protected abstract ActionMap createActionMap(); protected void installDefaults(JFileChooser fc) { diff --git a/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java b/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java index 7069c394ad6a7019b0f7a824ba8bc3b38ca40252..a2a4b2e5e0a7bb820e08542357b0e2137f44873d 100644 --- a/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java +++ b/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java @@ -38,8 +38,7 @@ import javax.swing.filechooser.*; import javax.swing.filechooser.FileFilter; import javax.swing.plaf.basic.*; import javax.swing.plaf.synth.*; - -import sun.swing.SwingUtilities2; +import javax.swing.plaf.ActionMapUIResource; import sun.awt.shell.ShellFolder; import sun.swing.*; @@ -286,9 +285,9 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { b.setAlignmentX(JComponent.LEFT_ALIGNMENT); b.setAlignmentY(JComponent.CENTER_ALIGNMENT); b.setMargin(shrinkwrap); + topButtonPanel.add(b); + topButtonPanel.add(Box.createRigidArea(hstrut5)); } - topButtonPanel.add(b); - topButtonPanel.add(Box.createRigidArea(hstrut5)); // View button group ButtonGroup viewButtonGroup = new ButtonGroup(); @@ -521,6 +520,9 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { } } + @Override public void rescanCurrentDirectory(JFileChooser fc) { + filePane.rescanCurrentDirectory(); + } protected void doSelectedFileChanged(PropertyChangeEvent e) { super.doSelectedFileChanged(e); @@ -635,6 +637,14 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { // ************ FileChooser UI PLAF methods ************** // ******************************************************* + protected ActionMap createActionMap() { + ActionMap map = new ActionMapUIResource(); + // add standard actions + FilePane.addActionsToMap(map, filePane.getActions()); + // add synth only actions + map.put("fileNameCompletion", getFileNameCompletionAction()); + return map; + } // ***************************** // ***** Directory Actions ***** @@ -649,32 +659,44 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { } protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) { - return new DirectoryComboBoxRenderer(); + return new DirectoryComboBoxRenderer(directoryComboBox.getRenderer()); } // // Renderer for DirectoryComboBox // - class DirectoryComboBoxRenderer extends DefaultListCellRenderer { + // Synth has some odd behavior with regards to renderers. Renderers are styled + // in a specific manner by the SynthComboBoxUI. If we extend DefaultListCellRenderer + // here, then we get none of those benefits or behaviors, leading to poor + // looking combo boxes. + // So what we do here is delegate most jobs to the "real" or original renderer, + // and simply monkey with the icon and text of the renderer. + private class DirectoryComboBoxRenderer implements ListCellRenderer { + private ListCellRenderer delegate; IndentIcon ii = new IndentIcon(); - public Component getListCellRendererComponent(JList list, Object value, - int index, boolean isSelected, - boolean cellHasFocus) { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + private DirectoryComboBoxRenderer(ListCellRenderer delegate) { + this.delegate = delegate; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + assert c instanceof JLabel; + JLabel label = (JLabel)c; if (value == null) { - setText(""); - return this; + label.setText(""); + return label; } - File directory = (File)value; - setText(getFileChooser().getName(directory)); + File directory = (File) value; + label.setText(getFileChooser().getName(directory)); Icon icon = getFileChooser().getIcon(directory); ii.icon = icon; ii.depth = directoryComboBoxModel.getDepth(index); - setIcon(ii); + label.setIcon(ii); - return this; + return label; } } @@ -862,24 +884,33 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { // Renderer for Types ComboBox // protected FilterComboBoxRenderer createFilterComboBoxRenderer() { - return new FilterComboBoxRenderer(); + return new FilterComboBoxRenderer(filterComboBox.getRenderer()); } /** * Render different type sizes and styles. */ - public class FilterComboBoxRenderer extends DefaultListCellRenderer { - public Component getListCellRendererComponent(JList list, - Object value, int index, boolean isSelected, - boolean cellHasFocus) { + public class FilterComboBoxRenderer implements ListCellRenderer { + private ListCellRenderer delegate; + private FilterComboBoxRenderer(ListCellRenderer delegate) { + this.delegate = delegate; + } - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + String text = null; if (value != null && value instanceof FileFilter) { - setText(((FileFilter)value).getDescription()); + text = ((FileFilter) value).getDescription(); } - return this; + //this should always be true, since SynthComboBoxUI's SynthComboBoxRenderer + //extends JLabel + assert c instanceof JLabel; + if (text != null) { + ((JLabel)c).setText(text); + } + return c; } } diff --git a/src/share/classes/sun/swing/table/DefaultTableCellHeaderRenderer.java b/src/share/classes/sun/swing/table/DefaultTableCellHeaderRenderer.java index 6198f1448237d1d567b068d071c34456f3eb0715..117ca3d4a0202bd789b2400bbbfee0d1c66db9ea 100644 --- a/src/share/classes/sun/swing/table/DefaultTableCellHeaderRenderer.java +++ b/src/share/classes/sun/swing/table/DefaultTableCellHeaderRenderer.java @@ -26,16 +26,23 @@ package sun.swing.table; import java.awt.Component; import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; import javax.swing.*; import javax.swing.plaf.UIResource; import javax.swing.border.Border; import javax.swing.table.*; +import sun.swing.DefaultLookup; + -/** - */ public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer implements UIResource { private boolean horizontalTextPositionSet; + private Icon sortArrow; + private EmptyIcon emptyIcon = new EmptyIcon(); public DefaultTableCellHeaderRenderer() { setHorizontalAlignment(JLabel.CENTER); @@ -58,8 +65,8 @@ public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer Color fgColor = null; Color bgColor = null; if (hasFocus) { - fgColor = UIManager.getColor("TableHeader.focusCellForeground"); - bgColor = UIManager.getColor("TableHeader.focusCellBackground"); + fgColor = DefaultLookup.getColor(this, ui, "TableHeader.focusCellForeground"); + bgColor = DefaultLookup.getColor(this, ui, "TableHeader.focusCellBackground"); } if (fgColor == null) { fgColor = header.getForeground(); @@ -85,16 +92,16 @@ public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer if (sortOrder != null) { switch(sortOrder) { case ASCENDING: - sortIcon = UIManager.getIcon( - "Table.ascendingSortIcon"); + sortIcon = DefaultLookup.getIcon( + this, ui, "Table.ascendingSortIcon"); break; case DESCENDING: - sortIcon = UIManager.getIcon( - "Table.descendingSortIcon"); + sortIcon = DefaultLookup.getIcon( + this, ui, "Table.descendingSortIcon"); break; case UNSORTED: - sortIcon = UIManager.getIcon( - "Table.naturalSortIcon"); + sortIcon = DefaultLookup.getIcon( + this, ui, "Table.naturalSortIcon"); break; } } @@ -103,13 +110,14 @@ public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer setText(value == null ? "" : value.toString()); setIcon(sortIcon); + sortArrow = sortIcon; Border border = null; if (hasFocus) { - border = UIManager.getBorder("TableHeader.focusCellBorder"); + border = DefaultLookup.getBorder(this, ui, "TableHeader.focusCellBorder"); } if (border == null) { - border = UIManager.getBorder("TableHeader.cellBorder"); + border = DefaultLookup.getBorder(this, ui, "TableHeader.cellBorder"); } setBorder(border); @@ -129,4 +137,60 @@ public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer } return rv; } + + @Override + public void paintComponent(Graphics g) { + boolean b = DefaultLookup.getBoolean(this, ui, + "TableHeader.rightAlignSortArrow", false); + if (b && sortArrow != null) { + //emptyIcon is used so that if the text in the header is right + //aligned, or if the column is too narrow, then the text will + //be sized appropriately to make room for the icon that is about + //to be painted manually here. + emptyIcon.width = sortArrow.getIconWidth(); + emptyIcon.height = sortArrow.getIconHeight(); + setIcon(emptyIcon); + super.paintComponent(g); + Point position = computeIconPosition(g); + sortArrow.paintIcon(this, g, position.x, position.y); + } else { + super.paintComponent(g); + } + } + + private Point computeIconPosition(Graphics g) { + FontMetrics fontMetrics = g.getFontMetrics(); + Rectangle viewR = new Rectangle(); + Rectangle textR = new Rectangle(); + Rectangle iconR = new Rectangle(); + Insets i = getInsets(); + viewR.x = i.left; + viewR.y = i.top; + viewR.width = getWidth() - (i.left + i.right); + viewR.height = getHeight() - (i.top + i.bottom); + SwingUtilities.layoutCompoundLabel( + this, + fontMetrics, + getText(), + sortArrow, + getVerticalAlignment(), + getHorizontalAlignment(), + getVerticalTextPosition(), + getHorizontalTextPosition(), + viewR, + iconR, + textR, + getIconTextGap()); + int x = getWidth() - i.right - sortArrow.getIconWidth(); + int y = iconR.y; + return new Point(x, y); + } + + private class EmptyIcon implements Icon { + int width = 0; + int height = 0; + public void paintIcon(Component c, Graphics g, int x, int y) {} + public int getIconWidth() { return width; } + public int getIconHeight() { return height; } + } } diff --git a/src/solaris/classes/sun/awt/X11/XToolkit.java b/src/solaris/classes/sun/awt/X11/XToolkit.java index 8a5030c83a1043478350200cd7243b9ec0f3ad82..967a2850f908d991265d007a24cafa70afadd574 100644 --- a/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -568,6 +568,17 @@ public final class XToolkit extends UNIXToolkit implements Runnable { { XEvent ev = new XEvent(); while(true) { + // Fix for 6829923: we should gracefully handle toolkit thread interruption + if (Thread.currentThread().isInterrupted()) { + // We expect interruption from the AppContext.dispose() method only. + // If the thread is interrupted from another place, let's skip it + // for compatibility reasons. Probably some time later we'll remove + // the check for AppContext.isDisposed() and will unconditionally + // break the loop here. + if (AppContext.getAppContext().isDisposed()) { + break; + } + } awtLock(); try { if (loop == SECONDARY_LOOP) { diff --git a/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java b/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fdb33571b4d04ea373e3f81486dcb25489626640 --- /dev/null +++ b/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel noteOn/noteOff overflow test */ + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.VoiceStatus; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +import com.sun.media.sound.AudioSynthesizer; +import com.sun.media.sound.SoftSynthesizer; + +public class NoteOverFlowTest { + + public static void main(String[] args) throws Exception + { + AudioSynthesizer synth = new SoftSynthesizer(); + AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + AudioInputStream stream = synth.openStream(format, null); + + // Make all voices busy, e.g. + // send midi on and midi off on all available voices + MidiChannel ch1 = synth.getChannels()[0]; + ch1.programChange(48); // Use contionus instrument like string ensemble + for (int i = 0; i < synth.getMaxPolyphony(); i++) { + ch1.noteOn(64, 64); + ch1.noteOff(64); + } + + // Now send single midi on, and midi off message + ch1.noteOn(64, 64); + ch1.noteOff(64); + + // Read 10 sec from stream, by this time all voices should be inactvie + stream.skip(format.getFrameSize() * ((int)(format.getFrameRate() * 20))); + + // If no voice are active, then this test will pass + VoiceStatus[] v = synth.getVoiceStatus(); + for (int i = 0; i < v.length; i++) { + if(v[i].active) + { + throw new RuntimeException("Not all voices are inactive!"); + } + } + + // Close the synthesizer after use + synth.close(); + } +} diff --git a/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java b/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java new file mode 100644 index 0000000000000000000000000000000000000000..032f66762c0f425a527d723d171259a037ed19ed --- /dev/null +++ b/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java @@ -0,0 +1,99 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftFilter processAudio method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Random; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class TestProcessAudio { + + public static void main(String[] args) throws Exception { + AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + SoftAudioBuffer sbuffer = new SoftAudioBuffer(3600, format); + SoftFilter filter = new SoftFilter(format.getSampleRate()); + Random random = new Random(42); + + + for (int t = 0; t <= 6; t++) + { + if(t == 0) filter.setFilterType(SoftFilter.FILTERTYPE_BP12); + if(t == 1) filter.setFilterType(SoftFilter.FILTERTYPE_HP12); + if(t == 2) filter.setFilterType(SoftFilter.FILTERTYPE_HP24); + if(t == 3) filter.setFilterType(SoftFilter.FILTERTYPE_LP12); + if(t == 4) filter.setFilterType(SoftFilter.FILTERTYPE_LP24); + if(t == 5) filter.setFilterType(SoftFilter.FILTERTYPE_LP6); + if(t == 6) filter.setFilterType(SoftFilter.FILTERTYPE_NP12); + + + // Try first by reseting always + for (int f = 1200; f < 3600; f+=100) + for (int r = 0; r <= 30; r+=5) { + filter.reset(); + filter.setResonance(r); + filter.setFrequency(f); + float[] data = sbuffer.array(); + int len = sbuffer.getSize(); + for (int i = 0; i < len; i++) + data[i] = random.nextFloat() - 0.5f; + filter.processAudio(sbuffer); + } + + // Now we skip reseting + // to test how changing frequency and resonance + // affect active filter + for (int f = 100; f < 12800; f+=1200) + for (int r = 0; r <= 30; r+=5) { + filter.setResonance(r); + filter.setFrequency(f); + float[] data = sbuffer.array(); + int len = sbuffer.getSize(); + for (int i = 0; i < len; i++) + data[i] = random.nextFloat() - 0.5f; + filter.processAudio(sbuffer); + } + for (int f = 12800; f >= 100; f-=1200) + for (int r = 30; r >= 0; r-=5) { + filter.setResonance(r); + filter.setFrequency(f); + float[] data = sbuffer.array(); + int len = sbuffer.getSize(); + for (int i = 0; i < len; i++) + data[i] = random.nextFloat() - 0.5f; + filter.processAudio(sbuffer); + } + filter.reset(); + } + + } + +} diff --git a/test/javax/sound/midi/Gervill/SoftLowFrequencyOscillator/TestProcessControlLogic.java b/test/javax/sound/midi/Gervill/SoftLowFrequencyOscillator/TestProcessControlLogic.java new file mode 100644 index 0000000000000000000000000000000000000000..6289a88cd86c17de427922f783a620d5fb14a4ef --- /dev/null +++ b/test/javax/sound/midi/Gervill/SoftLowFrequencyOscillator/TestProcessControlLogic.java @@ -0,0 +1,106 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLowFrequencyOscillator processControlLogic method */ + +import com.sun.media.sound.AudioSynthesizerPropertyInfo; +import com.sun.media.sound.SoftLowFrequencyOscillator; +import com.sun.media.sound.SoftSynthesizer; + +public class TestProcessControlLogic { + + private static float control_rate = 147f; + private static SoftSynthesizer synth = new SoftSynthesizer(); + private static SoftLowFrequencyOscillator lfo = new SoftLowFrequencyOscillator(); + + private static void testLFO(boolean shared, int instance, float freq, float delay, + float delay2) throws Exception { + SoftLowFrequencyOscillator lfo = + shared?TestProcessControlLogic.lfo:new SoftLowFrequencyOscillator(); + lfo.reset(); + double[] lfo_freq = lfo.get(instance, "freq"); + double[] lfo_delay = lfo.get(instance, "delay"); + double[] lfo_delay2 = lfo.get(instance, "delay2"); + double[] lfo_output = lfo.get(instance, null); + lfo_freq[0] = freq; + lfo_delay[0] = delay; + lfo_delay2[0] = delay2; + lfo.init(synth); + + // For delayCount amount time, the output LFO should be 0.5 + int delayCount = (int) ((Math.pow(2, delay / 1200.0) * control_rate)); + delayCount += (int) ((delay2 * control_rate) / 1000.0); + for (int i = 0; i < delayCount; i++) { + if (Math.abs(0.5 - lfo_output[0]) > 0.000001) + throw new Exception("Incorrect LFO output (" + +"0.5 != "+lfo_output[0]+")!"); + lfo.processControlLogic(); + } + + // After the delay the LFO should start oscillate + // Let make sure output is accurate enough + double p_step = (440.0 / control_rate) + * Math.exp((freq - 6900.0) * (Math.log(2) / 1200.0)); + double p = 0; + for (int i = 0; i < 30; i++) { + p += p_step; + double predicted_output = 0.5 + Math.sin(p * 2 * Math.PI) * 0.5; + if (Math.abs(predicted_output - lfo_output[0]) > 0.001) + throw new Exception("Incorrect LFO output (" + +predicted_output+" != "+lfo_output[0]+")!"); + lfo.processControlLogic(); + } + + } + + public static void main(String[] args) throws Exception { + + // Get default control rate from synthesizer + AudioSynthesizerPropertyInfo[] p = synth.getPropertyInfo(null); + for (int i = 0; i < p.length; i++) { + if (p[i].name.equals("control rate")) { + control_rate = ((Float) p[i].value).floatValue(); + break; + } + } + + // Test LFO under various configurations + for (int instance = 0; instance < 3; instance++) + for (int d1 = -3000; d1 < 0; d1 += 1000) + for (int d2 = 0; d2 < 5000; d2 += 1000) + for (int fr = -1000; fr < 1000; fr += 100) { + testLFO(true, instance, + (fr == -1000) ? Float.NEGATIVE_INFINITY : fr, + (d1 == -3000) ? Float.NEGATIVE_INFINITY : d1, + d2); + testLFO(false, instance, + (fr == -1000) ? Float.NEGATIVE_INFINITY : fr, + (d1 == -3000) ? Float.NEGATIVE_INFINITY : d1, + d2); + } + + } +}