diff --git a/diylc/diylc-core/src/org/diylc/common/PropertyWrapper.java b/diylc/diylc-core/src/org/diylc/common/PropertyWrapper.java index 4c32552f..07603625 100644 --- a/diylc/diylc-core/src/org/diylc/common/PropertyWrapper.java +++ b/diylc/diylc-core/src/org/diylc/common/PropertyWrapper.java @@ -4,7 +4,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.diylc.core.IPropertyValidator; -import org.diylc.core.annotations.EditableProperty; /** * Entity class for editable properties extracted from component objects. Represents a single @@ -23,12 +22,11 @@ public class PropertyWrapper implements Cloneable { private IPropertyValidator validator; private boolean unique = true; private boolean changed = false; - private String additionalOptions; private int sortOrder; - private Object[] listItems; + private Object ownerObject; public PropertyWrapper(String name, Class type, String getter, String setter, boolean defaultable, - IPropertyValidator validator, String additionalOptions, int sortOrder) { + IPropertyValidator validator, int sortOrder) { super(); this.name = name; this.type = type; @@ -36,18 +34,14 @@ public class PropertyWrapper implements Cloneable { this.setter = setter; this.defaultable = defaultable; this.validator = validator; - this.additionalOptions = additionalOptions; this.sortOrder = sortOrder; + this.ownerObject = null; } public void readFrom(Object object) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException { - this.value = object.getClass().getMethod(getter).invoke(object); - if (additionalOptions.startsWith(EditableProperty.DYNAMIC_LIST)) { - String functionName = additionalOptions.substring(EditableProperty.DYNAMIC_LIST.length()); - Method listMethod = object.getClass().getMethod(functionName); - listItems = (Object[]) listMethod.invoke(object); - } + this.ownerObject = object; + this.value = getGetter().invoke(object); } // public void readUniqueFrom(IDIYComponent component) @@ -64,6 +58,10 @@ public class PropertyWrapper implements Cloneable { object.getClass().getMethod(setter, type).invoke(object, this.value); } + public Method getGetter() throws SecurityException, NoSuchMethodException { + return getOwnerObject().getClass().getMethod(getter); + } + public String getName() { return name; } @@ -80,6 +78,10 @@ public class PropertyWrapper implements Cloneable { this.value = value; } + public Object getOwnerObject() { + return ownerObject; + } + public boolean isDefaultable() { return defaultable; } @@ -104,22 +106,10 @@ public class PropertyWrapper implements Cloneable { this.changed = changed; } - public String getAdditionalOptions() { - return additionalOptions; - } - public int getSortOrder() { return sortOrder; } - public Object[] getListItems() { - return listItems; - } - - public void setOptions(Object[] listItems) { - this.listItems = listItems; - } - // @Override // public Object clone() throws CloneNotSupportedException { // // Try to invoke clone method on value if possible. @@ -134,7 +124,7 @@ public class PropertyWrapper implements Cloneable { public Object clone() throws CloneNotSupportedException { PropertyWrapper clone = new PropertyWrapper(this.name, this.type, this.getter, this.setter, this.defaultable, this.validator, - this.additionalOptions, this.sortOrder); + this.sortOrder); clone.value = this.value; clone.changed = this.changed; clone.unique = this.unique; @@ -145,7 +135,6 @@ public class PropertyWrapper implements Cloneable { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((additionalOptions == null) ? 0 : additionalOptions.hashCode()); result = prime * result + (defaultable ? 1231 : 1237); result = prime * result + ((getter == null) ? 0 : getter.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); @@ -162,11 +151,6 @@ public class PropertyWrapper implements Cloneable { if (getClass() != obj.getClass()) return false; PropertyWrapper other = (PropertyWrapper) obj; - if (additionalOptions == null) { - if (other.additionalOptions != null) - return false; - } else if (!additionalOptions.equals(other.additionalOptions)) - return false; if (defaultable != other.defaultable) return false; if (getter == null) { diff --git a/diylc/diylc-core/src/org/diylc/core/Project.java b/diylc/diylc-core/src/org/diylc/core/Project.java index cfcdb30a..0d5f32c1 100644 --- a/diylc/diylc-core/src/org/diylc/core/Project.java +++ b/diylc/diylc-core/src/org/diylc/core/Project.java @@ -11,6 +11,7 @@ import java.util.Set; import org.diylc.appframework.update.VersionNumber; import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.MultiLineText; import org.diylc.core.annotations.PositiveMeasureValidator; import org.diylc.core.measures.Size; import org.diylc.core.measures.SizeUnit; @@ -72,7 +73,8 @@ public class Project implements Serializable { this.author = author; } - @EditableProperty(defaultable = false, additionalOptions = EditableProperty.MULTI_LINE, sortOrder = 2) + @MultiLineText + @EditableProperty(defaultable = false, sortOrder = 2) public String getDescription() { return description; } diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/Defaults.java b/diylc/diylc-core/src/org/diylc/core/annotations/Defaults.java new file mode 100644 index 00000000..8a709e3b --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/core/annotations/Defaults.java @@ -0,0 +1,54 @@ +package org.diylc.core.annotations; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public final class Defaults { + private Defaults() {} + + private static final Map, Object> DEFAULTS; + + static { + // Only add to this map via put(Map, Class, T) + Map, Object> map = new HashMap, Object>(); + put(map, boolean.class, false); + put(map, Boolean.class, false); + put(map, char.class, '\0'); + put(map, byte.class, (byte) 0); + put(map, Byte.class, (byte) 0); + put(map, short.class, (short) 0); + put(map, Short.class, (short) 0); + put(map, int.class, 0); + put(map, Integer.class, 0); + put(map, long.class, 0L); + put(map, Long.class, 0L); + put(map, float.class, 0f); + put(map, Float.class, 0f); + put(map, double.class, 0d); + put(map, Double.class, 0d); + DEFAULTS = Collections.unmodifiableMap(map); + } + + private static void put(Map, Object> map, Class type, T value) { + map.put(type, value); + } + + /** + * Returns the default value of {@code type} as defined by JLS --- {@code 0} for numbers, + * {@code false} for {@code boolean} and {@code '\0'} for {@code char}. For non-primitive types + * and {@code void}, {@code null} is returned. + * + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static T defaultValue(Class type) throws Exception { + // Primitives.wrap(type).cast(...) would avoid the warning, but we can't use that from here + // the put method enforces this key-value relationship + T t = (T) DEFAULTS.get(type); + if (t == null) { + return (T) type.getConstructors()[0].newInstance(); + } + return t; + } +} diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/DynamicList.java b/diylc/diylc-core/src/org/diylc/core/annotations/DynamicList.java new file mode 100644 index 00000000..9eacfc9e --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/core/annotations/DynamicList.java @@ -0,0 +1,10 @@ +package org.diylc.core.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface DynamicList { + + public String availableValueFunction(); +} diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/EditableProperty.java b/diylc/diylc-core/src/org/diylc/core/annotations/EditableProperty.java index a73f33f3..cdf0d9dc 100644 --- a/diylc/diylc-core/src/org/diylc/core/annotations/EditableProperty.java +++ b/diylc/diylc-core/src/org/diylc/core/annotations/EditableProperty.java @@ -33,18 +33,6 @@ import org.diylc.core.IPropertyValidator; @Retention(RetentionPolicy.RUNTIME) public @interface EditableProperty { - /** - * Used to designate that a {@link String} property can have multi-lined text. - */ - public static final String MULTI_LINE = "MULTI-LINE"; - /** - * Used when property can have one of the values from a dynamic list. In such cases, - * {@link EditableProperty#additionalOptions()} should begin with - * {@link EditableProperty#DYNAMIC_LIST} and contain a method name from the parent object that - * should be called to obtain the {@link String} array with possible options. - */ - public static final String DYNAMIC_LIST = "DYNAMIC_LIST:"; - /** * Returns property name. If left blank property name will be extracted from the getter name, e.g. * getter getXYZ will induce property name XYZ.
@@ -75,12 +63,4 @@ public @interface EditableProperty { * @return */ int sortOrder() default Integer.MAX_VALUE; - - /** - * Optional parameter for properties that require additional configuration. This will be passed - * down to the editor factory. - * - * @return - */ - String additionalOptions() default ""; } diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/ElementLabel.java b/diylc/diylc-core/src/org/diylc/core/annotations/ElementLabel.java new file mode 100644 index 00000000..a2bac603 --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/core/annotations/ElementLabel.java @@ -0,0 +1,6 @@ +package org.diylc.core.annotations; + +public @interface ElementLabel { + + public String functionName(); +} diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/MultiLineText.java b/diylc/diylc-core/src/org/diylc/core/annotations/MultiLineText.java new file mode 100644 index 00000000..bb8ffdd8 --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/core/annotations/MultiLineText.java @@ -0,0 +1,9 @@ +package org.diylc.core.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MultiLineText { + +} diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/ProjectEntity.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/ProjectEntity.java index 0c017a25..01259fd9 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/ProjectEntity.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/ProjectEntity.java @@ -2,7 +2,9 @@ package org.diylc.plugins.cloud.model; import java.io.Serializable; +import org.diylc.core.annotations.DynamicList; import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.MultiLineText; /** * Represents a cloud project object, identified by {@link ProjectEntity#id}. @@ -49,7 +51,8 @@ public class ProjectEntity implements Serializable { this.name = name; } - @EditableProperty(defaultable = false, additionalOptions = EditableProperty.MULTI_LINE, sortOrder = 3) + @MultiLineText + @EditableProperty(defaultable = false, sortOrder = 3) public String getDescription() { return description; } @@ -74,8 +77,8 @@ public class ProjectEntity implements Serializable { this.category = category; } - @EditableProperty(defaultable = false, sortOrder = 2, additionalOptions = EditableProperty.DYNAMIC_LIST - + "getCategories") + @DynamicList(availableValueFunction="getCategories") + @EditableProperty(defaultable = false, sortOrder = 2) public String getCategoryForDisplay() { return categoryForDisplay; } diff --git a/diylc/diylc-core/src/org/diylc/presenter/ComponentProcessor.java b/diylc/diylc-core/src/org/diylc/presenter/ComponentProcessor.java index 768b88e2..08ffdbb3 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/ComponentProcessor.java +++ b/diylc/diylc-core/src/org/diylc/presenter/ComponentProcessor.java @@ -139,26 +139,26 @@ public class ComponentProcessor { return cloneProperties(propertyCache.get(clazz.getName())); } List properties = new ArrayList(); - for (Method method : clazz.getMethods()) { - if (method.getName().startsWith("get")) { + for (Method getter : clazz.getMethods()) { + if (getter.getName().startsWith("get")) { try { - if (method.isAnnotationPresent(EditableProperty.class) && !method.isAnnotationPresent(Deprecated.class)) { - EditableProperty annotation = method.getAnnotation(EditableProperty.class); + if (getter.isAnnotationPresent(EditableProperty.class) && !getter.isAnnotationPresent(Deprecated.class)) { + EditableProperty annotation = getter.getAnnotation(EditableProperty.class); String name; if (annotation.name().equals("")) { - name = method.getName().substring(3); + name = getter.getName().substring(3); } else { name = annotation.name(); } - IPropertyValidator validator = getPropertyValidator(annotation.validatorClass()); - Method setter = clazz.getMethod("set" + method.getName().substring(3), method.getReturnType()); + IPropertyValidator validator = getPropertyValidator(annotation.validatorClass()); + Method setter = clazz.getMethod("set" + getter.getName().substring(3), getter.getReturnType()); PropertyWrapper property = - new PropertyWrapper(name, method.getReturnType(), method.getName(), setter.getName(), - annotation.defaultable(), validator, annotation.additionalOptions(), annotation.sortOrder()); + new PropertyWrapper(name, getter.getReturnType(), getter.getName(), setter.getName(), + annotation.defaultable(), validator, annotation.sortOrder()); properties.add(property); } } catch (NoSuchMethodException e) { - LOG.debug("No matching setter found for \"" + method.getName() + "\". Skipping..."); + LOG.debug("No matching setter found for \"" + getter.getName() + "\". Skipping..."); } } } diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index ac75d55c..b879c9a5 100644 Binary files a/diylc/diylc-library/lib/diylc-core.jar and b/diylc/diylc-library/lib/diylc-core.jar differ diff --git a/diylc/diylc-library/src/org/diylc/components/semiconductors/AbstractTransistorSymbol.java b/diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java similarity index 93% rename from diylc/diylc-library/src/org/diylc/components/semiconductors/AbstractTransistorSymbol.java rename to diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java index 7b6f4ee0..1a52251f 100644 --- a/diylc/diylc-library/src/org/diylc/components/semiconductors/AbstractTransistorSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java @@ -1,4 +1,4 @@ -package org.diylc.components.semiconductors; +package org.diylc.components; import java.awt.Color; import java.awt.FontMetrics; @@ -16,6 +16,7 @@ import org.diylc.common.IPlugInPort; import org.diylc.common.ObjectCache; import org.diylc.common.VerticalAlignment; import org.diylc.components.AbstractComponent; +import org.diylc.components.semiconductors.SymbolFlipping; import org.diylc.core.ComponentState; import org.diylc.core.IDrawingObserver; import org.diylc.core.Project; @@ -26,7 +27,7 @@ import org.diylc.core.measures.Size; import org.diylc.core.measures.SizeUnit; import org.diylc.utils.Constants; -public abstract class AbstractTransistorSymbol extends AbstractComponent { +public abstract class Abstract3LegSymbol extends AbstractComponent { private static final long serialVersionUID = 1L; @@ -41,7 +42,7 @@ public abstract class AbstractTransistorSymbol extends AbstractComponent protected Display display = Display.NAME; transient protected Shape[] body; - public AbstractTransistorSymbol() { + public Abstract3LegSymbol() { super(); updateControlPoints(); } diff --git a/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerSymbol.java b/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerSymbol.java index 5bd1b7ef..db4ec9f6 100644 --- a/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerSymbol.java @@ -11,14 +11,14 @@ import java.awt.geom.Rectangle2D; import org.diylc.core.IDIYComponent; import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.KeywordPolicy; -import org.diylc.components.semiconductors.AbstractTransistorSymbol; +import org.diylc.components.Abstract3LegSymbol; import org.diylc.components.semiconductors.SymbolFlipping; @ComponentDescriptor(name = "Potentiometer Symbol", author = "MCbx", category = "Schematics", - instanceNamePrefix = " VR", description = "Potentiometer symbol", stretchable = false, + instanceNamePrefix = "VR", description = "Potentiometer symbol", stretchable = false, zOrder = IDIYComponent.COMPONENT, rotatable = true, keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "Schematic") -public class PotentiometerSymbol extends AbstractTransistorSymbol { +public class PotentiometerSymbol extends Abstract3LegSymbol { private static final long serialVersionUID = 1L; diff --git a/diylc/diylc-library/src/org/diylc/components/passive/TransformerCoil.java b/diylc/diylc-library/src/org/diylc/components/passive/TransformerCoil.java new file mode 100644 index 00000000..9acb8e3a --- /dev/null +++ b/diylc/diylc-library/src/org/diylc/components/passive/TransformerCoil.java @@ -0,0 +1,263 @@ +package org.diylc.components.passive; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +import org.diylc.appframework.miscutils.ConfigurationManager; +import org.diylc.common.IPlugInPort; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.components.AbstractComponent; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.Theme; +import org.diylc.core.VisibilityPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Transformer Coil Symbol", author = "Branislav Stojkovic", category = "Schematics", + instanceNamePrefix = "L", description = "Transformer coil symbol. Use multiple instances together with \"Transformer Core Symbol\"
to draw transformer schematics.", stretchable = false, + zOrder = IDIYComponent.COMPONENT, rotatable = true, keywordPolicy = KeywordPolicy.SHOW_TAG, + keywordTag = "Schematic") +public class TransformerCoil extends AbstractComponent { + + private static final long serialVersionUID = 1L; + + public static Size TAP_SPACING = new Size(0.2d, SizeUnit.in); + public static Size LEAD_SPACING = new Size(0.1d, SizeUnit.in); + public static Color COLOR = Color.blue; + public static Color LEAD_COLOR = Color.black; + + private int tapCount = 0; + private Point[] controlPoints = new Point[] {new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0), + new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0)}; + private Orientation orientation = Orientation.DEFAULT; + private org.diylc.core.measures.Voltage voltage = null; + protected Color color = COLOR; + + private Shape[] body = null; + + public TransformerCoil() { + super(); + updateControlPoints(); + } + + private void updateControlPoints() { + double spacing = TAP_SPACING.convertToPixels(); + int fx = 1; + int fy = 1; + switch (this.orientation) { + case DEFAULT: + fx = 0; + break; + case _90: + fx = -1; + fy = 0; + break; + case _180: + fx = 0; + fy = -1; + break; + case _270: + fy = 0; + break; + default: + break; + } + + if (this.tapCount == 0) { + fx *= 2; + fy *= 2; + } + + Point refPoint = this.controlPoints[0]; + for (int i = 1; i < controlPoints.length; i++) { + this.controlPoints[i].setLocation(refPoint.x + i * fx * spacing, refPoint.y + i * fy * spacing); + } + } + + @EditableProperty + @Override + public org.diylc.core.measures.Voltage getValue() { + return voltage; + } + + @Override + public void setValue(org.diylc.core.measures.Voltage value) { + this.voltage = value; + } + + @EditableProperty(name = "Number of Taps", defaultable = true) + public int getTapCount() { + return tapCount; + } + + public void setTapCount(int tapCount) { + this.tapCount = tapCount; + updateControlPoints(); + this.body = null; + } + + @EditableProperty(defaultable = true) + public Orientation getOrientation() { + return orientation; + } + + public void setOrientation(Orientation orientation) { + this.orientation = orientation; + updateControlPoints(); + this.body = null; + } + + @Override + public int getControlPointCount() { + return this.tapCount + 2; + } + + @Override + public Point getControlPoint(int index) { + return this.controlPoints[index]; + } + + @Override + public void setControlPoint(Point point, int index) { + this.controlPoints[index].setLocation(point); + this.body = null; + } + + @Override + public boolean isControlPointSticky(int index) { + return true; + } + + @Override + public VisibilityPolicy getControlPointVisibilityPolicy(int index) { + return VisibilityPolicy.WHEN_SELECTED; + } + + @EditableProperty + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Shape[] body = getBody(); + + Color finalColor; + if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) { + finalColor = SELECTION_COLOR; + } else if (outlineMode) { + Theme theme = + (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME); + finalColor = theme.getOutlineColor(); + } else { + finalColor = color; + } + + g2d.setColor(LEAD_COLOR); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + g2d.draw(body[0]); + + g2d.setColor(finalColor); +// g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2)); + g2d.draw(body[1]); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.rotate(-Math.PI / 4, width / 2, height / 2); + g2d.setColor(LEAD_COLOR); + g2d.drawLine(width / 8, height / 2, width / 8, height * 6 / 8); + g2d.drawLine(width * 7 / 8, height / 2, width * 7 / 8, height * 6 / 8); + g2d.setColor(COLOR); + + GeneralPath polyline = new GeneralPath(); + polyline.moveTo(width / 8, height / 2); + polyline.curveTo(width / 8, height / 4, width * 3 / 8, height / 4, width * 3 / 8, height / 2); + polyline.curveTo(width * 3 / 8, height / 4, width * 5 / 8, height / 4, width * 5 / 8, height / 2); + polyline.curveTo(width * 5 / 8, height / 4, width * 7 / 8, height / 4, width * 7 / 8, height / 2); + + g2d.draw(polyline); + } + + public Shape[] getBody() { + if (body == null) { + double spacing = LEAD_SPACING.convertToPixels(); + int fx = 1; + int fy = 1; + switch (this.orientation) { + case DEFAULT: + fy = 0; + break; + case _90: + fx = 0; + break; + case _180: + fx = -1; + fy = 0; + break; + case _270: + fx = 0; + fy = -1; + break; + default: + break; + } + + GeneralPath leads = new GeneralPath(); + GeneralPath coil = new GeneralPath(); + + int coilsPerTap = 3; + + for (int i = 0; i < tapCount + 2; i++) { + leads.moveTo(this.controlPoints[i].x, this.controlPoints[i].y); + leads.lineTo(this.controlPoints[i].x + fx * spacing, this.controlPoints[i].y + fy * spacing); + + int dx = this.controlPoints[i + 1].x - this.controlPoints[i].x; + int dy = this.controlPoints[i + 1].y - this.controlPoints[i].y; + // skip the last tap + if (i < tapCount + 1) { + double x1 = this.controlPoints[i].x + fx * spacing * 2; + double y1 = this.controlPoints[i].y + fy * spacing * 2; + double x2 = this.controlPoints[i + 1].x + fx * spacing * 2; + double y2 = this.controlPoints[i + 1].y + fy * spacing * 2; + double dxa = x2 - x1; + double dya = y2 - y1; + + coil.moveTo(this.controlPoints[i].x + fx * spacing, this.controlPoints[i].y + fy * spacing); + + for (int j = 0; j < coilsPerTap; j++) { + coil.curveTo(x1 + dxa / coilsPerTap * j, y1 + dya / coilsPerTap * j, x1 + dxa / coilsPerTap * (j + 1), y1 + + dya / coilsPerTap * (j + 1), this.controlPoints[i].x + fx * spacing + dx / coilsPerTap * (j + 1), + this.controlPoints[i].y + fy * spacing + dy / coilsPerTap * (j + 1)); + } + } + } + body = new Shape[2]; + + body[0] = leads; + body[1] = coil; + + } + return body; + } +} diff --git a/diylc/diylc-library/src/org/diylc/components/passive/TransformerCore.java b/diylc/diylc-library/src/org/diylc/components/passive/TransformerCore.java new file mode 100644 index 00000000..38e77f38 --- /dev/null +++ b/diylc/diylc-library/src/org/diylc/components/passive/TransformerCore.java @@ -0,0 +1,141 @@ +package org.diylc.components.passive; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.geom.GeneralPath; + +import org.diylc.appframework.miscutils.ConfigurationManager; +import org.diylc.common.IPlugInPort; +import org.diylc.common.ObjectCache; +import org.diylc.components.AbstractComponent; +import org.diylc.core.ComponentState; +import org.diylc.core.CreationMethod; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.Theme; +import org.diylc.core.VisibilityPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor( + name = "Transformer Core Symbol", + author = "Branislav Stojkovic", + category = "Schematics", + instanceNamePrefix = "T", + description = "Transformer core symbol. Use multiple instances together with \"Transformer Coil Symbol\"
to draw transformer schematics.", + stretchable = false, zOrder = IDIYComponent.COMPONENT, rotatable = true, keywordPolicy = KeywordPolicy.SHOW_TAG, + creationMethod = CreationMethod.POINT_BY_POINT, keywordTag = "Schematic") +public class TransformerCore extends AbstractComponent { + + private static final long serialVersionUID = 1L; + + public static Size SPACING = new Size(0.03d, SizeUnit.in); + public static Color COLOR = Color.blue; + + private Point[] controlPoints = new Point[] {new Point(0, 0), new Point(0, 0)}; + + protected Color color = COLOR; + + public TransformerCore() { + super(); + } + + @Override + public int getControlPointCount() { + return 2; + } + + @Override + public Point getControlPoint(int index) { + return this.controlPoints[index]; + } + + @Override + public void setControlPoint(Point point, int index) { + this.controlPoints[index].setLocation(point); + } + + @Override + public boolean isControlPointSticky(int index) { + return false; + } + + @Override + public VisibilityPolicy getControlPointVisibilityPolicy(int index) { + return VisibilityPolicy.WHEN_SELECTED; + } + + @EditableProperty + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Color finalColor; + if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) { + finalColor = SELECTION_COLOR; + } else if (outlineMode) { + Theme theme = + (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME); + finalColor = theme.getOutlineColor(); + } else { + finalColor = color; + } + + double theta = + Math.atan2(this.controlPoints[1].y - this.controlPoints[0].y, this.controlPoints[1].x - this.controlPoints[0].x) + Math.PI / 2; + double spacing = SPACING.convertToPixels(); + // System.out.println(theta); + + g2d.setColor(finalColor); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + g2d.translate(spacing * Math.cos(theta) / 2, spacing * Math.sin(theta) / 2); + g2d.drawLine(this.controlPoints[0].x, this.controlPoints[0].y, this.controlPoints[1].x, this.controlPoints[1].y); + g2d.translate(-spacing * Math.cos(theta), -spacing * Math.sin(theta)); + g2d.drawLine(this.controlPoints[0].x, this.controlPoints[0].y, this.controlPoints[1].x, this.controlPoints[1].y); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.rotate(-Math.PI / 4, width / 2, height / 2); + g2d.setColor(COLOR); + + GeneralPath polyline = new GeneralPath(); + polyline.moveTo(width / 8, height / 2); + polyline.curveTo(width / 8, height / 4, width * 3 / 8, height / 4, width * 3 / 8, height / 2); + polyline.curveTo(width * 3 / 8, height / 4, width * 5 / 8, height / 4, width * 5 / 8, height / 2); + polyline.curveTo(width * 5 / 8, height / 4, width * 7 / 8, height / 4, width * 7 / 8, height / 2); + + g2d.draw(polyline); + } + + @Override + public Void getValue() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public void setValue(Void value) { + // TODO Auto-generated method stub + + } +} diff --git a/diylc/diylc-library/src/org/diylc/components/semiconductors/BJTSymbol.java b/diylc/diylc-library/src/org/diylc/components/semiconductors/BJTSymbol.java index 130b17af..910d743b 100644 --- a/diylc/diylc-library/src/org/diylc/components/semiconductors/BJTSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/semiconductors/BJTSymbol.java @@ -8,6 +8,7 @@ import java.awt.geom.Area; import java.awt.geom.GeneralPath; import org.diylc.common.ObjectCache; +import org.diylc.components.Abstract3LegSymbol; import org.diylc.core.IDIYComponent; import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.EditableProperty; @@ -17,7 +18,7 @@ import org.diylc.core.annotations.KeywordPolicy; instanceNamePrefix = "Q", description = "Bipolar junction transistor schematic symbol", stretchable = false, zOrder = IDIYComponent.COMPONENT, rotatable = true, keywordPolicy = KeywordPolicy.SHOW_TAG_AND_VALUE, keywordTag = "Schematic") -public class BJTSymbol extends AbstractTransistorSymbol { +public class BJTSymbol extends Abstract3LegSymbol { private static final long serialVersionUID = 1L; diff --git a/diylc/diylc-library/src/org/diylc/components/semiconductors/JFETSymbol.java b/diylc/diylc-library/src/org/diylc/components/semiconductors/JFETSymbol.java index 553945c0..5914b2e8 100644 --- a/diylc/diylc-library/src/org/diylc/components/semiconductors/JFETSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/semiconductors/JFETSymbol.java @@ -6,6 +6,7 @@ import java.awt.Shape; import java.awt.geom.GeneralPath; import org.diylc.common.ObjectCache; +import org.diylc.components.Abstract3LegSymbol; import org.diylc.core.IDIYComponent; import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.EditableProperty; @@ -15,7 +16,7 @@ import org.diylc.core.annotations.KeywordPolicy; instanceNamePrefix = "Q", description = "JFET transistor schematic symbol", stretchable = false, zOrder = IDIYComponent.COMPONENT, rotatable = true, keywordPolicy = KeywordPolicy.SHOW_TAG_AND_VALUE, keywordTag = "Schematic") -public class JFETSymbol extends AbstractTransistorSymbol { +public class JFETSymbol extends Abstract3LegSymbol { private static final long serialVersionUID = 1L; diff --git a/diylc/diylc-library/src/org/diylc/components/semiconductors/MOSFETSymbol.java b/diylc/diylc-library/src/org/diylc/components/semiconductors/MOSFETSymbol.java index 1fa51b2f..ddac6429 100644 --- a/diylc/diylc-library/src/org/diylc/components/semiconductors/MOSFETSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/semiconductors/MOSFETSymbol.java @@ -6,6 +6,7 @@ import java.awt.Shape; import java.awt.geom.GeneralPath; import org.diylc.common.ObjectCache; +import org.diylc.components.Abstract3LegSymbol; import org.diylc.core.IDIYComponent; import org.diylc.core.annotations.ComponentDescriptor; import org.diylc.core.annotations.EditableProperty; @@ -15,7 +16,7 @@ import org.diylc.core.annotations.KeywordPolicy; instanceNamePrefix = "Q", description = "MOSFET transistor schematic symbol", stretchable = false, zOrder = IDIYComponent.COMPONENT, rotatable = true, keywordPolicy = KeywordPolicy.SHOW_TAG_AND_VALUE, keywordTag = "Schematic") -public class MOSFETSymbol extends AbstractTransistorSymbol { +public class MOSFETSymbol extends Abstract3LegSymbol { private static final long serialVersionUID = 1L; diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index ac75d55c..b879c9a5 100644 Binary files a/diylc/diylc-swing/lib/diylc-core.jar and b/diylc/diylc-swing/lib/diylc-core.jar differ diff --git a/diylc/diylc-swing/library/main.jar b/diylc/diylc-swing/library/main.jar index 4ecbd66c..0487aa44 100644 Binary files a/diylc/diylc-swing/library/main.jar and b/diylc/diylc-swing/library/main.jar differ diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/FieldEditorFactory.java b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/FieldEditorFactory.java index 83a78d06..3461a4a5 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/FieldEditorFactory.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/FieldEditorFactory.java @@ -9,11 +9,13 @@ import javax.swing.JLabel; import org.apache.log4j.Logger; import org.diylc.common.PropertyWrapper; -import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.DynamicList; +import org.diylc.core.annotations.MultiLineText; import org.diylc.core.measures.AbstractMeasure; /** - * Based on {@link PropertyWrapper#getType()}, creates an appropriate {@link Component} that can edit that type. + * Based on {@link PropertyWrapper#getType()}, creates an appropriate {@link Component} that can + * edit that type. * * @author Branislav Stojkovic */ @@ -22,13 +24,21 @@ public class FieldEditorFactory { private static final Logger LOG = Logger.getLogger(FieldEditorFactory.class); public static Component createFieldEditor(PropertyWrapper property) { - if (property.getType().equals(String.class) && property.getListItems() != null) { - StringListEditor editor = new StringListEditor(property); - return editor; + try { + if (property.getType().equals(String.class) && property.getGetter().isAnnotationPresent(DynamicList.class)) { + StringListEditor editor = new StringListEditor(property); + return editor; + } + } catch (Exception e) { + LOG.error("Could not determine if a function is annotated with DynamicList", e); } - if (property.getType().equals(String.class) && EditableProperty.MULTI_LINE.equals(property.getAdditionalOptions())) { - MultiLineStringEditor editor = new MultiLineStringEditor(property); - return editor; + try { + if (property.getType().equals(String.class) && property.getGetter().isAnnotationPresent(MultiLineText.class)) { + MultiLineStringEditor editor = new MultiLineStringEditor(property); + return editor; + } + } catch (Exception e) { + LOG.error("Could not determine if a function is annotated with MultiLineText", e); } if (property.getType().equals(String.class)) { StringEditor editor = new StringEditor(property); diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/IntEditor.java b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/IntEditor.java index 54e6c055..9b3eb506 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/IntEditor.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/IntEditor.java @@ -24,7 +24,7 @@ public class IntEditor extends DoubleTextField { public void propertyChange(PropertyChangeEvent evt) { property.setChanged(true); setBackground(oldBg); - property.setValue(((Double) evt.getNewValue()).intValue()); + property.setValue(evt.getNewValue() == null ? null : ((Double) evt.getNewValue()).intValue()); } }); if (!property.isUnique()) { diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/StringListEditor.java b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/StringListEditor.java index bf618895..5bf1f27d 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/StringListEditor.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/StringListEditor.java @@ -3,11 +3,13 @@ package org.diylc.swing.gui.editor; import java.awt.Color; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.lang.reflect.Method; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import org.diylc.common.PropertyWrapper; +import org.diylc.core.annotations.DynamicList; import org.diylc.utils.Constants; public class StringListEditor extends JComboBox { @@ -18,9 +20,11 @@ public class StringListEditor extends JComboBox { private final PropertyWrapper property; - public StringListEditor(final PropertyWrapper property) { + public StringListEditor(final PropertyWrapper property) throws Exception { this.property = property; - Object[] values = property.getListItems(); + String listFunctionName = property.getGetter().getAnnotation(DynamicList.class).availableValueFunction(); + Method function = property.getOwnerObject().getClass().getMethod(listFunctionName); + Object[] values = (Object[]) function.invoke(property.getOwnerObject()); setModel(new DefaultComboBoxModel(values)); setSelectedItem(property.getValue()); addItemListener(new ItemListener() {