OpenJDK / aarch32-port / jdk9u / jdk
changeset 1173:7f45fcc04f8e
6591875: Nimbus Swing Look and Feel
Reviewed-by: jasper, ohair
line wrap: on
line diff
--- a/README Fri Apr 17 16:28:02 2009 +0400 +++ b/README Sat Apr 25 21:17:50 2009 +0400 @@ -9,25 +9,35 @@ 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
--- a/make/common/Sanity.gmk Fri Apr 17 16:28:02 2009 +0400 +++ b/make/common/Sanity.gmk Sat Apr 25 21:17:50 2009 +0400 @@ -92,7 +92,8 @@ sane-ld_run_path \ sane-alt_bootdir \ sane-bootdir \ - sane-alsa-headers + sane-alsa-headers \ + sane-jibx ifdef OPENJDK sanity-all:: sane-freetype
--- a/make/common/shared/Defs.gmk Fri Apr 17 16:28:02 2009 +0400 +++ b/make/common/shared/Defs.gmk Sat Apr 25 21:17:50 2009 +0400 @@ -515,6 +515,15 @@ # 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 @@ 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 \
--- a/make/common/shared/Platform.gmk Fri Apr 17 16:28:02 2009 +0400 +++ b/make/common/shared/Platform.gmk Sat Apr 25 21:17:50 2009 +0400 @@ -89,8 +89,8 @@ SYSTEM_UNAME := $(shell uname) -# Normal boot jdk is previous release, but a hard requirement is a 1.5 boot -REQUIRED_BOOT_VER = 1.5 +# Normal boot jdk is previous release, but a hard requirement is a 1.6 boot +REQUIRED_BOOT_VER = 1.6 # If we are using freetype, this is the required version REQUIRED_FREETYPE_VERSION=2.3.0
--- a/make/common/shared/Sanity-Settings.gmk Fri Apr 17 16:28:02 2009 +0400 +++ b/make/common/shared/Sanity-Settings.gmk Sat Apr 25 21:17:50 2009 +0400 @@ -237,6 +237,7 @@ 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
--- a/make/common/shared/Sanity.gmk Fri Apr 17 16:28:02 2009 +0400 +++ b/make/common/shared/Sanity.gmk Sat Apr 25 21:17:50 2009 +0400 @@ -169,6 +169,7 @@ sane-cacerts \ sane-alsa-versioncheck \ sane-alsa-headers \ + sane-jibx \ sane-ant_version \ sane-zip_version \ sane-unzip_version \ @@ -1504,6 +1505,18 @@ ###################################################### +# 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 ###################################################### sane-mozilla:
--- a/make/javax/swing/plaf/Makefile Fri Apr 17 16:28:02 2009 +0400 +++ b/make/javax/swing/plaf/Makefile Sat Apr 25 21:17:50 2009 +0400 @@ -34,9 +34,14 @@ # 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 @@ # 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/javax/swing/plaf/nimbus/Makefile Sat Apr 25 21:17:50 2009 +0400 @@ -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)
--- a/make/tools/Makefile Fri Apr 17 16:28:02 2009 +0400 +++ b/make/tools/Makefile Sat Apr 25 21:17:50 2009 +0400 @@ -51,6 +51,7 @@ makeclasslist \ strip_properties \ spp \ + swing-nimbus \ CharsetMapping all build clean clobber::
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/Makefile Sat Apr 25 21:17:50 2009 +0400 @@ -0,0 +1,89 @@ +# +# 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/*.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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/beans/AbstractBean.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + +/** + * <p>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.</p> + * + * <p>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.</p> + * + * <p>Here is a simple example bean that contains one property, foo, and the + * proper pattern for implementing property change notification: + * <pre><code> + * 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; + * } + * } + * </code></pre></p> + * + * <p>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.</p> + * + * <p>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()</p> + * + * <p><code>AbstractBean</code> also supports {@link VetoablePropertyChange} events. + * These events are similar to <code>PropertyChange</code> 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: + * <pre><code> + * 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 + * } + * } + * } + * </code></pre></p> + * + * @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 <code>listener</code> 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 <code>listener</code> was added more than once to the same event + * source, it will be notified one less time after being removed. + * If <code>listener</code> 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(). + * <p> + * If some listeners have been added with a named property, then + * the returned array will be a mixture of PropertyChangeListeners + * and <code>PropertyChangeListenerProxy</code>s. If the calling + * method is interested in distinguishing the listeners then it must + * test each element to see if it's a + * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine + * the parameter. + * + * <pre> + * 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" + * } + * } + * } + *</pre> + * + * @see java.beans.PropertyChangeListenerProxy + * @return all of the <code>PropertyChangeListeners</code> 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 <code>propertyName</code> or <code>listener</code> 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 <code>listener</code> 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 <code>propertyName</code> is null, no exception is thrown and no + * action is taken. + * If <code>listener</code> 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 <code>PropertyChangeListeners</code> associated with + * the named property. If no such listeners have been added, + * or if <code>propertyName</code> 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. + * + * <p> + * 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. + * <p> + * No event is fired if old and new values are equal + * and non-null. + * + * <p> + * 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 <code>propertyName</code> + * 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 <code>propertyName</code> + * 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 <code>listener</code> 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 <code>listener</code> was added more than once to the same event + * source, it will be notified one less time after being removed. + * If <code>listener</code> 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 + * <p> + * @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 <code>propertyName</code> or <code>listener</code> 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 <code>listener</code> 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 <code>propertyName</code> is null, no exception is thrown and no + * action is taken. + * If <code>listener</code> 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 <code>VetoableChangeListeners</code> associated with + * the named property. If no such listeners have been added, + * or if <code>propertyName</code> 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. + * <p> + * 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. + * <p> + * 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BezierControlPoint.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<ControlPoint> getControlPoints() { + if (isSharpCorner()) { + return Collections.emptyList(); + } else { + List<ControlPoint> points = new ArrayList<ControlPoint>(); + 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 <code>true</code> 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; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/BlendingMode.java Sat Apr 25 21:17:50 2009 +0400 @@ -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 + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Canvas.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<Layer> 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<Layer>(); + 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. + * <p/> + * 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<Layer> getLayerIterator() { + return Collections.unmodifiableList(layers).iterator(); + } + + public Collection<Layer> 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/ControlPoint.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<ControlPoint> 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); + } + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Designer.jibx.xml Sat Apr 25 21:17:50 2009 +0400 @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Copyright 1998-2004 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. +--> + +<!DOCTYPE binding SYSTEM "http://jibx.sourceforge.net"> +<binding> + <!-- == PAINTS =========================================================================================== --> + <mapping class="java.awt.Color" + marshaller="org.jdesktop.swingx.designer.jibxhelpers.ColorMapper" + unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.ColorMapper"/> + <mapping name="matte" class="org.jdesktop.swingx.designer.paint.Matte" post-set="postSet"> + <value name="red" field="red" style="attribute"/> + <value name="green" field="green" style="attribute"/> + <value name="blue" field="blue" style="attribute"/> + <value name="alpha" field="alpha" style="attribute"/> + <value name="uiDefaultParentName" field="uiDefaultParentName" style="attribute" usage="optional"/> + <value name="componentPropertyName" field="componentPropertyName" style="attribute" usage="optional"/> + <value name="hueOffset" field="hueOffset" style="attribute"/> + <value name="saturationOffset" field="saturationOffset" style="attribute"/> + <value name="brightnessOffset" field="brightnessOffset" style="attribute"/> + <value name="alphaOffset" field="alphaOffset" style="attribute"/> + <value name="uiResource" field="uiResource" style="attribute" usage="optional" default="true"/> + </mapping> + <mapping class="org.jdesktop.swingx.designer.paint.AbstractGradient" abstract="true"> + <value name="cycleMethod" field="cycleMethod" style="attribute"/> + <collection field="stops" set-method="setStops" pre-set="clear" create-type="java.util.ArrayList"> + <structure name="stop" type="org.jdesktop.swingx.designer.paint.GradientStop"> + <value name="position" field="position" style="attribute"/> + <value name="midpoint" field="midpoint" style="attribute"/> + <structure field="color" set-method="setColor"/> + </structure> + </collection> + </mapping> + <mapping name="gradient" class="org.jdesktop.swingx.designer.paint.Gradient" + extends="org.jdesktop.swingx.designer.paint.AbstractGradient"> + <structure map-as="org.jdesktop.swingx.designer.paint.AbstractGradient"/> + </mapping> + <mapping name="radialGradient" class="org.jdesktop.swingx.designer.paint.RadialGradient" + extends="org.jdesktop.swingx.designer.paint.AbstractGradient"> + <structure map-as="org.jdesktop.swingx.designer.paint.AbstractGradient"/> + </mapping> + <!-- == SHAPES =========================================================================================== --> + <mapping class="org.jdesktop.swingx.designer.SimpleShape" abstract="true"> + <!--protected AffineTransform transform = new AffineTransform();--> + </mapping> + <mapping class="org.jdesktop.swingx.designer.PaintedShape" abstract="true" + extends="org.jdesktop.swingx.designer.SimpleShape"> + <structure map-as="org.jdesktop.swingx.designer.SimpleShape"/> + <structure field="paint"/> + <structure name="paintPoints"> + <value name="x1" get-method="getPaintX1" set-method="setPaintX1" style="attribute"/> + <value name="y1" get-method="getPaintY1" set-method="setPaintY1" style="attribute"/> + <value name="x2" get-method="getPaintX2" set-method="setPaintX2" style="attribute"/> + <value name="y2" get-method="getPaintY2" set-method="setPaintY2" style="attribute"/> + </structure> + </mapping> + <mapping name="rectangle" class="org.jdesktop.swingx.designer.RectangleShape" + extends="org.jdesktop.swingx.designer.PaintedShape"> + <structure map-as="org.jdesktop.swingx.designer.PaintedShape"/> + <value name="x1" get-method="getX1" set-method="setX1" style="attribute"/> + <value name="x2" get-method="getX2" set-method="setX2" style="attribute"/> + <value name="y1" get-method="getY1" set-method="setY1" style="attribute"/> + <value name="y2" get-method="getY2" set-method="setY2" style="attribute"/> + <value name="rounding" get-method="getRounding" set-method="setRounding" style="attribute"/> + </mapping> + <mapping name="ellipse" class="org.jdesktop.swingx.designer.EllipseShape" + extends="org.jdesktop.swingx.designer.PaintedShape"> + <structure map-as="org.jdesktop.swingx.designer.PaintedShape"/> + <value name="x1" get-method="getX1" set-method="setX1" style="attribute"/> + <value name="x2" get-method="getX2" set-method="setX2" style="attribute"/> + <value name="y1" get-method="getY1" set-method="setY1" style="attribute"/> + <value name="y2" get-method="getY2" set-method="setY2" style="attribute"/> + </mapping> + <mapping name="path" class="org.jdesktop.swingx.designer.PathShape" + extends="org.jdesktop.swingx.designer.PaintedShape"> + <structure map-as="org.jdesktop.swingx.designer.PaintedShape"/> + <collection name="points" get-method="getBezierControlPoints" + set-method="setControlPoints" create-type="java.util.ArrayList"> + <structure name="point" type="org.jdesktop.swingx.designer.BezierControlPoint"> + <value name="x" get-method="getX" set-method="setX" style="attribute"/> + <value name="y" get-method="getY" set-method="setY" style="attribute"/> + <value name="cp1x" get-method="getCp1X" set-method="setCp1X" style="attribute"/> + <value name="cp1y" get-method="getCp1Y" set-method="setCp1Y" style="attribute"/> + <value name="cp2x" get-method="getCp2X" set-method="setCp2X" style="attribute"/> + <value name="cp2y" get-method="getCp2Y" set-method="setCp2Y" style="attribute"/> + </structure> + </collection> + </mapping> + <!-- == EFFECTS =========================================================================================== --> + <mapping class="org.jdesktop.swingx.designer.effects.ShadowEffect" abstract="true"> + <structure field="color"/> + <value name="blendingMode" field="blendingMode" style="attribute"/> + <value name="opacity" field="opacity" style="attribute"/> + <value name="angle" field="angle" style="attribute"/> + <value name="distance" field="distance" style="attribute"/> + <value name="spread" field="spread" style="attribute"/> + <value name="size" field="size" style="attribute"/> + </mapping> + <mapping name="dropShadow" class="org.jdesktop.swingx.designer.effects.DropShadowEffect" + extends="org.jdesktop.swingx.designer.effects.ShadowEffect"> + <structure map-as="org.jdesktop.swingx.designer.effects.ShadowEffect"/> + </mapping> + <mapping name="innerShadow" class="org.jdesktop.swingx.designer.effects.InnerShadowEffect" + extends="org.jdesktop.swingx.designer.effects.ShadowEffect"> + <structure map-as="org.jdesktop.swingx.designer.effects.ShadowEffect"/> + </mapping> + <mapping name="innerGlow" class="org.jdesktop.swingx.designer.effects.InnerGlowEffect" + extends="org.jdesktop.swingx.designer.effects.ShadowEffect"> + <structure map-as="org.jdesktop.swingx.designer.effects.ShadowEffect"/> + </mapping> + <mapping name="outerGlow" class="org.jdesktop.swingx.designer.effects.OuterGlowEffect" + extends="org.jdesktop.swingx.designer.effects.ShadowEffect"> + <structure map-as="org.jdesktop.swingx.designer.effects.ShadowEffect"/> + </mapping> + <!-- == TEMPLATE LAYER ================================================================================== --> + <mapping name="templateLayer" class="org.jdesktop.swingx.designer.TemplateLayer" + extends="org.jdesktop.swingx.designer.Layer" post-set="postInit"> + <structure map-as="org.jdesktop.swingx.designer.Layer"/> + <value name="fileName" field="fileName" style="attribute"/> + </mapping> + <!-- == LAYER =========================================================================================== --> + <mapping name="layer" class="org.jdesktop.swingx.designer.Layer" + extends="org.jdesktop.swingx.designer.SimpleShape" post-set="postInit"> + <structure map-as="org.jdesktop.swingx.designer.SimpleShape"/> + <value name="name" field="name" style="attribute"/> + <value name="type" field="type" style="attribute" default="standard"/> + <value name="opacity" field="opacity"/> + <value name="fillOpacity" field="fillOpacity"/> + <value name="blendingMode" field="blendingMode"/> + <value name="locked" field="locked"/> + <value name="visible" field="visible"/> + <structure name="shapes"> + <collection field="shapes" create-type="java.util.ArrayList"/> + </structure> + <structure name="effects"> + <collection field="effects" create-type="java.util.ArrayList"/> + </structure> + </mapping> + <!-- == CANVAS =========================================================================================== --> + <mapping name="canvas" class="org.jdesktop.swingx.designer.Canvas" pre-set="preSet" post-set="setupLayers"> + <structure name="size" get-method="getSize" set-method="setSize" + marshaller="org.jdesktop.swingx.designer.jibxhelpers.DimensionMapper" + unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.DimensionMapper"/> + <value name="nextLayerNameIndex" field="nextLayerNameIndex"/> + <structure name="stretchingInsets" field="stretchingInsets" + marshaller="org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper" + unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper"/> + <collection field="layers" create-type="java.util.ArrayList"/> + </mapping> +</binding>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/DoubleBean.java Sat Apr 25 21:17:50 2009 +0400 @@ -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)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/EllipseShape.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<ControlPoint> getControlPoints() { + List<ControlPoint> points = new ArrayList<ControlPoint>(); + 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/GraphicsHelper.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/Layer.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<SimpleShape>, 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<SimpleShape> shapes = new ArrayList<SimpleShape>(); + private List<Effect> effects = new ArrayList<Effect>(); + 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<SimpleShape> iterator() { + return Collections.unmodifiableList(shapes).iterator(); + } + + + public List<Effect> 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<SimpleShape> getShapes() { + return new ArrayList<SimpleShape>(shapes); + } + + public List<SimpleShape> getIntersectingShapes(Point2D p, double pixelSize) { + if (isLocked() || !isVisible()) return Collections.emptyList(); + List<SimpleShape> intersectingShapes = new ArrayList<SimpleShape>(); + 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<SimpleShape> getIntersectingShapes(Rectangle2D rect, double pixelSize) { + if (isLocked() || !isVisible()) return Collections.emptyList(); + List<SimpleShape> intersectingShapes = new ArrayList<SimpleShape>(); + 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<ControlPoint> 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<Layer> getLayers() { + List<Layer> layers = new ArrayList<Layer>(); + for (SimpleShape shape : shapes) { + if (shape instanceof Layer) layers.add((Layer) shape); + } + return Collections.unmodifiableList(layers); + } + + public Iterator<Layer> getLayerIterator() { + return new Iterator<Layer>() { + 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(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/LayerContainer.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<Layer> getLayerIterator(); + + public Collection<Layer> 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(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PaintedShape.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<? extends ControlPoint> 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); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/PathShape.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<BezierControlPoint> controlPoints = new ArrayList<BezierControlPoint>(); + 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<? extends ControlPoint> getControlPoints() { + List<ControlPoint> pts = new ArrayList<ControlPoint>(); + for (BezierControlPoint controlPoint : controlPoints) { + pts.add(controlPoint); + } + for (ControlPoint controlPoint : super.getControlPoints()) { + pts.add(controlPoint); + } + return pts; + } + + public void setControlPoints(List<BezierControlPoint> controlPoints) { + List<BezierControlPoint> 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<BezierControlPoint> getBezierControlPoints() { + return controlPoints; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/RectangleShape.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<ControlPoint> getControlPoints() { + List<ControlPoint> points = new ArrayList<ControlPoint>(); + 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); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/SimpleShape.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<? extends ControlPoint> 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(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/TemplateLayer.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<BufferedImage> 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<BufferedImage>(templateImage); + } + } + + // ================================================================================================================= + // Methods + + public String getName() { + return super.getName(); + } + + /** + * template layers are always locked + * + * @return <code>true</code> + */ + 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<BufferedImage>(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<BufferedImage>(img); + } + } + return img; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/DropShadowEffect.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/Effect.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<int[]> tmpIntArray = null; + private static SoftReference<byte[]> tmpByteArray1 = null; + private static SoftReference<byte[]> tmpByteArray2 = null; + private static SoftReference<byte[]> 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<int[]>(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<byte[]>(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<byte[]>(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<byte[]>(tmp); + } + return tmp; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtils.java Sat Apr 25 21:17:50 2009 +0400 @@ -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 { + + /** + * <p>Blurs the source pixels into the destination pixels. The force of the blur is specified by the radius which + * must be greater than 0.</p> <p>The source and destination pixels arrays are expected to be in the BYTE_GREY + * format.</p> <p>After this method is executed, dstPixels contains a transposed and filtered copy of + * srcPixels.</p> + * + * @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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/EffectUtilsTemp.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerGlowEffect.java Sat Apr 25 21:17:50 2009 +0400 @@ -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"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/InnerShadowEffect.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/OuterGlowEffect.java Sat Apr 25 21:17:50 2009 +0400 @@ -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"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/effects/ShadowEffect.java Sat Apr 25 21:17:50 2009 +0400 @@ -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()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/font/Typeface.java Sat Apr 25 21:17:50 2009 +0400 @@ -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 <em>font</em>. 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 <code>true</code> 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 <code>src</code> 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 <em>only</em> works if + * <code>isAbsolute</code> 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; + } + + /** + * <p>Sets the size of the font. THis method call will work whether + * <code>isAbsolute</code> 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.</p> + * + * <p>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".</p> + * + * @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()); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/CanvasMapper.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/ColorMapper.java Sat Apr 25 21:17:50 2009 +0400 @@ -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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/DimensionMapper.java Sat Apr 25 21:17:50 2009 +0400 @@ -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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/jibxhelpers/InsetsMapper.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/AbstractGradient.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<GradientStop> sorter = new Comparator<GradientStop>() { + 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<GradientStop> stops = new ArrayList<GradientStop>(); + private List<GradientStop> 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<GradientStop> stops = new ArrayList<GradientStop>(); + 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<GradientStop> old = new ArrayList<GradientStop>(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<GradientStop> stops) { + setStops(stops == null ? null : stops.toArray(new GradientStop[0])); + } + + public final List<GradientStop> 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<GradientStop> old = new ArrayList<GradientStop>(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<GradientStop> old = new ArrayList<GradientStop>(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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Gradient.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/GradientStop.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Matte.java Sat Apr 25 21:17:50 2009 +0400 @@ -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 <code>true</code> 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 <code>srcMatte</code> 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/PaintModel.java Sat Apr 25 21:17:50 2009 +0400 @@ -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. + * <p/> + * 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(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/RadialGradient.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/paint/Texture.java Sat Apr 25 21:17:50 2009 +0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasPath.java Sat Apr 25 21:17:50 2009 +0400 @@ -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(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasResources.java Sat Apr 25 21:17:50 2009 +0400 @@ -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(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/swingx/designer/utils/HasUIDefaults.java Sat Apr 25 21:17:50 2009 +0400 @@ -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(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/DefaultsGenerator.java Sat Apr 25 21:17:50 2009 +0400 @@ -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 + * <p/> + * 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 <code>d.put("activeCaption", new + * ColorUIResource(123, 45, 200));</code> + * @param styleInit The buffer to write out code to generate Synth Style populating the styles map <code>m + * = new HashMap<Key, LazyStyle>()</code> + * @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<String, String> 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<UIPaint> 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<UIFont> 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 <code>d.put("activeCaption", new + * ColorUIResource(123, 45, 200));</code> + * @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 <code>reg</code> 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 + * <code>reg</code> 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<String, String> 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<UIStateType> 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 <code>region</code> 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<String, String> 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/Generator.java Sat Apr 25 21:17:50 2009 +0400 @@ -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. + * <p/> + * 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). + * <p/> + * 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<String, String> variables; + + private boolean full = false; + private File buildPackageRoot; + private File srcPackageRoot; + private String packageNamePrefix; + private String lafName; + private SynthModel model; + + /** + * MAIN APPLICATION + * <p/> + * 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|false> True if we should build the whole LAF or false for building just states and painters.\n" + + " -skinFile <value> Path to the skin.laf file for the LAF to be generated from.\n" + + " -buildDir <value> 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 <value> 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 <value> The resources directory containing templates and images.\n" + + " -packagePrefix <value> The package name associated with this synth look and feel. For example,\n" + + " \"org.mypackage.mylaf\"\n" + + " -lafName <value> 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<String, String>(); + 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(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/GeneratorUtils.java Sat Apr 25 21:17:50 2009 +0400 @@ -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. + * <p/> + * For example: + * <p/> + * 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<src.length; i++) { + //if the src char is a period and there is a following character, + //make sure the character is capitalized. + if ((src[i] == '.' || src[i] == ':') && i < src.length -1) { + src[i+1] = Character.toUpperCase(src[i+1]); + continue; + } + //if the src char is one that is to be removed, skip it. + if (src[i] == '.' || src[i] == ':' || src[i] == '\\' || src[i] == '"') { + continue; + } + //copy over the current char. + dst[dstIndex++] = src[i]; + } + //at this point, dstIndex is 1 greater than the last valid index position in dst + //or in other words it represents the count. + return new String(dst, 0, dstIndex); + } + + /** + * Encodes the given synth state as if it were specified in java code, such as + * <p/> + * 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. + * <p/> + * 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/ObjectCodeConvertors.java Sat Apr 25 21:17:50 2009 +0400 @@ -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 + ")"; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/swing-nimbus/classes/org/jdesktop/synthdesigner/generator/PainterGenerator.java Sat Apr 25 21:17:50 2009 +0400 @@ -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<String, String> colors = new HashMap<String, String>(); + /** + * Code=>method name. + */ + private Map<String, String> methods = new HashMap<String, String>(); + + //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<String, List<ComponentColor>> componentColorsMap = + new LinkedHashMap<String, List<ComponentColor>>(); + /** + * 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<ComponentColor> 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<String, List<ComponentColor>> entry : componentColorsMap.entrySet()) { + getExtendedCacheKeysCode + .append(" case ") + .append(entry.getKey()).append(":\n") + .append(" extendedCacheKeys = new Object[] {\n"); + for (int i=0; i<entry.getValue().size(); i++) { + ComponentColor cc = entry.getValue().get(i); + getExtendedCacheKeysCode + .append(" getComponentColor(c, \"") + .append(cc.propertyName).append("\", ") + .append(cc.defaultColorVariableName).append(", ") + .append(cc.saturationOffset).append("f, ") + .append(cc.brightnessOffset).append("f, ") + .append(cc.alphaOffset); + if (i + 1 < entry.getValue().size()) { + getExtendedCacheKeysCode.append("),\n"); + } else { + getExtendedCacheKeysCode.append(")"); + } + } + getExtendedCacheKeysCode.append("};\n") + .append(" break;\n"); + } + getExtendedCacheKeysCode + .append(" }\n") + .append(" return extendedCacheKeys;\n") + .append(" }"); + } + } + + //type is background, foreground, border, upArrowIcon, etc. + private void generate(UIState state, Canvas canvas, String type) { + String states = UIState.keysToString(state.getStateKeys()); + String stateType = toConstantName(type + "_" + states); + String paintMethodName = "paint" + type + toClassName(states); + //create new array for component colors for this state + componentColors = new ArrayList<ComponentColor>(); + + 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<SimpleShape> 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<BezierControlPoint> 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<controlPoints.size(); j++) { + BezierControlPoint cp = controlPoints.get(j); + if (last.getCp2().isSharp() && cp.getCp1().isSharp()) { + float x = encode((float)cp.getX(), a, b, width); + float y = encode((float)cp.getY(), c, d, height); + buffer.append(" path.lineTo(" + writeDecodeX(x) + ", " + writeDecodeY(y) + ");\n"); + } else { + float x1 = encode((float)last.getX(), a, b, width); + float y1 = encode((float)last.getY(), c, d, height); + float x2 = encode((float)cp.getX(), a, b, width); + float y2 = encode((float)cp.getY(), c, d, height); + buffer.append( + " path.curveTo(" + writeDecodeBezierX(x1, last.getX(), last.getCp2X()) + ", " + + writeDecodeBezierY(y1, last.getY(), last.getCp2Y()) + ", " + + writeDecodeBezierX(x2, cp.getX(), cp.getCp1X()) + ", " + + writeDecodeBezierY(y2, cp.getY(), cp.getCp1Y()) + ", " + + writeDecodeX(x2) + ", " + writeDecodeY(y2) + ");\n"); + } + last = cp; + } + if (last.getCp2().isSharp() && first.getCp1().isSharp()) { + float x = encode((float)first.getX(), a, b, width); + float y = encode((float)first.getY(), c, d, height); + buffer.append(" path.lineTo(" + writeDecodeX(x) + ", " + writeDecodeY(y) + ");\n"); + } else { + float x1 = encode((float)last.getX(), a, b, width); + float y1 = encode((float)last.getY(), c, d, height); + float x2 = encode((float)first.getX(), a, b, width); + float y2 = encode((float)first.getY(), c, d, height); + buffer.append( + " path.curveTo(" + writeDecodeBezierX(x1, last.getX(), last.getCp2X()) + ", " + + writeDecodeBezierY(y1, last.getY(), last.getCp2Y()) + ", " + + writeDecodeBezierX(x2, first.getX(), first.getCp1X()) + ", " + + writeDecodeBezierY(y2, first.getY(), first.getCp1Y()) + ", " + + writeDecodeX(x2) + ", " + writeDecodeY(y2) + ");\n"); + } + buffer.append(" path.closePath();"); + shapeMethodBody = buffer.toString(); + shapeVariable = "path"; + } else { + throw new RuntimeException("Cannot happen unless a new Shape has been defined"); + } + + //now that we have the shape defined in shapeMethodBody, and a shapeVariable name, + //look to see if such a body has been previously defined. + shapeMethodName = methods.get(shapeMethodBody); + String returnType = null; + if (shapeMethodName == null) { + if ("rect".equals(shapeVariable)) { + shapeMethodName = "decodeRect" + rectCounter++; + returnType = "Rectangle2D"; + } else if ("roundRect".equals(shapeVariable)) { + shapeMethodName = "decodeRoundRect" + roundRectCounter++; + returnType = "RoundRectangle2D"; + } else if ("ellipse".equals(shapeVariable)) { + shapeMethodName = "decodeEllipse" + ellipseCounter++; + returnType = "Ellipse2D"; + } else { + shapeMethodName = "decodePath" + pathCounter++; + returnType = "Path2D"; + } + methods.put(shapeMethodBody, shapeMethodName); + + //since the method wasn't previously defined, time to define it + shapesCode.append(" private ").append(returnType).append(" ").append(shapeMethodName).append("() {\n"); + shapesCode.append(shapeMethodBody); + shapesCode.append("\n"); + shapesCode.append(" return " + shapeVariable + ";\n"); + shapesCode.append(" }\n\n"); + } + + //now that the method has been defined, I can go on and decode the + //paint. After the paint is decoded, I can write the g.fill() method call, + //using the result of the shapeMethodName. Yay! + +// if (shapeVariable != null) { + //first, calculate the bounds of the shape being painted and store in variables + paintingCode.append(" ").append(shapeVariable).append(" = ").append(shapeMethodName).append("();\n"); + + if (paint instanceof Matte) { + String colorVariable = encodeMatte((Matte)paint); + paintingCode.append(" g.setPaint(").append(colorVariable).append(");\n"); + } else if (paint instanceof Gradient) { + String gradientMethodName = encodeGradient(shape, (Gradient)paint); + paintingCode.append(" g.setPaint(").append(gradientMethodName).append("(").append(shapeVariable).append("));\n"); + } else if (paint instanceof RadialGradient) { + String radialMethodName = encodeRadial(shape, (RadialGradient)paint); + paintingCode.append(" g.setPaint(").append(radialMethodName).append("(").append(shapeVariable).append("));\n"); + } + paintingCode.append(" g.fill(").append(shapeVariable).append(");\n"); + } + } + } + + paintingCode.append("\n }\n\n"); + + //collect component colors + if (!componentColors.isEmpty()) { + componentColorsMap.put(stateType, componentColors); + componentColors = null; + } + } + + private float encode(float x, float a, float b, float width) { + return ObjectCodeConvertors.encode(x, a, b, width); + } + + private String writeDecodeX(float encodedX) { + return "decodeX(" + encodedX + "f)"; + } + + private String writeDecodeY(float encodedY) { + return "decodeY(" + encodedY + "f)"; + } + + /** + * + * @param ex encoded x value + * @param x unencoded x value + * @param cpx unencoded cpx value + * @return + */ + private static String writeDecodeBezierX(double ex, double x, double cpx) { + return "decodeAnchorX(" + ex + "f, " + (cpx - x) + "f)"; + } + + /** + * + * @param ey encoded y value + * @param y unencoded y value + * @param cpy unencoded cpy value + * @return + */ + private static String writeDecodeBezierY(double ey, double y, double cpy) { + return "decodeAnchorY(" + ey + "f, " + (cpy - y) + "f)"; + } + + private String encodeMatte(Matte m) { + String declaration = null; + if (m.isAbsolute()) { + Color c = m.getColor(); + declaration = ObjectCodeConvertors.convert(c); + } else { + declaration = "decodeColor(\"" + m.getUiDefaultParentName() + + "\", " + m.getHueOffset() + "f, " + + m.getSaturationOffset() + "f, " + + m.getBrightnessOffset() + "f, " + + m.getAlphaOffset() + ")"; + } + + String variableName = colors.get(declaration); + if (variableName == null) { + variableName = "color" + colorCounter++; + colors.put(declaration, variableName); + colorCode.append(" private Color ").append(variableName).append(" = "); + colorCode.append(declaration).append(";\n"); + } + // handle component colors + if (m.getComponentPropertyName() != null) { + ComponentColor cc = new ComponentColor(m.getComponentPropertyName(), + variableName, m.getSaturationOffset(), + m.getBrightnessOffset(), m.getAlphaOffset()); + int index = componentColors.indexOf(cc); + if (index == -1) { + index = componentColors.size(); + componentColors.add(cc); + } + return "(Color)componentColors[" + index + "]"; + } else { + return variableName; + } + } + + private String encodeColor(Color c) { + String declaration = ObjectCodeConvertors.convert(c); + String variableName = colors.get(declaration); + if (variableName == null) { + variableName = "color" + colorCounter++; + colors.put(declaration, variableName); + colorCode.append(" private Color ").append(variableName).append(" = "); + colorCode.append(declaration).append(";\n"); + } + + return variableName; + } + + private String encodeGradient(PaintedShape ps, Gradient g) { + StringBuilder b = new StringBuilder(); + float x1 = (float)ps.getPaintX1();