This commit is contained in:
Yuri Nesterenko 2009-04-28 13:41:11 -07:00
commit 33484a2710
175 changed files with 54364 additions and 630 deletions

View File

@ -9,25 +9,35 @@ Simple Build Instructions:
http://java.sun.com/javase/downloads/index.jsp
Set the environment variable ALT_BOOTDIR to the location of this JDK 6.
2. Download and install the Binary Plugs for the most recent JDK7 from
2. Download and install the JIBX libraries, version 1.1.5 from
http://sourceforge.net/project/showfiles.php?group_id=69358&package_id=68290
You'll need the following four JAR files:
bcel.jar
jibx-bind.jar
jibx-run.jar
xpp3.jar
Set the environment variable ALT_JIBX_LIBS_PATH to the location of
these JAR files.
3. Download and install the Binary Plugs for the most recent JDK7 from
http://download.java.net/openjdk/jdk7/
Set the environment variable ALT_BINARY_PLUGS_PATH to the location of
these binary plugs.
3. Either download and install the latest JDK7 from
4. Either download and install the latest JDK7 from
http://download.java.net/openjdk/jdk7/, or build your own complete
OpenJDK7 by using the top level Makefile in the OpenJDK Mercurial forest.
Set the environment variable ALT_JDK_IMPORT_PATH to the location of
this latest JDK7 or OpenJDK7 build.
4. Check the sanity of doing a build with the current machine:
5. Check the sanity of doing a build with the current machine:
cd make && gnumake sanity
See README-builds.html if you run into problems.
5. Do a partial build of the jdk:
6. Do a partial build of the jdk:
cd make && gnumake all
6. Construct the images:
7. Construct the images:
cd make && gnumake images
The resulting JDK image should be found in build/*/j2sdk-image

View File

@ -92,7 +92,8 @@ sanity-all:: sanity-base \
sane-ld_run_path \
sane-alt_bootdir \
sane-bootdir \
sane-alsa-headers
sane-alsa-headers \
sane-jibx
ifdef OPENJDK
sanity-all:: sane-freetype

View File

@ -515,6 +515,15 @@ endif
# NOTE: ISA_DIR is usually empty, on Solaris it might be /sparcv9 or /amd64
BINDIR = $(OUTPUTDIR)/bin$(ISA_DIR)
# JIBX_LIBS_PATH: path to JIBX libraries, needed for NimbusLookAndFeel
ifdef ALT_JIBX_LIBS_PATH
JIBX_LIBS_PATH:=$(call FullPath,$(ALT_JIBX_LIBS_PATH))
JIBX_LIBS_PATH:=$(call AltCheckSpaces,JIBX_LIBS_PATH)
JIBX_LIBS_PATH:=$(call AltCheckValue,JIBX_LIBS_PATH)
else
JIBX_LIBS_PATH=$(JDK_DEVTOOLS_DIR)/share/jibx/lib
endif
# MOZILLA_HEADERS_PATH: path to mozilla header files for plugin
ifdef ALT_MOZILLA_HEADERS_PATH
MOZILLA_HEADERS_PATH :=$(call FullPath,$(ALT_MOZILLA_HEADERS_PATH))
@ -529,7 +538,7 @@ ifneq ($(PLATFORM), windows)
JDK_CUPS_HEADERS_PATH=$(JDK_DEVTOOLS_DIR)/share/cups/include
ifdef ALT_CUPS_HEADERS_PATH
CUPS_HEADERS_PATH:=$(call FullPath,$(ALT_CUPS_HEADERS_PATH))
CUP_HEADERS_PATH:=$(call AltCheckValue,CUPS_HEADERS_PATH)
CUPS_HEADERS_PATH:=$(call AltCheckValue,CUPS_HEADERS_PATH)
else
CUPS_HEADERS_PATH:= \
$(shell if [ -d "$(JDK_CUPS_HEADERS_PATH)" ]; then \

View File

@ -233,6 +233,7 @@ ifeq ($(PLATFORM),windows)
endif
endif
ALL_SETTINGS+=$(call addAltSetting,CACERTS_FILE)
ALL_SETTINGS+=$(call addAltSetting,JIBX_LIBS_PATH)
ifndef OPENJDK
ALL_SETTINGS+=$(call addAltSetting,MOZILLA_HEADERS_PATH)
endif

View File

@ -213,6 +213,7 @@ include $(JDK_MAKE_SHARED_DIR)/Sanity-Settings.gmk
sane-link \
sane-cacerts \
sane-alsa-headers \
sane-jibx \
sane-ant_version \
sane-zip_version \
sane-unzip_version \
@ -1497,6 +1498,18 @@ ifeq ($(PLATFORM), solaris)
endif
######################################################
# JIBX_LIBS_PATH must be valid
######################################################
sane-jibx:
@if [ ! -r $(subst \,/,$(JIBX_LIBS_PATH))/jibx-run.jar ]; then \
$(ECHO) "ERROR: You do not have access to valid JIBX library files. \n" \
" Please check your access to \n" \
" $(subst \,/,$(JIBX_LIBS_PATH))/jibx-run.jar \n" \
" and/or check your value of ALT_JDK_DEVTOOLS_DIR, ALT_JIBX_LIBS_PATH \n" \
"" >> $(ERROR_FILE) ; \
fi
######################################################
# MOZILLA_HEADERS_PATH must be valid
######################################################

View File

@ -34,9 +34,14 @@ include $(BUILDDIR)/common/Defs.gmk
#
include FILES.gmk
AUTO_FILES_JAVA_DIRS = javax/swing/plaf sun/swing com/sun/java/swing/plaf
SUBDIRS = nimbus
# Nimbus is handled in its own directory
AUTO_JAVA_PRUNE = nimbus
ifeq ($(PLATFORM), windows)
# Don't build GTK L&F on Windows
AUTO_JAVA_PRUNE = gtk
AUTO_JAVA_PRUNE += gtk
endif
MISC_FILES = $(MISC_SWING_FILES)
@ -68,8 +73,10 @@ endif
# Process LOGO_ICONS and Motif Icons first.
#
build: $(LOGO_ICONS) $(MISC_SWING_FILES_MOTIF_GIF) $(MISC_SWING_FILES_MOTIF_PNG) other_files
$(SUBDIRS-loop)
clean:: classes.clean
clean clobber::
$(SUBDIRS-loop)
#
# Include

View File

@ -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)

View File

@ -51,6 +51,7 @@ SUBDIRS = \
makeclasslist \
strip_properties \
spp \
swing-nimbus \
CharsetMapping
all build clean clobber::

View File

@ -0,0 +1,91 @@
#
# Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
#
# Makefile for building the Nimbus generator
#
BUILDDIR = ../..
PACKAGE = org.jdesktop.synthdesigner.generator
PRODUCT = tools
PROGRAM = nimbus_generator
include $(BUILDDIR)/common/Defs.gmk
BUILDTOOL_SOURCE_ROOT = classes
BUILDTOOL_MAIN = $(PKGDIR)/Generator.java
#
# Files
#
MAIN_CLASS_FILE = $(BUILDTOOLCLASSDIR)/$(BUILDTOOL_MAIN:%.java=%.class)
SOURCE_FILES = $(shell $(FIND) $(BUILDTOOL_SOURCE_ROOT) -name '*.java' -print)
TEMPLATE_FILES = $(SHARE_SRC)/classes/javax/swing/plaf/nimbus/Defaults.template \
$(SHARE_SRC)/classes/javax/swing/plaf/nimbus/PainterImpl.template \
$(SHARE_SRC)/classes/javax/swing/plaf/nimbus/StateImpl.template
TEMPLATE_DEST = $(BUILDTOOLCLASSDIR)/org/jdesktop/synthdesigner/generator/resources
JIBX_FILES = $(BUILDTOOL_SOURCE_ROOT)/org/jdesktop/swingx/designer/Designer.jibx.xml \
$(BUILDTOOL_SOURCE_ROOT)/org/jdesktop/synthdesigner/synthmodel/SynthModel.jibx.xml
JIBX_LIBS_CP = $(JIBX_LIBS_PATH)/bcel.jar$(CLASSPATH_SEPARATOR)$(JIBX_LIBS_PATH)/xpp3.jar$(CLASSPATH_SEPARATOR)$(JIBX_LIBS_PATH)/jibx-bind.jar$(CLASSPATH_SEPARATOR)$(JIBX_LIBS_PATH)/jibx-run.jar
JIBX_LIBS_LIST = $(subst $(CLASSPATH_SEPARATOR), ,$(JIBX_LIBS_CP))
#
# Rules
#
include $(BUILDDIR)/common/BuildToolJar.gmk
$(MAIN_CLASS_FILE): $(SOURCE_FILES) $(JIBX_LIBS_LIST)
@$(MKDIR) -p $(BUILDTOOLCLASSDIR)
$(BOOT_JAVAC_CMD) -classpath "$(JIBX_LIBS_CP)" \
-d $(BUILDTOOLCLASSDIR) -sourcepath $(BUILDTOOL_SOURCE_ROOT) \
$(SOURCE_FILES)
$(TEMPLATE_DEST): $(TEMPLATE_FILES)
$(MKDIR) -p $(TEMPLATE_DEST)
$(RM) $(TEMPLATE_DEST)/*.template
$(CP) $(TEMPLATE_FILES) $(TEMPLATE_DEST)
$(BUILDTOOL_MANIFEST_FILE): $(MAIN_CLASS_FILE)
$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
$(ECHO) "Class-Path: $(JIBX_LIBS_LIST:$(JIBX_LIBS_PATH)/%=%)" >> $@
$(CP) $(JIBX_LIBS_LIST) $(BUILDTOOLJARDIR)
$(BUILDTOOL_JAR_FILE): $(MAIN_CLASS_FILE) $(TEMPLATE_DEST) \
$(JIBX_FILES) $(BUILDTOOL_MANIFEST_FILE)
@$(prep-target)
$(BOOT_JAVA_CMD) \
-classpath "$(JIBX_LIBS_CP)$(CLASSPATH_SEPARATOR)$(BUILDTOOLCLASSDIR)" \
org.jibx.binding.Compile $(JIBX_FILES)
$(BOOT_JAR_CMD) cfm $@ $(BUILDTOOL_MANIFEST_FILE) \
-C $(BUILDTOOLCLASSDIR) org \
$(BOOT_JAR_JFLAGS) || $(RM) $@
@$(java-vm-cleanup)
clean clobber::
$(RM) -r $(TEMPLATE_DEST)

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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
};
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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>

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 &lt;= midpoint &lt;= 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;
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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 + ")";
}
}

View File

@ -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();
float y1 = (float)ps.getPaintY1();
float x2 = (float)ps.getPaintX2();
float y2 = (float)ps.getPaintY2();
b.append(" return decodeGradient((");
b.append(x1);
b.append("f * w) + x, (");
b.append(y1);
b.append("f * h) + y, (");
b.append(x2);
b.append("f * w) + x, (");
b.append(y2);
b.append("f * h) + y,\n");
encodeGradientColorsAndFractions(g,b);
b.append(");");
String methodBody = b.toString();
String methodName = methods.get(methodBody);
if (methodName == null) {
methodName = "decodeGradient" + gradientCounter++;
gradientsCode.append(" private Paint ").append(methodName).append("(Shape s) {\n");
gradientsCode.append(" Rectangle2D bounds = s.getBounds2D();\n");
gradientsCode.append(" float x = (float)bounds.getX();\n");
gradientsCode.append(" float y = (float)bounds.getY();\n");
gradientsCode.append(" float w = (float)bounds.getWidth();\n");
gradientsCode.append(" float h = (float)bounds.getHeight();\n");
gradientsCode.append(methodBody);
gradientsCode.append("\n }\n\n");
methods.put(methodBody, methodName);
}
return methodName;
}
/**
* Takes a abstract gradient and creates the code for the fractions float
* array and the colors array that can be used in the constructors of linear
* and radial gradients.
*
* @param g The abstract gradient to get stops from
* @param b Append code string of the form "new float[]{...},
* new Color[]{...}" to this StringBuilder
*/
private void encodeGradientColorsAndFractions(AbstractGradient g,
StringBuilder b) {
List<GradientStop> stops = g.getStops();
// there are stops.size() number of main stops. Between each is a
// fractional stop. Thus, there are: stops.size() + stops.size() - 1
// number of fractions and colors.
float[] fractions = new float[stops.size() + stops.size() - 1];
String[] colors = new String[fractions.length];
//for each stop, create the stop and it's associated fraction
int index = 0; // the index into fractions and colors
for (int i = 0; i < stops.size(); i++) {
GradientStop s = stops.get(i);
//copy over the stop's data
colors[index] = encodeMatte(s.getColor());
fractions[index] = s.getPosition();
//If this isn't the last stop, then add in the fraction
if (index < fractions.length - 1) {
float f1 = s.getPosition();
float f2 = stops.get(i + 1).getPosition();
index++;
fractions[index] = f1 + (f2 - f1) * s.getMidpoint();
colors[index] = "decodeColor("+
colors[index - 1]+","+
encodeMatte(stops.get(i + 1).getColor())+",0.5f)";
}
index++;
}
// Check boundry conditions
for (int i = 1; i < fractions.length; i++) {
//to avoid an error with LinearGradientPaint where two fractions
//are identical, bump up the fraction value by a miniscule amount
//if it is identical to the previous one
//NOTE: The <= is critical because the previous value may already
//have been bumped up
if (fractions[i] <= fractions[i - 1]) {
fractions[i] = fractions[i - 1] + .000001f;
}
}
//another boundary condition where multiple stops are all at the end. The
//previous loop bumped all but one of these past 1.0, which is bad.
//so remove any fractions (and their colors!) that are beyond 1.0
int outOfBoundsIndex = -1;
for (int i = 0; i < fractions.length; i++) {
if (fractions[i] > 1) {
outOfBoundsIndex = i;
break;
}
}
if (outOfBoundsIndex >= 0) {
float[] f = fractions;
String[] c = colors;
fractions = new float[outOfBoundsIndex];
colors = new String[outOfBoundsIndex];
System.arraycopy(f, 0, fractions, 0, outOfBoundsIndex);
System.arraycopy(c, 0, colors, 0, outOfBoundsIndex);
}
// build string
b.append(" new float[] { ");
for (int i = 0; i < fractions.length; i++) {
if (i>0)b.append(',');
b.append(fractions[i]);
b.append('f');
}
b.append(" },\n new Color[] { ");
for (int i = 0; i < colors.length; i++) {
if (i>0) b.append(",\n ");
b.append(colors[i]);
}
b.append("}");
}
private String encodeRadial(PaintedShape ps, RadialGradient g) {
float centerX1 = (float)ps.getPaintX1();
float centerY1 = (float)ps.getPaintY1();
float x2 = (float)ps.getPaintX2();
float y2 = (float)ps.getPaintY2();
float radius = (float)Point2D.distance(centerX1, centerY1, x2, y2);
StringBuilder b = new StringBuilder();
b.append(" return decodeRadialGradient((");
b.append(centerX1);
b.append("f * w) + x, (");
b.append(centerY1);
b.append("f * h) + y, ");
b.append(radius);
b.append("f,\n");
encodeGradientColorsAndFractions(g,b);
b.append(");");
String methodBody = b.toString();
String methodName = methods.get(methodBody);
if (methodName == null) {
methodName = "decodeRadial" + radialCounter++;
gradientsCode.append(" private Paint ").append(methodName).append("(Shape s) {\n");
gradientsCode.append(" Rectangle2D bounds = s.getBounds2D();\n");
gradientsCode.append(" float x = (float)bounds.getX();\n");
gradientsCode.append(" float y = (float)bounds.getY();\n");
gradientsCode.append(" float w = (float)bounds.getWidth();\n");
gradientsCode.append(" float h = (float)bounds.getHeight();\n");
gradientsCode.append(methodBody);
gradientsCode.append("\n }\n\n");
methods.put(methodBody, methodName);
}
return methodName;
}
//note that this method is not thread-safe. In fact, none of this class is.
static void writePainter(UIRegion r, Map<String, String> variables, File painterPackageRoot, String prefix) throws IOException {
//Need only write out the stuff for this region, don't need to worry about subregions
//since this method will be called for each of those (and they go in their own file, anyway).
//The only subregion that we compound into this is the one for icons.
String painterName = makePretty(prefix) + "Painter";
PainterGenerator gen = new PainterGenerator(r);
System.out.println("Generating source file: " + painterName + ".java");
System.out.println(gen.stateTypeCode.toString());
variables.put("PAINTER_NAME", painterName);
variables.put("STATIC_DECL", gen.stateTypeCode.toString());
variables.put("COLORS_DECL", gen.colorCode.toString());
variables.put("DO_PAINT_SWITCH_BODY", gen.switchCode.toString());
variables.put("PAINTING_DECL", gen.paintingCode.toString());
variables.put("GET_EXTENDED_CACHE_KEYS", gen.getExtendedCacheKeysCode.toString());
variables.put("SHAPES_DECL", gen.shapesCode.toString());
variables.put("GRADIENTS_DECL", gen.gradientsCode.toString());
writeSrcFile(getPainterImplTemplate(), variables, new File(painterPackageRoot, painterName + ".java"));
variables.remove("PAINTER_NAME");
variables.remove("STATIC_DECL");
variables.remove("COLORS_DECL");
variables.remove("DO_PAINT_SWITCH_BODY");
variables.remove("PAINTING_DECL");
variables.remove("SHAPES_DECL");
variables.remove("GRADIENTS_DECL");
}
/**
* Represents the usage of a color from a component within a painter. That
* is, a painter can use colors from the component when it paints. This
* class represents the usage of such a color, containing a reference to
* the name of the property that contains the color, and the various
* derivation offsets to apply to that color.
*/
private static class ComponentColor {
public String propertyName;
public String defaultColorVariableName;
private float saturationOffset = 0, brightnessOffset = 0;
private int alphaOffset = 0;
private ComponentColor(String propertyName,
String defaultColorVariableName,
float saturationOffset,
float brightnessOffset,
int alphaOffset) {
this.propertyName = propertyName;
this.defaultColorVariableName = defaultColorVariableName;
this.saturationOffset = saturationOffset;
this.brightnessOffset = brightnessOffset;
this.alphaOffset = alphaOffset;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ComponentColor c = (ComponentColor)o;
if (alphaOffset != c.alphaOffset) return false;
if (Float.compare(saturationOffset, c.saturationOffset) != 0)
return false;
if (Float.compare(brightnessOffset, c.brightnessOffset) != 0)
return false;
if (defaultColorVariableName != null ?
!defaultColorVariableName.equals(c.defaultColorVariableName) :
c.defaultColorVariableName != null) return false;
if (propertyName != null ? !propertyName.equals(c.propertyName) :
c.propertyName != null) return false;
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 61 * hash + (this.propertyName != null ?
this.propertyName.hashCode() : 0);
hash = 61 * hash + (this.defaultColorVariableName != null ?
this.defaultColorVariableName.hashCode() : 0);
hash = 61 * hash + Float.floatToIntBits(this.saturationOffset);
hash = 61 * hash + Float.floatToIntBits(this.brightnessOffset);
hash = 61 * hash + this.alphaOffset;
return hash;
}
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.generator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.Map;
/**
* TemplateWriter - Class for writing Java Source files using a src template and variable subsitution
*
* @author Richard Bair
* @author Jasper Potts
*/
public class TemplateWriter {
/**
* Write a Java source file by taking a template file and applying variable substitution and writing to the output
* file.
*
* @param template The template to use
* @param variables Map of the variable names and values to substitute in the template
* @param output The file to write to
* @throws IOException If there was a problem writing the Java source file
*/
static void writeSrcFile(String template, Map<String, String> variables, File output) throws IOException {
TemplateReader in = new TemplateReader(variables, template);
PrintWriter out =
new PrintWriter(new FileWriter(output));
String line = in.readLine();
while (line != null) {
out.println(line);
line = in.readLine();
}
out.close();
}
/**
* Read a template file into a string
*
* @param name The template file path relative to Generator class
* @return The contents of the template file as string
* @throws IOException If there was a problem reading the template file
*/
static String read(String name) throws IOException {
InputStream in = Generator.class.getResourceAsStream(name);
if (in==null) throw new IOException("Could not find template ["+name+
"] relative to class ["+Generator.class.getName()+"]");
byte[] data = new byte[4096];
int length = -1;
StringBuilder buffer = new StringBuilder();
while ((length = in.read(data)) != -1) {
buffer.append(new String(data, 0, length));
}
return buffer.toString();
}
/** A BufferedReader implementation that automatically performs string replacements as needed. */
private static final class TemplateReader extends BufferedReader {
private Map<String, String> variables;
TemplateReader(Map<String, String> variables, String template) {
super(new StringReader(template));
this.variables = variables;
}
/**
* @return a line of text from the template but with variables substituted. Other methods will return the text
* sans substitution. Call this method.
* @throws java.io.IOException
*/
public String readLine() throws IOException {
return substituteVariables(super.readLine());
}
private String substituteVariables(String input) {
if (input == null) return null;
for (Map.Entry<String, String> variable : variables.entrySet()) {
input = input.replace("${" + variable.getKey() + "}", variable.getValue());
}
return input;
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
/**
* CustomUIDefault
*
* @author Richard Bair
* @author Jasper Potts
*/
public class CustomUIDefault<T> extends UIDefault<T> {
private static int counter = -1;
public CustomUIDefault() {
super("Unnamed" + (++counter == 0 ? "" : counter), null);
}
public void setName(String id) {
super.setName(id);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
/**
* HasUIStyle - A marker interface for all classes that have a UIStyle
*
* @author Richard Bair
* @author Jasper Potts
*/
public interface HasUIStyle {
public UIStyle getStyle();
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import javax.swing.border.EmptyBorder;
/**
* Represents a border that refers to a Painter to do it's work. This border
* doesn't actually render -- it is just used as part of the model.
*
* @author Richard Bair
*/
public class PainterBorder extends EmptyBorder {
private String painterName;
public PainterBorder(String painterName, int top, int left, int bottom, int right) {
super(top, left, bottom, right);
this.painterName = painterName;
}
public String getPainterName() { return painterName; }
}

View File

@ -0,0 +1,530 @@
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
import org.jdesktop.swingx.designer.utils.HasResources;
import org.jdesktop.swingx.designer.utils.HasUIDefaults;
import org.jibx.runtime.IUnmarshallingContext;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDesktopPane;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JRootPane;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.JViewport;
import javax.swing.UIDefaults;
import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.MetalLookAndFeel;
import static javax.swing.plaf.synth.SynthConstants.*;
import javax.swing.table.JTableHeader;
import java.awt.Insets;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Models a Synth look and feel. Contains all of the colors, fonts, painters, states, etc that compose a synth look and
* feel.
* <p/>
* To model Synth properly, I need to both Model the way Synth works (with styles, and so forth) and the way a look and
* feel works (UIDefaults table, etc) since both of these are supported ways of doing things in Synth.
* <p/>
* One important (but non-visual) thing that needs to be configurable is the support for InputMaps per component. In
* Synth, an input map can be associated with the main Synth element, meaning it applies to everything. Or it can be
* associated with a single style. An Inputmap can have an id, and it can contain multiple key/action pairs (where
* actions are denoted by name).
* <p/>
* It looks like Regions can have InputMaps? Sounds fishy to me. I think only Components really have input maps.
* <p/>
* I would like some way of denoting special keys between mac and other platforms. For example, cut, copy, paste etc
* should be different. In general, the ctrl key and apple (meta) key are reversed from what is typically on windows.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class SynthModel extends AbstractBean implements HasUIDefaults, HasUIStyle, HasResources {
//I'm going to want:
//entries related to the Control color, and other colors of the Basic LAF
//entries related to fonts (standard fonts) used in the Basic LAF
//entries related to standard insets, borders, dimensions, icons
//entries related to component specific entries in the LAF
private List<UIPaint> colors;
private List<UIFont> fonts;
private List<UIInsets> insets;
private List<UIBorder> borders;
private List<UIDimension> dimensions;
private List<UIIcon> icons;
private List<UIComponent> components;
/**
* This is a local UIDefaults that contains all the UIDefaults in this synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*/
private transient UIDefaults modelDefaults = new UIDefaults();
private transient UIStyle globalStyle = new UIStyle();
private transient File resourcesDir;
private transient File imagesDir;
private transient File templatesDir;
/** Default constructor used by JIBX to create new empty SynthModel */
protected SynthModel() {
this(false);
}
public SynthModel(boolean populateWithDefaults) {
// create observable lists that fire changes on as property changes
colors = new ArrayList<UIPaint>();
fonts = new ArrayList<UIFont>();
insets = new ArrayList<UIInsets>();
borders = new ArrayList<UIBorder>();
dimensions = new ArrayList<UIDimension>();
icons = new ArrayList<UIIcon>();
components = new ArrayList<UIComponent>();
if (populateWithDefaults) {
//get the ui defaults from the SynthLookAndFeel. Using the UIDefaults table,
//pre initialize everything.
// SynthLookAndFeel synth = new SynthLookAndFeel();
BasicLookAndFeel synth = new MetalLookAndFeel();
UIDefaults defaults = synth.getDefaults();
//pre-init the palettes
colors.add(new UIColor("desktop", defaults.getColor("desktop"), modelDefaults));
colors.add(new UIColor("activeCaption", defaults.getColor("activeCaption"), modelDefaults));
colors.add(new UIColor("activeCaptionText", defaults.getColor("activeCaptionText"), modelDefaults));
colors.add(new UIColor("activeCaptionBorder", defaults.getColor("activeCaptionBorder"), modelDefaults));
colors.add(new UIColor("inactiveCaption", defaults.getColor("inactiveCaption"), modelDefaults));
colors.add(new UIColor("inactiveCaptionText", defaults.getColor("inactiveCaptionText"), modelDefaults));
colors.add(new UIColor("inactiveCaptionBorder", defaults.getColor("inactiveCaptionBorder"), modelDefaults));
colors.add(new UIColor("window", defaults.getColor("window"), modelDefaults));
colors.add(new UIColor("windowBorder", defaults.getColor("windowBorder"), modelDefaults));
colors.add(new UIColor("windowText", defaults.getColor("windowText"), modelDefaults));
colors.add(new UIColor("menu", defaults.getColor("menu"), modelDefaults));
colors.add(new UIColor("menuText", defaults.getColor("menuText"), modelDefaults));
colors.add(new UIColor("text", defaults.getColor("text"), modelDefaults));
colors.add(new UIColor("textText", defaults.getColor("textText"), modelDefaults));
colors.add(new UIColor("textHighlight", defaults.getColor("textHighlight"), modelDefaults));
colors.add(new UIColor("textHighlightText", defaults.getColor("textHighlightText"), modelDefaults));
colors.add(new UIColor("textInactiveText", defaults.getColor("textInactiveText"), modelDefaults));
colors.add(new UIColor("control", defaults.getColor("control"), modelDefaults));
colors.add(new UIColor("controlText", defaults.getColor("controlText"), modelDefaults));
colors.add(new UIColor("controlHighlight", defaults.getColor("controlHighlight"), modelDefaults));
colors.add(new UIColor("controlLHighlight", defaults.getColor("controlLHighlight"), modelDefaults));
colors.add(new UIColor("controlShadow", defaults.getColor("controlShadow"), modelDefaults));
colors.add(new UIColor("controlDkShadow", defaults.getColor("controlDkShadow"), modelDefaults));
colors.add(new UIColor("scrollbar", defaults.getColor("scrollbar"), modelDefaults));
colors.add(new UIColor("info", defaults.getColor("info"), modelDefaults));
colors.add(new UIColor("infoText", defaults.getColor("infoText"), modelDefaults));
fonts.add(new UIFont("dialogPlain", defaults.getFont("Button.font"), modelDefaults));
fonts.add(new UIFont("serifPlain", defaults.getFont("TextPane.font"), modelDefaults));
fonts.add(new UIFont("sansSerifPlain", defaults.getFont("ToolTip.font"), modelDefaults));
fonts.add(new UIFont("monospacedPlain", defaults.getFont("TextArea.font"), modelDefaults));
fonts.add(new UIFont("dialogBold", defaults.getFont("InternalFrame.titleFont"), modelDefaults));
insets.add(new UIInsets("zeroInsets", new Insets(0, 0, 0, 0)));
insets.add(new UIInsets("twoInsets", new Insets(2, 2, 2, 2)));
insets.add(new UIInsets("threeInsets", new Insets(3, 3, 3, 3)));
borders.add(new UIBorder("marginBorder", defaults.getBorder("MenuItem.border")));
borders.add(new UIBorder("etchedBorder", defaults.getBorder("TitledBorder.border")));
borders.add(new UIBorder("loweredBevelBorder", defaults.getBorder("Table.scrollPaneBorder")));
borders.add(new UIBorder("blackLineBorder", defaults.getBorder("ToolTip.border")));
//TODO have to deal with the special arrow button region
//pre-init the list of UI components
UIComponent button = new UIComponent("Button", JButton.class.getName(), "ButtonUI");
addStates(this, button, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(button);
UIComponent toggleButton =
new UIComponent("ToggleButton", JToggleButton.class.getName(), "ToggleButtonUI");
addStates(this, toggleButton, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED, SELECTED,
SELECTED | PRESSED, SELECTED | MOUSE_OVER, DISABLED | SELECTED);
components.add(toggleButton);
UIComponent radioButton =
new UIComponent("RadioButton", JRadioButton.class.getName(), "RadioButtonUI");
addStates(this, radioButton, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED, SELECTED,
SELECTED | PRESSED, SELECTED | MOUSE_OVER, DISABLED | SELECTED);
components.add(radioButton);
UIComponent checkBox =
new UIComponent("CheckBox", JCheckBox.class.getName(), "CheckBoxUI");
addStates(this, checkBox, DEFAULT, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED, SELECTED,
SELECTED | PRESSED, SELECTED | MOUSE_OVER, DISABLED | SELECTED);
components.add(checkBox);
UIComponent colorChooser =
new UIComponent("ColorChooser", JColorChooser.class.getName(), "ColorChooserUI");
addStates(this, colorChooser, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(colorChooser);
UIComponent comboBox =
new UIComponent("ComboBox", JComboBox.class.getName(), "ComboBoxUI");
addStates(this, comboBox, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(comboBox);
UIComponent fileChooser =
new UIComponent("FileChooser", JFileChooser.class.getName(), "FileChooserUI");
addStates(this, fileChooser, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(fileChooser);
//not represented in Synth
// UIComponent fileView = new UIComponent ("FileView",
// list(DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
UIComponent internalFrame =
new UIComponent("InternalFrame", JInternalFrame.class.getName(), "InternalFrameUI");
addStates(this, internalFrame, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//has an internal frame title pane region
components.add(internalFrame);
//TODO DesktopIcon ???
UIComponent desktop =
new UIComponent("Desktop", JDesktopPane.class.getName(), "DesktopPaneUI");
addStates(this, desktop, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(desktop);
UIComponent label = new UIComponent("Label", JLabel.class.getName(), "LabelUI");
addStates(this, label, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(label);
UIComponent list = new UIComponent("List", JList.class.getName(), "ListUI");
addStates(this, list, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(list);
UIComponent menuBar = new UIComponent("MenuBar", JMenuBar.class.getName(), "MenuBarUI");
addStates(this, menuBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(menuBar);
UIComponent menuItem =
new UIComponent("MenuItem", JMenuItem.class.getName(), "MenuItemUI");
addStates(this, menuItem, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//has a menuItemAccelerator region
components.add(menuItem);
UIComponent radioButtonMenuItem =
new UIComponent("RadioButtonMenuItem", JRadioButtonMenuItem.class.getName(),
"RadioButtonMenuItemUI");
addStates(this, radioButtonMenuItem, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(radioButtonMenuItem);
UIComponent checkBoxMenuItem =
new UIComponent("CheckBoxMenuItem", JCheckBoxMenuItem.class.getName(),
"CheckBoxMenuItemUI");
addStates(this, checkBoxMenuItem, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(checkBoxMenuItem);
UIComponent menu = new UIComponent("Menu", JMenu.class.getName(), "MenuUI");
addStates(this, menu, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(menu);
UIComponent popupMenu =
new UIComponent("PopupMenu", JPopupMenu.class.getName(), "PopupMenuUI");
addStates(this, popupMenu, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//has a popupMenuSeparator region
components.add(popupMenu);
UIComponent optionPane =
new UIComponent("OptionPane", JOptionPane.class.getName(), "OptionPaneUI");
addStates(this, optionPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(optionPane);
UIComponent panel = new UIComponent("Panel", JPanel.class.getName(), "PanelUI");
addStates(this, panel, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(panel);
UIComponent progressBar =
new UIComponent("ProgressBar", JProgressBar.class.getName(), "ProgressBarUI");
addStates(this, progressBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(progressBar);
UIComponent separator =
new UIComponent("Separator", JSeparator.class.getName(), "SeparatorUI");
addStates(this, separator, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(separator);
UIRegion scrollBarThumb = new UIRegion("ScrollBar.Thumb");
addStates(this, scrollBarThumb, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
UIRegion scrollBarTrack = new UIRegion("ScrollBar.Track");
addStates(this, scrollBarTrack, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
UIComponent scrollBar =
new UIComponent("ScrollBar", JScrollBar.class.getName(), "ScrollBarUI", scrollBarThumb,
scrollBarTrack);
addStates(this, scrollBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(scrollBar);
UIComponent scrollPane =
new UIComponent("ScrollPane", JScrollPane.class.getName(), "ScrollPaneUI");
addStates(this, scrollPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(scrollPane);
UIComponent viewport =
new UIComponent("Viewport", JViewport.class.getName(), "ViewportUI");
addStates(this, viewport, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(viewport);
UIComponent slider = new UIComponent("Slider", JSlider.class.getName(), "SliderUI");
addStates(this, slider, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//has sliderThumb and sliderTrack sub regions
components.add(slider);
UIComponent spinner = new UIComponent("Spinner", JSpinner.class.getName(), "SpinnerUI");
addStates(this, spinner, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(spinner);
UIComponent splitPane =
new UIComponent("SplitPane", JSplitPane.class.getName(), "SplitPaneUI");
addStates(this, splitPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//has splitPaneDivider sub region
components.add(splitPane);
UIComponent tabbedPane =
new UIComponent("TabbedPane", JTabbedPane.class.getName(), "TabbedPaneUI");
addStates(this, tabbedPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//has tabbedPaneContent and tabbedPaneTab and TabbedPaneTabArea sub regions
components.add(tabbedPane);
UIComponent table = new UIComponent("Table", JTable.class.getName(), "TableUI");
addStates(this, table, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(table);
UIComponent tableHeader =
new UIComponent("TableHeader", JTableHeader.class.getName(), "TableHeaderUI");
addStates(this, tableHeader, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(tableHeader);
UIComponent textField =
new UIComponent("TextField", JTextField.class.getName(), "TextFieldUI");
addStates(this, textField, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(textField);
UIComponent formattedTextField =
new UIComponent("FormattedTextField", JFormattedTextField.class.getName(),
"FormattedTextFieldUI");
addStates(this, formattedTextField, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(formattedTextField);
UIComponent passwordField =
new UIComponent("PasswordField", JPasswordField.class.getName(), "PasswordFieldUI");
addStates(this, passwordField, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(passwordField);
UIComponent textArea =
new UIComponent("TextArea", JTextArea.class.getName(), "TextAreaUI");
addStates(this, textArea, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(textArea);
UIComponent textPane =
new UIComponent("TextPane", JTextPane.class.getName(), "TextPaneUI");
addStates(this, textPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(textPane);
UIComponent editorPane =
new UIComponent("EditorPane", JEditorPane.class.getName(), "EditorPaneUI");
addStates(this, editorPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(editorPane);
/*
* The only thing not represented in Synth as a region. I suppose we'll have
* to make it a CustomUIComponent
*/
// UIComponent titledBorder = new UIComponent ("TitledBorder",
// list(DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
UIComponent toolBar = new UIComponent("ToolBar", JToolBar.class.getName(), "ToolBarUI");
addStates(this, toolBar, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//toolBarContent, toolBarDragWindow, toolBarSeparator sub regions
components.add(toolBar);
UIComponent toolTip = new UIComponent("ToolTip", JToolTip.class.getName(), "ToolTipUI");
addStates(this, toolTip, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(toolTip);
//tooltip manager
UIComponent tree = new UIComponent("Tree", JTree.class.getName(), "TreeUI");
addStates(this, tree, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
//treeCell sub region
components.add(tree);
UIComponent rootPane =
new UIComponent("RootPane", JRootPane.class.getName(), "RootPaneUI");
addStates(this, rootPane, DISABLED, ENABLED, FOCUSED, MOUSE_OVER, PRESSED);
components.add(rootPane);
}
}
public List<UIPaint> getColorPalette() {
return colors;
}
public List<UIFont> getFontPalette() {
return fonts;
}
public List<UIInsets> getInsetPalette() {
return insets;
}
public List<UIBorder> getBorderPalette() {
return borders;
}
public List<UIDimension> getDimensionPalette() {
return dimensions;
}
public List<UIIcon> getIconPalette() {
return icons;
}
public List<UIComponent> getComponents() {
return components;
}
/**
* Get the local UIDefaults that contains all the UIDefaults in this synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*
* @return The UIDefaults for the synth model
*/
public UIDefaults getUiDefaults() {
return modelDefaults;
}
public UIStyle getStyle() {
return globalStyle;
}
// by default there are no painters assigned to the various states
private static void addStates(SynthModel model, UIRegion parentRegion, int... states) {
for (int state : states) {
List<String> stateList = new ArrayList<String>();
if ((state & ENABLED) != 0) {
stateList.add(UIStateType.ENABLED_KEY);
}
if ((state & MOUSE_OVER) != 0) {
stateList.add(UIStateType.MOUSE_OVER_KEY);
}
if ((state & PRESSED) != 0) {
stateList.add(UIStateType.PRESSED_KEY);
}
if ((state & DISABLED) != 0) {
stateList.add(UIStateType.DISABLED_KEY);
}
if ((state & FOCUSED) != 0) {
stateList.add(UIStateType.FOCUSED_KEY);
}
if ((state & SELECTED) != 0) {
stateList.add(UIStateType.SELECTED_KEY);
}
if ((state & DEFAULT) != 0) {
stateList.add(UIStateType.DEFAULT_KEY);
}
parentRegion.addBackgroundState(new UIState(model, parentRegion, stateList.toArray(new String[stateList.size()])));
}
}
public File getResourcesDir() {
return resourcesDir;
}
public void setResourcesDir(File resourcesDir) {
System.out.println("SynthModel.setResourcesDir(" + resourcesDir + ")");
File old = getResourcesDir();
this.resourcesDir = resourcesDir;
firePropertyChange("resourcesDir", old, getResourcesDir());
}
public File getImagesDir() {
return imagesDir;
}
public void setImagesDir(File imagesDir) {
System.out.println("SynthModel.setImagesDir(" + imagesDir + ")");
File old = getImagesDir();
this.imagesDir = imagesDir;
firePropertyChange("imagesDir", old, getImagesDir());
}
public File getTemplatesDir() {
return templatesDir;
}
public void setTemplatesDir(File templatesDir) {
System.out.println("SynthModel.setTemplatesDir(" + templatesDir + ")");
File old = getTemplatesDir();
this.templatesDir = templatesDir;
firePropertyChange("templatesDir", old, getTemplatesDir());
}
// =================================================================================================================
// JIBX Methods
public void preSet(IUnmarshallingContext context) {
File resourcesDir = (File) context.getUserContext();
this.resourcesDir = resourcesDir;
this.imagesDir = new File(resourcesDir, "images");
this.templatesDir = new File(resourcesDir, "templates");
}
}

View File

@ -0,0 +1,181 @@
<?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>
<mapping class="org.jdesktop.synthdesigner.synthmodel.UIDefault" abstract="true" post-set="postSet">
<value name="name" field="name" style="attribute"/>
</mapping>
<!-- == AWT TYPES =========================================================================================== -->
<mapping class="java.awt.Color"
marshaller="org.jdesktop.swingx.designer.jibxhelpers.ColorMapper"
unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.ColorMapper"/>
<mapping class="java.lang.Class"
marshaller="org.jdesktop.synthdesigner.synthmodel.jibxhelpers.ClassMapper"
unmarshaller="org.jdesktop.synthdesigner.synthmodel.jibxhelpers.ClassMapper"/>
<!-- == UI FONT =========================================================================================== -->
<mapping name="typeface" class="org.jdesktop.swingx.designer.font.Typeface" post-set="postSet">
<value name="family" field="name" style="attribute" usage="optional"/>
<value name="bold" field="bold" style="attribute" usage="optional" default="Default"/>
<value name="italic" field="italic" style="attribute" usage="optional" default="Default"/>
<value name="size" field="size" style="attribute" usage="optional"/>
<value name="sizeOffset" field="sizeOffset" style="attribute" usage="optional" default="1"/>
<value name="uiDefaultParentName" field="uiDefaultParentName" style="attribute" usage="optional"/>
</mapping>
<mapping name="uiFont" class="org.jdesktop.synthdesigner.synthmodel.UIFont"
extends="org.jdesktop.synthdesigner.synthmodel.UIDefault">
<structure map-as="org.jdesktop.synthdesigner.synthmodel.UIDefault"/>
<collection get-method="getFonts" set-method="setFonts" create-type="java.util.ArrayList"/>
</mapping>
<!-- == UI INSETS =========================================================================================== -->
<mapping name="uiInsets" class="org.jdesktop.synthdesigner.synthmodel.UIInsets"
extends="org.jdesktop.synthdesigner.synthmodel.UIDefault">
<structure map-as="org.jdesktop.synthdesigner.synthmodel.UIDefault"/>
<structure name="insets" get-method="getInsets" set-method="setInsets"
marshaller="org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper"
unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper"/>
</mapping>
<!-- == UI PAINT =========================================================================================== -->
<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.synthdesigner.synthmodel.UIPaint" abstract="true" type-name="uipaint"
extends="org.jdesktop.synthdesigner.synthmodel.UIDefault">
<structure map-as="org.jdesktop.synthdesigner.synthmodel.UIDefault"/>
<structure get-method="getPaint" set-method="setPaint"/>
</mapping>
<mapping name="uiPaint" class="org.jdesktop.synthdesigner.synthmodel.UIPaint"
extends="org.jdesktop.synthdesigner.synthmodel.UIDefault">
<structure map-as="uipaint"/>
</mapping>
<mapping name="uiColor" class="org.jdesktop.synthdesigner.synthmodel.UIColor"
extends="org.jdesktop.synthdesigner.synthmodel.UIPaint">
<structure map-as="uipaint"/>
</mapping>
<!-- == UI STYLE =========================================================================================== -->
<mapping class="org.jdesktop.synthdesigner.synthmodel.UIStyle" abstract="true" post-set="postSet">
<structure field="font" usage="optional"/>
<structure name="textForeground" usage="optional">
<structure field="textForeground" usage="optional"/>
</structure>
<structure name="textBackground" usage="optional">
<structure field="textBackground" usage="optional"/>
</structure>
<structure name="background" usage="optional">
<structure field="background" usage="optional"/>
</structure>
<value name="inherit-font" field="fontInherited" usage="optional" default="true"/>
<value name="inherit-textForeground" field="textForegroundInherited" usage="optional" default="true"/>
<value name="inherit-textBackground" field="textBackgroundInherited" usage="optional" default="true"/>
<value name="inherit-background" field="backgroundInherited" usage="optional" default="true"/>
<value name="hintAlphaInterpolation" field="hintAlphaInterpolation" usage="optional"/>
<value name="hintAntialiasing" field="hintAntialiasing" usage="optional"/>
<value name="hintColorRendering" field="hintColorRendering" usage="optional"/>
<value name="hintDithering" field="hintDithering" usage="optional"/>
<value name="hintFractionalMetrics" field="hintFractionalMetrics" usage="optional"/>
<value name="hintInterpolation" field="hintInterpolation" usage="optional"/>
<value name="hintRendering" field="hintRendering" usage="optional"/>
<value name="hintStrokeControl" field="hintStrokeControl" usage="optional"/>
<value name="hintTextAntialiasing" field="hintTextAntialiasing" usage="optional"/>
<value name="cacheSettingsInherited" field="cacheSettingsInherited" usage="optional" default="true"/>
<value name="cacheMode" field="cacheMode" usage="optional" default="FIXED_SIZES"/>
<value name="maxHozCachedImgScaling" field="maxHozCachedImgScaling" usage="optional" default="1"/>
<value name="maxVertCachedImgScaling" field="maxVertCachedImgScaling" usage="optional" default="1"/>
<collection name="uiproperties" field="uiProperties" create-type="java.util.ArrayList">
<structure marshaller="org.jdesktop.synthdesigner.synthmodel.jibxhelpers.UIPropertyMapper"
unmarshaller="org.jdesktop.synthdesigner.synthmodel.jibxhelpers.UIPropertyMapper"/>
</collection>
</mapping>
<!-- == UI STATE =========================================================================================== -->
<mapping name="stateType" class="org.jdesktop.synthdesigner.synthmodel.UIStateType">
<value name="key" field="key" style="attribute"/>
<structure name="codeSnippet" usage="optional" test-method="hasCodeSnippet">
<value field="codeSnippet" style="cdata" usage="optional"/>
</structure>
</mapping>
<mapping name="state" class="org.jdesktop.synthdesigner.synthmodel.UIState" post-set="postSet" pre-set="preSet">
<value name="stateKeys" field="stateKeys" style="attribute" get-method="getStateKeys" set-method="setStateKeys"
serializer="org.jdesktop.synthdesigner.synthmodel.UIState.keysToString"
deserializer="org.jdesktop.synthdesigner.synthmodel.UIState.stringToKeys"/>
<value name="inverted" field="inverted" style="attribute" usage="optional"/>
<structure name="style" field="style"/>
<structure field="canvas"
marshaller="org.jdesktop.swingx.designer.jibxhelpers.CanvasMapper"
unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.CanvasMapper"/>
</mapping>
<!-- == REGIONS =========================================================================================== -->
<mapping class="org.jdesktop.synthdesigner.synthmodel.UIRegion" abstract="true"
type-name="region" pre-set="preSet">
<value name="name" field="name" style="attribute"/>
<value name="ui" field="ui" style="attribute" usage="optional"/>
<value name="subregion" field="subregion" style="attribute"/>
<value name="key" field="key" style="attribute" usage="optional"/>
<value name="title" field="title" style="attribute" usage="optional"/>
<structure name="contentMargins" field="contentMargins"
marshaller="org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper"
unmarshaller="org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper"/>
<structure name="style" field="style"/>
<collection name="backgroundStates" field="backgroundStates" create-type="java.util.ArrayList"/>
<collection name="foregroundStates" field="foregroundStates" create-type="java.util.ArrayList"/>
<collection name="borderStates" field="borderStates" create-type="java.util.ArrayList"/>
<collection name="regions" field="subRegions" create-type="java.util.ArrayList"/>
</mapping>
<mapping name="region" class="org.jdesktop.synthdesigner.synthmodel.UIRegion">
<structure map-as="region"/>
</mapping>
<mapping name="uiIconRegion" class="org.jdesktop.synthdesigner.synthmodel.UIIconRegion"
extends="org.jdesktop.synthdesigner.synthmodel.UIRegion">
<structure map-as="region"/>
<value name="basicKey" field="basicKey" style="attribute" usage="optional"/>
</mapping>
<mapping name="uiComponent" class="org.jdesktop.synthdesigner.synthmodel.UIComponent"
extends="org.jdesktop.synthdesigner.synthmodel.UIRegion">
<value name="opaque" field="opaque" style="attribute"/>
<value name="componentName" field="componentName" style="attribute" usage="optional"/>
<value name="type" field="type" style="attribute"/>
<collection name="stateTypes" field="stateTypes" create-type="java.util.ArrayList"/>
<structure map-as="region"/>
</mapping>
<!-- == BASE MODEL =========================================================================================== -->
<mapping name="synthModel" class="org.jdesktop.synthdesigner.synthmodel.SynthModel" pre-set="preSet">
<collection name="insets" field="insets" create-type="java.util.ArrayList"/>
<collection name="colors" field="colors" create-type="java.util.ArrayList"/>
<collection name="fonts" field="fonts" create-type="java.util.ArrayList"/>
<structure name="style" field="globalStyle"/>
<collection name="components" field="components" create-type="java.util.ArrayList"/>
</mapping>
</binding>

View File

@ -0,0 +1,53 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import javax.swing.border.Border;
/**
* UIBorder
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIBorder extends UIDefault<Border> {
public UIBorder() {
}
public UIBorder(String id, Border b) {
super(id, b);
}
public Border getBorder() {
return super.getValue();
}
public void setBorder(Border b) {
Border old = getBorder();
super.setValue(b);
firePropertyChange("border", old, b);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.swingx.designer.paint.Matte;
import javax.swing.UIDefaults;
import java.awt.Color;
/**
* UIColor
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIColor extends UIPaint {
public UIColor() {
}
public UIColor(String id, Matte value) {
super(id, value);
}
public UIColor(String id, Color color, UIDefaults modelDefaults) {
this(id, new Matte(color, modelDefaults));
}
public Matte getPaint() {
return (Matte) super.getPaint();
}
public void setPaint(Matte c) {
super.setPaint(c);
}
}

View File

@ -0,0 +1,138 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.swingx.designer.utils.HasUIDefaults;
import java.util.List;
import java.util.ArrayList;
/**
* UIComponent - model node that represents the designs for a single swing component
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIComponent extends UIRegion implements HasUIDefaults {
/** The classname of the swing component that this UIComponent represents */
private String type;
/** The name of the component if its a named component or null if its a generic component */
private String componentName = null;
/** If this components is opaque which means that when it is painted all of its bounds are filled */
private boolean opaque = false;
/**
* A list of state types that are available to this region and sub regions of this component but not subcomponents
* of this component. If this list is empty then the standard synth set of state types are assumed.
*/
private List<UIStateType> stateTypes;
// =================================================================================================================
// Contructors
/** no-args contructor for JIBX */
protected UIComponent() {
super();
// create new observable list for state types so we get events for when the model changes
stateTypes = new ArrayList<UIStateType>();
}
public UIComponent(String name, String type, String ui, UIRegion... subRegions) {
super(name, ui, subRegions);
this.type = type;
for (UIRegion r : subRegions) {
r.setRegion(this);
}
// create new observable list for state types so we get events for when the model changes
stateTypes = new ArrayList<UIStateType>();
}
// =================================================================================================================
// Bean Methods
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
String old = getComponentName();
this.componentName = componentName;
firePropertyChange("componentName", old, getComponentName());
}
public boolean isOpaque() {
return opaque;
}
public void setOpaque(boolean opaque) {
boolean old = isOpaque();
this.opaque = opaque;
firePropertyChange("opaque", old, isOpaque());
}
public String getType() {
return type;
}
public void setType(String type) {
String old = getType();
this.type = type;
firePropertyChange("type", old, getType());
}
/**
* Get the list of state types that are available to this region and sub regions of this component but not
* subcomponents of this component. If this list is empty then the standard synth set of state types are assumed.
*
* @return List of available state types
*/
public List<UIStateType> getStateTypes() {
return stateTypes;
}
@Override public String getKey() {
if (key == null || "".equals(key)) {
if (componentName == null || "".equals(componentName)) {
return getName();
} else {
return "\"" + componentName + "\"";
}
} else {
return key;
}
}
@Override public String getTitle() {
if (title == null || "".equals(title)) {
if (componentName == null || "".equals(componentName)) {
return getName();
} else {
return componentName;
}
} else {
return title;
}
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
import org.jdesktop.swingx.designer.utils.HasUIDefaults;
import org.jibx.runtime.IUnmarshallingContext;
import javax.swing.UIDefaults;
/**
* Represents an entry in the UI defaults table.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIDefault<T> extends AbstractBean implements HasUIDefaults {
private String name;
private T value;
/**
* This is a local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*/
private transient UIDefaults modelDefaults = null;
public UIDefault() {
}
public UIDefault(String name, T value) {
this.name = name;
this.value = value;
}
public UIDefault(String name, T value, UIDefaults modelDefaults) {
this.name = name;
this.value = value;
this.modelDefaults = modelDefaults;
}
// =================================================================================================================
// JIBX Methods
/**
* Called by JIBX after all fields have been set
*
* @param context The JIBX Unmarshalling Context
*/
private void postSet(IUnmarshallingContext context) {
// walk up till we get synth model
for (int i = 0; i < context.getStackDepth(); i++) {
if (context.getStackObject(i) instanceof HasUIDefaults) {
modelDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults();
if (modelDefaults != null) break;
}
}
}
// =================================================================================================================
// Bean Methods
/**
* Get the local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*
* @return The UIDefaults for the synth model
*/
public UIDefaults getUiDefaults() {
return modelDefaults;
}
public void setValue(T t) {
T old = this.value;
this.value = t;
firePropertyChange("value", old, getValue());
}
public T getValue() {
return value;
}
public final String getName() {
return name;
}
public void setName(String name) {
String old = this.name;
firePropertyChange("name", old, name);
this.name = name;
// update model defaults
if (old != null) modelDefaults.remove(old);
modelDefaults.put(getName(), getValue());
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import java.awt.Dimension;
/**
* UIDimension
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIDimension extends UIDefault<Dimension> {
public UIDimension() {
}
public Dimension getDimension() {
return super.getValue();
}
public void setDimension(Dimension d) {
Dimension old = getDimension();
super.setValue(d);
firePropertyChange("dimension", old, d);
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import java.awt.Font;
import org.jdesktop.swingx.designer.font.Typeface;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import javax.swing.UIDefaults;
/**
* Represents a single font entry in the UIDefaults table. Each UIFont takes a
* list of Typefaces. These typefaces are listed by order of preference. Thus,
* when putting a font into UIDefaults, the code can check whether each font
* exists, and when it finds the first font that does, insert it.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIFont extends UIDefault<List<Typeface>> implements Cloneable {
private void updateUIDefaults() {
if (getUiDefaults() != null) {
for (Typeface t : getFonts()) {
if (t.isFontSupported()) {
getUiDefaults().put(getName(), t.getFont());
return;
}
}
}
//TODO must not have found any. Default to the Default platform font
getUiDefaults().put(getName(), new Font("Arial", Font.PLAIN, 12));
}
public UIFont() {
setValue(new ArrayList<Typeface>());
}
public UIFont(String id, List<Typeface> values, UIDefaults defaults) {
super(id, values, defaults);
updateUIDefaults();
}
public UIFont(String id, Font font, UIDefaults modelDefaults) {
this(id, Arrays.asList(new Typeface(font, modelDefaults)), modelDefaults);
}
public List<Typeface> getFonts() {
return super.getValue();
}
private void setFonts(List<Typeface> values) {
super.setValue(values);
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import javax.swing.Icon;
/**
* UIIcon
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIIcon extends UIDefault<Icon> {
public UIIcon() {
}
public Icon getIcon() {
return super.getValue();
}
public void setIcon(Icon i) {
Icon old = getIcon();
super.setValue(i);
firePropertyChange("icon", old, i);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
/**
* A UIRegion subclass which is used for generating icons. For example, JRadioButton and JCheckBox represent themselves
* mainly via their icons. However, from the designers perspective, the main design isn't an "icon", but just a region
* on the button.
* <p/>
* That type of region is represented by a UIIconRegion. UIIconRegion contains a string which references the UIDefault
* value associated with this icon. For example, RadioButton.icon.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIIconRegion extends UIRegion {
/** The UiDefaults key which this icon should be stored for basic LaF to find it. This is absolute */
private String basicKey = null;
public UIIconRegion() {
super();
}
public String getBasicKey() {
return basicKey;
}
public void setBasicKey(String basicKey) {
String old = getBasicKey();
this.basicKey = basicKey;
firePropertyChange("basicKey",old,getBasicKey());
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import java.awt.Insets;
/**
* UIInsets
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIInsets extends UIDefault<Insets> {
public UIInsets() {
}
public UIInsets(String id, Insets value) {
super(id, value);
}
public Insets getInsets() {
return super.getValue();
}
public void setInsets(Insets i) {
Insets old = getInsets();
super.setValue(i);
firePropertyChange("insets", old, i);
// update model defaults
getUiDefaults().put(getName(), i);
}
public String toString() {
return "UiInset(" + getName() + ")" +
((getInsets() == null) ? " NONE" : "(" + getInsets().top + "," + getInsets().left + "," +
getInsets().bottom + "," + getInsets().right + ")");
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.swingx.designer.paint.Matte;
import org.jdesktop.swingx.designer.paint.PaintModel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
* UIPaint
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIPaint extends UIDefault<PaintModel> {
/** Listener to keep model UiDefaults up to date for this UiPaint */
private PropertyChangeListener matteListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
PaintModel paintModel = getValue();
if (paintModel instanceof Matte) {
getUiDefaults().put(getName(), ((Matte) paintModel).getColor());
}
// propogate the paint change up as PaintModel is a mutable object
if (evt.getPropertyName().equals("paint")) {
firePropertyChange("paint", null, getPaint());
firePropertyChange("value", null, getPaint());
}
}
};
public UIPaint() {}
public UIPaint(String id, PaintModel value) {
super(id, value, (value instanceof Matte) ? ((Matte) value).getUiDefaults() : null);
// update model defaults
if (value instanceof Matte) {
Matte matte = (Matte) value;
if (getUiDefaults() != null) getUiDefaults().put(getName(), matte.getColor());
matte.addPropertyChangeListener(matteListener);
}
}
public PaintModel getPaint() {
return super.getValue();
}
public void setPaint(PaintModel c) {
PaintModel old = getPaint();
if (old instanceof Matte) old.removePropertyChangeListener(matteListener);
super.setValue(c);
firePropertyChange("paint", old, c);
// update model defaults
if (c instanceof Matte) {
Matte matte = (Matte) c;
getUiDefaults().put(getName(), matte.getColor());
matte.addPropertyChangeListener(matteListener);
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
/**
* UIProperty
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIProperty extends AbstractBean {
public static enum PropertyType {
BOOLEAN, INT, FLOAT, DOUBLE, STRING, FONT, COLOR, INSETS, DIMENSION, BORDER
}
private String name;
private PropertyType type;
private Object value;
protected UIProperty() {
}
public UIProperty(String name, PropertyType type, Object value) {
this.name = name;
this.type = type;
this.value = value;
}
// =================================================================================================================
// Bean Methods
public String getName() {
return name;
}
public void setName(String name) {
String old = getName();
this.name = name;
firePropertyChange("name", old, getName());
}
public PropertyType getType() {
return type;
}
public void setType(PropertyType type) {
PropertyType old = getType();
this.type = type;
firePropertyChange("type", old, getType());
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
Object old = getValue();
this.value = value;
firePropertyChange("value", old, getValue());
}
}

View File

@ -0,0 +1,253 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
import org.jdesktop.swingx.designer.utils.HasUIDefaults;
import org.jibx.runtime.IUnmarshallingContext;
import javax.swing.UIDefaults;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.ArrayList;
/**
* Represents a "Region" in synth, which also includes entire components.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIRegion extends AbstractBean implements HasUIDefaults, HasUIStyle {
private String name;//the code-wise name of the region
protected String key; //the UIdefaults key for this region
protected String title; //the user friendly name/title of this region
/** List of background states */
private List<UIState> backgroundStates;
/** List of foreground states */
private List<UIState> foregroundStates;
/** List of border states */
private List<UIState> borderStates;
private UIStyle style = new UIStyle();
protected Insets contentMargins = new Insets(0, 0, 0, 0);
/** Sub regions, if any */
private List<UIRegion> subRegions;
//together with name, these two fields allow me to reconstruct, in
//code, a synth Region, including a custom Region, if you make one.
private String ui;
private boolean subregion;
/**
* This is a local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*/
private transient UIDefaults modelDefaults = null;
private UIRegion region; //the region that this region belongs to
// =================================================================================================================
// Constructors
/** no-args contructor for JIBX */
protected UIRegion() {
subRegions = new ArrayList<UIRegion>();
backgroundStates = new ArrayList<UIState>();
foregroundStates = new ArrayList<UIState>();
borderStates = new ArrayList<UIState>();
style.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("style." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
});
}
public UIRegion(String name, UIRegion... subRegions) {
this(name, null, true, subRegions);
}
public UIRegion(String name, String ui, UIRegion... subRegions) {
this(name, ui, false, subRegions);
}
public UIRegion(String name, String ui, boolean subregion, UIRegion... subRegions) {
this();
this.name = name;
this.ui = ui;
this.subregion = subregion;
if (subRegions != null) {
for (UIRegion r : subRegions) {
if (r != null) {
this.subRegions.add(r);
r.getStyle().setParentStyle(getStyle());
}
}
}
}
// =================================================================================================================
// JIBX Methods
/**
* Called by JIBX after all fields have been set
*
* @param context The JIBX Unmarshalling Context
*/
private void preSet(IUnmarshallingContext context) {
// walk up till we get synth model
for (int i = 0; i < context.getStackDepth(); i++) {
if (context.getStackObject(i) instanceof HasUIDefaults) {
modelDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults();
if (modelDefaults != null) break;
}
}
for (int i = 0; i < context.getStackDepth(); i++) {
if (context.getStackObject(i) instanceof UIRegion && context.getStackObject(i) != this) {
region = (UIRegion) context.getStackObject(i);
break;
}
}
}
// =================================================================================================================
// Bean Methods
public Insets getContentMargins() {
return contentMargins;
}
public void setContentMargins(Insets contentMargins) {
Insets old = getContentMargins();
this.contentMargins = contentMargins;
firePropertyChange("contentMargins", old, getContentMargins());
}
void setRegion(UIRegion r) {
this.region = r;
}
public UIRegion getRegion() {
return region;
}
/**
* Get the local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*
* @return The UIDefaults for the synth model
*/
public UIDefaults getUiDefaults() {
return modelDefaults;
}
public String getName() {
return name;
}
public final UIRegion[] getSubRegions() {
return subRegions.toArray(new UIRegion[0]);
}
public final UIState[] getBackgroundStates() {
return backgroundStates.toArray(new UIState[0]);
}
public final UIState[] getForegroundStates() {
return foregroundStates.toArray(new UIState[0]);
}
public final UIState[] getBorderStates() {
return borderStates.toArray(new UIState[0]);
}
public UIStyle getStyle() {
return style;
}
public final boolean isSubRegion() {
return subregion;
}
public final String getUi() {
return ui;
}
public void addBackgroundState(UIState state) {
// check if we already have that state
for (UIState uiState : backgroundStates) {
if (uiState.getName().equals(state.getName())) return;
}
backgroundStates.add(state);
state.setRegion(this);
firePropertyChange("backgroundStates", null, backgroundStates);
}
public void removeBackgroundState(UIState state) {
if (backgroundStates.remove(state)) {
firePropertyChange("backgroundStates", null, backgroundStates);
}
}
public void addForegroundState(UIState state) {
// check if we already have that state
for (UIState uiState : foregroundStates) {
if (uiState.getName().equals(state.getName())) return;
}
foregroundStates.add(state);
state.setRegion(this);
firePropertyChange("foregroundStates", null, foregroundStates);
}
public void removeForegroundState(UIState state) {
if (foregroundStates.remove(state)) {
firePropertyChange("foregroundStates", null, foregroundStates);
}
}
public void addBorderState(UIState state) {
// check if we already have that state
for (UIState uiState : borderStates) {
if (uiState.getName().equals(state.getName())) return;
}
borderStates.add(state);
state.setRegion(this);
firePropertyChange("borderStates", null, borderStates);
}
public void removeBorderState(UIState state) {
if (borderStates.remove(state)) {
firePropertyChange("borderStates", null, borderStates);
}
}
public String getKey() {
return key == null || "".equals(key) ? name : key;
}
public String getTitle() {
return title == null || "".equals(title) ? name : title;
}
}

View File

@ -0,0 +1,298 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
import org.jdesktop.swingx.designer.Canvas;
import org.jdesktop.swingx.designer.utils.HasPath;
import org.jdesktop.swingx.designer.utils.HasUIDefaults;
import org.jibx.runtime.IUnmarshallingContext;
import javax.swing.UIDefaults;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Represents a State in the Synth LAF.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIState extends AbstractBean implements HasUIStyle, HasPath {
private List<String> stateKeys;
private boolean inverted; //indicates whether to invert the meaning of the 9-square stretching insets
/** A cached string representing the list of stateKeys deliminated with "+" */
private String cachedName = null;
private Canvas canvas;
private UIStyle style;
/** the region that this state belongs to */
private UIRegion region;
/**
* This is a local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*/
private transient UIDefaults modelDefaults = null;
// =================================================================================================================
// Contructors
public UIState() {
// Create state keys as event list so model changes are propogated
stateKeys = new ArrayList<String>();
}
public UIState(SynthModel model, UIRegion parentRegion, String... stateTypeKeys) {
// Create state keys as event list so model changes are propogated
stateKeys = new ArrayList<String>();
this.stateKeys.addAll(Arrays.asList(stateTypeKeys));
//
modelDefaults = model.getUiDefaults();
region = parentRegion;
// create new canvas
canvas = new Canvas(100, 30);
canvas.setUiDefaults(modelDefaults);
String canvasPath = getPath();
canvas.setResourcesDir(new File(model.getResourcesDir(), canvasPath));
canvas.setTemplatesDir(new File(model.getTemplatesDir(), canvasPath));
canvas.setImagesDir(new File(model.getImagesDir(), canvasPath));
canvas.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("canvas." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
});
// create new style
style = new UIStyle();
style.setParentStyle(region.getStyle());
style.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("style." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
});
}
// =================================================================================================================
// JIBX Methods
/**
* JIBX needs this
*
* @param stateKeys The new list of states
*/
private void setStateKeys(List<String> stateKeys) {
if (stateKeys != this.stateKeys) {
this.stateKeys.clear();
this.stateKeys.addAll(stateKeys);
}
}
/**
* Called by JIBX after all fields have been set
*
* @param context The JIBX Unmarshalling Context
*/
private void preSet(IUnmarshallingContext context) {
// walk up till we get synth model
for (int i = 0; i < context.getStackDepth(); i++) {
if (context.getStackObject(i) instanceof HasUIDefaults) {
modelDefaults = ((HasUIDefaults) context.getStackObject(i)).getUiDefaults();
if (modelDefaults != null) break;
}
}
for (int i = 0; i < context.getStackDepth(); i++) {
if (context.getStackObject(i) instanceof UIRegion) {
region = (UIRegion) context.getStackObject(i);
break;
}
}
}
/**
* Called by JIBX after all fields have been set
*
* @param context The JIBX Unmarshalling Context
*/
private void postSet(IUnmarshallingContext context) {
// add listeners to pass canvas and style events up tree
canvas.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("canvas." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
});
style.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("style." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
});
}
// =================================================================================================================
// Bean Methods
/**
* Get path to this UI State of the form /RegionA/RegionB/StateName
*
* @return Path to this state
*/
public String getPath() {
StringBuilder buf = new StringBuilder(getName());
UIRegion region = getRegion();
// check if we are foreground background or border
boolean found = false;
for (UIState state : region.getBackgroundStates()) {
if (state == this) {
buf.insert(0, "Background/");
found = true;
break;
}
}
if (!found) {
for (UIState state : region.getForegroundStates()) {
if (state == this) {
buf.insert(0, "Foreground/");
found = true;
break;
}
}
}
if (!found) {
for (UIState state : region.getBorderStates()) {
if (state == this) {
buf.insert(0, "Border/");
found = true;
break;
}
}
}
// add parent regions
while (region != null) {
buf.insert(0, '/');
if (region instanceof UIComponent && ((UIComponent) region).getComponentName() != null) {
buf.insert(0, ((UIComponent) region).getComponentName());
} else {
buf.insert(0, region.getName());
}
region = region.getRegion();
}
return buf.toString();
}
void setRegion(UIRegion r) {
this.region = r;
this.style.setParentStyle(r.getStyle());
}
public UIRegion getRegion() {
return region;
}
/**
* Get the local UIDefaults that contains all the UIDefaults in the synth model. It is kept uptodate by the
* indervidual UIDefaults nodes
*
* @return The UIDefaults for the synth model
*/
public UIDefaults getUIDefaults() {
return modelDefaults;
}
/**
* Get the list of state type keys for this state. This state is applied when the current component state matches as
* many as possible of these state types.
*
* @return List of state types that need to be true for this state. This is direct access to the data and changes to
* the returned list will effect this UiState.
*/
public List<String> getStateKeys() {
return stateKeys;
}
public void setInverted(boolean b) {
boolean old = inverted;
inverted = b;
firePropertyChange("invert", old, b);
}
public final boolean isInverted() {
return inverted;
}
/**
* Get the name of this state
*
* @return
*/
public String getName() {
if (cachedName == null) {
StringBuilder buf = new StringBuilder();
List<String> keys = new ArrayList<String>(stateKeys);
Collections.sort(keys);
for (Iterator<String> iter = keys.iterator(); iter.hasNext();) {
buf.append(iter.next());
if (iter.hasNext()) buf.append('+');
}
cachedName = buf.toString();
}
return cachedName;
}
public final Canvas getCanvas() {
return canvas;
}
public void setCanvas(Canvas c) {
Canvas old = canvas;
canvas = c;
firePropertyChange("canvas", old, c);
}
public UIStyle getStyle() {
return style;
}
// =================================================================================================================
// JIBX Helper Methods
public static String keysToString(List<String> keys) {
StringBuilder buf = new StringBuilder();
for (Iterator<String> iter = keys.iterator(); iter.hasNext();) {
buf.append(iter.next());
if (iter.hasNext()) buf.append('+');
}
return buf.toString();
}
public static List<String> stringToKeys(String keysString) {
return Arrays.asList(keysString.split("\\+"));
}
}

View File

@ -0,0 +1,129 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
/**
* UIStateType - A UIComponents has a collection of these which constitute the avilables states which can be chosen in
* the components regions. A UIStateType can be either a custom state or one of the predefined standard states.
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIStateType extends AbstractBean {
/* Keys for standard synth states */
public static final String ENABLED_KEY = "Enabled";
public static final String MOUSE_OVER_KEY = "MouseOver";
public static final String PRESSED_KEY = "Pressed";
public static final String DISABLED_KEY = "Disabled";
public static final String FOCUSED_KEY = "Focused";
public static final String SELECTED_KEY = "Selected";
public static final String DEFAULT_KEY = "Default";
public static final String[] STANDARD_SYNTH_STATE_KEYS = new String[]{
ENABLED_KEY, MOUSE_OVER_KEY, PRESSED_KEY, DISABLED_KEY, FOCUSED_KEY, SELECTED_KEY, DEFAULT_KEY
};
public static final UIStateType[] STANDARD_SYNTH_STATES = new UIStateType[]{
new UIStateType(ENABLED_KEY),
new UIStateType(MOUSE_OVER_KEY),
new UIStateType(PRESSED_KEY),
new UIStateType(DISABLED_KEY),
new UIStateType(FOCUSED_KEY),
new UIStateType(SELECTED_KEY),
new UIStateType(DEFAULT_KEY)
};
/** Unique string for the ui key for this state, must be unique within a components set of UiStateTypes */
private String key;
/**
* Snippet of java code that defines calculates the value of this state for a particular component. The varaiable
* <code>c</code> is the component. You end with a return statement returning boolean true/false for the current
* value of this state for this component. This can be null if the key is one of that standard synth states defined
* in constants in this class.
*/
private String codeSnippet;
/** JIBX no-args contructor */
private UIStateType() {}
private UIStateType(String key) {
this.key = key;
this.codeSnippet = null;
}
public UIStateType(String key, String codeSnippet) {
this.key = key;
this.codeSnippet = codeSnippet;
}
// =================================================================================================================
// Bean Methods
/**
* Get the ui defaults key for this state type. Unique string for the ui key for this state, must be unique within a
* components set of UiStateTypes.
*
* @return Unique ui default key
*/
public String getKey() {
return key;
}
/**
* Get the snippet of java code that defines calculates the value of this state for a particular component. The
* varaiable <code>c</code> is the component. You end with a return statement returning boolean true/false for the
* current value of this state for this component. This can be null if the key is one of that standard synth states
* defined in constants in this class.
*
* @return Snippet of java code or null if this is a synth standard state
*/
public String getCodeSnippet() {
return codeSnippet;
}
/**
* Set the snippet of java code that defines calculates the value of this state for a particular component. The
* varaiable <code>c</code> is the component. You end with a return statement returning boolean true/false for the
* current value of this state for this component. This can be null if the key is one of that standard synth states
* defined in constants in this class.
*
* @param codeSnippet Snippet of java code or null if this is a synth standard state
*/
public void setCodeSnippet(String codeSnippet) {
this.codeSnippet = codeSnippet;
}
/**
* Returns if this state type is a standard synth type and has no code snippet or a custom type that has a code
* snippet. It is used by JIBX to determin if the code snippet should be written to XML.
*
* @return <code>true</code> if codeSnippet is non null
*/
public boolean hasCodeSnippet() {
return codeSnippet != null;
}
}

View File

@ -0,0 +1,467 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel;
import org.jdesktop.beans.AbstractBean;
import org.jdesktop.swingx.designer.font.Typeface;
import org.jdesktop.swingx.designer.paint.Matte;
import org.jibx.runtime.IUnmarshallingContext;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.ArrayList;
/**
* UIStyle
*
* @author Richard Bair
* @author Jasper Potts
*/
public class UIStyle extends AbstractBean {
public static enum CacheMode {NO_CACHING,FIXED_SIZES,NINE_SQUARE_SCALE}
public static enum HintAlphaInterpolation {
DEFAULT, QUALITY, SPEED
}
public static enum HintAntialiasing {
DEFAULT, ON, OFF
}
public static enum HintColorRendering {
DEFAULT, QUALITY, SPEED
}
public static enum HintDithering {
DEFAULT, DISABLE, ENABLE
}
public static enum HintFractionalMetrics {
DEFAULT, ON, OFF
}
public static enum HintInterpolation {
NEAREST_NEIGHBOR, BILINEAR, BICUBIC
}
public static enum HintRendering {
DEFAULT, QUALITY, SPEED
}
public static enum HintStrokeControl {
DEFAULT, NORMALIZE, PURE
}
public static enum HintTextAntialiasing {
DEFAULT, ON, OFF, GASP, LCD_HBGR, LCD_HRGB, LCD_VBGR, LCD_VRGB
}
private Typeface font = null;
private boolean fontInherited = true;
private Matte textForeground = null;
private boolean textForegroundInherited = true;
private Matte textBackground = null;
private boolean textBackgroundInherited = true;
private Matte background = null;
private boolean backgroundInherited = true;
private boolean cacheSettingsInherited = true;
private CacheMode cacheMode = CacheMode.FIXED_SIZES;
private double maxHozCachedImgScaling = 1;
private double maxVertCachedImgScaling = 1;
private HintAlphaInterpolation hintAlphaInterpolation = null;
private HintAntialiasing hintAntialiasing = null;
private HintColorRendering hintColorRendering = null;
private HintDithering hintDithering = null;
private HintFractionalMetrics hintFractionalMetrics = null;
private HintInterpolation hintInterpolation = null;
private HintRendering hintRendering = null;
private HintStrokeControl hintStrokeControl = null;
private HintTextAntialiasing hintTextAntialiasing = null;
private List<UIProperty> uiProperties;
private UIStyle parentStyle = null;
private PropertyChangeListener textForegoundListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("textForeground." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
};
private PropertyChangeListener textBackgroundListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("textBackground." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
};
private PropertyChangeListener backgroundListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("background." + evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
};
// =================================================================================================================
// Constructors
public UIStyle() {
uiProperties = new ArrayList<UIProperty>();
}
// =================================================================================================================
// JIBX Methods
/**
* Called by JIBX after all fields have been set
*
* @param context The JIBX Unmarshalling Context
*/
private void postSet(IUnmarshallingContext context) {
// walk up till we get a parent style
for (int i = 0; i < context.getStackDepth(); i++) {
if (context.getStackObject(i) instanceof HasUIStyle) {
HasUIStyle hasStyle = (HasUIStyle) context.getStackObject(i);
if (hasStyle.getStyle() != this) {
parentStyle = hasStyle.getStyle();
if (parentStyle != null) break;
}
}
}
}
// =================================================================================================================
// Bean Methods
public UIStyle getParentStyle() {
return parentStyle;
}
public void setParentStyle(UIStyle parentStyle) {
UIStyle old = getParentStyle();
this.parentStyle = parentStyle;
firePropertyChange("parentStyle", old, getParentStyle());
}
public List<UIProperty> getUiProperties() {
return uiProperties;
}
public void addUiProperty(UIProperty uiProperty) {
uiProperties.add(uiProperty);
// todo not quite sure what events we want here
fireIndexedPropertyChange("uiProperties", uiProperties.size(), null, uiProperty);
// firePropertyChange("uiProperties", null, uiProperties);
}
public void removeUiProperty(UIProperty uiProperty) {
int index = uiProperties.indexOf(uiProperty);
if (index != -1) {
uiProperties.remove(uiProperty);
// todo not quite sure what events we want here
fireIndexedPropertyChange("uiProperties", index, null, uiProperty);
// firePropertyChange("uiProperties", null, uiProperties);
}
}
public Typeface getFont() {
if (isFontInherited()) {
return parentStyle == null ? font : parentStyle.getFont();
} else {
return font;
}
}
public void setFont(Typeface font) {
Typeface old = getFont();
this.font = font;
firePropertyChange("font", old, font);
}
public boolean isFontInherited() {
return fontInherited;
}
public void setFontInherited(boolean b) {
boolean old = isFontInherited();
fontInherited = b;
firePropertyChange("fontInherited", old, b);
if (!fontInherited && font == null && parentStyle != null && parentStyle.getFont() != null) {
font = parentStyle.getFont().clone();
firePropertyChange("font", null, font);
}
}
public Matte getTextForeground() {
if (isTextForegroundInherited()) {
return parentStyle == null ? null : parentStyle.getTextForeground();
} else {
return textForeground;
}
}
public boolean isTextForegroundInherited() {
return textForegroundInherited;
}
public void setTextForegroundInherited(boolean b) {
boolean old = isTextForegroundInherited();
textForegroundInherited = b;
firePropertyChange("foregroundInherited", old, b);
if (!textForegroundInherited && textForeground == null && parentStyle != null &&
parentStyle.getTextForeground() != null) {
textForeground = parentStyle.getTextForeground().clone();
firePropertyChange("textForeground", null, textForeground);
}
}
public void setTextForeground(Matte textForeground) {
Matte old = this.textForeground;
if (old != null) old.removePropertyChangeListener(textForegoundListener);
this.textForeground = textForeground;
if (this.textForeground != null) this.textForeground.addPropertyChangeListener(textForegoundListener);
firePropertyChange("textForeground", old, this.textForeground);
}
public Matte getTextBackground() {
if (isTextBackgroundInherited()) {
return parentStyle == null ? null : parentStyle.getBackground();
} else {
return textBackground;
}
}
public boolean isTextBackgroundInherited() {
return textBackgroundInherited;
}
public void setTextBackgroundInherited(boolean b) {
boolean old = isBackgroundInherited();
textBackgroundInherited = b;
firePropertyChange("textBackgroundInherited", old, b);
if (!textBackgroundInherited && textBackground == null && parentStyle != null &&
parentStyle.getTextBackground() != null) {
textBackground = parentStyle.getTextBackground().clone();
firePropertyChange("textBackground", null, textBackground);
}
}
public void setTextBackground(Matte textBackground) {
Matte old = this.textBackground;
if (old != null) old.removePropertyChangeListener(textBackgroundListener);
this.textBackground = textBackground;
if (this.textBackground != null) this.textBackground.addPropertyChangeListener(textBackgroundListener);
firePropertyChange("textBackground", old, this.textBackground);
}
public Matte getBackground() {
if (isBackgroundInherited()) {
return parentStyle == null ? null : parentStyle.getBackground();
} else {
return background;
}
}
public boolean isBackgroundInherited() {
return backgroundInherited;
}
public void setBackgroundInherited(boolean b) {
boolean old = isBackgroundInherited();
backgroundInherited = b;
firePropertyChange("backgroundInherited", old, b);
if (!backgroundInherited && background == null && parentStyle != null && parentStyle.getBackground() != null) {
background = parentStyle.getBackground().clone();
firePropertyChange("background", null, background);
}
}
public void setBackground(Matte background) {
Matte old = this.background;
if (old != null) old.removePropertyChangeListener(backgroundListener);
this.background = background;
if (this.background != null) this.background.addPropertyChangeListener(backgroundListener);
firePropertyChange("background", old, this.background);
}
public HintAlphaInterpolation getHintAlphaInterpolation() {
return hintAlphaInterpolation;
}
public void setHintAlphaInterpolation(HintAlphaInterpolation hintAlphaInterpolation) {
HintAlphaInterpolation old = getHintAlphaInterpolation();
this.hintAlphaInterpolation = hintAlphaInterpolation;
firePropertyChange("hintAlphaInterpolation", old, getHintAlphaInterpolation());
}
public HintAntialiasing getHintAntialiasing() {
return hintAntialiasing;
}
public void setHintAntialiasing(HintAntialiasing hintAntialiasing) {
HintAntialiasing old = getHintAntialiasing();
this.hintAntialiasing = hintAntialiasing;
firePropertyChange("hintAntialiasing", old, getHintAntialiasing());
}
public HintColorRendering getHintColorRendering() {
return hintColorRendering;
}
public void setHintColorRendering(HintColorRendering hintColorRendering) {
HintColorRendering old = getHintColorRendering();
this.hintColorRendering = hintColorRendering;
firePropertyChange("hintColorRendering", old, getHintColorRendering());
}
public HintDithering getHintDithering() {
return hintDithering;
}
public void setHintDithering(HintDithering hintDithering) {
HintDithering old = getHintDithering();
this.hintDithering = hintDithering;
firePropertyChange("hintDithering", old, getHintDithering());
}
public HintFractionalMetrics getHintFractionalMetrics() {
return hintFractionalMetrics;
}
public void setHintFractionalMetrics(HintFractionalMetrics hintFractionalMetrics) {
HintFractionalMetrics old = getHintFractionalMetrics();
this.hintFractionalMetrics = hintFractionalMetrics;
firePropertyChange("hintFractionalMetrics", old, getHintFractionalMetrics());
}
public HintInterpolation getHintInterpolation() {
return hintInterpolation;
}
public void setHintInterpolation(HintInterpolation hintInterpolation) {
HintInterpolation old = getHintInterpolation();
this.hintInterpolation = hintInterpolation;
firePropertyChange("hintInterpolation", old, getHintInterpolation());
}
public HintRendering getHintRendering() {
return hintRendering;
}
public void setHintRendering(HintRendering hintRendering) {
HintRendering old = getHintRendering();
this.hintRendering = hintRendering;
firePropertyChange("hintRendering", old, getHintRendering());
}
public HintStrokeControl getHintStrokeControl() {
return hintStrokeControl;
}
public void setHintStrokeControl(HintStrokeControl hintStrokeControl) {
HintStrokeControl old = getHintStrokeControl();
this.hintStrokeControl = hintStrokeControl;
firePropertyChange("hintStrokeControl", old, getHintStrokeControl());
}
public HintTextAntialiasing getHintTextAntialiasing() {
return hintTextAntialiasing;
}
public void setHintTextAntialiasing(HintTextAntialiasing hintTextAntialiasing) {
HintTextAntialiasing old = getHintTextAntialiasing();
this.hintTextAntialiasing = hintTextAntialiasing;
firePropertyChange("hintTextAntialiasing", old, getHintTextAntialiasing());
}
public boolean isCacheSettingsInherited() {
return cacheSettingsInherited;
}
public void setCacheSettingsInherited(boolean cacheSettingsInherited) {
boolean old = isCacheSettingsInherited();
this.cacheSettingsInherited = cacheSettingsInherited;
firePropertyChange("cacheSettingsInherited", old, isCacheSettingsInherited());
}
public CacheMode getCacheMode() {
if (isCacheSettingsInherited()) {
return (parentStyle == null)?CacheMode.FIXED_SIZES : parentStyle.getCacheMode();
} else {
return cacheMode;
}
}
public void setCacheMode(CacheMode cacheMode) {
CacheMode old = this.cacheMode;
this.cacheMode = cacheMode;
if (isCacheSettingsInherited()) {
setCacheSettingsInherited(false);
UIStyle parent = getParentStyle();
setMaxHozCachedImgScaling(parent == null ? 1 : parent.getMaxHozCachedImgScaling());
setMaxVertCachedImgScaling(parent == null ? 1 : parent.getMaxVertCachedImgScaling());
}
firePropertyChange("cacheMode",old,cacheMode);
}
public double getMaxHozCachedImgScaling() {
if (isCacheSettingsInherited()) {
return parentStyle == null ? 1 : parentStyle.getMaxHozCachedImgScaling();
} else {
return maxHozCachedImgScaling;
}
}
public void setMaxHozCachedImgScaling(double maxHozCachedImgScaling) {
double old = getMaxHozCachedImgScaling();
this.maxHozCachedImgScaling = maxHozCachedImgScaling;
if (isCacheSettingsInherited()) {
setCacheSettingsInherited(false);
setCacheMode((parentStyle == null)?CacheMode.FIXED_SIZES : parentStyle.getCacheMode());
setMaxVertCachedImgScaling(parentStyle == null ? 1 : parentStyle.getMaxVertCachedImgScaling());
}
firePropertyChange("maxHozCachedImgScaling", old, getMaxHozCachedImgScaling());
}
public double getMaxVertCachedImgScaling() {
if (isCacheSettingsInherited()) {
return parentStyle == null ? 1 : parentStyle.getMaxVertCachedImgScaling();
} else {
return maxVertCachedImgScaling;
}
}
public void setMaxVertCachedImgScaling(double maxVertCachedImgScaling) {
double old = getMaxVertCachedImgScaling();
this.maxVertCachedImgScaling = maxVertCachedImgScaling;
if (isCacheSettingsInherited()) {
setCacheSettingsInherited(false);
setCacheMode((parentStyle == null)?CacheMode.FIXED_SIZES : parentStyle.getCacheMode());
setMaxHozCachedImgScaling(parentStyle == null ? 1 : parentStyle.getMaxHozCachedImgScaling());
}
firePropertyChange("maxVertCachedImgScaling", old, getMaxVertCachedImgScaling());
}
}

View File

@ -0,0 +1,285 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel.jibxhelpers;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IAliasable;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.impl.MarshallingContext;
import org.jibx.runtime.impl.UnmarshallingContext;
import org.jdesktop.swingx.designer.jibxhelpers.ColorMapper;
import javax.swing.border.LineBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.BevelBorder;
import javax.swing.border.MatteBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.Border;
import javax.swing.BorderFactory;
import java.awt.Insets;
import java.awt.Color;
import org.jdesktop.synthdesigner.synthmodel.PainterBorder;
/**
* BorderMapper - JIBX xml mapper for swing standard borders
*
* @author Jasper Potts
*/
public class BorderMapper implements IMarshaller, IUnmarshaller, IAliasable {
private static enum BorderType {
empty, line, etched, bevel, matte, compound, painter
}
private static enum SubType {
raised(EtchedBorder.RAISED), lowered(EtchedBorder.LOWERED);
private int subtype;
SubType(int type) {
this.subtype = type;
}
public int getSubType() {
return subtype;
}
}
private static final String ELEMENT_NAME = "border";
private static final String TYPE_NAME = "type";
private static final String SUB_TYPE_NAME = "subtype";
private static final String TOP_NAME = "top";
private static final String BOTTOM_NAME = "bottom";
private static final String LEFT_NAME = "left";
private static final String RIGHT_NAME = "right";
private static final String THICKNESS_NAME = "thickness";
private static final String INSIDE_NAME = "inside";
private static final String OUTSIDE_NAME = "outside";
private static final String PAINTER_NAME = "painter";
private String uri;
private int index;
private String name;
public BorderMapper() {
uri = null;
index = 0;
name = ELEMENT_NAME;
}
public BorderMapper(String uri, int index, String name) {
this.uri = uri;
this.index = index;
this.name = name;
}
public boolean isExtension(int i) {
return false;
}
public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws
JiBXException {
return iUnmarshallingContext.isAt(uri, ELEMENT_NAME);
}
public void marshal(Object object, IMarshallingContext iMarshallingContext)
throws JiBXException {
if (!(iMarshallingContext instanceof MarshallingContext)) {
throw new JiBXException("Invalid object type for marshaller");
} else {
MarshallingContext ctx = (MarshallingContext) iMarshallingContext;
if (object instanceof PainterBorder) {
PainterBorder border = (PainterBorder) object;
Insets insets = border.getBorderInsets();
ctx.startTagAttributes(index, name)
.attribute(index, TYPE_NAME, BorderType.painter.toString())
.attribute(index, PAINTER_NAME, border.getPainterName())
.attribute(index, TOP_NAME, insets.top)
.attribute(index, BOTTOM_NAME, insets.bottom)
.attribute(index, LEFT_NAME, insets.left)
.attribute(index, RIGHT_NAME, insets.right)
.closeStartContent();
ctx.endTag(index, name);
} else if (object instanceof EmptyBorder) {
Insets insets = ((EmptyBorder) object).getBorderInsets();
ctx.startTagAttributes(index, name)
.attribute(index, TYPE_NAME,
BorderType.empty.toString())
.attribute(index, TOP_NAME, insets.top)
.attribute(index, BOTTOM_NAME, insets.bottom)
.attribute(index, LEFT_NAME, insets.left)
.attribute(index, RIGHT_NAME, insets.right)
.closeStartEmpty();
} else if (object instanceof LineBorder) {
LineBorder border = (LineBorder) object;
ctx.startTagAttributes(index, name).
attribute(index, TYPE_NAME, BorderType.line.toString()).
attribute(index, THICKNESS_NAME, border.getThickness()).
closeStartContent();
new ColorMapper().marshal(border.getLineColor(), ctx);
ctx.endTag(index, name);
} else if (object instanceof EtchedBorder) {
EtchedBorder border = (EtchedBorder) object;
ctx.startTagAttributes(index, name).
attribute(index, TYPE_NAME,
BorderType.etched.toString()).
attribute(index, SUB_TYPE_NAME,
border.getEtchType()==EtchedBorder.RAISED?
SubType.raised.toString():
SubType.lowered.toString()).
closeStartContent();
new ColorMapper().marshal(border.getHighlightColor(), ctx);
new ColorMapper().marshal(border.getShadowColor(), ctx);
ctx.endTag(index, name);
} else if (object instanceof BevelBorder) {
BevelBorder border = (BevelBorder) object;
ctx.startTagAttributes(index, name).
attribute(index, TYPE_NAME,
BorderType.bevel.toString()).
attribute(index, SUB_TYPE_NAME,
border.getBevelType()==BevelBorder.RAISED?
SubType.raised.toString():
SubType.lowered.toString()).
closeStartContent();
new ColorMapper().marshal(border.getHighlightInnerColor(), ctx);
new ColorMapper().marshal(border.getHighlightOuterColor(), ctx);
new ColorMapper().marshal(border.getShadowInnerColor(), ctx);
new ColorMapper().marshal(border.getHighlightOuterColor(), ctx);
ctx.endTag(index, name);
} else if (object instanceof MatteBorder) {
MatteBorder border = (MatteBorder) object;
Insets insets = ((EmptyBorder) object).getBorderInsets();
ctx.startTagAttributes(index, name)
.attribute(index, TYPE_NAME,
BorderType.matte.toString())
.attribute(index, TOP_NAME, insets.top)
.attribute(index, BOTTOM_NAME, insets.bottom)
.attribute(index, LEFT_NAME, insets.left)
.attribute(index, RIGHT_NAME, insets.right)
.closeStartContent();
new ColorMapper().marshal(border.getMatteColor(), ctx);
// todo: we should support tiled icons here to be 100% complete
ctx.endTag(index, name);
} else if (object instanceof CompoundBorder) {
CompoundBorder border = (CompoundBorder) object;
ctx.startTagAttributes(index, name)
.attribute(index, TYPE_NAME,
BorderType.compound.toString())
.closeStartContent();
new BorderMapper(null,0, INSIDE_NAME).marshal(border.getInsideBorder(),ctx);
new BorderMapper(null,0, OUTSIDE_NAME).marshal(border.getOutsideBorder(),ctx);
ctx.endTag(index, name);
} else {
throw new JiBXException("Invalid object type for marshaller");
}
}
}
public Object unmarshal(Object object,
IUnmarshallingContext iUnmarshallingContext)
throws JiBXException {
Border border = null;
// make sure we're at the appropriate start tag
UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext;
if (!ctx.isAt(uri, name)) {
ctx.throwStartTagNameError(uri, name);
}
// get type
BorderType type = BorderType.valueOf(ctx.attributeText(uri, TYPE_NAME)
.toLowerCase());
int top,bottom,left,right;
Color color;
switch(type){
case empty:
top = ctx.attributeInt(uri, TOP_NAME, index);
bottom = ctx.attributeInt(uri, BOTTOM_NAME, index);
left = ctx.attributeInt(uri, LEFT_NAME, index);
right = ctx.attributeInt(uri, RIGHT_NAME, index);
border = BorderFactory.createEmptyBorder(top,left,bottom,right);
break;
case line:
int thickness = ctx.attributeInt(uri, THICKNESS_NAME, index);
ctx.parsePastStartTag(uri,name);
color = (Color)new ColorMapper().unmarshal(null,ctx);
border = BorderFactory.createLineBorder(color,thickness);
break;
case etched:
SubType etchedType = SubType.valueOf(
ctx.attributeText(uri, SUB_TYPE_NAME).toLowerCase());
ctx.parsePastStartTag(uri,name);
Color highColor = (Color)new ColorMapper()
.unmarshal(null,ctx);
Color shadowColor = (Color)new ColorMapper()
.unmarshal(null,ctx);
border = BorderFactory.createEtchedBorder(
etchedType.getSubType(),highColor,shadowColor);
break;
case bevel:
SubType bevelType = SubType.valueOf(
ctx.attributeText(uri, SUB_TYPE_NAME).toLowerCase());
ctx.parsePastStartTag(uri,name);
Color innerHighColor = (Color)new ColorMapper()
.unmarshal(null,ctx);
Color outerHighColor = (Color)new ColorMapper()
.unmarshal(null,ctx);
Color innerShadowColor = (Color)new ColorMapper()
.unmarshal(null,ctx);
Color outerShadowColor = (Color)new ColorMapper()
.unmarshal(null,ctx);
border = BorderFactory.createBevelBorder(
bevelType.getSubType(),outerHighColor,innerHighColor,
outerShadowColor,innerShadowColor);
break;
case matte:
top = ctx.attributeInt(uri, TOP_NAME, index);
bottom = ctx.attributeInt(uri, BOTTOM_NAME, index);
left = ctx.attributeInt(uri, LEFT_NAME, index);
right = ctx.attributeInt(uri, RIGHT_NAME, index);
ctx.parsePastStartTag(uri,name);
color = (Color)new ColorMapper().unmarshal(null,ctx);
border = BorderFactory.createMatteBorder(top,left,bottom,right,
color);
break;
case compound:
ctx.parsePastStartTag(uri,name);
Border inside = (Border) new BorderMapper(null,0, INSIDE_NAME)
.unmarshal(null,ctx);
Border outside = (Border) new BorderMapper(null,0, OUTSIDE_NAME)
.unmarshal(null,ctx);
border = BorderFactory.createCompoundBorder(outside, inside);
break;
case painter:
String painterName = ctx.attributeText(uri, PAINTER_NAME);
top = ctx.attributeInt(uri, TOP_NAME, index);
bottom = ctx.attributeInt(uri, BOTTOM_NAME, index);
left = ctx.attributeInt(uri, LEFT_NAME, index);
right = ctx.attributeInt(uri, RIGHT_NAME, index);
border = new PainterBorder(painterName, top, left, bottom, right);
}
ctx.parsePastEndTag(uri, name);
return border;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel.jibxhelpers;
/**
* ClassConverter
*
* @author Created by Jasper Potts (Jul 16, 2007)
*/
public class ClassConverter {
public static String classToString(Class c) {
return c == null ? "" : c.getName();
}
public static Class stringToClass(String className) {
if (className == null || className.length() == 0) {
return null;
}
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) classLoader = ClassConverter.class.getClassLoader();
return classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
System.err.println("Failed to find class with name [" + className + "] in ClassConverter");
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,78 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel.jibxhelpers;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;
import org.jibx.runtime.impl.UnmarshallingContext;
public class ClassMapper implements IMarshaller, IUnmarshaller {
private static final String ELEMENT_NAME = "type";
public boolean isExtension(int i) {
return false;
}
public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException {
return iUnmarshallingContext.isAt(null, ELEMENT_NAME);
}
public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException {
if (!(object instanceof Class)) {
throw new JiBXException("Invalid object type for marshaller");
} else if (!(iMarshallingContext instanceof MarshallingContext)) {
throw new JiBXException("Invalid object type for marshaller");
} else {
MarshallingContext ctx = (MarshallingContext) iMarshallingContext;
Class clazz = (Class) object;
ctx.startTagAttributes(0, ELEMENT_NAME).
attribute(0, "value", clazz.getName()).
closeStartEmpty();
}
}
public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException {
// make sure we're at the appropriate start tag
UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext;
if (!ctx.isAt(null, ELEMENT_NAME)) {
ctx.throwStartTagNameError(null, ELEMENT_NAME);
}
// get values
String value = ctx.attributeText(null, "value", null);
ctx.parsePastEndTag(null, ELEMENT_NAME);
// create
try {
return Class.forName(value);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel.jibxhelpers;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;
import org.jibx.runtime.impl.UnmarshallingContext;
import java.awt.Font;
/**
* FontMapper
*
* @author Created by Jasper Potts (Jun 8, 2007)
*/
public class FontMapper implements IMarshaller, IUnmarshaller {
private static final String ELEMENT_NAME = "font";
private static final String FAMILY_NAME = "family";
private static final String STYLE_NAME = "style";
private static final String SIZE_NAME = "size";
public boolean isExtension(int i) {
return false;
}
public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException {
return iUnmarshallingContext.isAt(null, ELEMENT_NAME);
}
public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException {
if (!(object instanceof Font)) {
throw new JiBXException("Invalid object type for marshaller");
} else if (!(iMarshallingContext instanceof MarshallingContext)) {
throw new JiBXException("Invalid object type for marshaller");
} else {
MarshallingContext ctx = (MarshallingContext) iMarshallingContext;
Font font = (Font) object;
ctx.startTagAttributes(0, ELEMENT_NAME).
attribute(0, FAMILY_NAME, font.getFamily()).
attribute(0, STYLE_NAME, font.getStyle()).
attribute(0, SIZE_NAME, font.getSize()).
closeStartEmpty();
}
}
public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException {
// make sure we're at the appropriate start tag
UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext;
if (!ctx.isAt(null, ELEMENT_NAME)) {
ctx.throwStartTagNameError(null, ELEMENT_NAME);
}
// get values
String name = ctx.attributeText(null, FAMILY_NAME, null);
int style = ctx.attributeInt(null, STYLE_NAME, 0);
int size = ctx.attributeInt(null, SIZE_NAME, 0);
ctx.parsePastEndTag(null, ELEMENT_NAME);
// create
return new Font(name, style, size);
}
}

View File

@ -0,0 +1,155 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.synthmodel.jibxhelpers;
import org.jdesktop.swingx.designer.jibxhelpers.DimensionMapper;
import org.jdesktop.swingx.designer.jibxhelpers.InsetsMapper;
import org.jdesktop.synthdesigner.synthmodel.UIProperty;
import org.jibx.runtime.IMarshallable;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;
import org.jibx.runtime.impl.UnmarshallingContext;
/**
* UIPropertyMapper
*
* @author Created by Jasper Potts (Jul 10, 2007)
*/
public class UIPropertyMapper implements IMarshaller, IUnmarshaller {
private static final String ELEMENT_NAME = "uiProperty";
private static final String NAME_NAME = "name";
private static final String TYPE_NAME = "type";
private static final String VALUE_NAME = "value";
public boolean isExtension(int i) {
return false;
}
public boolean isPresent(IUnmarshallingContext iUnmarshallingContext) throws JiBXException {
return iUnmarshallingContext.isAt(null, ELEMENT_NAME);
}
public void marshal(Object object, IMarshallingContext iMarshallingContext) throws JiBXException {
if (!(object instanceof UIProperty)) {
throw new JiBXException("Invalid object type for marshaller");
} else if (!(iMarshallingContext instanceof MarshallingContext)) {
throw new JiBXException("Invalid object type for marshaller");
} else {
MarshallingContext ctx = (MarshallingContext) iMarshallingContext;
UIProperty property = (UIProperty) object;
ctx.startTagAttributes(0, ELEMENT_NAME);
ctx.attribute(0, NAME_NAME, property.getName());
ctx.attribute(0, TYPE_NAME, property.getType().toString());
switch (property.getType()) {
case BOOLEAN:
case DOUBLE:
case INT:
case FLOAT:
case STRING:
ctx.attribute(0, VALUE_NAME, property.getValue().toString());
ctx.closeStartEmpty();
break;
case INSETS:
ctx.closeStartContent();
new InsetsMapper().marshal(property.getValue(), ctx);
ctx.endTag(0, ELEMENT_NAME);
break;
case COLOR:
case FONT:
ctx.closeStartContent();
if (property.getValue() instanceof IMarshallable) {
((IMarshallable) property.getValue()).marshal(ctx);
} else {
throw new JiBXException("Mapped value is not marshallable");
}
ctx.endTag(0, ELEMENT_NAME);
break;
case DIMENSION:
ctx.closeStartContent();
new DimensionMapper().marshal(property.getValue(), ctx);
ctx.endTag(0, ELEMENT_NAME);
break;
case BORDER:
ctx.closeStartContent();
new BorderMapper().marshal(property.getValue(), ctx);
ctx.endTag(0, ELEMENT_NAME);
break;
}
}
}
public Object unmarshal(Object object, IUnmarshallingContext iUnmarshallingContext) throws JiBXException {
// make sure we're at the appropriate start tag
UnmarshallingContext ctx = (UnmarshallingContext) iUnmarshallingContext;
if (!ctx.isAt(null, ELEMENT_NAME)) {
ctx.throwStartTagNameError(null, ELEMENT_NAME);
}
// get values
Object value = null;
String name = ctx.attributeText(null, NAME_NAME, null);
UIProperty.PropertyType type = UIProperty.PropertyType.valueOf(ctx.attributeText(null, TYPE_NAME, null));
switch (type) {
case BOOLEAN:
value = Boolean.parseBoolean(ctx.attributeText(null, VALUE_NAME, null));
break;
case DOUBLE:
value = Double.parseDouble(ctx.attributeText(null, VALUE_NAME, null));
break;
case INT:
value = Integer.parseInt(ctx.attributeText(null, VALUE_NAME, null));
break;
case FLOAT:
value = Float.parseFloat(ctx.attributeText(null, VALUE_NAME, null));
break;
case STRING:
value = ctx.attributeText(null, VALUE_NAME, null);
break;
case INSETS:
ctx.parsePastStartTag(null, ELEMENT_NAME);
value = new InsetsMapper().unmarshal(value, ctx);
break;
case COLOR:
case FONT:
ctx.parsePastStartTag(null, ELEMENT_NAME);
value = ctx.unmarshalElement();
break;
case DIMENSION:
ctx.parsePastStartTag(null, ELEMENT_NAME);
value = new DimensionMapper().unmarshal(value, ctx);
break;
case BORDER:
ctx.parsePastStartTag(null, ELEMENT_NAME);
value = new BorderMapper().unmarshal(value, ctx);
break;
}
ctx.parsePastEndTag(null, ELEMENT_NAME);
// create
return new UIProperty(name, type, value);
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.java.swing;
/**
* This class is preserved for backward compatibility with JDK 6.
*
* @deprecated Use {@link javax.swing.Painter} instead.
*/
public interface Painter<T> extends javax.swing.Painter {
}

View File

@ -134,6 +134,15 @@ class GTKFileChooserUI extends SynthFileChooserUI {
super(filechooser);
}
protected ActionMap createActionMap() {
ActionMap map = new ActionMapUIResource();
map.put("approveSelection", getApproveSelectionAction());
map.put("cancelSelection", getCancelSelectionAction());
map.put("Go Up", getChangeToParentDirectoryAction());
map.put("fileNameCompletion", getFileNameCompletionAction());
return map;
}
public String getFileName() {
JFileChooser fc = getFileChooser();
String typedInName = fileNameTextField != null ?

View File

@ -0,0 +1,33 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.java.swing.plaf.nimbus;
/**
* This class is preserved for backward compatibility with JDK 6.
*
* @deprecated Use {@link javax.swing.plaf.nimbus.AbstractRegionPainter} instead.
*/
public abstract class AbstractRegionPainter extends javax.swing.plaf.nimbus.AbstractRegionPainter {
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.java.swing.plaf.nimbus;
/**
* This class is preserved for backward compatibility with JDK 6.
*
* @deprecated Use {@link javax.swing.plaf.nimbus.NimbusLookAndFeel} instead.
*/
public class NimbusLookAndFeel extends javax.swing.plaf.nimbus.NimbusLookAndFeel {
}

View File

@ -1009,6 +1009,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel
"PopupMenu.background", MenuBackgroundColor,
"PopupMenu.foreground", MenuTextColor,
"PopupMenu.popupSound", "win.sound.menuPopup",
"PopupMenu.consumeEventOnClose", Boolean.TRUE,
// Menus
"Menu.font", MenuFont,

View File

@ -54,6 +54,7 @@ public class SoftAudioPusher implements Runnable {
return;
active = true;
audiothread = new Thread(this);
audiothread.setDaemon(true);
audiothread.setPriority(Thread.MAX_PRIORITY);
audiothread.start();
}

View File

@ -93,7 +93,6 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
protected double portamento_time = 1; // keyschanges per control buffer time
protected int[] portamento_lastnote = new int[128];
protected int portamento_lastnote_ix = 0;
private int portamento_control_note = -1;
private boolean portamento = false;
private boolean mono = false;
private boolean mute = false;
@ -369,12 +368,12 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
voice.setSoloMute(solomute);
if (releaseTriggered)
return;
if (portamento_control_note != -1) {
if (controller[84] != 0) {
voice.co_noteon_keynumber[0]
= (tuning.getTuning(portamento_control_note) / 100.0)
= (tuning.getTuning(controller[84]) / 100.0)
* (1f / 128f);
voice.portamento = true;
portamento_control_note = -1;
controlChange(84, 0);
} else if (portamento) {
if (mono) {
if (portamento_lastnote[0] != -1) {
@ -382,7 +381,7 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
= (tuning.getTuning(portamento_lastnote[0]) / 100.0)
* (1f / 128f);
voice.portamento = true;
portamento_control_note = -1;
controlChange(84, 0);
}
portamento_lastnote[0] = noteNumber;
} else {
@ -449,19 +448,19 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
}
}
if (portamento_control_note != -1) {
if (controller[84] != 0) {
boolean n_found = false;
for (int i = 0; i < voices.length; i++) {
if (voices[i].on && voices[i].channel == channel
&& voices[i].active
&& voices[i].note == portamento_control_note
&& voices[i].note == controller[84]
&& voices[i].releaseTriggered == false) {
voices[i].portamento = true;
voices[i].setNote(noteNumber);
n_found = true;
}
}
portamento_control_note = -1;
controlChange(84, 0);
if (n_found)
return;
}
@ -556,6 +555,18 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
&& voices[i].releaseTriggered == false) {
voices[i].noteOff(velocity);
}
// We must also check stolen voices
if (voices[i].stealer_channel == this && voices[i].stealer_noteNumber == noteNumber) {
SoftVoice v = voices[i];
v.stealer_releaseTriggered = false;
v.stealer_channel = null;
v.stealer_performer = null;
v.stealer_voiceID = -1;
v.stealer_noteNumber = 0;
v.stealer_velocity = 0;
v.stealer_extendedConnectionBlocks = null;
v.stealer_channelmixer = null;
}
}
// Try play back note-off triggered voices,
@ -1141,9 +1152,6 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
}
}
break;
case 84:
portamento_control_note = value;
break;
case 98:
nrpn_control = (nrpn_control & (127 << 7)) + value;
rpn_control = RPN_NULL_VALUE;

View File

@ -38,11 +38,11 @@ public class SoftChorus implements SoftAudioProcessor {
private float[] delaybuffer;
private int rovepos = 0;
private volatile float gain = 1;
private volatile float rgain = 0;
private volatile float delay = 0;
private float gain = 1;
private float rgain = 0;
private float delay = 0;
private float lastdelay = 0;
private volatile float feedback = 0;
private float feedback = 0;
public VariableDelay(int maxbuffersize) {
delaybuffer = new float[maxbuffersize];
@ -115,10 +115,8 @@ public class SoftChorus implements SoftAudioProcessor {
private static class LFODelay {
private volatile double c_cos_delta;
private volatile double c_sin_delta;
private double c_cos = 1;
private double c_sin = 0;
private double phase = 1;
private double phase_step = 0;
private double depth = 0;
private VariableDelay vdelay;
private double samplerate;
@ -139,13 +137,11 @@ public class SoftChorus implements SoftAudioProcessor {
public void setRate(double rate) {
double g = (Math.PI * 2) * (rate / controlrate);
c_cos_delta = Math.cos(g);
c_sin_delta = Math.sin(g);
phase_step = g;
}
public void setPhase(double phase) {
c_cos = Math.cos(phase);
c_sin = Math.sin(phase);
this.phase = phase;
}
public void setFeedBack(float feedback) {
@ -161,16 +157,16 @@ public class SoftChorus implements SoftAudioProcessor {
}
public void processMix(float[] in, float[] out, float[] rout) {
c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta;
c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta;
vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2)));
phase += phase_step;
while(phase > (Math.PI * 2)) phase -= (Math.PI * 2);
vdelay.setDelay((float) (depth * 0.5 * (Math.cos(phase) + 2)));
vdelay.processMix(in, out, rout);
}
public void processReplace(float[] in, float[] out, float[] rout) {
c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta;
c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta;
vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2)));
phase += phase_step;
while(phase > (Math.PI * 2)) phase -= (Math.PI * 2);
vdelay.setDelay((float) (depth * 0.5 * (Math.cos(phase) + 2)));
vdelay.processReplace(in, out, rout);
}

View File

@ -543,8 +543,6 @@ public class SoftFilter {
public void filter1(SoftAudioBuffer sbuffer) {
float[] buffer = sbuffer.array();
if (dirty) {
filter1calc();
dirty = false;
@ -559,6 +557,7 @@ public class SoftFilter {
if (wet > 0 || last_wet > 0) {
float[] buffer = sbuffer.array();
int len = buffer.length;
float a0 = this.last_a0;
float q = this.last_q;
@ -577,14 +576,16 @@ public class SoftFilter {
q += q_delta;
gain += gain_delta;
wet += wet_delta;
y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
y2 = (1 - q * a0) * y2 + (a0) * y1;
float ga0 = (1 - q * a0);
y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
y2 = ga0 * y2 + (a0) * y1;
buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet);
}
} else if (a0_delta == 0 && q_delta == 0) {
float ga0 = (1 - q * a0);
for (int i = 0; i < len; i++) {
y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
y2 = (1 - q * a0) * y2 + (a0) * y1;
y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
y2 = ga0 * y2 + (a0) * y1;
buffer[i] = y2 * gain;
}
} else {
@ -592,8 +593,9 @@ public class SoftFilter {
a0 += a0_delta;
q += q_delta;
gain += gain_delta;
y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
y2 = (1 - q * a0) * y2 + (a0) * y1;
float ga0 = (1 - q * a0);
y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
y2 = ga0 * y2 + (a0) * y1;
buffer[i] = y2 * gain;
}
}

View File

@ -216,6 +216,7 @@ public class SoftJitterCorrector extends AudioInputStream {
};
thread = new Thread(runnable);
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
}

View File

@ -45,6 +45,13 @@ public class SoftLowFrequencyOscillator implements SoftProcess {
private double sin_factor = 0;
private static double PI2 = 2.0 * Math.PI;
public SoftLowFrequencyOscillator() {
// If sin_step is 0 then sin_stepfreq must be -INF
for (int i = 0; i < sin_stepfreq.length; i++) {
sin_stepfreq[i] = Double.NEGATIVE_INFINITY;
}
}
public void reset() {
for (int i = 0; i < used_count; i++) {
out[i][0] = 0;
@ -53,7 +60,8 @@ public class SoftLowFrequencyOscillator implements SoftProcess {
freq[i][0] = 0;
delay_counter[i] = 0;
sin_phase[i] = 0;
sin_stepfreq[i] = 0;
// If sin_step is 0 then sin_stepfreq must be -INF
sin_stepfreq[i] = Double.NEGATIVE_INFINITY;
sin_step[i] = 0;
}
used_count = 0;

View File

@ -48,16 +48,18 @@ public class SoftMainMixer {
public final static int CHANNEL_LEFT = 0;
public final static int CHANNEL_RIGHT = 1;
public final static int CHANNEL_EFFECT1 = 2;
public final static int CHANNEL_EFFECT2 = 3;
public final static int CHANNEL_EFFECT3 = 4;
public final static int CHANNEL_EFFECT4 = 5;
public final static int CHANNEL_MONO = 2;
public final static int CHANNEL_EFFECT1 = 3;
public final static int CHANNEL_EFFECT2 = 4;
public final static int CHANNEL_EFFECT3 = 5;
public final static int CHANNEL_EFFECT4 = 6;
public final static int CHANNEL_LEFT_DRY = 10;
public final static int CHANNEL_RIGHT_DRY = 11;
public final static int CHANNEL_SCRATCH1 = 12;
public final static int CHANNEL_SCRATCH2 = 13;
public final static int CHANNEL_CHANNELMIXER_LEFT = 14;
public final static int CHANNEL_CHANNELMIXER_RIGHT = 15;
public final static int CHANNEL_CHANNELMIXER_MONO = 16;
protected boolean active_sensing_on = false;
private long msec_last_activity = -1;
private boolean pusher_silent = false;
@ -485,8 +487,10 @@ public class SoftMainMixer {
// to channelmixer left,right input/output
SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT];
SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT];
SoftAudioBuffer monobak = buffers[CHANNEL_MONO];
buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_RIGHT];
buffers[CHANNEL_MONO] = buffers[CHANNEL_CHANNELMIXER_MONO];
int bufferlen = buffers[CHANNEL_LEFT].getSize();
@ -503,6 +507,7 @@ public class SoftMainMixer {
for (ModelChannelMixer cmixer : act_registeredMixers) {
for (int i = 0; i < cbuffer.length; i++)
Arrays.fill(cbuffer[i], 0);
buffers[CHANNEL_MONO].clear();
boolean hasactivevoices = false;
for (int i = 0; i < voicestatus.length; i++)
if (voicestatus[i].active)
@ -517,6 +522,26 @@ public class SoftMainMixer {
}
}
if(!buffers[CHANNEL_MONO].isSilent())
{
float[] mono = buffers[CHANNEL_MONO].array();
float[] left = buffers[CHANNEL_LEFT].array();
if (nrofchannels != 1) {
float[] right = buffers[CHANNEL_RIGHT].array();
for (int i = 0; i < bufferlen; i++) {
float v = mono[i];
left[i] += v;
right[i] += v;
}
}
else
{
for (int i = 0; i < bufferlen; i++) {
left[i] += mono[i];
}
}
}
for (int i = 0; i < cbuffer.length; i++) {
float[] cbuff = cbuffer[i];
float[] obuff = obuffer[i];
@ -539,6 +564,7 @@ public class SoftMainMixer {
buffers[CHANNEL_LEFT] = leftbak;
buffers[CHANNEL_RIGHT] = rightbak;
buffers[CHANNEL_MONO] = monobak;
}
@ -547,6 +573,27 @@ public class SoftMainMixer {
if (voicestatus[i].channelmixer == null)
voicestatus[i].processAudioLogic(buffers);
if(!buffers[CHANNEL_MONO].isSilent())
{
float[] mono = buffers[CHANNEL_MONO].array();
float[] left = buffers[CHANNEL_LEFT].array();
int bufferlen = buffers[CHANNEL_LEFT].getSize();
if (nrofchannels != 1) {
float[] right = buffers[CHANNEL_RIGHT].array();
for (int i = 0; i < bufferlen; i++) {
float v = mono[i];
left[i] += v;
right[i] += v;
}
}
else
{
for (int i = 0; i < bufferlen; i++) {
left[i] += mono[i];
}
}
}
// Run effects
if (synth.chorus_on)
chorus.processAudio();
@ -665,7 +712,7 @@ public class SoftMainMixer {
/ synth.getControlRate());
control_mutex = synth.control_mutex;
buffers = new SoftAudioBuffer[16];
buffers = new SoftAudioBuffer[17];
for (int i = 0; i < buffers.length; i++) {
buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat());
}

View File

@ -889,9 +889,12 @@ public class SoftSynthesizer implements AudioSynthesizer,
return;
}
synchronized (control_mutex) {
Throwable causeException = null;
try {
if (line != null)
if (line != null) {
// can throw IllegalArgumentException
setFormat(line.getFormat());
}
AudioInputStream ais = openStream(getFormat(), info);
@ -900,10 +903,13 @@ public class SoftSynthesizer implements AudioSynthesizer,
if (line == null)
{
if(testline != null)
if (testline != null) {
line = testline;
else
} else {
// can throw LineUnavailableException,
// IllegalArgumentException, SecurityException
line = AudioSystem.getSourceDataLine(getFormat());
}
}
double latency = this.latency;
@ -911,6 +917,8 @@ public class SoftSynthesizer implements AudioSynthesizer,
if (!line.isOpen()) {
int bufferSize = getFormat().getFrameSize()
* (int)(getFormat().getFrameRate() * (latency/1000000f));
// can throw LineUnavailableException,
// IllegalArgumentException, SecurityException
line.open(getFormat(), bufferSize);
// Remember that we opened that line
@ -954,13 +962,22 @@ public class SoftSynthesizer implements AudioSynthesizer,
weakstream.sourceDataLine = sourceDataLine;
}
} catch (LineUnavailableException e) {
causeException = e;
} catch (IllegalArgumentException e) {
causeException = e;
} catch (SecurityException e) {
causeException = e;
}
if (causeException != null) {
if (isOpen())
close();
// am: need MidiUnavailableException(Throwable) ctor!
throw new MidiUnavailableException(e.toString());
MidiUnavailableException ex = new MidiUnavailableException(
"Can not open line");
ex.initCause(causeException);
throw ex;
}
}

View File

@ -782,6 +782,7 @@ public class SoftVoice extends VoiceStatus {
SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
SoftAudioBuffer mono = buffer[SoftMainMixer.CHANNEL_MONO];
SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
@ -803,13 +804,22 @@ public class SoftVoice extends VoiceStatus {
mixAudioStream(rightdry, left, last_out_mixer_left,
out_mixer_left);
} else {
mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
if (rightdry != null)
mixAudioStream(rightdry, right, last_out_mixer_right,
out_mixer_right);
if(rightdry == null &&
last_out_mixer_left == last_out_mixer_right &&
out_mixer_left == out_mixer_right)
{
mixAudioStream(leftdry, mono, last_out_mixer_left, out_mixer_left);
}
else
mixAudioStream(leftdry, right, last_out_mixer_right,
{
mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
if (rightdry != null)
mixAudioStream(rightdry, right, last_out_mixer_right,
out_mixer_right);
else
mixAudioStream(leftdry, right, last_out_mixer_right,
out_mixer_right);
}
}
if (rightdry == null) {

View File

@ -687,7 +687,7 @@ public class Color implements Paint, java.io.Serializable {
* @since JDK1.0
*/
public boolean equals(Object obj) {
return obj instanceof Color && ((Color)obj).value == this.value;
return obj instanceof Color && ((Color)obj).getRGB() == this.getRGB();
}
/**

View File

@ -102,6 +102,29 @@ public class MetaMessage extends MidiMessage {
this(defaultMessage);
}
/**
* Constructs a new {@code MetaMessage} and sets the message parameters.
* The contents of the message can be changed by using
* the {@code setMessage} method.
*
* @param type meta-message type (must be less than 128)
* @param data the data bytes in the MIDI message
* @param length an amount of bytes in the {@code data} byte array;
* it should be non-negative and less than or equal to
* {@code data.length}
* @throws InvalidMidiDataException if the parameter values do not specify
* a valid MIDI meta message
* @see #setMessage(int, byte[], int)
* @see #getType()
* @see #getData()
* @since 1.7
*/
public MetaMessage(int type, byte[] data, int length)
throws InvalidMidiDataException {
super(null);
setMessage(type, data, length); // can throw InvalidMidiDataException
}
/**
* Constructs a new <code>MetaMessage</code>.

View File

@ -187,6 +187,83 @@ public class ShortMessage extends MidiMessage {
length = 3;
}
/**
* Constructs a new {@code ShortMessage} which represents a MIDI
* message that takes no data bytes.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param status the MIDI status byte
* @throws InvalidMidiDataException if {@code status} does not specify
* a valid MIDI status byte for a message that requires no data bytes
* @see #setMessage(int)
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
* @see #getStatus()
* @since 1.7
*/
public ShortMessage(int status) throws InvalidMidiDataException {
super(null);
setMessage(status); // can throw InvalidMidiDataException
}
/**
* Constructs a new {@code ShortMessage} which represents a MIDI message
* that takes up to two data bytes. If the message only takes one data byte,
* the second data byte is ignored. If the message does not take
* any data bytes, both data bytes are ignored.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param status the MIDI status byte
* @param data1 the first data byte
* @param data2 the second data byte
* @throws InvalidMidiDataException if the status byte or all data bytes
* belonging to the message do not specify a valid MIDI message
* @see #setMessage(int)
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
* @see #getStatus()
* @see #getData1()
* @see #getData2()
* @since 1.7
*/
public ShortMessage(int status, int data1, int data2)
throws InvalidMidiDataException {
super(null);
setMessage(status, data1, data2); // can throw InvalidMidiDataException
}
/**
* Constructs a new {@code ShortMessage} which represents a channel
* MIDI message that takes up to two data bytes. If the message only takes
* one data byte, the second data byte is ignored. If the message does not
* take any data bytes, both data bytes are ignored.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param command the MIDI command represented by this message
* @param channel the channel associated with the message
* @param data1 the first data byte
* @param data2 the second data byte
* @throws InvalidMidiDataException if the command value, channel value
* or all data bytes belonging to the message do not specify
* a valid MIDI message
* @see #setMessage(int)
* @see #setMessage(int, int, int)
* @see #setMessage(int, int, int, int)
* @see #getCommand()
* @see #getChannel()
* @see #getData1()
* @see #getData2()
* @since 1.7
*/
public ShortMessage(int command, int channel, int data1, int data2)
throws InvalidMidiDataException {
super(null);
setMessage(command, channel, data1, data2);
}
/**
* Constructs a new <code>ShortMessage</code>.

View File

@ -120,6 +120,54 @@ public class SysexMessage extends MidiMessage {
data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF);
}
/**
* Constructs a new {@code SysexMessage} and sets the data for
* the message. The first byte of the data array must be a valid system
* exclusive status byte (0xF0 or 0xF7).
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param data the system exclusive message data including the status byte
* @param length the length of the valid message data in the array,
* including the status byte; it should be non-negative and less than
* or equal to {@code data.length}
* @throws InvalidMidiDataException if the parameter values
* do not specify a valid MIDI meta message.
* @see #setMessage(byte[], int)
* @see #setMessage(int, byte[], int)
* @see #getData()
* @since 1.7
*/
public SysexMessage(byte[] data, int length)
throws InvalidMidiDataException {
super(null);
setMessage(data, length);
}
/**
* Constructs a new {@code SysexMessage} and sets the data for the message.
* The contents of the message can be changed by using one of
* the {@code setMessage} methods.
*
* @param status the status byte for the message; it must be a valid system
* exclusive status byte (0xF0 or 0xF7)
* @param data the system exclusive message data (without the status byte)
* @param length the length of the valid message data in the array;
* it should be non-negative and less than or equal to
* {@code data.length}
* @throws InvalidMidiDataException if the parameter values
* do not specify a valid MIDI meta message.
* @see #setMessage(byte[], int)
* @see #setMessage(int, byte[], int)
* @see #getData()
* @since 1.7
*/
public SysexMessage(int status, byte[] data, int length)
throws InvalidMidiDataException {
super(null);
setMessage(status, data, length);
}
/**
* Constructs a new <code>SysexMessage</code>.

View File

@ -131,13 +131,31 @@ public abstract class FloatControl extends Control {
* @param minLabel the label for the minimum value, such as "Left" or "Off"
* @param midLabel the label for the midpoint value, such as "Center" or "Default"
* @param maxLabel the label for the maximum value, such as "Right" or "Full"
*
* @throws IllegalArgumentException if {@code minimum} is greater
* than {@code maximum} or {@code initialValue} does not fall
* within the allowable range
*/
protected FloatControl(Type type, float minimum, float maximum,
float precision, int updatePeriod, float initialValue,
String units, String minLabel, String midLabel, String maxLabel) {
float precision, int updatePeriod, float initialValue,
String units, String minLabel, String midLabel, String maxLabel) {
super(type);
if (minimum > maximum) {
throw new IllegalArgumentException("Minimum value " + minimum
+ " exceeds maximum value " + maximum + ".");
}
if (initialValue < minimum) {
throw new IllegalArgumentException("Initial value " + initialValue
+ " smaller than allowable minimum value " + minimum + ".");
}
if (initialValue > maximum) {
throw new IllegalArgumentException("Initial value " + initialValue
+ " exceeds allowable maximum value " + maximum + ".");
}
this.minimum = minimum;
this.maximum = maximum;
@ -167,10 +185,15 @@ public abstract class FloatControl extends Control {
* @param initialValue the value that the control starts with when constructed
* @param units the label for the units in which the control's values are expressed,
* such as "dB" or "frames per second"
*
* @throws IllegalArgumentException if {@code minimum} is greater
* than {@code maximum} or {@code initialValue} does not fall
* within the allowable range
*/
protected FloatControl(Type type, float minimum, float maximum,
float precision, int updatePeriod, float initialValue, String units) {
this(type, minimum, maximum, precision, updatePeriod, initialValue, units, "", "", "");
float precision, int updatePeriod, float initialValue, String units) {
this(type, minimum, maximum, precision, updatePeriod,
initialValue, units, "", "", "");
}
@ -306,9 +329,21 @@ public abstract class FloatControl extends Control {
* @param to final value after the shift
* @param microseconds maximum duration of the shift in microseconds
*
* @throws IllegalArgumentException if either {@code from} or {@code to}
* value does not fall within the allowable range
*
* @see #getUpdatePeriod
*/
public void shift(float from, float to, int microseconds) {
// test "from" value, "to" value will be tested by setValue()
if (from < minimum) {
throw new IllegalArgumentException("Requested value " + from
+ " smaller than allowable minimum value " + minimum + ".");
}
if (from > maximum) {
throw new IllegalArgumentException("Requested value " + from
+ " exceeds allowable maximum value " + maximum + ".");
}
setValue(to);
}

View File

@ -42,9 +42,15 @@ public abstract class MixerProvider {
/**
* Indicates whether the mixer provider supports the mixer represented by
* the specified mixer info object.
* <p>
* The full set of mixer info objects that represent the mixers supported
* by this {@code MixerProvider} may be obtained
* through the {@code getMixerInfo} method.
*
* @param info an info object that describes the mixer for which support is queried
* @return <code>true</code> if the specified mixer is supported,
* otherwise <code>false</code>
* @return {@code true} if the specified mixer is supported,
* otherwise {@code false}
* @see #getMixerInfo()
*/
public boolean isMixerSupported(Mixer.Info info) {
@ -62,17 +68,34 @@ public abstract class MixerProvider {
/**
* Obtains the set of info objects representing the mixer
* or mixers provided by this MixerProvider.
* @return set of mixer info objects
* <p>
* The {@code isMixerSupported} method returns {@code true}
* for all the info objects returned by this method.
* The corresponding mixer instances for the info objects
* are returned by the {@code getMixer} method.
*
* @return a set of mixer info objects
* @see #getMixer(javax.sound.sampled.Mixer.Info) getMixer(Mixer.Info)
* @see #isMixerSupported(javax.sound.sampled.Mixer.Info) isMixerSupported(Mixer.Info)
*/
public abstract Mixer.Info[] getMixerInfo();
/**
* Obtains an instance of the mixer represented by the info object.
* <p>
* The full set of the mixer info objects that represent the mixers
* supported by this {@code MixerProvider} may be obtained
* through the {@code getMixerInfo} method.
* Use the {@code isMixerSupported} method to test whether
* this {@code MixerProvider} supports a particular mixer.
*
* @param info an info object that describes the desired mixer
* @return mixer instance
* @throws IllegalArgumentException if the info object specified does not
* match the info object for a mixer supported by this MixerProvider.
* match the info object for a mixer supported by this MixerProvider.
* @see #getMixerInfo()
* @see #isMixerSupported(javax.sound.sampled.Mixer.Info) isMixerSupported(Mixer.Info)
*/
public abstract Mixer getMixer(Mixer.Info info);
}

View File

@ -266,6 +266,26 @@ public class DefaultCellEditor extends AbstractCellEditor
boolean isSelected,
int row, int column) {
delegate.setValue(value);
if (editorComponent instanceof JCheckBox) {
//in order to avoid a "flashing" effect when clicking a checkbox
//in a table, it is important for the editor to have as a border
//the same border that the renderer has, and have as the background
//the same color as the renderer has. This is primarily only
//needed for JCheckBox since this editor doesn't fill all the
//visual space of the table cell, unlike a text field.
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component c = renderer.getTableCellRendererComponent(table, value,
isSelected, true, row, column);
if (c != null) {
editorComponent.setOpaque(true);
editorComponent.setBackground(c.getBackground());
if (c instanceof JComponent) {
editorComponent.setBorder(((JComponent)c).getBorder());
}
} else {
editorComponent.setOpaque(false);
}
}
return editorComponent;
}

Some files were not shown because too many files have changed in this diff Show More