diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/lib/bancika-gui-framework.jar b/ diy-layout-creator --username bancika@gmail.com/DIYLC/lib/bancika-gui-framework.jar index d3374bf4..acef8105 100644 Binary files a/ diy-layout-creator --username bancika@gmail.com/DIYLC/lib/bancika-gui-framework.jar and b/ diy-layout-creator --username bancika@gmail.com/DIYLC/lib/bancika-gui-framework.jar differ diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/library/main.jar b/ diy-layout-creator --username bancika@gmail.com/DIYLC/library/main.jar index 3634937b..bb39c9f5 100644 Binary files a/ diy-layout-creator --username bancika@gmail.com/DIYLC/library/main.jar and b/ diy-layout-creator --username bancika@gmail.com/DIYLC/library/main.jar differ diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/common/PropertyWrapper.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/common/PropertyWrapper.java index 20829d82..d320695e 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/common/PropertyWrapper.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/common/PropertyWrapper.java @@ -3,6 +3,8 @@ package org.diylc.common; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import org.diylc.core.IPropertyValidator; + /** * Entity class for editable properties extracted from component objects. * Represents a single editable property together with it's current value. @@ -17,19 +19,21 @@ public class PropertyWrapper implements Cloneable { private Method setter; private Method getter; private boolean defaultable; + private IPropertyValidator validator; public PropertyWrapper(String name, Class type, Method getter, Method setter, - boolean defaultable) { + boolean defaultable, IPropertyValidator validator) { super(); this.name = name; this.type = type; this.getter = getter; this.setter = setter; this.defaultable = defaultable; + this.validator = validator; } - public void readFrom(Object object) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { + public void readFrom(Object object) throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { this.value = getter.invoke(object); } @@ -42,8 +46,8 @@ public class PropertyWrapper implements Cloneable { // } // } - public void writeTo(Object object) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { + public void writeTo(Object object) throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { setter.invoke(object, value); } @@ -67,8 +71,8 @@ public class PropertyWrapper implements Cloneable { return defaultable; } - public void setDefaultable(boolean defaultable) { - this.defaultable = defaultable; + public IPropertyValidator getValidator() { + return validator; } // @Override diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/AllowAllValidator.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/AllowAllValidator.java new file mode 100644 index 00000000..0b194256 --- /dev/null +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/AllowAllValidator.java @@ -0,0 +1,13 @@ +package org.diylc.core; + +/** + * Validator that allows all values. + * + * @author Branislav Stojkovic + */ +public class AllowAllValidator implements IPropertyValidator { + + @Override + public void validate(Object value) throws ValidationException { + } +} diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/IPropertyValidator.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/IPropertyValidator.java new file mode 100644 index 00000000..9dbdee24 --- /dev/null +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/IPropertyValidator.java @@ -0,0 +1,16 @@ +package org.diylc.core; + +/** + * Interface for validating property value changes. + * + * @author Branislav Stojkovic + */ +public interface IPropertyValidator { + + /** + * @param value + * @throws ValidationException + * if validation fails. Message will contain the reason. + */ + void validate(Object value) throws ValidationException; +} diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/Project.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/Project.java index 2b54b590..942bd1ee 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/Project.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/Project.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Set; import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.PositiveMeasureValidator; import org.diylc.core.measures.Size; import org.diylc.core.measures.SizeUnit; @@ -92,7 +93,7 @@ public class Project implements Serializable { this.height = height; } - @EditableProperty(name = "Grid spacing") + @EditableProperty(name = "Grid spacing", validatorClass = SpacingValidator.class) public Size getGridSpacing() { return gridSpacing; } @@ -118,7 +119,7 @@ public class Project implements Serializable { public Set>> getGroups() { return groups; } - + public Set getLockedLayers() { return lockedLayers; } @@ -177,12 +178,27 @@ public class Project implements Serializable { return false; return true; } - + @Override public String toString() { return title; } + public static class SpacingValidator extends PositiveMeasureValidator { + + @Override + public void validate(Object value) throws ValidationException { + super.validate(value); + Size size = (Size) value; + if (size.compareTo(new Size(1d, SizeUnit.mm)) < 0) { + throw new ValidationException("must be greater than 1mm"); + } + if (size.compareTo(new Size(1d, SizeUnit.in)) > 0) { + throw new ValidationException("must be less than 1in"); + } + } + } + // @Override // public Project clone() throws CloneNotSupportedException { // List clonedComponents = new diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/ValidationException.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/ValidationException.java new file mode 100644 index 00000000..f78cc348 --- /dev/null +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/ValidationException.java @@ -0,0 +1,11 @@ + +package org.diylc.core; + +public class ValidationException extends Exception { + + private static final long serialVersionUID = 1L; + + public ValidationException(String message) { + super(message); + } +} diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/EditableProperty.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/EditableProperty.java index 14a926a0..9642d074 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/EditableProperty.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/EditableProperty.java @@ -3,6 +3,9 @@ package org.diylc.core.annotations; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.diylc.core.AllowAllValidator; +import org.diylc.core.IPropertyValidator; + /** * Used to annotate editable component property. Editable property XYZ must have * both getter and setter named getXYZ and setXYZ @@ -30,4 +33,10 @@ public @interface EditableProperty { * @return */ boolean defaultable() default true; + + /** + * Class of validator to use to + * @return + */ + Class validatorClass() default AllowAllValidator.class; } diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/PositiveMeasureValidator.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/PositiveMeasureValidator.java new file mode 100644 index 00000000..98b91b75 --- /dev/null +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/annotations/PositiveMeasureValidator.java @@ -0,0 +1,20 @@ +package org.diylc.core.annotations; + +import org.diylc.core.IPropertyValidator; +import org.diylc.core.ValidationException; +import org.diylc.core.measures.AbstractMeasure; + +public class PositiveMeasureValidator implements IPropertyValidator { + + @Override + public void validate(Object value) throws ValidationException { + if (value instanceof AbstractMeasure) { + AbstractMeasure measure = (AbstractMeasure) value; + if (measure.getValue() <= 0) { + throw new ValidationException("must be greater than zero."); + } + } else { + throw new ValidationException("wrong data type, measure expected."); + } + } +} diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/measures/Size.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/measures/Size.java index ec3b06a3..9aee9460 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/measures/Size.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/core/measures/Size.java @@ -2,7 +2,7 @@ package org.diylc.core.measures; import org.diylc.utils.Constants; -public class Size extends AbstractMeasure { +public class Size extends AbstractMeasure implements Comparable { private static final long serialVersionUID = 1L; @@ -39,4 +39,9 @@ public class Size extends AbstractMeasure { } throw new IllegalArgumentException("Could not parse size: " + value); } + + @Override + public int compareTo(Size o) { + return new Double(value * unit.getFactor()).compareTo(o.getValue() * o.getUnit().getFactor()); + } } diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/ComponentProcessor.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/ComponentProcessor.java index d98c59fa..32f1c365 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/ComponentProcessor.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/ComponentProcessor.java @@ -19,6 +19,7 @@ import org.diylc.common.ComponentType; import org.diylc.common.PropertyWrapper; import org.diylc.core.CreationMethod; import org.diylc.core.IDIYComponent; +import org.diylc.core.IPropertyValidator; import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.EditableProperty; @@ -35,7 +36,8 @@ public class ComponentProcessor { private static ComponentProcessor instance; - private Map, List> propertyCache; + private Map> propertyCache; + private Map propertyValidatorCache; private Map componentTypeMap; private Cloner cloner; @@ -50,8 +52,9 @@ public class ComponentProcessor { private ComponentProcessor() { super(); this.cloner = new Cloner(); - this.propertyCache = new HashMap, List>(); + this.propertyCache = new HashMap>(); this.componentTypeMap = new HashMap(); + this.propertyValidatorCache = new HashMap(); } public ComponentType extractComponentTypeFrom(Class> clazz) { @@ -117,8 +120,8 @@ public class ComponentProcessor { * @return */ public List extractProperties(Class clazz) { - if (propertyCache.containsKey(clazz)) { - return cloner.deepClone(propertyCache.get(clazz)); + if (propertyCache.containsKey(clazz.getName())) { + return cloner.deepClone(propertyCache.get(clazz.getName())); } List properties = new ArrayList(); for (Method method : clazz.getMethods()) { @@ -133,10 +136,13 @@ public class ComponentProcessor { } else { name = annotation.name(); } + IPropertyValidator validator = getPropertyValidator(annotation + .validatorClass()); Method setter = clazz.getMethod("set" + method.getName().substring(3), method.getReturnType()); PropertyWrapper property = new PropertyWrapper(name, - method.getReturnType(), method, setter, annotation.defaultable()); + method.getReturnType(), method, setter, annotation.defaultable(), + validator); properties.add(property); } } catch (NoSuchMethodException e) { @@ -146,7 +152,7 @@ public class ComponentProcessor { } } - propertyCache.put(clazz, properties); + propertyCache.put(clazz.getName(), properties); return cloner.deepClone(properties); } @@ -187,4 +193,19 @@ public class ComponentProcessor { Collections.sort(properties, ComparatorFactory.getInstance().getPropertyNameComparator()); return properties; } + + private IPropertyValidator getPropertyValidator(Class clazz) { + if (propertyValidatorCache.containsKey(clazz.getName())) { + return propertyValidatorCache.get(clazz.getName()); + } + IPropertyValidator validator; + try { + validator = clazz.newInstance(); + } catch (Exception e) { + LOG.error("Could not instantiate validator for " + clazz.getName(), e); + return null; + } + propertyValidatorCache.put(clazz.getName(), validator); + return validator; + } } diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java index 6ff3ebe3..b8242a71 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java @@ -18,10 +18,12 @@ import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import org.apache.log4j.Logger; import org.diylc.common.PropertyWrapper; +import org.diylc.core.ValidationException; import com.diyfever.gui.ButtonDialog; @@ -65,6 +67,23 @@ public class PropertyEditorDialog extends ButtonDialog { // setLocationRelativeTo(owner); } + @Override + protected boolean validateInput(String button) { + if (button.equals(ButtonDialog.OK)) { + for (PropertyWrapper property : properties) { + try { + property.getValidator().validate(property.getValue()); + } catch (ValidationException ve) { + JOptionPane.showMessageDialog(PropertyEditorDialog.this, "Input error for \"" + + property.getName() + "\": " + ve.getMessage(), "Error", + JOptionPane.ERROR_MESSAGE); + return false; + } + } + } + return true; + } + private JPanel createEditorFields() { JPanel editorPanel = new JPanel(new GridBagLayout()); editorPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); diff --git a/ diy-layout-creator --username bancika@gmail.com/Library/lib/diylc.jar b/ diy-layout-creator --username bancika@gmail.com/Library/lib/diylc.jar index 21dbaea5..d744a258 100644 Binary files a/ diy-layout-creator --username bancika@gmail.com/Library/lib/diylc.jar and b/ diy-layout-creator --username bancika@gmail.com/Library/lib/diylc.jar differ diff --git a/ diy-layout-creator --username bancika@gmail.com/Library/src/org/diylc/components/passive/Resistor.java b/ diy-layout-creator --username bancika@gmail.com/Library/src/org/diylc/components/passive/Resistor.java index 69efcc02..dfade752 100644 --- a/ diy-layout-creator --username bancika@gmail.com/Library/src/org/diylc/components/passive/Resistor.java +++ b/ diy-layout-creator --username bancika@gmail.com/Library/src/org/diylc/components/passive/Resistor.java @@ -12,6 +12,7 @@ import org.diylc.core.CreationMethod; import org.diylc.core.IDIYComponent; import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.PositiveMeasureValidator; import org.diylc.core.measures.Resistance; import org.diylc.core.measures.ResistanceUnit; import org.diylc.core.measures.Size; @@ -36,7 +37,7 @@ public class Resistor extends AbstractLeadedComponent { this.borderColor = BORDER_COLOR; } - @EditableProperty + @EditableProperty(validatorClass = PositiveMeasureValidator.class) public Resistance getValue() { return value; }