Some components can be placed in any layer using Send to Back/Bring to Front

This commit is contained in:
bancika
2012-08-21 11:06:19 +00:00
parent e3b1f0d4e6
commit 5adbc2c6ca
4 changed files with 87 additions and 59 deletions
@@ -24,12 +24,13 @@ public class ComponentType {
private Icon icon; private Icon icon;
private Class<? extends IDIYComponent<?>> instanceClass; private Class<? extends IDIYComponent<?>> instanceClass;
private double zOrder; private double zOrder;
private boolean flexibleZOrder;
private boolean stretchable; private boolean stretchable;
private BomPolicy bomPolicy; private BomPolicy bomPolicy;
public ComponentType(String name, String description, CreationMethod creationMethod, public ComponentType(String name, String description, CreationMethod creationMethod,
String category, String namePrefix, String author, Icon icon, String category, String namePrefix, String author, Icon icon,
Class<? extends IDIYComponent<?>> instanceClass, double zOrder, Class<? extends IDIYComponent<?>> instanceClass, double zOrder, boolean flexibleZOrder,
boolean stretchable, BomPolicy bomPolicy) { boolean stretchable, BomPolicy bomPolicy) {
super(); super();
this.name = name; this.name = name;
@@ -41,6 +42,7 @@ public class ComponentType {
this.icon = icon; this.icon = icon;
this.instanceClass = instanceClass; this.instanceClass = instanceClass;
this.zOrder = zOrder; this.zOrder = zOrder;
this.flexibleZOrder = flexibleZOrder;
this.stretchable = stretchable; this.stretchable = stretchable;
this.bomPolicy = bomPolicy; this.bomPolicy = bomPolicy;
} }
@@ -81,6 +83,10 @@ public class ComponentType {
return zOrder; return zOrder;
} }
public boolean isFlexibleZOrder() {
return flexibleZOrder;
}
public boolean isStretchable() { public boolean isStretchable() {
return stretchable; return stretchable;
} }
@@ -53,6 +53,13 @@ public @interface ComponentDescriptor {
*/ */
double zOrder(); double zOrder();
/**
* @return true if the component may go beyond it's predefined layer. In
* that case, <code>zOrder</code> is used as initial z order of the
* component.
*/
boolean flexibleZOrder() default false;
/** /**
* @return when false, moving one control point will cause all the others to * @return when false, moving one control point will cause all the others to
* move together with it. * move together with it.
@@ -33,7 +33,8 @@ import com.rits.cloning.Cloner;
*/ */
public class ComponentProcessor { public class ComponentProcessor {
private static final Logger LOG = Logger.getLogger(ComponentProcessor.class); private static final Logger LOG = Logger
.getLogger(ComponentProcessor.class);
private static ComponentProcessor instance; private static ComponentProcessor instance;
@@ -58,7 +59,8 @@ public class ComponentProcessor {
this.propertyValidatorCache = new HashMap<String, IPropertyValidator>(); this.propertyValidatorCache = new HashMap<String, IPropertyValidator>();
} }
public ComponentType extractComponentTypeFrom(Class<? extends IDIYComponent<?>> clazz) { public ComponentType extractComponentTypeFrom(
Class<? extends IDIYComponent<?>> clazz) {
if (componentTypeMap.containsKey(clazz.getName())) { if (componentTypeMap.containsKey(clazz.getName())) {
return componentTypeMap.get(clazz.getName()); return componentTypeMap.get(clazz.getName());
} }
@@ -70,10 +72,12 @@ public class ComponentProcessor {
String author; String author;
Icon icon; Icon icon;
double zOrder; double zOrder;
boolean flexibleZOrder;
boolean stretchable; boolean stretchable;
BomPolicy bomPolicy; BomPolicy bomPolicy;
if (clazz.isAnnotationPresent(ComponentDescriptor.class)) { if (clazz.isAnnotationPresent(ComponentDescriptor.class)) {
ComponentDescriptor annotation = clazz.getAnnotation(ComponentDescriptor.class); ComponentDescriptor annotation = clazz
.getAnnotation(ComponentDescriptor.class);
name = annotation.name(); name = annotation.name();
description = annotation.description(); description = annotation.description();
creationMethod = annotation.creationMethod(); creationMethod = annotation.creationMethod();
@@ -81,6 +85,7 @@ public class ComponentProcessor {
namePrefix = annotation.instanceNamePrefix(); namePrefix = annotation.instanceNamePrefix();
author = annotation.author(); author = annotation.author();
zOrder = annotation.zOrder(); zOrder = annotation.zOrder();
flexibleZOrder = annotation.flexibleZOrder();
stretchable = annotation.stretchable(); stretchable = annotation.stretchable();
bomPolicy = annotation.bomPolicy(); bomPolicy = annotation.bomPolicy();
} else { } else {
@@ -91,28 +96,30 @@ public class ComponentProcessor {
namePrefix = "Unknown"; namePrefix = "Unknown";
author = "Unknown"; author = "Unknown";
zOrder = IDIYComponent.COMPONENT; zOrder = IDIYComponent.COMPONENT;
flexibleZOrder = false;
stretchable = true; stretchable = true;
bomPolicy = BomPolicy.SHOW_ALL_NAMES; bomPolicy = BomPolicy.SHOW_ALL_NAMES;
} }
icon = null; icon = null;
// Draw component icon. // Draw component icon.
try { try {
IDIYComponent<?> componentInstance = (IDIYComponent<?>) clazz.newInstance(); IDIYComponent<?> componentInstance = (IDIYComponent<?>) clazz
Image image = new BufferedImage(Presenter.ICON_SIZE, Presenter.ICON_SIZE, .newInstance();
Image image = new BufferedImage(Presenter.ICON_SIZE,
Presenter.ICON_SIZE,
java.awt.image.BufferedImage.TYPE_INT_ARGB); java.awt.image.BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) image.getGraphics(); Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON); RenderingHints.VALUE_ANTIALIAS_ON);
componentInstance.drawIcon(g2d, Presenter.ICON_SIZE, Presenter.ICON_SIZE); componentInstance.drawIcon(g2d, Presenter.ICON_SIZE,
Presenter.ICON_SIZE);
icon = new ImageIcon(image); icon = new ImageIcon(image);
} catch (InstantiationException e) { } catch (Exception e) {
e.printStackTrace(); throw new RuntimeException(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
ComponentType componentType = new ComponentType(name, description, creationMethod, ComponentType componentType = new ComponentType(name, description,
category, namePrefix, author, icon, clazz, zOrder, stretchable, bomPolicy); creationMethod, category, namePrefix, author, icon, clazz,
zOrder, flexibleZOrder, stretchable, bomPolicy);
componentTypeMap.put(clazz.getName(), componentType); componentTypeMap.put(clazz.getName(), componentType);
return componentType; return componentType;
} }
@@ -133,7 +140,8 @@ public class ComponentProcessor {
try { try {
if (method.isAnnotationPresent(EditableProperty.class) if (method.isAnnotationPresent(EditableProperty.class)
&& !method.isAnnotationPresent(Deprecated.class)) { && !method.isAnnotationPresent(Deprecated.class)) {
EditableProperty annotation = method.getAnnotation(EditableProperty.class); EditableProperty annotation = method
.getAnnotation(EditableProperty.class);
String name; String name;
if (annotation.name().equals("")) { if (annotation.name().equals("")) {
name = method.getName().substring(3); name = method.getName().substring(3);
@@ -142,16 +150,18 @@ public class ComponentProcessor {
} }
IPropertyValidator validator = getPropertyValidator(annotation IPropertyValidator validator = getPropertyValidator(annotation
.validatorClass()); .validatorClass());
Method setter = clazz.getMethod("set" + method.getName().substring(3), Method setter = clazz.getMethod("set"
method.getReturnType()); + method.getName().substring(3), method
.getReturnType());
PropertyWrapper property = new PropertyWrapper(name, PropertyWrapper property = new PropertyWrapper(name,
method.getReturnType(), method.getName(), setter.getName(), method.getReturnType(), method.getName(),
annotation.defaultable(), validator); setter.getName(), annotation.defaultable(),
validator);
properties.add(property); properties.add(property);
} }
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
LOG.debug("No matching setter found for \"" + method.getName() LOG.debug("No matching setter found for \""
+ "\". Skipping..."); + method.getName() + "\". Skipping...");
} }
} }
} }
@@ -181,7 +191,8 @@ public class ComponentProcessor {
} }
for (int i = 1; i < selectedComponents.size(); i++) { for (int i = 1; i < selectedComponents.size(); i++) {
IDIYComponent<?> component = selectedComponents.get(i); IDIYComponent<?> component = selectedComponents.get(i);
List<PropertyWrapper> newProperties = extractProperties(component.getClass()); List<PropertyWrapper> newProperties = extractProperties(component
.getClass());
for (PropertyWrapper property : newProperties) { for (PropertyWrapper property : newProperties) {
property.readFrom(component); property.readFrom(component);
} }
@@ -190,11 +201,14 @@ public class ComponentProcessor {
// their values match. // their values match.
for (PropertyWrapper oldProperty : properties) { for (PropertyWrapper oldProperty : properties) {
if (newProperties.contains(oldProperty)) { if (newProperties.contains(oldProperty)) {
PropertyWrapper newProperty = newProperties.get(newProperties PropertyWrapper newProperty = newProperties
.indexOf(oldProperty)); .get(newProperties.indexOf(oldProperty));
if ((newProperty.getValue() != null && newProperty.getValue() == null) if ((newProperty.getValue() != null && newProperty
|| !newProperty.getValue().equals(oldProperty.getValue())) { .getValue() == null)
// Values don't match, so the property is not unique valued. || !newProperty.getValue().equals(
oldProperty.getValue())) {
// Values don't match, so the property is not unique
// valued.
oldProperty.setUnique(false); oldProperty.setUnique(false);
} }
} }
@@ -208,11 +222,13 @@ public class ComponentProcessor {
// } // }
// } // }
} }
Collections.sort(properties, ComparatorFactory.getInstance().getPropertyNameComparator()); Collections.sort(properties, ComparatorFactory.getInstance()
.getPropertyNameComparator());
return properties; return properties;
} }
private IPropertyValidator getPropertyValidator(Class<? extends IPropertyValidator> clazz) { private IPropertyValidator getPropertyValidator(
Class<? extends IPropertyValidator> clazz) {
if (propertyValidatorCache.containsKey(clazz.getName())) { if (propertyValidatorCache.containsKey(clazz.getName())) {
return propertyValidatorCache.get(clazz.getName()); return propertyValidatorCache.get(clazz.getName());
} }
@@ -220,7 +236,8 @@ public class ComponentProcessor {
try { try {
validator = clazz.newInstance(); validator = clazz.newInstance();
} catch (Exception e) { } catch (Exception e) {
LOG.error("Could not instantiate validator for " + clazz.getName(), e); LOG.error("Could not instantiate validator for " + clazz.getName(),
e);
return null; return null;
} }
propertyValidatorCache.put(clazz.getName(), validator); propertyValidatorCache.put(clazz.getName(), validator);
@@ -56,8 +56,8 @@ public class Presenter implements IPlugInPort {
private static final Logger LOG = Logger.getLogger(Presenter.class); private static final Logger LOG = Logger.getLogger(Presenter.class);
public static final VersionNumber CURRENT_VERSION = new VersionNumber(3, 10, public static final VersionNumber CURRENT_VERSION = new VersionNumber(3,
0); 11, 0);
public static final String DEFAULTS_KEY_PREFIX = "default."; public static final String DEFAULTS_KEY_PREFIX = "default.";
public static final List<IDIYComponent<?>> EMPTY_SELECTION = Collections public static final List<IDIYComponent<?>> EMPTY_SELECTION = Collections
@@ -503,7 +503,8 @@ public class Presenter implements IPlugInPort {
// Notify the listeners. // Notify the listeners.
if (!oldProject.equals(currentProject)) { if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage( messageDispatcher.dispatchMessage(
EventType.PROJECT_MODIFIED, oldProject, currentProject.clone(), "Add " EventType.PROJECT_MODIFIED, oldProject,
currentProject.clone(), "Add "
+ componentTypeSlot.getName()); + componentTypeSlot.getName());
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
} }
@@ -1222,7 +1223,8 @@ public class Presenter implements IPlugInPort {
.extractComponentTypeFrom( .extractComponentTypeFrom(
(Class<? extends IDIYComponent<?>>) componentBefore (Class<? extends IDIYComponent<?>>) componentBefore
.getClass()); .getClass());
if (componentBeforeType.getZOrder() < componentType if (!componentType.isFlexibleZOrder()
&& componentBeforeType.getZOrder() < componentType
.getZOrder()) .getZOrder())
break; break;
Collections.swap(currentProject.getComponents(), index, Collections.swap(currentProject.getComponents(), index,
@@ -1232,8 +1234,7 @@ public class Presenter implements IPlugInPort {
} }
if (!oldProject.equals(currentProject)) { if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
oldProject, currentProject.clone(), oldProject, currentProject.clone(), "Send to Back");
"Send to Back");
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} }
@@ -1261,7 +1262,8 @@ public class Presenter implements IPlugInPort {
.extractComponentTypeFrom( .extractComponentTypeFrom(
(Class<? extends IDIYComponent<?>>) componentAfter (Class<? extends IDIYComponent<?>>) componentAfter
.getClass()); .getClass());
if (componentAfterType.getZOrder() > componentType if (!componentType.isFlexibleZOrder()
&& componentAfterType.getZOrder() > componentType
.getZOrder()) .getZOrder())
break; break;
Collections.swap(currentProject.getComponents(), index, Collections.swap(currentProject.getComponents(), index,
@@ -1271,8 +1273,7 @@ public class Presenter implements IPlugInPort {
} }
if (!oldProject.equals(currentProject)) { if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
oldProject, currentProject.clone(), oldProject, currentProject.clone(), "Bring to Front");
"Bring to Front");
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} }
@@ -1366,8 +1367,7 @@ public class Presenter implements IPlugInPort {
} }
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
oldProject, currentProject.clone(), oldProject, currentProject.clone(), "Renumber selection");
"Renumber selection");
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} }
@@ -1535,15 +1535,15 @@ public class Presenter implements IPlugInPort {
*/ */
private void addComponent(IDIYComponent<?> component, private void addComponent(IDIYComponent<?> component,
ComponentType componentType, boolean canCreatePads) { ComponentType componentType, boolean canCreatePads) {
int index = 0; int index = currentProject.getComponents().size();
while (index < currentProject.getComponents().size() while (index > 0
&& componentType.getZOrder() >= ComponentProcessor && componentType.getZOrder() < ComponentProcessor
.getInstance() .getInstance()
.extractComponentTypeFrom( .extractComponentTypeFrom(
(Class<? extends IDIYComponent<?>>) currentProject (Class<? extends IDIYComponent<?>>) currentProject
.getComponents().get(index).getClass()) .getComponents().get(index - 1).getClass())
.getZOrder()) { .getZOrder()) {
index++; index--;
} }
if (index < currentProject.getComponents().size()) { if (index < currentProject.getComponents().size()) {
currentProject.getComponents().add(index, component); currentProject.getComponents().add(index, component);
@@ -1610,8 +1610,7 @@ public class Presenter implements IPlugInPort {
// Notify the listeners. // Notify the listeners.
if (!oldProject.equals(currentProject)) { if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
oldProject, currentProject.clone(), oldProject, currentProject.clone(), "Edit Selection");
"Edit Selection");
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
} }
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
@@ -1653,8 +1652,7 @@ public class Presenter implements IPlugInPort {
// Notify the listeners. // Notify the listeners.
if (!oldProject.equals(currentProject)) { if (!oldProject.equals(currentProject)) {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED,
oldProject, currentProject.clone(), oldProject, currentProject.clone(), "Edit Project");
"Edit Project");
projectFileManager.notifyFileChange(); projectFileManager.notifyFileChange();
} }
drawingManager.fireZoomChanged(); drawingManager.fireZoomChanged();