提交 8ee647d1 编写于 作者: P peterz

6844267: Nimbus generator depends on JIBX

Summary: Nimbus generator now uses JAXB instead of JIBX
Reviewed-by: jasper
上级 a79fc170
......@@ -9,35 +9,25 @@ 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 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
2. 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.
4. Either download and install the latest JDK7 from
3. 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.
5. Check the sanity of doing a build with the current machine:
4. Check the sanity of doing a build with the current machine:
cd make && gnumake sanity
See README-builds.html if you run into problems.
6. Do a partial build of the jdk:
5. Do a partial build of the jdk:
cd make && gnumake all
7. Construct the images:
6. Construct the images:
cd make && gnumake images
The resulting JDK image should be found in build/*/j2sdk-image
......
......@@ -93,8 +93,7 @@ sanity-all:: sanity-base \
sane-alt_bootdir \
sane-bootdir \
sane-local-bootdir \
sane-alsa-headers \
sane-jibx
sane-alsa-headers
ifdef OPENJDK
sanity-all:: sane-freetype
......
......@@ -536,15 +536,6 @@ 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))
......
......@@ -233,7 +233,6 @@ 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
......
......@@ -214,7 +214,6 @@ 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 \
......@@ -1516,22 +1515,6 @@ ifeq ($(PLATFORM), solaris)
endif
######################################################
# JIBX_LIBS_PATH must be valid
######################################################
sane-jibx:
ifdef DISABLE_NIMBUS
$(call SanityWarning,Disabling Nimbus will remove public API in javax.swing.plaf.nimbus.)
else
@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
endif
######################################################
# MOZILLA_HEADERS_PATH must be valid
######################################################
......
......@@ -34,16 +34,14 @@ include $(BUILDDIR)/common/Defs.gmk
#
include FILES.gmk
AUTO_FILES_JAVA_DIRS = javax/swing/plaf sun/swing com/sun/java/swing/plaf
ifndef DISABLE_NIMBUS
SUBDIRS = nimbus
endif
# 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
ifdef DISABLE_NIMBUS
AUTO_JAVA_PRUNE += nimbus
endif
MISC_FILES = $(MISC_SWING_FILES)
......@@ -52,6 +50,10 @@ ifneq ($(PLATFORM), windows)
MISC_FILES += $(MISC_SWING_FILES_UNIX)
endif
NIMBUS_GENSRC_DIR = $(GENSRCDIR)/javax/swing/plaf/nimbus
NIMBUS_SKIN_FILE = $(SWING_SRC)/plaf/nimbus/skin.laf
NIMBUS_GENERATOR_JAR = $(BUILDTOOLJARDIR)/generatenimbus.jar
FILES_java = $(FILES_SWING_java)
#
......@@ -75,14 +77,25 @@ 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 clobber::
$(SUBDIRS-loop)
$(NIMBUS_GENSRC_DIR): $(NIMBUS_SKIN_FILE) $(NIMBUS_GENERATOR_JAR)
@$(ECHO) "Generating Nimbus source files:"
$(RM) -r $(NIMBUS_GENSRC_DIR)
$(BOOT_JAVA_CMD) -jar $(NIMBUS_GENERATOR_JAR) \
-skinFile $(NIMBUS_SKIN_FILE) -buildDir $(GENSRCDIR) \
-packagePrefix $(PACKAGE).nimbus -lafName Nimbus
@$(ECHO) "Finished generating Nimbus source files"
clean:: classes.clean
$(RM) -r $(NIMBUS_GENSRC_DIR)
#
# Include
#
ifndef DISABLE_NIMBUS
CLASSES_INIT = $(NIMBUS_GENSRC_DIR)
endif
include $(BUILDDIR)/common/Classes.gmk
ifndef OPENJDK
......
......@@ -54,7 +54,7 @@ SUBDIRS = \
CharsetMapping
ifndef DISABLE_NIMBUS
SUBDIRS += swing-nimbus
SUBDIRS += generate_nimbus
endif
all build clean clobber::
......
#
# Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
# 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
......@@ -23,38 +23,50 @@
# have any questions.
#
BUILDDIR = ../../../..
PACKAGE = javax.swing.plaf.nimbus
PRODUCT = com
SWING_SRC = $(SHARE_SRC)/classes/javax/swing
#
# Makefile for building the Nimbus generator
#
BUILDDIR = ../..
PACKAGE = build.tools.generatenimbus
PRODUCT = tools
PROGRAM = generatenimbus
include $(BUILDDIR)/common/Defs.gmk
BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src
BUILDTOOL_MAIN = $(PKGDIR)/Generator.java
#
# 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)
SOURCE_FILES = Generator.java \
ObjectFactory.java \
Paint.java \
SynthModel.java \
UIDefault.java \
UIStyle.java
TEMPLATE_FILES = Defaults.template \
PainterImpl.template \
StateImpl.template
TEMPLATE_DEST = $(BUILDTOOLCLASSDIR)/$(PKGDIR)/resources
#
# Rules
#
CLASSES_INIT = $(NIMBUS_GENSRC_DIR)
include $(BUILDDIR)/common/Classes.gmk
all: $(TEMPLATE_DEST) $(BUILDTOOL_JAR_FILE)
include $(BUILDDIR)/common/BuildToolJar.gmk
$(TEMPLATE_DEST): $(TEMPLATE_FILES:%=$(SHARE_SRC)/classes/javax/swing/plaf/nimbus/%)
$(MKDIR) -p $@
$(RM) $(TEMPLATE_FILES:%=$@/%)
$(CP) $^ $@
$(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"
BUILDTOOL_MAIN_SOURCE_FILE = $(SOURCE_FILES:%=$(BUILDTOOL_SOURCE_ROOT)/$(PKGDIR)/%)
clean clobber::
$(RM) -r $(NIMBUS_GENSRC_DIR)
$(RM) -r $(TEMPLATE_DEST)
......@@ -22,20 +22,13 @@
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.synthdesigner.generator;
package build.tools.generatenimbus;
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.io.*;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
/**
* Generates the various Java artifacts based on a SynthModel.
......@@ -51,12 +44,12 @@ import java.util.Map;
* @author Jasper Potts
*/
public class Generator {
private static Generator instance;
/** 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;
......@@ -68,7 +61,7 @@ public class Generator {
*
* @param args The commandline arguments
*/
public static void main(String[] args) {
public static void main(String[] args) throws Exception {
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" +
......@@ -76,9 +69,6 @@ public class Generator {
" -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" +
......@@ -87,7 +77,6 @@ public class Generator {
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";
......@@ -100,8 +89,6 @@ public class Generator {
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)) {
......@@ -114,25 +101,15 @@ public class Generator {
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();
}
JAXBContext ctx = JAXBContext.newInstance("build.tools.generatenimbus");
Unmarshaller u = ctx.createUnmarshaller();
SynthModel model = (SynthModel) u.unmarshal(skinFile);
Generator.init(full, buildDir, packagePrefix, lafName, model);
Generator.getInstance().generate();
}
}
......@@ -152,8 +129,8 @@ public class Generator {
* @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) {
private Generator(boolean full, File buildDir,
String packageNamePrefix, String lafName, SynthModel model) {
this.full = full;
//validate the input variables
if (packageNamePrefix == null) {
......@@ -162,9 +139,6 @@ public class Generator {
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");
}
......@@ -183,8 +157,6 @@ public class Generator {
//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;
......@@ -192,98 +164,104 @@ public class Generator {
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 static void init(boolean full, File buildDir,
String packageNamePrefix, String lafName, SynthModel model) {
instance = new Generator(full, buildDir, packageNamePrefix, lafName, model);
model.initStyles();
}
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"));
public static Generator getInstance() {
return instance;
}
//create the IconImpl class
template = read("resources/IconImpl.template");
writeSrcFile(template, variables, new File(buildPackageRoot, lafName + "Icon.java"));
public static Map<String, String> getVariables() {
return new HashMap<String, String>(instance.variables);
}
//create the StyleImpl class
template = read("resources/StyleImpl.template");
writeSrcFile(template, variables, new File(buildPackageRoot, lafName + "Style.java"));
public void generate() {
if (full) {
//create the LookAndFeel file
writeSrcFileImpl("LookAndFeel", variables, lafName + "LookAndFeel");
//write out Effect.java
template = read("resources/Effect.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "Effect.java"));
writeSrcFileImpl("AbstractRegionPainter", variables);
writeSrcFileImpl("BlendingMode", variables);
writeSrcFileImpl("SynthPainterImpl", variables);
writeSrcFileImpl("IconImpl", variables, lafName + "Icon.java");
writeSrcFileImpl("StyleImpl", variables, lafName + "Style.java");
writeSrcFileImpl("Effect", variables);
writeSrcFileImpl("EffectUtils", variables);
writeSrcFileImpl("ShadowEffect", variables);
writeSrcFileImpl("DropShadowEffect", variables);
writeSrcFileImpl("InnerShadowEffect", variables);
writeSrcFileImpl("InnerGlowEffect", variables);
writeSrcFileImpl("OuterGlowEffect", variables);
writeSrcFileImpl("State", variables);
writeSrcFileImpl("ImageCache", variables);
writeSrcFileImpl("ImageScalingHelper", variables);
}
//next, populate the first set of ui defaults based on what is in the
//various palettes of the synth model
StringBuilder defBuffer = new StringBuilder();
StringBuilder styleBuffer = new StringBuilder();
model.write(defBuffer, styleBuffer, packageNamePrefix);
//write out EffectUtils.java
template = read("resources/EffectUtils.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "EffectUtils.java"));
Map<String, String> vars = getVariables();
vars.put("UI_DEFAULT_INIT", defBuffer.toString());
vars.put("STYLE_INIT", styleBuffer.toString());
writeSrcFile("Defaults", vars, lafName + "Defaults");
}
//write out ShadowEffect.java
template = read("resources/ShadowEffect.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "ShadowEffect.java"));
private void writeSrcFileImpl(String name, Map<String, String> variables) {
writeSrcFileImpl(name, variables, name);
}
//write out DropShadowEffect.java
template = read("resources/DropShadowEffect.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "DropShadowEffect.java"));
private void writeSrcFileImpl(String templateName,
Map<String, String> variables, String outputName) {
PrintWriter out = null;
try {
InputStream stream = getClass().getResourceAsStream(
"resources/" + templateName + ".template");
TemplateReader in = new TemplateReader(variables, stream);
//write out InnerShadowEffect.java
template = read("resources/InnerShadowEffect.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "InnerShadowEffect.java"));
out = new PrintWriter(new File(buildPackageRoot, outputName + ".java"));
String line = in.readLine();
while (line != null) {
out.println(line);
line = in.readLine();
}
} catch (IOException e) {
throw new RuntimeException("IOException in writer", e);
} finally {
if (out != null) out.close();
}
}
//write out InnerGlowEffect.java
template = read("resources/InnerGlowEffect.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "InnerGlowEffect.java"));
public static void writeSrcFile(String templateName,
Map<String, String> variables, String outputName) {
instance.writeSrcFileImpl(templateName, variables, outputName);
}
//write out OuterGlowEffect.java
template = read("resources/OuterGlowEffect.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "OuterGlowEffect.java"));
/** A BufferedReader implementation that automatically performs
* string replacements as needed.
*/
private static final class TemplateReader extends BufferedReader {
private Map<String, String> variables;
//write out State.java
template = read("resources/State.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "State.java"));
TemplateReader(Map<String, String> variables, InputStream template) {
super(new InputStreamReader(template));
this.variables = variables;
}
template = read("resources/ImageCache.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "ImageCache.java"));
@Override public String readLine() throws IOException {
return substituteVariables(super.readLine());
}
template = read("resources/ImageScalingHelper.template");
writeSrcFile(template, variables, new File(buildPackageRoot, "ImageScalingHelper.java"));
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());
}
//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();
return input;
}
}
}
......@@ -22,34 +22,41 @@
* 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;
package build.tools.generatenimbus;
import javax.xml.bind.annotation.XmlRegistry;
import javax.swing.UIDefaults;
import java.awt.Color;
/**
* OuterGlowEffect
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the test package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
* @author Created by Jasper Potts (Jun 21, 2007)
*/
public class OuterGlowEffect extends DropShadowEffect {
protected OuterGlowEffect() {
distance = 0;
}
@XmlRegistry
public class ObjectFactory {
public OuterGlowEffect(UIDefaults uiDefaults) {
color = new Matte(new Color(255, 255, 211), uiDefaults);
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: test
*
*/
public ObjectFactory() {
}
/**
* Get the display name for this effect
* Create an instance of {@link SynthModel }
*
* @return The user displayable name
*/
public String getDisplayName() {
return "Outer Glow";
public SynthModel createSynthModel() {
return new SynthModel();
}
}
/*
* 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 build.tools.generatenimbus;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
public abstract class Paint {
}
class Matte extends Paint {
@XmlAttribute private int red;
@XmlAttribute private int green;
@XmlAttribute private int blue;
@XmlAttribute private int alpha;
@XmlAttribute private String uiDefaultParentName = null;
@XmlAttribute private float hueOffset = 0;
@XmlAttribute private float saturationOffset = 0;
@XmlAttribute private float brightnessOffset = 0;
@XmlAttribute private int alphaOffset = 0;
@XmlAttribute private String componentPropertyName = null;
public String getComponentPropertyName() { return componentPropertyName; }
@XmlAttribute private boolean uiResource = true;
public boolean isAbsolute() {
return uiDefaultParentName == null;
}
public String getDeclaration() {
if (isAbsolute()) {
return String.format("new Color(%d, %d, %d, %d)",
red, green, blue, alpha);
} else {
return String.format("decodeColor(\"%s\", %sf, %sf, %sf, %d)",
uiDefaultParentName, String.valueOf(hueOffset),
String.valueOf(saturationOffset),
String.valueOf(brightnessOffset), alphaOffset);
}
}
public String write() {
if (isAbsolute()) {
return String.format("%s, %s, %s, %s", red, green, blue, alpha);
} else {
String s = String.format("\"%s\", %sf, %sf, %sf, %d",
uiDefaultParentName, String.valueOf(hueOffset),
String.valueOf(saturationOffset),
String.valueOf(brightnessOffset), alphaOffset);
if (! uiResource) {
s += ", false";
}
return s;
}
}
public ComponentColor createComponentColor(String variableName) {
return new ComponentColor(componentPropertyName, variableName,
saturationOffset, brightnessOffset, alphaOffset);
}
}
class ComponentColor {
private String propertyName;
private String defaultColorVariableName;
private float saturationOffset = 0, brightnessOffset = 0;
private int alphaOffset = 0;
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;
}
public void write(StringBuilder sb) {
sb.append(" getComponentColor(c, \"").
append(propertyName).append("\", ").
append(defaultColorVariableName).append(", ").
append(saturationOffset).append("f, ").
append(brightnessOffset).append("f, ").
append(alphaOffset);
}
}
class GradientStop {
@XmlAttribute private float position;
public float getPosition() { return position; }
@XmlAttribute private float midpoint;
public float getMidpoint() { return midpoint; }
@XmlElement private Matte matte;
public Matte getColor() { return matte; }
}
class AbstractGradient extends Paint {
public static enum CycleMethod {
NO_CYCLE, REFLECT, REPEAT
}
@XmlElement(name="stop") private ArrayList<GradientStop> stops;
public List<GradientStop> getStops() { return stops; }
}
class Gradient extends AbstractGradient {
}
class RadialGradient extends AbstractGradient {
}
/*
* 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 build.tools.generatenimbus;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
public abstract class Shape {
@XmlElement
private PaintPoints paintPoints;
public double getPaintX1() { return paintPoints.x1; }
public double getPaintX2() { return paintPoints.x2; }
public double getPaintY1() { return paintPoints.y1; }
public double getPaintY2() { return paintPoints.y2; }
@XmlElements({
@XmlElement(name = "matte", type = Matte.class),
@XmlElement(name = "gradient", type = Gradient.class),
@XmlElement(name = "radialGradient", type = RadialGradient.class)
})
private Paint paint;
public Paint getPaint() { return paint; }
static class PaintPoints {
@XmlAttribute double x1;
@XmlAttribute double y1;
@XmlAttribute double x2;
@XmlAttribute double y2;
}
}
class Point {
@XmlAttribute private double x;
public double getX() { return x; }
@XmlAttribute private double y;
public double getY() { return y; }
@XmlAttribute(name="cp1x") private double cp1x;
public double getCp1X() { return cp1x; }
@XmlAttribute(name="cp1y") private double cp1y;
public double getCp1Y() { return cp1y; }
@XmlAttribute(name="cp2x") private double cp2x;
public double getCp2X() { return cp2x; }
@XmlAttribute(name="cp2y") private double cp2y;
public double getCp2Y() { return cp2y; }
public boolean isP1Sharp() {
return cp1x == x && cp1y == y;
}
public boolean isP2Sharp() {
return cp2x == x && cp2y == y;
}
}
class Path extends Shape {
@XmlElement(name="point")
@XmlElementWrapper(name="points")
private List<Point> controlPoints = new ArrayList<Point>();
public List<Point> getControlPoints() { return controlPoints; }
}
class Rectangle extends Shape {
@XmlAttribute private double x1;
public double getX1() { return x1; }
@XmlAttribute private double x2;
public double getX2() { return x2; }
@XmlAttribute private double y1;
public double getY1() { return y1; }
@XmlAttribute private double y2;
public double getY2() { return y2; }
@XmlAttribute
public double getRounding() {
double rounding = Math.abs(roundingX - x1) * 2;
return rounding > 2 ? rounding : 0;
}
public void setRounding(double rounding) {
if (rounding > 0 && rounding < 2) {
rounding = 0;
}
roundingX = rounding / 2d + x1;
}
private double roundingX;
public boolean isRounded() {
return getRounding() > 0;
}
}
class Ellipse extends Shape {
@XmlAttribute private double x1;
public double getX1() { return x1; }
@XmlAttribute private double x2;
public double getX2() { return x2; }
@XmlAttribute private double y1;
public double getY1() { return y1; }
@XmlAttribute private double y2;
public double getY2() { return y2; }
}
/*
* 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 build.tools.generatenimbus;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="synthModel")
public class SynthModel {
@XmlElement private UIStyle style;
@XmlElement(name="uiColor")
@XmlElementWrapper(name="colors")
private ArrayList<UIColor> colors;
@XmlElement(name="uiFont")
@XmlElementWrapper(name="fonts")
private ArrayList<UIFont> fonts;
@XmlElement(name="uiComponent")
@XmlElementWrapper(name="components")
private ArrayList<UIComponent> components;
public void initStyles() {
for (UIComponent c: components) {
c.initStyles(this.style);
}
}
public void write(StringBuilder defBuffer, StringBuilder styleBuffer, String packageName) {
defBuffer.append(" //Color palette\n");
for (UIColor c: colors) defBuffer.append(c.write());
defBuffer.append('\n');
defBuffer.append(" //Font palette\n");
defBuffer.append(" d.put(\"defaultFont\", new FontUIResource(defaultFont));\n");
for (UIFont f: fonts) defBuffer.append(f.write());
defBuffer.append('\n');
defBuffer.append(" //Border palette\n");
defBuffer.append('\n');
defBuffer.append(" //The global style definition\n");
defBuffer.append(style.write(""));
defBuffer.append('\n');
for (UIComponent c: components) {
String prefix = Utils.escape(c.getKey());
defBuffer.append(" //Initialize ").append(prefix).append("\n");
c.write(defBuffer, styleBuffer, c, prefix, packageName);
defBuffer.append('\n');
}
}
}
class Typeface {
public enum DeriveStyle {
Default, Off, On;
@Override public String toString() {
switch (this) {
default: return "null";
case On: return "true";
case Off: return "false";
}
}
}
@XmlAttribute private String uiDefaultParentName;
@XmlAttribute(name="family") private String name;
@XmlAttribute private int size;
@XmlAttribute private DeriveStyle bold = DeriveStyle.Default;
@XmlAttribute private DeriveStyle italic = DeriveStyle.Default;
@XmlAttribute private float sizeOffset = 1f;
public boolean isAbsolute() {
return uiDefaultParentName == null;
}
public String write() {
if (isAbsolute()) {
int style = Font.PLAIN;
if (bold == DeriveStyle.On) {
style = style | Font.BOLD;
}
if (italic == DeriveStyle.On) {
style = style | Font.ITALIC;
}
return String.format(
"new javax.swing.plaf.FontUIResource(\"%s\", %d, %d)",
name, style, size);
} else {
return String.format(
"new DerivedFont(\"%s\", %sf, %s, %s)",
uiDefaultParentName, String.valueOf(sizeOffset), bold, italic);
}
}
}
class Border {
enum BorderType {
@XmlEnumValue("empty") EMPTY,
@XmlEnumValue("painter") PAINTER
}
@XmlAttribute private BorderType type;
@XmlAttribute private String painter;
@XmlAttribute private int top;
@XmlAttribute private int left;
@XmlAttribute private int bottom;
@XmlAttribute private int right;
public String write() {
switch (type) {
case PAINTER:
return String.format("new PainterBorder(\"%s\", new Insets(%d, %d, %d, %d))",
painter, top, left, bottom, right);
case EMPTY:
return String.format("BorderFactory.createEmptyBorder(%d, %d, %d, %d)",
top, left, bottom, right);
default:
return "### Look, here's an unknown border! $$$";
}
}
}
class Insets {
@XmlAttribute int top;
@XmlAttribute int left;
@XmlAttribute int bottom;
@XmlAttribute int right;
public Insets() {
this(0, 0, 0, 0);
}
public Insets(int top, int left, int bottom, int right) {
this.top = top;
this.left = left;
this.bottom = bottom;
this.right = right;
}
public String write(boolean uiResource) {
String uiSuffix = (uiResource ? "UIResource" : "");
return String.format("new Insets%s(%d, %d, %d, %d)",
uiSuffix, top, left, bottom, right);
}
}
class Dimension {
@XmlAttribute int width;
@XmlAttribute int height;
public String write(boolean uiResource) {
String uiSuffix = (uiResource ? "UIResource" : "");
return String.format("new Dimension%s(%d, %d)", uiSuffix, width, height);
}
}
class Canvas {
@XmlElement private Dimension size;
public Dimension getSize() { return size; }
@XmlElement(name="layer") private List<Layer> layers;
public List<Layer> getLayers() { return layers; }
@XmlElement private Insets stretchingInsets = null;
public Insets getStretchingInsets() { return stretchingInsets; }
public boolean isBlank() {
return layers.size() == 0 || (layers.size() == 1 && layers.get(0).isEmpty());
}
}
class Layer {
/** List of shapes in this layer, first shape is painted on top */
@XmlElements({
@XmlElement(name = "ellipse", type = Ellipse.class),
@XmlElement(name = "path", type = Path.class),
@XmlElement(name = "rectangle", type = Rectangle.class)
})
@XmlElementWrapper(name="shapes")
private List<Shape> shapes = new ArrayList<Shape>();
public List<Shape> getShapes() { return shapes; }
public boolean isEmpty() {
return shapes.isEmpty();
}
}
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* 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
......@@ -22,64 +22,105 @@
* 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;
package build.tools.generatenimbus;
/**
* 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
}
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
private String name;
private PropertyType type;
private Object value;
public class UIDefault<T> {
@XmlAttribute private String name;
private T value;
protected UIProperty() {
public String getName() {
return name;
}
public UIProperty(String name, PropertyType type, Object value) {
this.name = name;
this.type = type;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
// =================================================================================================================
// Bean Methods
class UIColor extends UIDefault<Matte> {
public String getName() {
return name;
@XmlElement
public void setMatte(Matte m) {
setValue(m);
}
public void setName(String name) {
String old = getName();
this.name = name;
firePropertyChange("name", old, getName());
public String write() {
return String.format(" addColor(d, \"%s\", %s);\n",
getName(), getValue().write());
}
}
public PropertyType getType() {
return type;
class UIFont extends UIDefault<Typeface> {
@XmlElement
public void setTypeface(Typeface t) {
setValue(t);
}
public void setType(PropertyType type) {
PropertyType old = getType();
this.type = type;
firePropertyChange("type", old, getType());
public String write() {
return String.format(" d.put(\"%s\", %s);\n",
getName(), getValue().write());
}
}
public Object getValue() {
return value;
class UIProperty extends UIDefault<String> {
public static enum PropertyType {
BOOLEAN, INT, FLOAT, DOUBLE, STRING, FONT, COLOR, INSETS, DIMENSION, BORDER
}
@XmlAttribute private PropertyType type;
public void setValue(Object value) {
Object old = getValue();
this.value = value;
firePropertyChange("value", old, getValue());
@XmlElement private Border border;
@XmlElement private Dimension dimension;
@XmlElement private Insets insets;
@XmlElement private Matte matte;
@XmlElement private Typeface typeface;
@XmlAttribute
@Override public void setValue(String value) {
super.setValue(value);
}
public String write(String prefix) {
switch (type) {
case BOOLEAN:
return String.format(" d.put(\"%s%s\", Boolean.%s);\n",
prefix, getName(), getValue().toUpperCase()); ///autobox
case STRING:
return String.format(" d.put(\"%s%s\", \"%s\");\n",
prefix, getName(), getValue());
case INT:
return String.format(" d.put(\"%s%s\", new Integer(%s));\n",
prefix, getName(), getValue());
case FLOAT:
return String.format(" d.put(\"%s%s\", new Float(%sf));\n",
prefix, getName(), getValue());
case DOUBLE:
return String.format(" d.put(\"%s%s\", new Double(%s));\n",
prefix, getName(), getValue());
case COLOR:
return String.format(" addColor(d, \"%s%s\", %s);\n",
prefix, getName(), matte.write());
case FONT:
return String.format(" d.put(\"%s%s\", %s);\n",
prefix, getName(), typeface.write());
case INSETS:
return String.format(" d.put(\"%s%s\", %s);\n",
prefix, getName(), insets.write(true));
case DIMENSION:
return String.format(" d.put(\"%s%s\", new DimensionUIResource(%d, %d));\n",
prefix, getName(), dimension.width, dimension.height);
case BORDER:
return String.format(" d.put(\"%s%s\", new BorderUIResource(%s));\n",
prefix, getName(), border.write());
default:
return "### Look, something's wrong with UIProperty.write() $$$";
}
}
}
/*
* 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 build.tools.generatenimbus;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
class UIStyle {
public static enum CacheMode {
NO_CACHING, FIXED_SIZES, NINE_SQUARE_SCALE
}
@XmlElement private UIColor textForeground = null;
@XmlElement(name="inherit-textForeground")
private boolean textForegroundInherited = true;
@XmlElement private UIColor textBackground = null;
@XmlElement(name="inherit-textBackground")
private boolean textBackgroundInherited = true;
@XmlElement private UIColor background = null;
@XmlElement(name="inherit-background")
private boolean backgroundInherited = true;
@XmlElement private boolean cacheSettingsInherited = true;
@XmlElement CacheMode cacheMode = CacheMode.FIXED_SIZES;
@XmlElement String maxHozCachedImgScaling = "1.0";
@XmlElement String maxVertCachedImgScaling = "1.0";
@XmlElement(name="uiProperty")
@XmlElementWrapper(name="uiproperties")
private List<UIProperty> uiProperties = new ArrayList<UIProperty>();
private UIStyle parentStyle = null;
public void setParentStyle(UIStyle parentStyle) {
this.parentStyle = parentStyle;
}
public CacheMode getCacheMode() {
if (cacheSettingsInherited) {
return (parentStyle == null ?
CacheMode.FIXED_SIZES : parentStyle.getCacheMode());
} else {
return cacheMode;
}
}
public String getMaxHozCachedImgScaling() {
if (cacheSettingsInherited) {
return (parentStyle == null ?
"1.0" : parentStyle.getMaxHozCachedImgScaling());
} else {
return maxHozCachedImgScaling;
}
}
public String getMaxVertCachedImgScaling() {
if (cacheSettingsInherited) {
return (parentStyle == null ?
"1.0" : parentStyle.getMaxVertCachedImgScaling());
} else {
return maxVertCachedImgScaling;
}
}
public String write(String prefix) {
StringBuilder sb = new StringBuilder();
if (! textForegroundInherited) {
sb.append(String.format(" addColor(d, \"%s%s\", %s);\n",
prefix, "textForeground", textForeground.getValue().write()));
}
if (! textBackgroundInherited) {
sb.append(String.format(" addColor(d, \"%s%s\", %s);\n",
prefix, "textBackground", textBackground.getValue().write()));
}
if (! backgroundInherited) {
sb.append(String.format(" addColor(d, \"%s%s\", %s);\n",
prefix, "background", background.getValue().write()));
}
for (UIProperty property : uiProperties) {
sb.append(property.write(prefix));
}
return sb.toString();
}
}
class UIRegion {
@XmlAttribute protected String name;
@XmlAttribute protected String key;
@XmlAttribute private boolean opaque = false;
@XmlElement private Insets contentMargins = new Insets(0, 0, 0, 0);
@XmlElement(name="state")
@XmlElementWrapper(name="backgroundStates")
protected List<UIState> backgroundStates = new ArrayList<UIState>();
public List<UIState> getBackgroundStates() { return backgroundStates; }
@XmlElement(name="state")
@XmlElementWrapper(name="foregroundStates")
protected List<UIState> foregroundStates = new ArrayList<UIState>();
public List<UIState> getForegroundStates() { return foregroundStates; }
@XmlElement(name="state")
@XmlElementWrapper(name="borderStates")
protected List<UIState> borderStates = new ArrayList<UIState>();
public List<UIState> getBorderStates() { return borderStates; }
@XmlElement private UIStyle style = new UIStyle();
@XmlElements({
@XmlElement(name = "region", type = UIRegion.class),
@XmlElement(name = "uiComponent", type = UIComponent.class),
@XmlElement(name = "uiIconRegion", type = UIIconRegion.class)
})
@XmlElementWrapper(name="regions")
private List<UIRegion> subRegions = new ArrayList<UIRegion>();
public List<UIRegion> getSubRegions() { return subRegions; }
protected void initStyles(UIStyle parentStyle) {
style.setParentStyle(parentStyle);
for (UIState state: backgroundStates) {
state.getStyle().setParentStyle(this.style);
}
for (UIState state: foregroundStates) {
state.getStyle().setParentStyle(this.style);
}
for (UIState state: borderStates) {
state.getStyle().setParentStyle(this.style);
}
for (UIRegion region: subRegions) {
region.initStyles(this.style);
}
}
public String getKey() {
return key == null || "".equals(key) ? name : key;
}
private boolean hasCanvas() {
for (UIState s : backgroundStates) {
if (s.hasCanvas()) return true;
}
for (UIState s : borderStates) {
if (s.hasCanvas()) return true;
}
for (UIState s : foregroundStates) {
if (s.hasCanvas()) return true;
}
for (UIRegion r: subRegions) {
if (r.hasCanvas()) return true;
}
return false;
}
public void write(StringBuilder sb, StringBuilder styleBuffer,
UIComponent comp, String prefix, String pkg) {
// write content margins
sb.append(String.format(" d.put(\"%s.contentMargins\", %s);\n",
prefix, contentMargins.write(true)));
// write opaque if true
if (opaque) {
sb.append(String.format(" d.put(\"%s.opaque\", Boolean.TRUE);\n", prefix));
}
// register component with LAF
String regionCode = "Region." + Utils.regionNameToCaps(name);
styleBuffer.append(String.format(" register(%s, \"%s\");\n",
regionCode, prefix));
//write the State, if necessary
StringBuffer regString = new StringBuffer();
List<UIStateType> types = comp.getStateTypes();
if (types != null && types.size() > 0) {
for (UIStateType type : types) {
regString.append(type.getKey());
regString.append(",");
}
//remove the last ","
regString.deleteCharAt(regString.length() - 1);
}
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
sb.append(String.format(" d.put(\"%s.States\", \"%s\");\n",
prefix, regString));
}
// 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.
//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.
String className = Utils.normalize(prefix) + synthState + "State";
sb.append(String.format(" d.put(\"%s.%s\", new %s());\n",
prefix, synthState, className));
String body = type.getCodeSnippet();
Map<String, String> variables = Generator.getVariables();
variables.put("STATE_NAME", className);
variables.put("STATE_KEY", synthState);
variables.put("BODY", body);
Generator.writeSrcFile("StateImpl", variables, className);
}
}
// write style
sb.append(style.write(prefix + '.'));
String fileName = Utils.normalize(prefix) + "Painter";
boolean hasCanvas = hasCanvas();
if (hasCanvas) {
PainterGenerator.writePainter(this, fileName);
}
// write states ui defaults
for (UIState state : backgroundStates) {
state.write(sb, prefix, pkg, fileName, "background");
}
for (UIState state : foregroundStates) {
state.write(sb, prefix, pkg, fileName, "foreground");
}
for (UIState state : borderStates) {
state.write(sb, prefix, pkg, fileName, "border");
}
// handle sub regions
for (UIRegion subreg : subRegions) {
String p = prefix;
if (! (subreg instanceof UIIconRegion)) {
p = prefix + ":" + Utils.escape(subreg.getKey());
}
UIComponent c = comp;
if (subreg instanceof UIComponent) {
c = (UIComponent) subreg;
}
subreg.write(sb, styleBuffer, c, p, pkg);
}
}
}
class UIIconRegion extends UIRegion {
@XmlAttribute private String basicKey;
@Override public void write(StringBuilder sb, StringBuilder styleBuffer, UIComponent comp, String prefix, String pkg) {
Dimension size = null;
String fileNamePrefix = Utils.normalize(prefix) + "Painter";
// write states ui defaults
for (UIState state : backgroundStates) {
Canvas canvas = state.getCanvas();
if (!canvas.isBlank()) {
state.write(sb, prefix, pkg, fileNamePrefix, getKey());
size = canvas.getSize();
}
}
if (size != null) {
// Put SynthIconImpl wrapper in UiDefaults
String k = (basicKey == null ? prefix + "." + getKey() : basicKey);
sb.append(String.format(
" d.put(\"%s\", new NimbusIcon(\"%s\", \"%sPainter\", %d, %d));\n",
k, prefix, getKey(), size.width, size.height));
}
}
}
class UIComponent extends UIRegion {
@XmlAttribute private String componentName;
@XmlElement(name="stateType")
@XmlElementWrapper(name="stateTypes")
private List<UIStateType> stateTypes = new ArrayList<UIStateType>();
public List<UIStateType> getStateTypes() { return stateTypes; }
@Override public String getKey() {
if (key == null || "".equals(key)) {
if (componentName == null || "".equals(componentName)) {
return name;
} else {
return "\"" + componentName + "\"";
}
} else {
return key;
}
}
}
class UIState {
@XmlAttribute private String stateKeys;
public String getStateKeys() { return stateKeys; }
/** Indicates whether to invert the meaning of the 9-square stretching insets */
@XmlAttribute private boolean inverted;
/** A cached string representing the list of stateKeys deliminated with "+" */
private String cachedName = null;
@XmlElement private Canvas canvas;
public Canvas getCanvas() { return canvas; }
@XmlElement private UIStyle style;
public UIStyle getStyle() { return style; }
public boolean hasCanvas() {
return ! canvas.isBlank();
}
public static List<String> stringToKeys(String keysString) {
return Arrays.asList(keysString.split("\\+"));
}
public String getName() {
if (cachedName == null) {
StringBuilder buf = new StringBuilder();
List<String> keys = stringToKeys(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 void write(StringBuilder sb, String prefix, String pkg, String fileNamePrefix, String painterPrefix) {
String statePrefix = prefix + "[" + getName() + "]";
// write state style
sb.append(style.write(statePrefix + '.'));
// write painter
if (hasCanvas()) {
writeLazyPainter(sb, statePrefix, pkg, fileNamePrefix, painterPrefix);
}
}
private void writeLazyPainter(StringBuilder sb, String statePrefix, String packageNamePrefix, String fileNamePrefix, String painterPrefix) {
String cacheModeString = "AbstractRegionPainter.PaintContext.CacheMode." + style.getCacheMode();
String stateConstant = Utils.statesToConstantName(painterPrefix + "_" + stateKeys);
sb.append(String.format(
" d.put(\"%s.%sPainter\", new LazyPainter(\"%s.%s\", %s.%s, %s, %s, %b, %s, %s, %s));\n",
statePrefix, painterPrefix, packageNamePrefix, fileNamePrefix,
fileNamePrefix, stateConstant, canvas.getStretchingInsets().write(false),
canvas.getSize().write(false), inverted, cacheModeString,
Utils.formatDouble(style.getMaxHozCachedImgScaling()),
Utils.formatDouble(style.getMaxVertCachedImgScaling())));
}
}
class UIStateType {
@XmlAttribute private String key;
public String getKey() { return key; }
@XmlElement private String codeSnippet;
public String getCodeSnippet() { return codeSnippet; }
}
......@@ -22,158 +22,61 @@
* 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() {}
package build.tools.generatenimbus;
/**
* 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();
}
import java.util.ArrayList;
import java.util.List;
import javax.swing.plaf.synth.Region;
//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;
}
public class Utils {
//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();
public static String escape(String s) {
return s.replace("\"", "\\\"");
}
/**
* 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) {
public static String normalize(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;
StringBuilder buf = new StringBuilder();
List<String> parts = new ArrayList<String>();
boolean capitalize = false;
for (int i = 0; i < src.length; i++) {
switch (src[i]) {
case '\\':
case '"':
break;
case '.':
capitalize = true;
break;
case ':':
parts.add(buf.toString());
buf.delete(0, buf.length());
capitalize = true;
break;
default:
buf.append(capitalize ? Character.toUpperCase(src[i]) : src[i]);
capitalize = false;
break;
}
//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);
}
parts.add(buf.toString());
/**
* 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");
// Try to optimize long class names by omitting repeating prefixes, e.g.
// SliderTrackPainter.java instead of SliderSliderTrackPainter.java
String result = parts.get(0);
for (int i = 1; i < parts.size(); i++) {
String part = parts.get(i);
if (part.startsWith(result)) {
result = part;
} else {
result += part;
}
}
return buffer.toString();
return result;
}
/**
* 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) {
public static String regionNameToCaps(String regionName) {
if (Region.ARROW_BUTTON.getName().equals(regionName)) {
return "ARROW_BUTTON";
} else if (Region.BUTTON.getName().equals(regionName)) {
......@@ -289,7 +192,24 @@ class GeneratorUtils {
} else if (Region.VIEWPORT.getName().equals(regionName)) {
return "VIEWPORT";
}
System.err.println("[Info] Couldn't find a Region for " + regionName);
return null;
throw new RuntimeException("Bad Region name " + regionName);
}
public static String statesToConstantName(String states) {
String s = states.replace(" ", "");
s = states.replace("+", "_");
return s.toUpperCase();
}
//takes a states string of the form Enabled+Foo+Bar.
//removes any whitespace. Replaces the + signs with And.
public static String statesToClassName(String states) {
String s = states.replace(" ", "");
s = states.replace("+", "And");
return s;
}
public static String formatDouble(String doubleValue) {
return doubleValue.replace("INF", "Double.POSITIVE_INFINITY");
}
}
#
# 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)
/*
* 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;
}
}
/*
* 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;
}
}
}
/*
* 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
};
}
/*
* 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);
}
}
/*
* 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);
}
}
}
<?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>
/*
* 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));
}
}
/*
* 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);
}
}
/*
* 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;
}
/*
* 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();
}
}
/*
* 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();
}
/*
* 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();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册