diff --git a/diylc/diylc-core/src/org/diylc/core/AllowAllValidator.java b/diylc/diylc-core/src/org/diylc/core/AllowAllValidator.java index 943fa509..bc060dca 100644 --- a/diylc/diylc-core/src/org/diylc/core/AllowAllValidator.java +++ b/diylc/diylc-core/src/org/diylc/core/AllowAllValidator.java @@ -29,5 +29,5 @@ package org.diylc.core; public class AllowAllValidator implements IPropertyValidator { @Override - public void validate(Object value) throws ValidationException {} + public void validate(Object owner, Object value) throws ValidationException {} } diff --git a/diylc/diylc-core/src/org/diylc/core/IDIYComponent.java b/diylc/diylc-core/src/org/diylc/core/IDIYComponent.java index 04a9dadf..0d5c8681 100644 --- a/diylc/diylc-core/src/org/diylc/core/IDIYComponent.java +++ b/diylc/diylc-core/src/org/diylc/core/IDIYComponent.java @@ -45,7 +45,7 @@ import org.diylc.core.annotations.EditableProperty; * * @param type of component values, e.g. Resistance for resistors or String for transistors. */ -public interface IDIYComponent extends Serializable { +public interface IDIYComponent extends Serializable, Cloneable { public static final int CHASSIS = 1; public static final int BOARD = 2; diff --git a/diylc/diylc-core/src/org/diylc/core/IPropertyValidator.java b/diylc/diylc-core/src/org/diylc/core/IPropertyValidator.java index bc312f4e..15b8fa91 100644 --- a/diylc/diylc-core/src/org/diylc/core/IPropertyValidator.java +++ b/diylc/diylc-core/src/org/diylc/core/IPropertyValidator.java @@ -28,9 +28,10 @@ package org.diylc.core; */ public interface IPropertyValidator { - /** + /** + * @param owner * @param value * @throws ValidationException if validation fails. Message will contain the reason. */ - void validate(Object value) throws ValidationException; + void validate(Object owner, Object value) throws ValidationException; } diff --git a/diylc/diylc-core/src/org/diylc/core/Project.java b/diylc/diylc-core/src/org/diylc/core/Project.java index 428f368a..627db442 100644 --- a/diylc/diylc-core/src/org/diylc/core/Project.java +++ b/diylc/diylc-core/src/org/diylc/core/Project.java @@ -45,7 +45,7 @@ import org.diylc.core.measures.SizeUnit; * * @author Branislav Stojkovic */ -public class Project implements Serializable { +public class Project implements Serializable, Cloneable { private static final long serialVersionUID = 1L; @@ -292,8 +292,8 @@ public class Project implements Serializable { public static class SpacingValidator extends PositiveMeasureValidator { @Override - public void validate(Object value) throws ValidationException { - super.validate(value); + public void validate(Object owner, Object value) throws ValidationException { + super.validate(owner, value); Size size = (Size) value; if (size.compareTo(new Size(0.1d, SizeUnit.mm)) < 0) { throw new ValidationException("must be at least 0.1mm"); diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/PositiveMeasureValidator.java b/diylc/diylc-core/src/org/diylc/core/annotations/PositiveMeasureValidator.java index 9938888d..b9eb6743 100644 --- a/diylc/diylc-core/src/org/diylc/core/annotations/PositiveMeasureValidator.java +++ b/diylc/diylc-core/src/org/diylc/core/annotations/PositiveMeasureValidator.java @@ -21,8 +21,8 @@ */ package org.diylc.core.annotations; -import org.diylc.core.IPropertyValidator; -import org.diylc.core.ValidationException; +import org.diylc.core.IPropertyValidator; +import org.diylc.core.ValidationException; import org.diylc.core.measures.AbstractMeasure; /** @@ -34,7 +34,7 @@ import org.diylc.core.measures.AbstractMeasure; public class PositiveMeasureValidator implements IPropertyValidator { @Override - public void validate(Object value) throws ValidationException { + public void validate(Object owner, Object value) throws ValidationException { if (value == null) return; if (value instanceof AbstractMeasure) { diff --git a/diylc/diylc-core/src/org/diylc/core/annotations/PositiveNonZeroMeasureValidator.java b/diylc/diylc-core/src/org/diylc/core/annotations/PositiveNonZeroMeasureValidator.java index c0c3f2d6..fc4479c1 100644 --- a/diylc/diylc-core/src/org/diylc/core/annotations/PositiveNonZeroMeasureValidator.java +++ b/diylc/diylc-core/src/org/diylc/core/annotations/PositiveNonZeroMeasureValidator.java @@ -21,8 +21,8 @@ */ package org.diylc.core.annotations; -import org.diylc.core.IPropertyValidator; -import org.diylc.core.ValidationException; +import org.diylc.core.IPropertyValidator; +import org.diylc.core.ValidationException; import org.diylc.core.measures.AbstractMeasure; /** @@ -34,7 +34,7 @@ import org.diylc.core.measures.AbstractMeasure; public class PositiveNonZeroMeasureValidator implements IPropertyValidator { @Override - public void validate(Object value) throws ValidationException { + public void validate(Object owner, Object value) throws ValidationException { if (value == null) return; if (value instanceof AbstractMeasure) { diff --git a/diylc/diylc-core/src/org/diylc/core/measures/AbstractMeasure.java b/diylc/diylc-core/src/org/diylc/core/measures/AbstractMeasure.java index 2a599e0e..83a45b58 100644 --- a/diylc/diylc-core/src/org/diylc/core/measures/AbstractMeasure.java +++ b/diylc/diylc-core/src/org/diylc/core/measures/AbstractMeasure.java @@ -53,15 +53,6 @@ public class AbstractMeasure> implements Serializ public T getUnit() { return unit; - } - - /*** - * Flag that designates if measure value should be converted between different units. eg. 2.54mm <-> 0.1in - * - * @return - */ - public boolean isConvertible() { - return false; } @Override diff --git a/diylc/diylc-core/src/org/diylc/core/measures/Size.java b/diylc/diylc-core/src/org/diylc/core/measures/Size.java index 7536e291..378f64b0 100644 --- a/diylc/diylc-core/src/org/diylc/core/measures/Size.java +++ b/diylc/diylc-core/src/org/diylc/core/measures/Size.java @@ -65,10 +65,5 @@ public class Size extends AbstractMeasure implements Comparable @Override public int compareTo(Size o) { return new Double(value * unit.getFactor()).compareTo(o.getValue() * o.getUnit().getFactor()); - } - - @Override - public boolean isConvertible() { - return true; } } diff --git a/diylc/diylc-core/src/org/diylc/presenter/update.xml b/diylc/diylc-core/src/org/diylc/presenter/update.xml index db3ed0d5..d9e3fe72 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/update.xml +++ b/diylc/diylc-core/src/org/diylc/presenter/update.xml @@ -2710,6 +2710,10 @@ NEW_FEATURE Added "Tape Measure" component for measuring the distance between any two points on the drawing + + NEW_FEATURE + Added ability to set board size explicitly by typing in dimensions, instead of dragging two control points + NEW_FEATURE New app bundle for Mac OS using appbundler instead of javabundler diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index e341f4bc..d864ccbe 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/boards/AbstractBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/AbstractBoard.java index d3a9ad05..33ec9943 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/AbstractBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/AbstractBoard.java @@ -65,11 +65,17 @@ public abstract class AbstractBoard extends AbstractTransparentComponent protected CoordinateOrigin coordinateOrigin = CoordinateOrigin.Top_Left; protected CoordinateDisplay coordinateDisplay = CoordinateDisplay.One_Side; protected CoordinateType yType = CoordinateType.Letters; + + protected Size length; + protected Size width; + protected BoardSizingMode mode = BoardSizingMode.TwoPoints; @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, IDrawingObserver drawingObserver) { g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + Point finalSecondPoint = getFinalSecondPoint(); Composite oldComposite = g2d.getComposite(); // render as transparent when dragging @@ -78,7 +84,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); } g2d.setColor(boardColor); - g2d.fillRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); + g2d.fillRect(firstPoint.x, firstPoint.y, finalSecondPoint.x - firstPoint.x, finalSecondPoint.y - firstPoint.y); g2d.setComposite(oldComposite); // Do not track any changes that follow because the whole board has been @@ -86,7 +92,17 @@ public abstract class AbstractBoard extends AbstractTransparentComponent drawingObserver.stopTracking(); g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR : borderColor); - g2d.drawRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); + g2d.drawRect(firstPoint.x, firstPoint.y, finalSecondPoint.x - firstPoint.x, finalSecondPoint.y - firstPoint.y); + } + + protected Point getFinalSecondPoint() { + Point finalSecondPoint; + if (getMode() == BoardSizingMode.TwoPoints) + finalSecondPoint = secondPoint; + else + finalSecondPoint = new Point((int)(firstPoint.x + getLength().convertToPixels()), + (int)(firstPoint.y + getWidth().convertToPixels())); + return finalSecondPoint; } protected void drawCoordinates(Graphics2D g2d, int spacing, Project project) { @@ -97,6 +113,8 @@ public abstract class AbstractBoard extends AbstractTransparentComponent int halfSpace = spacing / 2; CoordinateOrigin origin = getCoordinateOrigin(); + Point finalSecondPoint = getFinalSecondPoint(); + if (getCoordinateDisplay() != CoordinateDisplay.None) { int range; int yOffset; @@ -104,12 +122,12 @@ public abstract class AbstractBoard extends AbstractTransparentComponent Point drawPoint = new Point(firstPoint); if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Top_Right) { - range = (int) ((secondPoint.y - firstPoint.y + halfSpace) / spacing); + range = (int) ((finalSecondPoint.y - firstPoint.y + halfSpace) / spacing); yOffset = spacing; } else { - range = (int) ((secondPoint.y - firstPoint.y + halfSpace) / spacing); + range = (int) ((finalSecondPoint.y - firstPoint.y + halfSpace) / spacing); yOffset = -spacing; - drawPoint.y = secondPoint.y; + drawPoint.y = finalSecondPoint.y; } for (int c = 1; c < range; c++) { @@ -122,7 +140,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent HorizontalAlignment.LEFT, VerticalAlignment.CENTER); if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) { StringUtils.drawCenteredText(g2d, label, - secondPoint.x - xOffset, drawPoint.y, + finalSecondPoint.x - xOffset, drawPoint.y, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); } } @@ -135,12 +153,12 @@ public abstract class AbstractBoard extends AbstractTransparentComponent Point drawPoint = new Point(firstPoint); if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Bottom_Left) { - range = (int) ((secondPoint.x - firstPoint.x + halfSpace) / spacing); + range = (int) ((finalSecondPoint.x - firstPoint.x + halfSpace) / spacing); xOffset = spacing; } else { - range = (int) ((secondPoint.x - firstPoint.x + halfSpace) / spacing); + range = (int) ((finalSecondPoint.x - firstPoint.x + halfSpace) / spacing); xOffset = -spacing; - drawPoint.x = secondPoint.x; + drawPoint.x = finalSecondPoint.x; } for (int c = 1; c < range; c++) { @@ -152,7 +170,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent HorizontalAlignment.CENTER, VerticalAlignment.TOP); if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) { StringUtils.drawCenteredText(g2d, label, - drawPoint.x, (int) (secondPoint.y - COORDINATE_FONT_SIZE), + drawPoint.x, (int) (finalSecondPoint.y - COORDINATE_FONT_SIZE), HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); } } @@ -263,7 +281,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent @Override public VisibilityPolicy getControlPointVisibilityPolicy(int index) { - return VisibilityPolicy.WHEN_SELECTED; + return getMode() == BoardSizingMode.TwoPoints ? VisibilityPolicy.WHEN_SELECTED : VisibilityPolicy.NEVER; } @Override @@ -285,7 +303,36 @@ public abstract class AbstractBoard extends AbstractTransparentComponent public void setValue(String value) { this.value = value; } + + @EditableProperty(name = "Explicit Length", validatorClass = BoardModeValidator.class) + public Size getLength() { + return length; + } + + public void setLength(Size length) { + this.length = length; + } + + @EditableProperty(name = "Explicit Width", validatorClass = BoardModeValidator.class) + public Size getWidth() { + return width; + } + + public void setWidth(Size width) { + this.width = width; + } + @EditableProperty(name = "Sizing Mode") + public BoardSizingMode getMode() { + if (mode == null) + mode = BoardSizingMode.TwoPoints; + return mode; + } + + public void setMode(BoardSizingMode mode) { + this.mode = mode; + } + public static enum CoordinateType { Letters, Numbers } @@ -307,4 +354,19 @@ public abstract class AbstractBoard extends AbstractTransparentComponent return super.toString().replace('_', ' '); }; } + + public static enum BoardSizingMode { + TwoPoints("Opposing Points"), Explicit("Explicit Dimensions"); + + private String label; + + private BoardSizingMode(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } + } } diff --git a/diylc/diylc-library/src/org/diylc/components/boards/BlankBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/BlankBoard.java index 40ae0f00..300a21ed 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/BlankBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/BlankBoard.java @@ -25,6 +25,7 @@ import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Shape; import org.diylc.common.ObjectCache; @@ -57,12 +58,14 @@ public class BlankBoard extends AbstractBoard { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { + IDrawingObserver drawingObserver) { + Point finalSecondPoint = getFinalSecondPoint(); + Shape clip = g2d.getClip(); - if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, secondPoint.y) - && !clip.contains(secondPoint.x, firstPoint.y)) { + if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, finalSecondPoint.y) + && !clip.contains(finalSecondPoint.x, firstPoint.y)) { return; - } + } g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); if (componentState != ComponentState.DRAGGING) { @@ -72,9 +75,9 @@ public class BlankBoard extends AbstractBoard { } g2d.setColor(boardColor); if (getType() == Type.SQUARE) - g2d.fillRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); + g2d.fillRect(firstPoint.x, firstPoint.y, finalSecondPoint.x - firstPoint.x, finalSecondPoint.y - firstPoint.y); else - g2d.fillOval(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); + g2d.fillOval(firstPoint.x, firstPoint.y, finalSecondPoint.x - firstPoint.x, finalSecondPoint.y - firstPoint.y); g2d.setComposite(oldComposite); } // Do not track any changes that follow because the whole board has been @@ -83,9 +86,9 @@ public class BlankBoard extends AbstractBoard { g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR : borderColor); if (getType() == Type.SQUARE) - g2d.drawRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); + g2d.drawRect(firstPoint.x, firstPoint.y, finalSecondPoint.x - firstPoint.x, finalSecondPoint.y - firstPoint.y); else - g2d.drawOval(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); + g2d.drawOval(firstPoint.x, firstPoint.y, finalSecondPoint.x - firstPoint.x, finalSecondPoint.y - firstPoint.y); } @Override diff --git a/diylc/diylc-library/src/org/diylc/components/boards/BoardModeValidator.java b/diylc/diylc-library/src/org/diylc/components/boards/BoardModeValidator.java new file mode 100644 index 00000000..e3ef4c24 --- /dev/null +++ b/diylc/diylc-library/src/org/diylc/components/boards/BoardModeValidator.java @@ -0,0 +1,19 @@ +package org.diylc.components.boards; + +import org.diylc.components.boards.AbstractBoard.BoardSizingMode; +import org.diylc.core.IPropertyValidator; +import org.diylc.core.ValidationException; +import org.diylc.core.measures.Size; + +public class BoardModeValidator implements IPropertyValidator { + + public BoardModeValidator() {} + + @Override + public void validate(Object owner, Object value) throws ValidationException { + AbstractBoard board = (AbstractBoard)owner; + Size size = (Size)value; + if (board.getMode() == BoardSizingMode.Explicit && (value == null || size.getValue() == null || size.getUnit() == null)) + throw new ValidationException("Dimensions are required when mode is set to " + BoardSizingMode.Explicit); + } +} \ No newline at end of file diff --git a/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java index d47e9999..66dff972 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/EyeletBoard.java @@ -68,10 +68,12 @@ public class EyeletBoard extends AbstractBoard { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { + IDrawingObserver drawingObserver) { + Point finalSecondPoint = getFinalSecondPoint(); + Shape clip = g2d.getClip(); - if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, secondPoint.y) - && !clip.contains(secondPoint.x, firstPoint.y)) { + if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, finalSecondPoint.y) + && !clip.contains(finalSecondPoint.x, firstPoint.y)) { return; } super.draw(g2d, componentState, outlineMode, project, drawingObserver); @@ -84,10 +86,10 @@ public class EyeletBoard extends AbstractBoard { int holeDiameter = getClosestOdd((int) HOLE_SIZE.convertToPixels()); int spacing = (int) this.spacing.convertToPixels(); - while (p.y < secondPoint.y - spacing) { + while (p.y < finalSecondPoint.y - spacing) { p.x = firstPoint.x; p.y += spacing; - while (p.x < secondPoint.x - spacing - diameter) { + while (p.x < finalSecondPoint.x - spacing - diameter) { p.x += spacing; g2d.setColor(eyeletColor); g2d.fillOval(p.x - diameter / 2, p.y - diameter / 2, diameter, diameter); diff --git a/diylc/diylc-library/src/org/diylc/components/boards/MarshallPerfBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/MarshallPerfBoard.java index 4a0eda81..fed20b27 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/MarshallPerfBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/MarshallPerfBoard.java @@ -66,10 +66,12 @@ public class MarshallPerfBoard extends AbstractBoard { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { + IDrawingObserver drawingObserver) { + Point finalSecondPoint = getFinalSecondPoint(); + Shape clip = g2d.getClip(); - if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, secondPoint.y) - && !clip.contains(secondPoint.x, firstPoint.y)) { + if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, finalSecondPoint.y) + && !clip.contains(finalSecondPoint.x, firstPoint.y)) { return; } super.draw(g2d, componentState, outlineMode, project, drawingObserver); @@ -81,10 +83,10 @@ public class MarshallPerfBoard extends AbstractBoard { int holeDiameter = getClosestOdd((int) HOLE_SIZE.convertToPixels()); int spacing = (int) this.spacing.convertToPixels(); - while (p.y < secondPoint.y - spacing) { + while (p.y < finalSecondPoint.y - spacing) { p.x = firstPoint.x; p.y += spacing; - while (p.x < secondPoint.x - spacing - holeDiameter) { + while (p.x < finalSecondPoint.x - spacing - holeDiameter) { p.x += spacing; g2d.setColor(Constants.CANVAS_COLOR); g2d.fillOval(p.x - holeDiameter / 2, p.y - holeDiameter / 2, holeDiameter, holeDiameter); diff --git a/diylc/diylc-library/src/org/diylc/components/boards/PerfBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/PerfBoard.java index a88f7c8c..905b0c3a 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/PerfBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/PerfBoard.java @@ -61,10 +61,12 @@ public class PerfBoard extends AbstractBoard { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { + IDrawingObserver drawingObserver) { + Point finalSecondPoint = getFinalSecondPoint(); + Shape clip = g2d.getClip(); - if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, secondPoint.y) - && !clip.contains(secondPoint.x, firstPoint.y)) { + if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, finalSecondPoint.y) + && !clip.contains(finalSecondPoint.x, firstPoint.y)) { return; } super.draw(g2d, componentState, outlineMode, project, drawingObserver); @@ -77,10 +79,10 @@ public class PerfBoard extends AbstractBoard { int holeDiameter = getClosestOdd((int) HOLE_SIZE.convertToPixels()); int spacing = (int) this.spacing.convertToPixels(); - while (p.y < secondPoint.y - spacing) { + while (p.y < finalSecondPoint.y - spacing) { p.x = firstPoint.x; p.y += spacing; - while (p.x < secondPoint.x - spacing - diameter) { + while (p.x < finalSecondPoint.x - spacing - diameter) { p.x += spacing; g2d.setColor(padColor); g2d.fillOval(p.x - diameter / 2, p.y - diameter / 2, diameter, diameter); diff --git a/diylc/diylc-library/src/org/diylc/components/boards/TriPadBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/TriPadBoard.java index b2058def..a9c95edd 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/TriPadBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/TriPadBoard.java @@ -64,10 +64,12 @@ public class TriPadBoard extends AbstractBoard { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { + IDrawingObserver drawingObserver) { + Point finalSecondPoint = getFinalSecondPoint(); + Shape clip = g2d.getClip(); - if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, secondPoint.y) - && !clip.contains(secondPoint.x, firstPoint.y)) { + if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, finalSecondPoint.y) + && !clip.contains(finalSecondPoint.x, firstPoint.y)) { return; } super.draw(g2d, componentState, outlineMode, project, drawingObserver); @@ -82,13 +84,13 @@ public class TriPadBoard extends AbstractBoard { int spacing = (int) this.spacing.convertToPixels(); if (orientation == OrientationHV.HORIZONTAL) { - while (p.y < secondPoint.y - spacing) { + while (p.y < finalSecondPoint.y - spacing) { p.x = firstPoint.x; p.y += spacing; - while (p.x + spacing < secondPoint.x) { + while (p.x + spacing < finalSecondPoint.x) { - int remainingSpace = secondPoint.x - p.x; + int remainingSpace = finalSecondPoint.x - p.x; int spacesToDraw = stripSpan; if (remainingSpace < (stripSize + (stripSpan * spacing))) { @@ -111,7 +113,7 @@ public class TriPadBoard extends AbstractBoard { // draw holes p.x = firstPoint.x; - while (p.x < secondPoint.x - spacing - holeSize) { + while (p.x < finalSecondPoint.x - spacing - holeSize) { p.x += spacing; g2d.setColor(Constants.CANVAS_COLOR); g2d.fillOval(p.x - holeSize / 2, p.y - holeSize / 2, holeSize, holeSize); @@ -120,13 +122,13 @@ public class TriPadBoard extends AbstractBoard { } } } else { - while (p.x < secondPoint.x - spacing) { + while (p.x < finalSecondPoint.x - spacing) { p.x += spacing; p.y = firstPoint.y; - while (p.y + spacing < secondPoint.y) { + while (p.y + spacing < finalSecondPoint.y) { - int remainingSpace = secondPoint.y - p.y; + int remainingSpace = finalSecondPoint.y - p.y; int spacesToDraw = stripSpan; if (remainingSpace < (stripSize + (stripSpan * spacing))) { @@ -148,7 +150,7 @@ public class TriPadBoard extends AbstractBoard { // draw holes p.y = firstPoint.y; - while (p.y < secondPoint.y - spacing - holeSize) { + while (p.y < finalSecondPoint.y - spacing - holeSize) { p.y += spacing; g2d.setColor(Constants.CANVAS_COLOR); g2d.fillOval(p.x - holeSize / 2, p.y - holeSize / 2, holeSize, holeSize); diff --git a/diylc/diylc-library/src/org/diylc/components/boards/VeroBoard.java b/diylc/diylc-library/src/org/diylc/components/boards/VeroBoard.java index c3816130..32298eb4 100644 --- a/diylc/diylc-library/src/org/diylc/components/boards/VeroBoard.java +++ b/diylc/diylc-library/src/org/diylc/components/boards/VeroBoard.java @@ -64,10 +64,12 @@ public class VeroBoard extends AbstractBoard { @Override public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { + IDrawingObserver drawingObserver) { + Point finalSecondPoint = getFinalSecondPoint(); + Shape clip = g2d.getClip(); - if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, secondPoint.y) - && !clip.contains(secondPoint.x, firstPoint.y)) { + if (checkPointsClipped(clip) && !clip.contains(firstPoint.x, finalSecondPoint.y) + && !clip.contains(finalSecondPoint.x, firstPoint.y)) { return; } super.draw(g2d, componentState, outlineMode, project, drawingObserver); @@ -82,16 +84,16 @@ public class VeroBoard extends AbstractBoard { int spacing = (int) this.spacing.convertToPixels(); if (orientation == OrientationHV.HORIZONTAL) { - while (p.y < secondPoint.y - spacing) { + while (p.y < finalSecondPoint.y - spacing) { p.x = firstPoint.x; p.y += spacing; g2d.setColor(stripColor); drawingObserver.startTrackingContinuityArea(true); - g2d.fillRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize); + g2d.fillRect(p.x + spacing / 2, p.y - stripSize / 2, finalSecondPoint.x - spacing - p.x, stripSize); drawingObserver.stopTrackingContinuityArea(); g2d.setColor(stripColor.darker()); - g2d.drawRect(p.x + spacing / 2, p.y - stripSize / 2, secondPoint.x - spacing - p.x, stripSize); - while (p.x < secondPoint.x - spacing - holeSize) { + g2d.drawRect(p.x + spacing / 2, p.y - stripSize / 2, finalSecondPoint.x - spacing - p.x, stripSize); + while (p.x < finalSecondPoint.x - spacing - holeSize) { p.x += spacing; g2d.setColor(Constants.CANVAS_COLOR); g2d.fillOval(p.x - holeSize / 2, p.y - holeSize / 2, holeSize, holeSize); @@ -100,16 +102,16 @@ public class VeroBoard extends AbstractBoard { } } } else { - while (p.x < secondPoint.x - spacing) { + while (p.x < finalSecondPoint.x - spacing) { p.x += spacing; p.y = firstPoint.y; g2d.setColor(stripColor); drawingObserver.startTrackingContinuityArea(true); - g2d.fillRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y); + g2d.fillRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, finalSecondPoint.y - spacing - p.y); drawingObserver.stopTrackingContinuityArea(); g2d.setColor(stripColor.darker()); - g2d.drawRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, secondPoint.y - spacing - p.y); - while (p.y < secondPoint.y - spacing - holeSize) { + g2d.drawRect(p.x - stripSize / 2, p.y + spacing / 2, stripSize, finalSecondPoint.y - spacing - p.y); + while (p.y < finalSecondPoint.y - spacing - holeSize) { p.y += spacing; g2d.setColor(Constants.CANVAS_COLOR); g2d.fillOval(p.x - holeSize / 2, p.y - holeSize / 2, holeSize, holeSize); diff --git a/diylc/diylc-library/src/org/diylc/components/tube/DiodeSymbol.java b/diylc/diylc-library/src/org/diylc/components/tube/DiodeSymbol.java index 3e02c889..2a93fcae 100644 --- a/diylc/diylc-library/src/org/diylc/components/tube/DiodeSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/tube/DiodeSymbol.java @@ -193,7 +193,7 @@ public class DiodeSymbol extends AbstractTubeSymbol { public class HeaterValidator implements IPropertyValidator { @Override - public void validate(Object value) throws ValidationException { + public void validate(Object owner, Object value) throws ValidationException { if (value != null && value instanceof Boolean) { boolean b = (Boolean) value; if (!b && getDirectlyHeated()) { diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index e341f4bc..d864ccbe 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 413e7255..8acaf704 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/MeasureEditor.java b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/MeasureEditor.java index 97d07b3e..526e023b 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/MeasureEditor.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/MeasureEditor.java @@ -89,7 +89,7 @@ public class MeasureEditor extends Container { try { Constructor ctor = property.getType().getConstructors()[0]; Double newValue = valueField.getValue(); - if (newValue != null && property.isReadOnly() && measure.isConvertible()) { + if (newValue != null && property.isReadOnly()) { double oldFactor = ((Unit)((AbstractMeasure)property.getValue()).getUnit()).getFactor(); double newFactor = ((Unit)unitBox.getSelectedItem()).getFactor(); newValue = newValue * oldFactor / newFactor; @@ -111,7 +111,7 @@ public class MeasureEditor extends Container { if (property.isReadOnly()) { valueField.setEnabled(false); - unitBox.setEnabled(measure.isConvertible()); + unitBox.setEnabled(true); } if (!property.isUnique()) { diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java index 6da46f9d..82a716fa 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/editor/PropertyEditorDialog.java @@ -1,195 +1,215 @@ /* + * + * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * DIYLC 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 for more details. + * + * You should have received a copy of the GNU General Public License along with DIYLC. If not, see + * . + * + */ +package org.diylc.swing.gui.editor; - DIY Layout Creator (DIYLC). - Copyright (c) 2009-2018 held jointly by the individual authors. +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.List; +import java.util.Set; - This file is part of DIYLC. +import javax.swing.BorderFactory; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; - DIYLC is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. +import org.apache.log4j.Logger; +import org.diylc.common.PropertyWrapper; +import org.diylc.core.ValidationException; +import org.diylc.swingframework.ButtonDialog; - DIYLC 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 for more details. +public class PropertyEditorDialog extends ButtonDialog { - You should have received a copy of the GNU General Public License - along with DIYLC. If not, see . + private static final Logger LOG = Logger.getLogger(PropertyEditorDialog.class); -*/ -package org.diylc.swing.gui.editor; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.swing.BorderFactory; -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 org.diylc.swingframework.ButtonDialog; - -public class PropertyEditorDialog extends ButtonDialog { - - private static final Logger LOG = Logger.getLogger(PropertyEditorDialog.class); - - private static final long serialVersionUID = 1L; - - private static final String DEFAULT_BOX_TOOLTIP = - "If this box is checked application will use the current value as a
default when creating new components of the same type"; - - private List properties; - private Set defaultedProperties; - private Component componentToFocus = null; - private boolean saveDefaults; - - public PropertyEditorDialog(JFrame owner, List properties, String title, boolean saveDefaults) { - super(owner, title, new String[] {ButtonDialog.OK, ButtonDialog.CANCEL}); - this.saveDefaults = saveDefaults; - - LOG.debug("Creating property editor for: " + properties); - - this.properties = properties; - this.defaultedProperties = new HashSet(); - - setMinimumSize(new Dimension(240, 40)); - - layoutGui(); - 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)); - - GridBagConstraints gbc = new GridBagConstraints(); - - gbc.gridy = 0; - - gbc.anchor = GridBagConstraints.FIRST_LINE_START; - - for (PropertyWrapper property : properties) { - gbc.gridx = 0; - gbc.fill = GridBagConstraints.NONE; - gbc.weightx = 0; - gbc.insets = new Insets(4, 2, 2, 2); - gbc.anchor = GridBagConstraints.WEST; - editorPanel.add(new JLabel(property.getName() + ": "), gbc); - - gbc.gridx = 1; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 1; - gbc.insets = new Insets(2, 2, 2, 2); - - Component editor = FieldEditorFactory.createFieldEditor(property); - editor.addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - getButton(OK).doClick(); - } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - getButton(CANCEL).doClick(); - } - } - }); - editorPanel.add(editor, gbc); - - if (property.isDefaultable()) { - gbc.gridx = 2; - gbc.fill = GridBagConstraints.NONE; - gbc.weightx = 0; - - if (saveDefaults && !property.isReadOnly()) { - editorPanel.add(createDefaultCheckBox(property), gbc); - } - } - - if (property.getName().equalsIgnoreCase("value")) { - componentToFocus = editor; - } - - // Make value field focused - try { - if (componentToFocus == null && property.getGetter().getName().equalsIgnoreCase("getValue")) { - componentToFocus = editor; - } - } catch (Exception e1) { - LOG.warn("Could not determine editor component to focus", e1); - } - - gbc.gridy++; - } - - return editorPanel; - } - - private JCheckBox createDefaultCheckBox(final PropertyWrapper property) { - final JCheckBox checkBox = new JCheckBox(); - checkBox.setToolTipText(DEFAULT_BOX_TOOLTIP); - checkBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (checkBox.isSelected()) { - defaultedProperties.add(property); - } else { - defaultedProperties.remove(property); - } - } - }); - return checkBox; - } - - public Set getDefaultedProperties() { - return defaultedProperties; - } - - @Override - public void setVisible(boolean b) { - if (b && componentToFocus != null) { - componentToFocus.requestFocusInWindow(); - componentToFocus = null; - } - super.setVisible(b); - } - - @Override - protected JComponent getMainComponent() { - return createEditorFields(); - } -} + private static final long serialVersionUID = 1L; + + private static final String DEFAULT_BOX_TOOLTIP = + "If this box is checked application will use the current value as a
default when creating new components of the same type"; + + private List properties; + private Set defaultedProperties; + private Component componentToFocus = null; + private boolean saveDefaults; + + public PropertyEditorDialog(JFrame owner, List properties, String title, + boolean saveDefaults) { + super(owner, title, new String[] {ButtonDialog.OK, ButtonDialog.CANCEL}); + this.saveDefaults = saveDefaults; + + LOG.debug("Creating property editor for: " + properties); + + this.properties = properties; + this.defaultedProperties = new HashSet(); + + setMinimumSize(new Dimension(240, 40)); + + layoutGui(); + setLocationRelativeTo(owner); + } + + @Override + protected boolean validateInput(String button) { + if (button.equals(ButtonDialog.OK)) { + Object testObject = null; + if (properties.size() > 0) { + if (properties.get(0).getOwnerObject() instanceof Cloneable) { + try { + Object object = ((Cloneable) properties.get(0).getOwnerObject()); + Method method = object.getClass().getMethod("clone"); + method.setAccessible(true); + testObject = method.invoke(object); + for (PropertyWrapper property : properties) { + property.writeTo(testObject); + } + } catch (Exception e) { + LOG.warn("Could not clone test object", e); + testObject = properties.get(0).getOwnerObject(); + } + } else { + testObject = properties.get(0).getOwnerObject(); + } + } + for (PropertyWrapper property : properties) { + try { + property.getValidator().validate(testObject, 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)); + + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridy = 0; + + gbc.anchor = GridBagConstraints.FIRST_LINE_START; + + for (PropertyWrapper property : properties) { + gbc.gridx = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0; + gbc.insets = new Insets(4, 2, 2, 2); + gbc.anchor = GridBagConstraints.WEST; + editorPanel.add(new JLabel(property.getName() + ": "), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1; + gbc.insets = new Insets(2, 2, 2, 2); + + Component editor = FieldEditorFactory.createFieldEditor(property); + editor.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + getButton(OK).doClick(); + } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + getButton(CANCEL).doClick(); + } + } + }); + editorPanel.add(editor, gbc); + + if (property.isDefaultable()) { + gbc.gridx = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0; + + if (saveDefaults && !property.isReadOnly()) { + editorPanel.add(createDefaultCheckBox(property), gbc); + } + } + + if (property.getName().equalsIgnoreCase("value")) { + componentToFocus = editor; + } + + // Make value field focused + try { + if (componentToFocus == null + && property.getGetter().getName().equalsIgnoreCase("getValue")) { + componentToFocus = editor; + } + } catch (Exception e1) { + LOG.warn("Could not determine editor component to focus", e1); + } + + gbc.gridy++; + } + + return editorPanel; + } + + private JCheckBox createDefaultCheckBox(final PropertyWrapper property) { + final JCheckBox checkBox = new JCheckBox(); + checkBox.setToolTipText(DEFAULT_BOX_TOOLTIP); + checkBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (checkBox.isSelected()) { + defaultedProperties.add(property); + } else { + defaultedProperties.remove(property); + } + } + }); + return checkBox; + } + + public Set getDefaultedProperties() { + return defaultedProperties; + } + + @Override + public void setVisible(boolean b) { + if (b && componentToFocus != null) { + componentToFocus.requestFocusInWindow(); + componentToFocus = null; + } + super.setVisible(b); + } + + @Override + protected JComponent getMainComponent() { + return createEditorFields(); + } +}