From 82752269425848574bec7b4ebac57f9807fc754a Mon Sep 17 00:00:00 2001 From: bancika Date: Sun, 14 Feb 2021 17:23:01 +0100 Subject: [PATCH] eurorack stripboard added --- .../src/org/diylc/presenter/update.xml | 6 +- .../components/boards/EurorackStripboard.java | 774 ++++++++++++++++++ diylc/diylc-swing/build.xml | 2 +- diylc/diylc-swing/library/main.jar | Bin 755630 -> 767217 bytes 4 files changed, 780 insertions(+), 2 deletions(-) create mode 100644 diylc/diylc-library/src/org/diylc/components/boards/EurorackStripboard.java diff --git a/diylc/diylc-core/src/org/diylc/presenter/update.xml b/diylc/diylc-core/src/org/diylc/presenter/update.xml index 05d4bc3a..cccab76c 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/update.xml +++ b/diylc/diylc-core/src/org/diylc/presenter/update.xml @@ -3523,9 +3523,13 @@ 17 0 - 2021-01-17 00:00:00.000 CET + 2021-02-14 00:00:00.000 CET + + NEW_FEATURE + Added 'Eurorack Stripboard' component, designed by David Haillant + NEW_FEATURE Allow multi-line text in label components diff --git a/diylc/diylc-library/src/org/diylc/components/boards/EurorackStripboard.java b/diylc/diylc-library/src/org/diylc/components/boards/EurorackStripboard.java new file mode 100644 index 00000000..6994a41e --- /dev/null +++ b/diylc/diylc-library/src/org/diylc/components/boards/EurorackStripboard.java @@ -0,0 +1,774 @@ +/* + * + * 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.components.boards; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.util.ArrayList; +import java.util.List; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.transform.ProtoBoardTransformer; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.VisibilityPolicy; +import org.diylc.core.annotations.BomPolicy; +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 com.sun.prism.BasicStroke; + +@ComponentDescriptor(name = "Eurorack Stripboard", category = "Boards", + author = "Branislav Stojkovic", + description = "David Haillant's eurorack format stripboard for prototyping and building simple modules", + instanceNamePrefix = "BB", zOrder = IDIYComponent.BOARD, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, + keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, enableCache = true, + transformer = ProtoBoardTransformer.class) +public class EurorackStripboard extends AbstractProtoBoard { + + private static final long serialVersionUID = 1L; + + public static Color FILL_COLOR = Color.decode("#6B9B6B"); + public static Size SPACING = new Size(0.1d, SizeUnit.in); + public static Size CORNER_RADIUS = new Size(0.1d, SizeUnit.in); + public static Color SELECTION_COLOR = Color.red; + public static Color PAD_COLOR = COPPER_COLOR; + public static Color TRACE_COLOR = PAD_COLOR.brighter(); + public static Color HOLE_COLOR = Color.white; + + public static float COORDINATE_FONT_SIZE = 10f; + public static Color COORDINATE_COLOR = Color.decode("#DDDDDD"); + + public static Size PAD_SIZE = new Size(2d, SizeUnit.mm); + public static Size FILTER_CAP_SIZE = new Size(0.23d, SizeUnit.in); + public static Size LARGE_PAD_SIZE = new Size(0.25d, SizeUnit.in); + + public static Size WIDTH_SIZE = new Size(2d, SizeUnit.in); + public static Size LENGTH_SIZE = new Size(4d, SizeUnit.in); + public static Size BODY_OFFSET_Y = new Size(0.1d, SizeUnit.in); + + protected Point2D point = new Point2D.Double(0, 0); + + protected Color boardColor = FILL_COLOR; + protected Color padColor = PAD_COLOR; + protected Color traceColor = TRACE_COLOR; + protected Color textColor = COORDINATE_COLOR; + + private static String[] connectorLabels = + new String[] {"Conn1", "GND", "GND", "GND", "Conn2", "+5V", "CV", "Gate"}; + transient private List segments; + transient private List potPads; + transient private List filterPads; + transient private List potTraces; + + public List getSegments() { + if (segments == null) { + segments = new ArrayList(); + segments.add(new Segment(5, 0, 5, 1, "CenterLeft0")); + segments.add(new Segment(10, 0, 5, 1, "CenterRight0")); + segments.add(new Segment(5, 1, 5, 1, "CenterLeft1")); + segments.add(new Segment(10, 1, 5, 1, "CenterRight1")); + + segments.add(new Segment(5, 2, 1, 30, "GND")); + + for (int i = 0; i < 29; i++) { + segments.add(new Segment(6, 2 + i, 4, 1, "CenterLeft" + (2 + i))); + segments.add(new Segment(10, 2 + i, 5, 1, "CenterRight" + (2 + i))); + } + segments.add(new Segment(6, 2 + 29, 4, 1, "CenterRight29")); + + segments.add(new Segment(15, 3, 1, 30, "-")); + segments.add(new Segment(16, 3, 1, 30, "GND")); + segments.add(new Segment(17, 3, 1, 30, "+")); + + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + segments.add(new Segment(3, 8 * i + j, 2, 1, ((char) ('A' + j)) + Integer.toString(i), false)); + } + if (i < 4) { + for (int j = 0; j < 3; j++) { + segments.add(new Segment(0, 8 * i + j + 5, 5, 1, i + "-" + (j + 5))); + } + } + } + } + return segments; + } + + public List getPotPads() { + if (potPads == null) { + potPads = new ArrayList(); + potPads.add(new Pad(1.5, 0.2, "A")); + + potPads.add(new Pad(0.5, 0, "B", true)); + potPads.add(new Pad(0, 0.2, "B", false)); + potPads.add(new Pad(1, 1, "B", true)); + + potPads.add(new Pad(0.5, 2, "C")); + potPads.add(new Pad(1, 2, "C")); + + potPads.add(new Pad(0.5, 4, "D")); + potPads.add(new Pad(0, 3.8, "D")); + potPads.add(new Pad(1, 3, "D")); + + potPads.add(new Pad(1.5, 3.8, "E")); + } + return potPads; + } + + public List getFilterPads() { + if (filterPads == null) { + filterPads = new ArrayList(); + + filterPads.add(new Pad(6, 32.8, "GND", true)); + filterPads.add(new Pad(6, 33.8, "-")); + + filterPads.add(new Pad(8, 33, "-")); + filterPads.add(new Pad(8, 34, "Conn1", true)); + + filterPads.add(new Pad(9, 33, "+", true)); + filterPads.add(new Pad(9, 34, "Conn2")); + + filterPads.add(new Pad(11, 32.8, "+", true)); + filterPads.add(new Pad(11, 33.8, "GND")); + + filterPads.add(new Pad(11.5, 31, "+5V", true)); + filterPads.add(new Pad(12.5, 31, "CV")); + filterPads.add(new Pad(13.5, 31, "Gate")); + } + return filterPads; + } + + public List getPotTraces() { + if (potTraces == null) { + potTraces = new ArrayList(); + potTraces.add(new Point2D[] {new Point2D.Double(1.5, 0.2), new Point2D.Double(3, 0.2)}); + potTraces.add(new Point2D[] {new Point2D.Double(1, 2), new Point2D.Double(3, 2)}); + potTraces.add(new Point2D[] {new Point2D.Double(1, 1), new Point2D.Double(3, 1)}); + potTraces.add(new Point2D[] {new Point2D.Double(1, 3), new Point2D.Double(3, 3)}); + potTraces.add(new Point2D[] {new Point2D.Double(1.5, 3.8), new Point2D.Double(3, 3.8)}); + + potTraces.add(new Point2D[] {new Point2D.Double(0.8, 0.2), new Point2D.Double(0.8, 1)}); + potTraces.add(new Point2D[] {new Point2D.Double(0.8, 3.8), new Point2D.Double(0.8, 3)}); + } + return potTraces; + } + + @SuppressWarnings("incomplete-switch") + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, + Project project, IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + // adjust the angle + double theta = 0; + switch (getOrientation()) { + case _90: + theta = Math.PI / 2; + break; + case _180: + theta = Math.PI; + break; + case _270: + theta = Math.PI * 3 / 2; + break; + } + if (theta != 0) { + g2d.rotate(theta, point.getX(), point.getY()); + } + + double spacing = SPACING.convertToPixels(); + + // draw body + g2d.setColor(boardColor); + int width = (int) WIDTH_SIZE.convertToPixels(); + int length = (int) LENGTH_SIZE.convertToPixels(); + int radius = (int) CORNER_RADIUS.convertToPixels(); + int bodyOffsetY = (int) BODY_OFFSET_Y.convertToPixels(); + + Shape rect = new RoundRectangle2D.Double(point.getX(), point.getY() - bodyOffsetY, width, + length, radius, radius); + g2d.fill(rect); + g2d.setColor( + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? SELECTION_COLOR + : boardColor.darker()); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + drawingObserver.stopTracking(); + + g2d.draw(rect); + + int padSize = getClosestOdd(PAD_SIZE.convertToPixels()); + int holeSize = getClosestOdd(padSize / 3); + + g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE)); + g2d.setColor(textColor); + + double x0 = point.getX() + spacing; + double y0 = point.getY() + spacing; + + for (int i = 0; i < 3; i++) { + String text = (char) ((int) 'A' + (i * 5)) + ""; + StringUtils.drawCenteredText(g2d, text, x0 + spacing * i * 5, y0 - spacing - 2, + HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + text = (char) ((int) 'A' + (i * 5 + 4)) + ""; + StringUtils.drawCenteredText(g2d, text, x0 + spacing * (i * 5 + 4), y0 - spacing - 2, + HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + StringUtils.drawCenteredText(g2d, "GND", x0 + spacing * 16, y0 + 2 * spacing - 2, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "+", x0 + spacing * 17, y0 + 2 * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "GND", x0 + spacing * 16, y0 + 33 * spacing + 2, + HorizontalAlignment.CENTER, VerticalAlignment.TOP); + StringUtils.drawCenteredText(g2d, "+", x0 + spacing * 17, y0 + 33 * spacing + 2, + HorizontalAlignment.CENTER, VerticalAlignment.TOP); + + g2d.setFont(LABEL_FONT); + StringUtils.drawCenteredText(g2d, "-", x0 + spacing * 15, y0 + 2 * spacing + 2, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "-", x0 + spacing * 15, y0 + 33 * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.TOP); + + g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE)); + for (int i = 0; i < 6; i++) { + StringUtils.drawCenteredText(g2d, Integer.toString((i + 1) * 5), x0 + spacing * 18 - 4, + y0 + (5 * (i + 1) - 1) * spacing, HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + } + + StringUtils.drawCenteredText(g2d, "Eurorack Stripboard", x0 - 8, y0 + (36.8) * spacing, + HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "davidhaillant.com", x0 - 8, y0 + (37.3) * spacing, + HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM); + + StringUtils.drawCenteredText(g2d, "GND", x0 + 17 * spacing, y0 + (37) * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + + // filter caps + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(2)); + int filterCapSize = (int) FILTER_CAP_SIZE.convertToPixels(); + + int centerX = (int) (x0 + 6 * spacing); + int centerY = (int) (y0 + 33.3 * spacing); + + Ellipse2D filterCap = new Ellipse2D.Double(centerX - filterCapSize / 2, + centerY - filterCapSize / 2, filterCapSize, filterCapSize); + g2d.draw(filterCap); + Area area = new Area(filterCap); + area.subtract(new Area(new Rectangle2D.Double(centerX - filterCapSize, centerY - filterCapSize, + filterCapSize * 2, filterCapSize))); + g2d.fill(area); + + centerX = (int) (x0 + 11 * spacing); + filterCap = new Ellipse2D.Double(centerX - filterCapSize / 2, centerY - filterCapSize / 2, + filterCapSize, filterCapSize); + g2d.draw(filterCap); + area = new Area(filterCap); + area.subtract(new Area(new Rectangle2D.Double(centerX - filterCapSize, centerY - filterCapSize, + filterCapSize * 2, filterCapSize))); + g2d.fill(area); + + int circleSize = getClosestOdd(padSize * 1.2); + centerX = (int) (x0 + 8 * spacing); + centerY = (int) (y0 + 33 * spacing); + g2d.drawOval(centerX - circleSize / 2, centerY - circleSize / 2, circleSize, circleSize); + g2d.drawLine(centerX - circleSize / 2, (int) (centerY + circleSize / 2 + spacing + 1), centerX + circleSize / 2, (int) (centerY + circleSize / 2 + spacing + 1)); + + centerX = (int) (x0 + 9 * spacing); + centerY = (int) (y0 + 34 * spacing); + g2d.drawOval(centerX - circleSize / 2, centerY - circleSize / 2, circleSize, circleSize); + g2d.drawLine(centerX - circleSize / 2, (int) (centerY - circleSize / 2 - spacing), centerX + circleSize / 2, (int) (centerY - circleSize / 2 - spacing)); + + StringUtils.drawCenteredText(g2d, "GND", x0 + spacing * 5.1, y0 + 31.6 * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "+5V", x0 + spacing * 11.3, y0 + 31.5 * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "CV", x0 + spacing * 12.5, y0 + 31.5 * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + StringUtils.drawCenteredText(g2d, "Gate", x0 + spacing * 13.7, y0 + 31.5 * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + + // pot traces + List potTraces = getPotTraces(); + g2d.setColor(traceColor); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); + for (int i = 0; i < 5; i++) { + for (Point2D[] trace : potTraces) { + int padX1 = (int) (x0 + trace[0].getX() * spacing); + int padY1 = (int) (y0 + (trace[0].getY() + 8 * i) * spacing); + int padX2 = (int) (x0 + trace[1].getX() * spacing); + int padY2 = (int) (y0 + (trace[1].getY() + 8 * i) * spacing); + g2d.drawLine(padX1, padY1, padX2, padY2); + } + } + + // segments + for (Segment segment : getSegments()) { + + if (segment.spanX > 1) { + drawingObserver.stopTrackingContinuityArea(); + g2d.setColor(textColor); + Rectangle2D segmentRect = new Rectangle2D.Double(x0 + segment.x * spacing - spacing / 2, + y0 + segment.y * spacing - spacing / 2, (segment.spanX) * spacing, spacing); + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(2)); + g2d.draw(segmentRect); + + if (segment.includeTrace) { + g2d.setColor(traceColor); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); + g2d.drawLine((int) (x0 + segment.x * spacing), (int) (y0 + segment.y * spacing), + (int) (x0 + (segment.x + segment.spanX - 1) * spacing), + (int) (y0 + segment.y * spacing)); + } + + } else if (segment.spanY > 1) { + drawingObserver.stopTrackingContinuityArea(); + g2d.setColor(textColor); + Rectangle2D segmentRect = new Rectangle2D.Double(x0 + segment.x * spacing - spacing / 2, + y0 + segment.y * spacing - spacing / 2, spacing, (segment.spanY) * spacing); + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(2)); + g2d.draw(segmentRect); + + if (segment.includeTrace) { + g2d.setColor(traceColor); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(padSize / 4)); + g2d.drawLine((int) (x0 + segment.x * spacing), (int) (y0 + segment.y * spacing), + (int) (x0 + segment.x * spacing), + (int) (y0 + (segment.y + segment.spanY - 1) * spacing)); + } + } + + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + for (int i = 0; i < segment.spanX; i++) { + for (int j = 0; j < segment.spanY; j++) { + + int padX = (int) (x0 + (segment.x + i) * spacing); + int padY = (int) (y0 + (segment.y + j) * spacing); + + drawingObserver.startTrackingContinuityArea(true); + drawingObserver.setContinuityMarker(segment.label); + + g2d.setColor(padColor); + g2d.fillRect(padX - padSize / 2, padY - padSize / 2, padSize, padSize); + + drawingObserver.setContinuityMarker(null); + + drawingObserver.stopTrackingContinuityArea(); + + g2d.setColor(padColor.darker()); + g2d.drawRect(padX - padSize / 2, padY - padSize / 2, padSize, padSize); + + g2d.setColor(HOLE_COLOR); + g2d.fillOval(padX - holeSize / 2, padY - holeSize / 2, holeSize, holeSize); + } + } + } + + g2d.setColor(textColor); + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(3)); + g2d.drawLine((int) (x0 + 5 * spacing), (int) (y0 + 35 * spacing), (int) (x0 + 15 * spacing), + (int) (y0 + 35 * spacing)); + g2d.drawLine((int) (x0 + 15 * spacing), (int) (y0 + 35 * spacing), (int) (x0 + 15 * spacing), + (int) (y0 + 38 * spacing) - 2); + g2d.drawLine((int) (x0 + 5 * spacing), (int) (y0 + 35 * spacing), (int) (x0 + 5 * spacing), + (int) (y0 + 38 * spacing) - 2); + + g2d.setStroke(ObjectCache.getInstance().fetchStroke(1, new float[] { 3, 6 }, 6, BasicStroke.CAP_SQUARE)); + g2d.drawLine((int) (x0 + 11 * spacing), (int) (y0 + 35.25 * spacing), (int) (x0 + 11 * spacing), + (int) (y0 + 38 * spacing) - 2); + + + g2d.fillRect((int) (x0 + 5 * spacing + 4), (int) (y0 + 35 * spacing + 4), 8, + (int) (3 * spacing) - 4); + + // pots + int potPadSize = (int) (padSize * 0.9); + List potPads = getPotPads(); + for (int i = 0; i < 5; i++) { + + g2d.setColor(textColor); + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(3)); + g2d.drawRect((int) (x0 - 0.8 * spacing), (int) (y0 + (8 * i) * spacing), (int) (3 * spacing), + (int) (4 * spacing)); + + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + for (Pad potPad : potPads) { + int padX = (int) (x0 + potPad.x * spacing); + int padY = (int) (y0 + (potPad.y + 8 * i) * spacing); + + drawingObserver.startTrackingContinuityArea(true); + drawingObserver.setContinuityMarker(potPad.label + i); + + g2d.setColor(padColor); + if (potPad.square) + g2d.fillRect(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + else + g2d.fillOval(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + + drawingObserver.setContinuityMarker(null); + + drawingObserver.stopTrackingContinuityArea(); + + g2d.setColor(padColor.darker()); + if (potPad.square) + g2d.drawRect(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + else + g2d.drawOval(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + + g2d.setColor(HOLE_COLOR); + g2d.fillOval(padX - holeSize / 2, padY - holeSize / 2, holeSize, holeSize); + } + + g2d.setColor(textColor); + g2d.setFont(LABEL_FONT.deriveFont(16f)); + + StringUtils.drawCenteredText(g2d, Integer.toString(i + 1), x0 - 4, y0 + (2 + i * 8) * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE)); + + StringUtils.drawCenteredText(g2d, "B", x0 - 2, y0 + (1 + i * 8) * spacing - 4, + HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "D", x0 - 2, y0 + (3 + i * 8) * spacing + 4, + HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + + g2d.setFont(LABEL_FONT.deriveFont(COORDINATE_FONT_SIZE * 0.9f)); + for (int j = 0; j < 5; j++) { + StringUtils.drawCenteredText(g2d, (char)('A' + j) + "", x0 + 3.5 * spacing, y0 + (j + i * 8) * spacing, + HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + } + + List filterPads = getFilterPads(); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + // filter pads + for (Pad potPad : filterPads) { + int padX = (int) (x0 + potPad.x * spacing); + int padY = (int) (y0 + potPad.y * spacing); + + drawingObserver.startTrackingContinuityArea(true); + drawingObserver.setContinuityMarker(potPad.label); + + g2d.setColor(padColor); + if (potPad.square) + g2d.fillRect(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + else + g2d.fillOval(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + + drawingObserver.setContinuityMarker(null); + + drawingObserver.stopTrackingContinuityArea(); + + g2d.setColor(padColor.darker()); + if (potPad.square) + g2d.drawRect(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + else + g2d.drawOval(padX - potPadSize / 2, padY - potPadSize / 2, potPadSize, potPadSize); + + g2d.setColor(HOLE_COLOR); + g2d.fillOval(padX - holeSize / 2, padY - holeSize / 2, holeSize, holeSize); + } + + + // bottom connector + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 2; j++) { + int padX = (int) (x0 + (6.5 + i) * spacing); + int padY = (int) (y0 + (36 + j) * spacing); + + drawingObserver.startTrackingContinuityArea(true); + drawingObserver.setContinuityMarker(connectorLabels[i]); + + g2d.setColor(padColor); + if (i == 0 && j == 1) + g2d.fillRect(padX - padSize / 2, padY - padSize / 2, padSize, padSize); + else + g2d.fillOval(padX - padSize / 2, padY - padSize / 2, padSize, padSize); + + drawingObserver.setContinuityMarker(null); + drawingObserver.stopTrackingContinuityArea(); + + g2d.setColor(padColor.darker()); + if (i == 0 && j == 1) + g2d.drawRect(padX - padSize / 2, padY - padSize / 2, padSize, padSize); + else + g2d.drawOval(padX - padSize / 2, padY - padSize / 2, padSize, padSize); + + g2d.setColor(HOLE_COLOR); + g2d.fillOval(padX - holeSize / 2, padY - holeSize / 2, holeSize, holeSize); + } + } + + // GND pad + int largePadSize = (int) LARGE_PAD_SIZE.convertToPixels(); + int largeHoleSize = (int) (LARGE_PAD_SIZE.convertToPixels() * 0.6); + + int padX = (int) (x0 + (17) * spacing); + int padY = (int) (y0 + 35.5 * spacing); + + drawingObserver.startTrackingContinuityArea(true); + drawingObserver.setContinuityMarker("GND"); + + g2d.setColor(padColor); + g2d.fillOval(padX - largePadSize / 2, padY - largePadSize / 2, largePadSize, largePadSize); + g2d.setColor(HOLE_COLOR); + g2d.fillOval(padX - largeHoleSize / 2, padY - largeHoleSize / 2, largeHoleSize, largeHoleSize); + + drawingObserver.setContinuityMarker(null); + drawingObserver.stopTrackingContinuityArea(); + + padY = (int) (y0 + 0.5 * spacing); + + g2d.setColor(textColor); + g2d.fillOval(padX - largePadSize / 2, padY - largePadSize / 2, largePadSize, largePadSize); + g2d.setColor(HOLE_COLOR); + g2d.fillOval(padX - largeHoleSize / 2, padY - largeHoleSize / 2, largeHoleSize, largeHoleSize); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + int factor = 32 / width; + g2d.setColor(FILL_COLOR); + g2d.fillRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor); + g2d.setColor(FILL_COLOR.darker()); + g2d.drawRect(2 / factor, 2 / factor, width - 4 / factor, height - 4 / factor); + + g2d.setColor(PAD_COLOR.brighter()); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2 / factor)); + + int size = (int) (8.0 / factor); + + g2d.drawLine(width / 3 - 2 / factor + size / 2, 6 / factor + size / 2, width, + 6 / factor + size / 2); + g2d.drawLine(width / 3 - 2 / factor + size / 2, 2 * width / 3 - 2 / factor + size / 2, width, + 2 * width / 3 - 2 / factor + size / 2); + + + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + + g2d.setColor(PAD_COLOR); + g2d.fillRect(width / 3 - 2 / factor, 6 / factor, size, size); + g2d.setColor(PAD_COLOR.darker()); + g2d.drawRect(width / 3 - 2 / factor, 6 / factor, size, size); + + g2d.setColor(PAD_COLOR); + g2d.fillRect(2 * width / 3 - 2 / factor, 6 / factor, size, size); + g2d.setColor(PAD_COLOR.darker()); + g2d.drawRect(2 * width / 3 - 2 / factor, 6 / factor, size, size); + + g2d.setColor(PAD_COLOR); + g2d.fillRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, size, size); + g2d.setColor(PAD_COLOR.darker()); + g2d.drawRect(width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, size, size); + + g2d.setColor(PAD_COLOR); + g2d.fillRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, size, size); + g2d.setColor(PAD_COLOR.darker()); + g2d.drawRect(2 * width / 3 - 2 / factor, 2 * width / 3 - 2 / factor, size, size); + + g2d.setColor(HOLE_COLOR); + g2d.fillOval(width / 3 - 2 / factor + size / 2 - 1, 6 / factor + size / 2 - 1, 3, 3); + g2d.fillOval(width / 3 - 2 / factor + size / 2 - 1, 2 * width / 3 - 2 / factor + size / 2 - 1, + 3, 3); + g2d.fillOval(2 * width / 3 - 2 / factor + size / 2 - 1, 6 / factor + size / 2 - 1, 3, 3); + g2d.fillOval(2 * width / 3 - 2 / factor + size / 2 - 1, + 2 * width / 3 - 2 / factor + size / 2 - 1, 3, 3); + } + + @EditableProperty(name = "Board Color") + public Color getBoardColor() { + return boardColor; + } + + public void setBoardColor(Color boardColor) { + this.boardColor = boardColor; + } + + @EditableProperty(name = "Pad Color") + public Color getPadColor() { + return padColor; + } + + public void setPadColor(Color padColor) { + this.padColor = padColor; + } + + @EditableProperty(name = "Trace Color") + public Color getTraceColor() { + return traceColor; + } + + public void setTraceColor(Color traceColor) { + this.traceColor = traceColor; + } + + @EditableProperty(name = "Text Color") + public Color getTextColor() { + return textColor; + } + + public void setTextColor(Color textColor) { + this.textColor = textColor; + } + + @Override + public int getControlPointCount() { + return 2; + } + + @Override + public boolean canPointMoveFreely(int pointIndex) { + return false; + } + + @SuppressWarnings("incomplete-switch") + @Override + public Point2D getControlPoint(int index) { + if (index == 0) + return point; + + // create a synthetic second control point for clipping check and to make sure that we cannot + // drag the right side of the board off the screen + + // adjust the angle + double theta = 0; + switch (getOrientation()) { + case _90: + theta = Math.PI / 2; + break; + case _180: + theta = Math.PI; + break; + case _270: + theta = Math.PI * 3 / 2; + break; + } + int width = (int) WIDTH_SIZE.convertToPixels(); + int length = (int) LENGTH_SIZE.convertToPixels(); + Point2D secondPoint = new Point2D.Double(point.getX() + width, point.getY() + length); + if (theta != 0) { + AffineTransform tx = AffineTransform.getRotateInstance(theta, point.getX(), point.getY()); + tx.transform(secondPoint, secondPoint); + } + return secondPoint; + } + + @Override + public boolean isControlPointSticky(int index) { + return false; + } + + @Override + public VisibilityPolicy getControlPointVisibilityPolicy(int index) { + return VisibilityPolicy.NEVER; + } + + @Override + public void setControlPoint(Point2D point, int index) { + if (index == 0) + this.point.setLocation(point); + } + + @Override + public Void getValue() { + return null; + } + + @Override + public void setValue(Void value) {} + + @Override + public String getControlPointNodeName(int index) { + return null; + } + + @Override + public Rectangle2D getCachingBounds() { + Point2D finalSecondPoint = getControlPoint(1); + double offset = BODY_OFFSET_Y.convertToPixels(); + return new Rectangle2D.Double(Math.min(point.getX(), finalSecondPoint.getX()) - offset, + Math.min(point.getY(), finalSecondPoint.getY()) - offset, + Math.abs(finalSecondPoint.getX() - point.getX()) + offset + 2, + Math.abs(finalSecondPoint.getY() - point.getY()) + offset + 2); + } + + class Segment { + int x; + int y; + int spanX; + int spanY; + String label; + boolean includeTrace = true; + + public Segment(int x, int y, int spanX, int spanY, String label) { + super(); + this.x = x; + this.y = y; + this.spanX = spanX; + this.spanY = spanY; + this.label = label; + } + + public Segment(int x, int y, int spanX, int spanY, String label, boolean includeTrace) { + this(x, y, spanX, spanY, label); + this.includeTrace = includeTrace; + } + } + + class Pad { + double x; + double y; + String label; + boolean square; + + public Pad(double x, double y, String label, boolean square) { + this.x = x; + this.y = y; + this.label = label; + this.square = square; + } + + public Pad(double x, double y, String label) { + this(x, y, label, false); + } + } +} diff --git a/diylc/diylc-swing/build.xml b/diylc/diylc-swing/build.xml index f3df1bba..dbdc9d84 100644 --- a/diylc/diylc-swing/build.xml +++ b/diylc/diylc-swing/build.xml @@ -10,7 +10,7 @@ - + diff --git a/diylc/diylc-swing/library/main.jar b/diylc/diylc-swing/library/main.jar index 0f14c469c021be00705e26ee9066846db0b5e0cd..5cf9c61afc176d117ec24e4ff376c20aa8250dcb 100644 GIT binary patch delta 34378 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�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 z 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 delta 23157 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