From b6f302007262456f5b93a1368d05732c7ca17453 Mon Sep 17 00:00:00 2001 From: Bane Stojkovic Date: Mon, 12 Dec 2022 23:35:02 +0100 Subject: [PATCH] DIL IC pin labels don't match between the rendered values and values in the netlist --- .../src/org/diylc/presenter/update.xml | 6 +- diylc/diylc-library/lib/diylc-core.jar | Bin 392101 -> 392140 bytes .../components/semiconductors/DIL_IC.java | 1111 +++++++++-------- diylc/diylc-swing/lib/diylc-core.jar | Bin 392101 -> 392140 bytes diylc/diylc-swing/library/main.jar | Bin 921421 -> 921400 bytes 5 files changed, 565 insertions(+), 552 deletions(-) diff --git a/diylc/diylc-core/src/org/diylc/presenter/update.xml b/diylc/diylc-core/src/org/diylc/presenter/update.xml index 00a34f29..98f52c12 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/update.xml +++ b/diylc/diylc-core/src/org/diylc/presenter/update.xml @@ -4261,7 +4261,11 @@ IMPROVEMENT Improved find tool usability, make the screen pan to the selected components - + + + BUG_FIX + DIL IC pin labels don't match between the rendered values and values in the netlist + https://github.com/bancika/diy-layout-creator/releases diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index 21ea907e48d321407c0bdcf89f96a6375b74323f..83ee75c5db07f2be5a4fbef1338f6fd55378b071 100644 GIT binary patch delta 7141 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 Vh=XcjjA2EZ;48~YmPI@qwR$D2? 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. + * + */ +package org.diylc.components.semiconductors; - 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.semiconductors; - import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; @@ -53,516 +50,494 @@ import org.diylc.core.annotations.PositiveNonZeroMeasureValidator; import org.diylc.core.measures.Size; import org.diylc.core.measures.SizeUnit; import org.diylc.utils.Constants; - -@ComponentDescriptor(name = "DIP IC", author = "Branislav Stojkovic", category = "Semiconductors", - instanceNamePrefix = "IC", description = "Dual-in-line package IC", - zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = DIL_ICTransformer.class, - enableCache = true) -public class DIL_IC extends AbstractLabeledComponent { - - private static final long serialVersionUID = 1L; - - public static Color BODY_COLOR = Color.gray; - public static Color BORDER_COLOR = Color.gray.darker(); - public static Color PIN_COLOR = METAL_COLOR; - public static Color PIN_BORDER_COLOR = PIN_COLOR.darker(); - public static Color INDENT_COLOR = Color.gray.darker(); - public static Color LABEL_COLOR = Color.white; - public static int EDGE_RADIUS = 6; - public static Size PIN_SIZE = new Size(0.04d, SizeUnit.in); - public static Size INDENT_SIZE = new Size(0.07d, SizeUnit.in); - public static DisplayNumbers DISPLAY_NUMBERS = DisplayNumbers.NO; - - private String value = ""; - private Orientation orientation = Orientation.DEFAULT; - private PinCount pinCount = PinCount._8; - private Size pinSpacing = new Size(0.1d, SizeUnit.in); - private Size rowSpacing = new Size(0.3d, SizeUnit.in); - private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)}; - protected Display display = Display.BOTH; - private Color bodyColor = BODY_COLOR; - private Color borderColor = BORDER_COLOR; - private Color labelColor = LABEL_COLOR; - private Color indentColor = INDENT_COLOR; - private DisplayNumbers displayNumbers = DISPLAY_NUMBERS; - // new Point(0, pinSpacing.convertToPixels()), - // new Point(0, 2 * pinSpacing.convertToPixels()), - // new Point(0, 3 * pinSpacing.convertToPixels()), - // new Point(3 * pinSpacing.convertToPixels(), 0), - // new Point(3 * pinSpacing.convertToPixels(), - // pinSpacing.convertToPixels()), - // new Point(3 * pinSpacing.convertToPixels(), 2 * - // pinSpacing.convertToPixels()), - // new Point(3 * pinSpacing.convertToPixels(), 3 * - // pinSpacing.convertToPixels()) }; - transient private Area[] body; - - public DIL_IC() { - super(); - updateControlPoints(); - } - - @EditableProperty - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - @EditableProperty - public Orientation getOrientation() { - return orientation; - } - - public void setOrientation(Orientation orientation) { - this.orientation = orientation; - updateControlPoints(); - // Reset body shape. - body = null; - } - - @EditableProperty(name = "Pins") - public PinCount getPinCount() { - return pinCount; - } - - public void setPinCount(PinCount pinCount) { - this.pinCount = pinCount; - updateControlPoints(); - // Reset body shape; - body = null; - } - - @EditableProperty(name = "Pin Spacing", validatorClass = PositiveNonZeroMeasureValidator.class) - public Size getPinSpacing() { - return pinSpacing; - } - - public void setPinSpacing(Size pinSpacing) { - this.pinSpacing = pinSpacing; - updateControlPoints(); - // Reset body shape; - body = null; - } - - @EditableProperty(name = "Row Spacing", validatorClass = PositiveNonZeroMeasureValidator.class) - public Size getRowSpacing() { - return rowSpacing; - } - - public void setRowSpacing(Size rowSpacing) { - this.rowSpacing = rowSpacing; - updateControlPoints(); - // Reset body shape; - body = null; - } - - @EditableProperty - public Display getDisplay() { - if (display == null) { - display = Display.VALUE; - } - return display; - } - - public void setDisplay(Display display) { - this.display = display; - } - - @Override - public int getControlPointCount() { - return controlPoints.length; - } - - @Override - public Point2D getControlPoint(int index) { - return controlPoints[index]; - } - - @Override - public boolean isControlPointSticky(int index) { - return true; - } - - @Override - public VisibilityPolicy getControlPointVisibilityPolicy(int index) { - return VisibilityPolicy.NEVER; - } - - @Override - public void setControlPoint(Point2D point, int index) { - controlPoints[index].setLocation(point); - body = null; - } - - private void updateControlPoints() { - Point2D firstPoint = controlPoints[0]; - controlPoints = new Point2D[pinCount.getValue()]; - controlPoints[0] = firstPoint; - double pinSpacing = this.pinSpacing.convertToPixels(); - double rowSpacing = this.rowSpacing.convertToPixels(); - // Update control points. - double dx1; - double dy1; - double dx2; - double dy2; - for (int i = 0; i < pinCount.getValue() / 2; i++) { - switch (orientation) { - case DEFAULT: - dx1 = 0; - dy1 = i * pinSpacing; - dx2 = rowSpacing; - dy2 = i * pinSpacing; - break; - case _90: - dx1 = -i * pinSpacing; - dy1 = 0; - dx2 = -i * pinSpacing; - dy2 = rowSpacing; - break; - case _180: - dx1 = 0; - dy1 = -i * pinSpacing; - dx2 = -rowSpacing; - dy2 = -i * pinSpacing; - break; - case _270: - dx1 = i * pinSpacing; - dy1 = 0; - dx2 = i * pinSpacing; - dy2 = -rowSpacing; - break; - default: - throw new RuntimeException("Unexpected orientation: " + orientation); - } - controlPoints[i] = new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1)); - controlPoints[i + pinCount.getValue() / 2] = new Point2D.Double((int) (firstPoint.getX() + dx2), (int) (firstPoint.getY() + dy2)); - } - } - - public Area[] getBody() { - if (body == null) { - body = new Area[2]; - double x = controlPoints[0].getX(); - double y = controlPoints[0].getY(); - double width; - double height; - double pinSize = PIN_SIZE.convertToPixels(); - double pinSpacing = this.pinSpacing.convertToPixels(); - double rowSpacing = this.rowSpacing.convertToPixels(); - Area indentation = null; - int indentationSize = getClosestOdd(INDENT_SIZE.convertToPixels()); - switch (orientation) { - case DEFAULT: - width = rowSpacing - pinSize; - height = (pinCount.getValue() / 2) * pinSpacing; - x += pinSize / 2; - y -= pinSpacing / 2; - indentation = - new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, y - indentationSize / 2, - indentationSize, indentationSize)); - break; - case _90: - width = (pinCount.getValue() / 2) * pinSpacing; - height = rowSpacing - pinSize; - x -= (pinSpacing / 2) + width - pinSpacing; - y += pinSize / 2; - indentation = - new Area(new Ellipse2D.Double(x + width - indentationSize / 2, y + height / 2 - indentationSize / 2, - indentationSize, indentationSize)); - break; - case _180: - width = rowSpacing - pinSize; - height = (pinCount.getValue() / 2) * pinSpacing; - x -= rowSpacing - pinSize / 2; - y -= (pinSpacing / 2) + height - pinSpacing; - indentation = - new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, y + height - indentationSize / 2, - indentationSize, indentationSize)); - break; - case _270: - width = (pinCount.getValue() / 2) * pinSpacing; - height = rowSpacing - pinSize; - x -= pinSpacing / 2; - y += pinSize / 2 - rowSpacing; - indentation = - new Area(new Ellipse2D.Double(x - indentationSize / 2, y + height / 2 - indentationSize / 2, - indentationSize, indentationSize)); - break; - default: - throw new RuntimeException("Unexpected orientation: " + orientation); - } - body[0] = new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS)); - body[1] = indentation; - if (indentation != null) { - indentation.intersect(body[0]); - } - } - return body; - } - - @Override - public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, - IDrawingObserver drawingObserver) { - if (checkPointsClipped(g2d.getClip())) { - return; - } + +@ComponentDescriptor(name = "DIP IC", author = "Branislav Stojkovic", category = "Semiconductors", + instanceNamePrefix = "IC", description = "Dual-in-line package IC", + zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, + transformer = DIL_ICTransformer.class, enableCache = true) +public class DIL_IC extends AbstractLabeledComponent { + + private static final long serialVersionUID = 1L; + + public static Color BODY_COLOR = Color.gray; + public static Color BORDER_COLOR = Color.gray.darker(); + public static Color PIN_COLOR = METAL_COLOR; + public static Color PIN_BORDER_COLOR = PIN_COLOR.darker(); + public static Color INDENT_COLOR = Color.gray.darker(); + public static Color LABEL_COLOR = Color.white; + public static int EDGE_RADIUS = 6; + public static Size PIN_SIZE = new Size(0.04d, SizeUnit.in); + public static Size INDENT_SIZE = new Size(0.07d, SizeUnit.in); + public static DisplayNumbers DISPLAY_NUMBERS = DisplayNumbers.NO; + + private String value = ""; + private Orientation orientation = Orientation.DEFAULT; + private PinCount pinCount = PinCount._8; + private Size pinSpacing = new Size(0.1d, SizeUnit.in); + private Size rowSpacing = new Size(0.3d, SizeUnit.in); + private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)}; + protected Display display = Display.BOTH; + private Color bodyColor = BODY_COLOR; + private Color borderColor = BORDER_COLOR; + private Color labelColor = LABEL_COLOR; + private Color indentColor = INDENT_COLOR; + private DisplayNumbers displayNumbers = DISPLAY_NUMBERS; + // new Point(0, pinSpacing.convertToPixels()), + // new Point(0, 2 * pinSpacing.convertToPixels()), + // new Point(0, 3 * pinSpacing.convertToPixels()), + // new Point(3 * pinSpacing.convertToPixels(), 0), + // new Point(3 * pinSpacing.convertToPixels(), + // pinSpacing.convertToPixels()), + // new Point(3 * pinSpacing.convertToPixels(), 2 * + // pinSpacing.convertToPixels()), + // new Point(3 * pinSpacing.convertToPixels(), 3 * + // pinSpacing.convertToPixels()) }; + transient private Area[] body; + + public DIL_IC() { + super(); + updateControlPoints(); + } + + @EditableProperty + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @EditableProperty + public Orientation getOrientation() { + return orientation; + } + + public void setOrientation(Orientation orientation) { + this.orientation = orientation; + updateControlPoints(); + // Reset body shape. + body = null; + } + + @EditableProperty(name = "Pins") + public PinCount getPinCount() { + return pinCount; + } + + public void setPinCount(PinCount pinCount) { + this.pinCount = pinCount; + updateControlPoints(); + // Reset body shape; + body = null; + } + + @EditableProperty(name = "Pin Spacing", validatorClass = PositiveNonZeroMeasureValidator.class) + public Size getPinSpacing() { + return pinSpacing; + } + + public void setPinSpacing(Size pinSpacing) { + this.pinSpacing = pinSpacing; + updateControlPoints(); + // Reset body shape; + body = null; + } + + @EditableProperty(name = "Row Spacing", validatorClass = PositiveNonZeroMeasureValidator.class) + public Size getRowSpacing() { + return rowSpacing; + } + + public void setRowSpacing(Size rowSpacing) { + this.rowSpacing = rowSpacing; + updateControlPoints(); + // Reset body shape; + body = null; + } + + @EditableProperty + public Display getDisplay() { + if (display == null) { + display = Display.VALUE; + } + return display; + } + + public void setDisplay(Display display) { + this.display = display; + } + + @Override + public int getControlPointCount() { + return controlPoints.length; + } + + @Override + public Point2D getControlPoint(int index) { + return controlPoints[index]; + } + + @Override + public boolean isControlPointSticky(int index) { + return true; + } + + @Override + public VisibilityPolicy getControlPointVisibilityPolicy(int index) { + return VisibilityPolicy.NEVER; + } + + @Override + public void setControlPoint(Point2D point, int index) { + controlPoints[index].setLocation(point); + body = null; + } + + private void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + controlPoints = new Point2D[pinCount.getValue()]; + controlPoints[0] = firstPoint; + double pinSpacing = this.pinSpacing.convertToPixels(); + double rowSpacing = this.rowSpacing.convertToPixels(); + // Update control points. + double dx1; + double dy1; + double dx2; + double dy2; + for (int i = 0; i < pinCount.getValue() / 2; i++) { + switch (orientation) { + case DEFAULT: + dx1 = 0; + dy1 = i * pinSpacing; + dx2 = rowSpacing; + dy2 = i * pinSpacing; + break; + case _90: + dx1 = -i * pinSpacing; + dy1 = 0; + dx2 = -i * pinSpacing; + dy2 = rowSpacing; + break; + case _180: + dx1 = 0; + dy1 = -i * pinSpacing; + dx2 = -rowSpacing; + dy2 = -i * pinSpacing; + break; + case _270: + dx1 = i * pinSpacing; + dy1 = 0; + dx2 = i * pinSpacing; + dy2 = -rowSpacing; + break; + default: + throw new RuntimeException("Unexpected orientation: " + orientation); + } + controlPoints[i] = + new Point2D.Double((int) (firstPoint.getX() + dx1), (int) (firstPoint.getY() + dy1)); + controlPoints[i + pinCount.getValue() / 2] = + new Point2D.Double((int) (firstPoint.getX() + dx2), (int) (firstPoint.getY() + dy2)); + } + } + + public Area[] getBody() { + if (body == null) { + body = new Area[2]; + double x = controlPoints[0].getX(); + double y = controlPoints[0].getY(); + double width; + double height; + double pinSize = PIN_SIZE.convertToPixels(); + double pinSpacing = this.pinSpacing.convertToPixels(); + double rowSpacing = this.rowSpacing.convertToPixels(); + Area indentation = null; + int indentationSize = getClosestOdd(INDENT_SIZE.convertToPixels()); + switch (orientation) { + case DEFAULT: + width = rowSpacing - pinSize; + height = (pinCount.getValue() / 2) * pinSpacing; + x += pinSize / 2; + y -= pinSpacing / 2; + indentation = new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, + y - indentationSize / 2, indentationSize, indentationSize)); + break; + case _90: + width = (pinCount.getValue() / 2) * pinSpacing; + height = rowSpacing - pinSize; + x -= (pinSpacing / 2) + width - pinSpacing; + y += pinSize / 2; + indentation = new Area(new Ellipse2D.Double(x + width - indentationSize / 2, + y + height / 2 - indentationSize / 2, indentationSize, indentationSize)); + break; + case _180: + width = rowSpacing - pinSize; + height = (pinCount.getValue() / 2) * pinSpacing; + x -= rowSpacing - pinSize / 2; + y -= (pinSpacing / 2) + height - pinSpacing; + indentation = new Area(new Ellipse2D.Double(x + width / 2 - indentationSize / 2, + y + height - indentationSize / 2, indentationSize, indentationSize)); + break; + case _270: + width = (pinCount.getValue() / 2) * pinSpacing; + height = rowSpacing - pinSize; + x -= pinSpacing / 2; + y += pinSize / 2 - rowSpacing; + indentation = new Area(new Ellipse2D.Double(x - indentationSize / 2, + y + height / 2 - indentationSize / 2, indentationSize, indentationSize)); + break; + default: + throw new RuntimeException("Unexpected orientation: " + orientation); + } + body[0] = + new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS)); + body[1] = indentation; + if (indentation != null) { + indentation.intersect(body[0]); + } + } + return body; + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, + Project project, IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } Area mainArea = getBody()[0]; - g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f)); - if (!outlineMode) { - int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2; + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f)); + if (!outlineMode) { + int pinSize = (int) PIN_SIZE.convertToPixels() / 2 * 2; for (Point2D point : controlPoints) { - Rectangle2D rect = new Rectangle2D.Double(point.getX() - pinSize / 2, point.getY() - pinSize / 2, pinSize, pinSize); - g2d.setColor(PIN_COLOR); - g2d.fill(rect); - g2d.setColor(PIN_BORDER_COLOR); - g2d.draw(rect); - } - } - Composite oldComposite = g2d.getComposite(); - if (alpha < MAX_ALPHA) { - g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); - } - g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor()); - g2d.fill(mainArea); - g2d.setComposite(oldComposite); - - Color finalBorderColor; - if (outlineMode) { - Theme theme = - (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME); - finalBorderColor = - componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR - : theme.getOutlineColor(); - } else { - finalBorderColor = - componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR - : getBorderColor(); - } - g2d.setColor(finalBorderColor); - g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); - if (outlineMode) { - Area area = new Area(mainArea); - area.subtract(getBody()[1]); - g2d.draw(area); - } else { - g2d.draw(mainArea); - if (getBody()[1] != null) { - g2d.setColor(getIndentColor()); - g2d.fill(getBody()[1]); - } - } - - drawingObserver.stopTracking(); - - // Draw label. + Rectangle2D rect = new Rectangle2D.Double(point.getX() - pinSize / 2, + point.getY() - pinSize / 2, pinSize, pinSize); + g2d.setColor(PIN_COLOR); + g2d.fill(rect); + g2d.setColor(PIN_BORDER_COLOR); + g2d.draw(rect); + } + } + Composite oldComposite = g2d.getComposite(); + if (alpha < MAX_ALPHA) { + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); + } + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : getBodyColor()); + g2d.fill(mainArea); + g2d.setComposite(oldComposite); + + Color finalBorderColor; + if (outlineMode) { + Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, + Constants.DEFAULT_THEME); + finalBorderColor = + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? SELECTION_COLOR + : theme.getOutlineColor(); + } else { + finalBorderColor = + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? SELECTION_COLOR + : getBorderColor(); + } + g2d.setColor(finalBorderColor); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + if (outlineMode) { + Area area = new Area(mainArea); + area.subtract(getBody()[1]); + g2d.draw(area); + } else { + g2d.draw(mainArea); + if (getBody()[1] != null) { + g2d.setColor(getIndentColor()); + g2d.fill(getBody()[1]); + } + } + + drawingObserver.stopTracking(); + + // Draw label. g2d.setFont(project.getFont()); - + // Override font size if (getFontSizeOverride() != null) g2d.setFont(g2d.getFont().deriveFont(1f * getFontSizeOverride())); - - Color finalLabelColor; - if (outlineMode) { - Theme theme = - (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME); - finalLabelColor = - componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED - : theme.getOutlineColor(); - } else { - finalLabelColor = - componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? LABEL_COLOR_SELECTED - : getLabelColor(); - } - g2d.setColor(finalLabelColor); - FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont()); - String[] label = null; - - if (getDisplay() == Display.NAME) { - label = new String[] {getName()}; - } else if (getDisplay() == Display.VALUE) { - label = new String[] {getValue().toString()}; - } else if (getDisplay() == Display.BOTH) { - String value = getValue().toString(); - label = value.isEmpty() ? new String[] {getName()} : new String[] {getName(), value}; - } - - if (label != null) { - for (int i = 0; i < label.length; i++) { - String l = label[i]; - Rectangle2D rect = fontMetrics.getStringBounds(l, g2d); - int textHeight = (int) (rect.getHeight()); - int textWidth = (int) (rect.getWidth()); - // Center text horizontally and vertically - Rectangle bounds = mainArea.getBounds(); - double x = bounds.getX() + (bounds.width - textWidth) / 2; - double y = bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent(); - - AffineTransform oldTransform = g2d.getTransform(); - - if (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180) { - double centerX = bounds.getX() + bounds.width / 2; - double centerY = bounds.getY() + bounds.height / 2; - g2d.rotate(-Math.PI / 2, centerX, centerY); - } - - if (label.length == 2) { - if (i == 0) - g2d.translate(0, -textHeight / 2); - else if (i == 1) - g2d.translate(0, textHeight / 2); - } - - g2d.drawString(l, (int)x, (int)y); - - g2d.setTransform(oldTransform); - } - } - - // draw pin numbers - int pinNo = 0; - int j = 0; - int k = 0; - int pinSize = (int) PIN_SIZE.convertToPixels(); - for (Point2D point : controlPoints) { - pinNo++; - - // determine points relative to rotation - int textX1 = (int) (point.getX() - 2 * pinSize); - int textY1 = (int) (point.getY() + pinSize / 2); - int textX2 = (int) (point.getX() + pinSize); - int textY2 = (int) (point.getY() + pinSize / 2); - if (orientation == Orientation._90) { - textX2 = textX2 - pinSize - pinSize / 2; - textY2 = textY2 + pinSize; - textX1 = textX1 + 2 * pinSize - pinSize / 2; - textY1 = textY1 - pinSize; - } - if (orientation == Orientation._180) { - textX1 = textX1 + 3 * pinSize; - textX2 = textX2 - 3 * pinSize; - } - if (orientation == Orientation._270) { - textX1 = textX1 + pinSize + pinSize / 2; - textY1 = textY1 + pinSize; - textX2 = textX2 - pinSize - pinSize / 2; - textY2 = textY2 - pinSize; - } - - g2d.setFont(project.getFont().deriveFont((float) (project.getFont().getSize2D() * 0.66))); - if (displayNumbers == DisplayNumbers.DIP) { - if (pinNo > pinCount.getValue() / 2) { - g2d.drawString(Integer.toString(pinCount.getValue() - j), textX1, textY1); - j++; - } else { - g2d.drawString(Integer.toString(pinNo), textX2, textY2); - } - } else if (displayNumbers == DisplayNumbers.CONNECTOR) { - if (pinNo > pinCount.getValue() / 2) { - k++; - g2d.drawString(Integer.toString(pinNo - (pinCount.getValue() / 2) + k), textX1, textY1); - } else { - g2d.drawString(Integer.toString(pinNo + j), textX2, textY2); - j++; - } - } else if (displayNumbers == DisplayNumbers.DIP_MIRROR) { - if (pinNo > pinCount.getValue() / 2) { - g2d.drawString(Integer.toString(pinCount.getValue() - pinCount.getValue() + j + 1), textX1, textY1); - j++; - } else { - g2d.drawString(Integer.toString(pinCount.getValue() - pinNo + 1), textX2, textY2); + + Color finalLabelColor; + if (outlineMode) { + Theme theme = (Theme) ConfigurationManager.getInstance().readObject(IPlugInPort.THEME_KEY, + Constants.DEFAULT_THEME); + finalLabelColor = + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? LABEL_COLOR_SELECTED + : theme.getOutlineColor(); + } else { + finalLabelColor = + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? LABEL_COLOR_SELECTED + : getLabelColor(); + } + g2d.setColor(finalLabelColor); + FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont()); + String[] label = null; + + if (getDisplay() == Display.NAME) { + label = new String[] {getName()}; + } else if (getDisplay() == Display.VALUE) { + label = new String[] {getValue().toString()}; + } else if (getDisplay() == Display.BOTH) { + String value = getValue().toString(); + label = value.isEmpty() ? new String[] {getName()} : new String[] {getName(), value}; + } + + if (label != null) { + for (int i = 0; i < label.length; i++) { + String l = label[i]; + Rectangle2D rect = fontMetrics.getStringBounds(l, g2d); + int textHeight = (int) (rect.getHeight()); + int textWidth = (int) (rect.getWidth()); + // Center text horizontally and vertically + Rectangle bounds = mainArea.getBounds(); + double x = bounds.getX() + (bounds.width - textWidth) / 2; + double y = bounds.getY() + (bounds.height - textHeight) / 2 + fontMetrics.getAscent(); + + AffineTransform oldTransform = g2d.getTransform(); + + if (getOrientation() == Orientation.DEFAULT || getOrientation() == Orientation._180) { + double centerX = bounds.getX() + bounds.width / 2; + double centerY = bounds.getY() + bounds.height / 2; + g2d.rotate(-Math.PI / 2, centerX, centerY); } - } else if (displayNumbers == DisplayNumbers.CONNECTOR_MIRROR) { - if (pinNo > pinCount.getValue() / 2) { - k++; - g2d.drawString(Integer.toString(pinNo - (pinCount.getValue() / 2) + k - 1), textX1, textY1); - } else { - g2d.drawString(Integer.toString(pinNo + j + 1), textX2, textY2); - j++; + + if (label.length == 2) { + if (i == 0) + g2d.translate(0, -textHeight / 2); + else if (i == 1) + g2d.translate(0, textHeight / 2); } - } - } - } - - @Override - public void drawIcon(Graphics2D g2d, int width, int height) { - int radius = 6 * width / 32; - g2d.setColor(BODY_COLOR); - g2d.fillRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius); - g2d.setColor(BORDER_COLOR); - g2d.drawRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius); - int pinSize = 2 * width / 32; - g2d.setColor(PIN_COLOR); - for (int i = 0; i < 4; i++) { - g2d.fillRect(width / 6 - pinSize, (height / 5) * (i + 1) - 1, pinSize, pinSize); - g2d.fillRect(5 * width / 6 + 1, (height / 5) * (i + 1) - 1, pinSize, pinSize); - } - } - - @EditableProperty(name = "Body") - public Color getBodyColor() { - if (bodyColor == null) { - bodyColor = BODY_COLOR; - } - return bodyColor; - } - - public void setBodyColor(Color bodyColor) { - this.bodyColor = bodyColor; - } - - @EditableProperty(name = "Border") - public Color getBorderColor() { - if (borderColor == null) { - borderColor = BORDER_COLOR; - } - return borderColor; - } - - public void setBorderColor(Color borderColor) { - this.borderColor = borderColor; - } - - @EditableProperty(name = "Label") - public Color getLabelColor() { - if (labelColor == null) { - labelColor = LABEL_COLOR; - } - return labelColor; - } - - public void setLabelColor(Color labelColor) { - this.labelColor = labelColor; - } - - @EditableProperty(name = "Indent") - public Color getIndentColor() { - if (indentColor == null) { - indentColor = INDENT_COLOR; - } - return indentColor; - } - - public void setIndentColor(Color indentColor) { - this.indentColor = indentColor; - } - - @EditableProperty(name = "Display Pin #s") - public DisplayNumbers getDisplayNumbers() { - return displayNumbers; - } - - public void setDisplayNumbers(DisplayNumbers numbers) { - this.displayNumbers = numbers; + + g2d.drawString(l, (int) x, (int) y); + + g2d.setTransform(oldTransform); + } + } + + // draw pin numbers + if (getDisplayNumbers() != DisplayNumbers.NO) { + int pinSize = (int) PIN_SIZE.convertToPixels(); + + for (int i = 0; i < controlPoints.length; i++) { + Point2D point = controlPoints[i]; + + // determine points relative to rotation + int textX1 = (int) (point.getX() - 2 * pinSize); + int textY1 = (int) (point.getY() + pinSize / 2); + int textX2 = (int) (point.getX() + pinSize); + int textY2 = (int) (point.getY() + pinSize / 2); + if (orientation == Orientation._90) { + textX2 = textX2 - pinSize - pinSize / 2; + textY2 = textY2 + pinSize; + textX1 = textX1 + 2 * pinSize - pinSize / 2; + textY1 = textY1 - pinSize; + } + if (orientation == Orientation._180) { + textX1 = textX1 + 3 * pinSize; + textX2 = textX2 - 3 * pinSize; + } + if (orientation == Orientation._270) { + textX1 = textX1 + pinSize + pinSize / 2; + textY1 = textY1 + pinSize; + textX2 = textX2 - pinSize - pinSize / 2; + textY2 = textY2 - pinSize; + } + + g2d.setFont(project.getFont().deriveFont((float) (project.getFont().getSize2D() * 0.66))); + if (i >= pinCount.getValue() / 2) { + g2d.drawString(getControlPointNodeName(i), textX1, textY1); + } else { + g2d.drawString(getControlPointNodeName(i), textX2, textY2); + } + } + } } - + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + int radius = 6 * width / 32; + g2d.setColor(BODY_COLOR); + g2d.fillRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius); + g2d.setColor(BORDER_COLOR); + g2d.drawRoundRect(width / 6, 1, 4 * width / 6, height - 4, radius, radius); + int pinSize = 2 * width / 32; + g2d.setColor(PIN_COLOR); + for (int i = 0; i < 4; i++) { + g2d.fillRect(width / 6 - pinSize, (height / 5) * (i + 1) - 1, pinSize, pinSize); + g2d.fillRect(5 * width / 6 + 1, (height / 5) * (i + 1) - 1, pinSize, pinSize); + } + } + + @EditableProperty(name = "Body") + public Color getBodyColor() { + if (bodyColor == null) { + bodyColor = BODY_COLOR; + } + return bodyColor; + } + + public void setBodyColor(Color bodyColor) { + this.bodyColor = bodyColor; + } + + @EditableProperty(name = "Border") + public Color getBorderColor() { + if (borderColor == null) { + borderColor = BORDER_COLOR; + } + return borderColor; + } + + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + @EditableProperty(name = "Label") + public Color getLabelColor() { + if (labelColor == null) { + labelColor = LABEL_COLOR; + } + return labelColor; + } + + public void setLabelColor(Color labelColor) { + this.labelColor = labelColor; + } + + @EditableProperty(name = "Indent") + public Color getIndentColor() { + if (indentColor == null) { + indentColor = INDENT_COLOR; + } + return indentColor; + } + + public void setIndentColor(Color indentColor) { + this.indentColor = indentColor; + } + + @EditableProperty(name = "Display Pin #s") + public DisplayNumbers getDisplayNumbers() { + return displayNumbers; + } + + public void setDisplayNumbers(DisplayNumbers numbers) { + this.displayNumbers = numbers; + } + @Override public boolean canPointMoveFreely(int pointIndex) { return false; } - + @Override public Rectangle2D getCachingBounds() { double minX = Integer.MAX_VALUE; @@ -581,37 +556,71 @@ public class DIL_IC extends AbstractLabeledComponent { if (p.getY() > maxY) maxY = p.getY(); } + + return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, + maxY - minY + 2 * margin); + } + + @Override + public String getControlPointNodeName(int index) { + index++; - return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin); - } - - public static enum PinCount { - - _4, _6, _8, _10, _12, _14, _16, _18, _20, _22, _24, _26, _28, _30, _32, _34, _36, _38, _40, _42, _44, _46, _48, _50; - - @Override - public String toString() { - return name().replace("_", ""); - } - - public int getValue() { - return Integer.parseInt(toString()); - } - } - - public enum DisplayNumbers { - - NO("No"), DIP("DIP"), CONNECTOR("Connector"), DIP_MIRROR("DIP (Mirrored)"), CONNECTOR_MIRROR("Connector (Mirrored)"); - - private String label; - - private DisplayNumbers(String label) { - this.label = label; - } - - @Override - public String toString() { - return label; - } - } -} + if (displayNumbers == DisplayNumbers.DIP) { + if (index > pinCount.getValue() / 2) { + return Integer.toString(pinCount.getValue() * 3 / 2 - index + 1); + } else { + return Integer.toString(index); + } + } else if (displayNumbers == DisplayNumbers.CONNECTOR) { + if (index > pinCount.getValue() / 2) { + return Integer.toString(index - pinCount.getValue() + index); + } else { + return Integer.toString(index * 2 - 1); + } + } else if (displayNumbers == DisplayNumbers.DIP_MIRROR) { + if (index > pinCount.getValue() / 2) { + return Integer.toString((index - pinCount.getValue() / 2)); + } else { + return Integer.toString(pinCount.getValue() - index + 1); + } + } else if (displayNumbers == DisplayNumbers.CONNECTOR_MIRROR) { + if (index > pinCount.getValue() / 2) { + return Integer.toString(index - pinCount.getValue() + index - 1); + } else { + return Integer.toString(2 * index); + } + } + return null; + } + + public static enum PinCount { + + _4, _6, _8, _10, _12, _14, _16, _18, _20, _22, _24, _26, _28, _30, _32, _34, _36, _38, _40, _42, _44, _46, _48, _50; + + @Override + public String toString() { + return name().replace("_", ""); + } + + public int getValue() { + return Integer.parseInt(toString()); + } + } + + public enum DisplayNumbers { + + NO("No"), DIP("DIP"), CONNECTOR("Connector"), DIP_MIRROR("DIP (Mirrored)"), CONNECTOR_MIRROR( + "Connector (Mirrored)"); + + private String label; + + private DisplayNumbers(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } + } +} diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index 21ea907e48d321407c0bdcf89f96a6375b74323f..83ee75c5db07f2be5a4fbef1338f6fd55378b071 100644 GIT binary patch delta 7141 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 Vh=XcjjA2EZ;48~YmPI@qwR$D2? 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 delta 20566 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