From c1c87a245490dc59022d29bb259a89a382b74f06 Mon Sep 17 00:00:00 2001 From: bancika Date: Thu, 26 Jan 2017 12:31:40 +0100 Subject: [PATCH] prepare the release --- diylc/diylc-library/lib/diylc-core.jar | Bin 236911 -> 236911 bytes .../diylc/components/Abstract3LegSymbol.java | 5 +- .../diylc/components/smd/SOT23Package.java | 427 ++++++++++++++++++ .../transform/TubeSymbolTransformer.java | 103 +++++ .../components/tube/AbstractTubeSymbol.java | 130 ++++-- .../diylc/components/tube/DiodeSymbol.java | 35 +- .../diylc/components/tube/PentodeSymbol.java | 46 +- .../diylc/components/tube/TriodeSymbol.java | 36 +- diylc/diylc-swing/build.xml | 4 +- diylc/diylc-swing/lib/diylc-core.jar | Bin 236911 -> 236911 bytes diylc/diylc-swing/update.xml | 6 +- 11 files changed, 712 insertions(+), 80 deletions(-) create mode 100644 diylc/diylc-library/src/org/diylc/components/smd/SOT23Package.java create mode 100644 diylc/diylc-library/src/org/diylc/components/transform/TubeSymbolTransformer.java diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index 92b6a30c8fb4c3e0eecd852131e8dc3ca54c7805..81f34ce0fef122a615e8e1febd55642f321a5bc5 100644 GIT binary patch delta 4668 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 delta 4668 zcmXw5d0dvo7XD@qiztgAn?Fh*gD^<*VyFQIii)79$R?|xpaL2SDhMH~f{H93@d7Go zxnYYG<#&}#Q&ZB4tXrw6_v*Dw%`2oS7rA+7&YABIe$O*!dCr+L@65;jqt^G2T3gKv z2a};X-4LDb=cLK?R$g#fz@&!~^y8Q-;(X@G#j=1+kZ_3kfQZ#!V=p7x@>dZf_=|{z z+z+vUx#)YiGx9^sMJu*r=6XvQiiVN!5=zffSOC5h2$K=-LLj2I$vDI$6CY8#bBjqG zm-wvtbyI;2RySowzgi7S<4x;xOk&4yW+JiEej~2^9Xl}Tp7SciMJ}U3`YT7d;d;MY zCt~90P>kRA{1n7rJu;b9(&Vt*tHr-H=ybaCI(?sqvp(F*LJLZUVfyM9c1js9uNn+D zj2X!+Mfk1hGhVwY!ejNl9wW7hDPXU+@cvCi>K}Ly$b|boFPKSm_N~LjgA<$(PrVX} z=rr+L#M_hVv9BWkIf&;2|3Ew*)Qq@r+G51drvG6&TonHC$7ft`aGma`sZQsm|J>eQ zTfZ2bI`4+x!?4Q{Zn*8i`819XqKeS&6I);^&P8AEp$3J zdwp=_XstaRY&v_F*IS@-qTN7LnypS3;fc}@R!Eko*j0m&4-Gj2Gp(HlFeYy!m1&DMymt%teX;I1WJ2iA+pR*63keP7!MEj|+* z^i?}6<#cV@E}+`K+vZUrzul=sTHi4lDhIyn{S`O?n-70N-QPORux{_iBXK><@FFEl zI#NvJNY_U)wvXGyK|VI;`Yt7aFCk&Rk#D-8kub8{cb|qs?(L(9qfX&qP~CG#k#H zwP72;&JdT+x+!;bAq%67oMLvE*qAalhFEkZD@3Mk4C2oj{;XoF$&tC0Inor%>(~~u z*)|$Cb6sQYWUJZE9#Wx-Ha3%N-|S}dX)gC3%v{$e=JLCCXeM_ygzRBvBs%8+dxlu{ zd+aP7jo&fWLsCOdu-n8Qo)pK5yPO`_e{P770@#AC zeaw#7s)t7D^N(31+1#G6B4Tg-#TFAY<=l;!mnrvR*nVAyMMkeUq`P=XhBanfeXbQ2 z+?;~9S@Ko1C7(}Uc*$OLX(RVK(%>u?i|2gvS>8tFX?caV?C|~4SZJXHA zfz4oRFmvIzXo9`Z@={94bLVf6{<}#xGAe}r1{#^82XCT~LtgwovE4r6XBt1bYvcF_ z3|Z}Xol!r)4~qY=v2T3T9}ZX7g{+S-XO77=g^Tl)I7Kgfc#c z*rIYiidbm{{|?_pL(C?AmTYd-d@en5*ur}lzR@d> z?D6_axZBBXI8wvu*)_D(@>Y`dYv7*~8))R`iFIo{$_ATr-On%EBOC1EJE-C9J-m+^ zslC8Q;}5OjlN&sQatCkn!^A$h#X0T&=pDX-qADWn&%2twt$c@gAEv`(dd(o-qlkV^69X@s$9WN%NS zz8Ct6>3JOmbE2tHUDOGe_IFVdx}IA7>V@=ZQWMKYoQLXgB4h|4Km`wNuLJtOg5uSyge$*J|? z^2uPELX{pY!D-rq;!K){?bTnOH}ahHR5H-Edg%~++CvDyj7y+=U1xsU0$l%>@gCT zGSyvHnUe1;gPExFzcM8sQm$NE%azWha+r@XFI9-+mEDzBsF?E=D$A}?1*cR(IL5qh zv(cwH>=?8&8md$78Sg3i;CH`MYVdzNG5DmGc4JvV$K?gb&cvLp+>phu2JdY zi0DgsWt(ypZBwo@+f*BlwJIj1R=L`1)kpNORw)P9i4NrtKy{rs0!gmcsf!;_5AkSe zsaKZ%dUemE8Xy&2e{X>2t{BNg4PsEIPE%L^j;0=ipk{G>W%CWqkbtDOS+zR5MLi+ATU7Al7WFWMwJNf+ rRrT|qR;3)eT^x!OY}_usC`oP@En|0x(Me0;4mGi!9V*>zC(Qjnwsn7# diff --git a/diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java b/diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java index 6b3abad1..bdbbb12c 100644 --- a/diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/Abstract3LegSymbol.java @@ -34,12 +34,11 @@ public abstract class Abstract3LegSymbol extends AbstractComponent { public static Size PIN_SPACING = new Size(0.1d, SizeUnit.in); public static Color COLOR = Color.black; - - public static SymbolFlipping FLIPPING = SymbolFlipping.NONE; + protected String value = ""; protected Point[] controlPoints = new Point[] {new Point(0, 0), new Point(0, 0), new Point(0, 0)}; protected Color color = COLOR; - protected SymbolFlipping flip = FLIPPING; + protected SymbolFlipping flip = SymbolFlipping.NONE; protected Display display = Display.NAME; transient protected Shape[] body; protected Orientation orientation = Orientation.DEFAULT; diff --git a/diylc/diylc-library/src/org/diylc/components/smd/SOT23Package.java b/diylc/diylc-library/src/org/diylc/components/smd/SOT23Package.java new file mode 100644 index 00000000..b8cae926 --- /dev/null +++ b/diylc/diylc-library/src/org/diylc/components/smd/SOT23Package.java @@ -0,0 +1,427 @@ +//package org.diylc.components.smd; +// +//import java.awt.AlphaComposite; +//import java.awt.Color; +//import java.awt.Composite; +//import java.awt.FontMetrics; +//import java.awt.Graphics2D; +//import java.awt.Point; +//import java.awt.Rectangle; +//import java.awt.geom.Area; +//import java.awt.geom.Rectangle2D; +//import java.awt.geom.RoundRectangle2D; +// +//import org.diylc.appframework.miscutils.ConfigurationManager; +//import org.diylc.common.Display; +//import org.diylc.common.IPlugInPort; +//import org.diylc.common.ObjectCache; +//import org.diylc.common.Orientation; +//import org.diylc.components.AbstractTransparentComponent; +//import org.diylc.core.ComponentState; +//import org.diylc.core.IDIYComponent; +//import org.diylc.core.IDrawingObserver; +//import org.diylc.core.Project; +//import org.diylc.core.Theme; +//import org.diylc.core.VisibilityPolicy; +//import org.diylc.core.annotations.ComponentDescriptor; +//import org.diylc.core.annotations.EditableProperty; +//import org.diylc.core.annotations.KeywordPolicy; +//import org.diylc.core.annotations.PositiveMeasureValidator; +//import org.diylc.core.measures.Size; +//import org.diylc.core.measures.SizeUnit; +//import org.diylc.utils.Constants; +// +//@ComponentDescriptor(name = "SOT-23 Case", author = "Branislav Stojkovic", category = "SMD", instanceNamePrefix = "C", +// description = "Small outline transistor for SMD", stretchable = false, zOrder = IDIYComponent.COMPONENT, +// keywordPolicy = KeywordPolicy.SHOW_VALUE) +//public class SOT23Package extends AbstractTransparentComponent { +// +// 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 = Color.decode("#00B2EE"); +// public static Color PIN_BORDER_COLOR = PIN_COLOR.darker(); +// public static Color LABEL_COLOR = Color.white; +// public static int EDGE_RADIUS = 4; +// public static Size PIN_SIZE = new Size(0.8d, SizeUnit.mm); +// +// public static Size LENGTH = new Size(3d, SizeUnit.mm); +// public static Size WIDTH = new Size(1.4d, SizeUnit.mm); +// +// public static Size PIN_LENGTH = new Size(0.6d, SizeUnit.mm); +// public static Size PIN_WIDTH = new Size(0.4d, SizeUnit.mm); +// +// protected String value; +// private Orientation orientation = Orientation.DEFAULT; +// +// private SOT23Variation variation = SOT23Variation._3; +// private Point[] controlPoints = new Point[] {new Point(0, 0), new Point(0, 0)}; +// protected Display display = Display.NAME; +// protected Color bodyColor = BODY_COLOR; +// protected Color borderColor = BORDER_COLOR; +// private Color labelColor = LABEL_COLOR; +// transient private Area[] body; +// +// public SOT23Package() { +// super(); +// updateControlPoints(); +// } +// +// @EditableProperty(validatorClass = PositiveMeasureValidator.class) +// 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 +// public Display getDisplay() { +// if (display == null) { +// display = Display.VALUE; +// } +// return display; +// } +// +// public void setDisplay(Display display) { +// this.display = display; +// } +// +// @EditableProperty(name = "Contacts") +// public SOT23Variation getVariation() { +// return variation; +// } +// +// public void setVariation(SOT23Variation variation) { +// this.variation = variation; +// updateControlPoints(); +// // Reset body shape. +// body = null; +// } +// +// @Override +// public int getControlPointCount() { +// return controlPoints.length; +// } +// +// @Override +// public Point 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(Point point, int index) { +// controlPoints[index].setLocation(point); +// body = null; +// } +// +// private void updateControlPoints() { +// Point firstPoint = controlPoints[0]; +// controlPoints[0] = firstPoint; +// int pinSize = (int) PIN_SIZE.convertToPixels(); +// int smdLength = (int) LENGTH.convertToPixels(); +// int pinSpacing = smdLength - pinSize; +// +// // Update control points. +// int dx1; +// int dy1; +// switch (orientation) { +// case DEFAULT: +// dx1 = 0; +// dy1 = pinSpacing; +// break; +// case _90: +// dx1 = -pinSpacing; +// dy1 = 0; +// break; +// case _180: +// dx1 = 0; +// dy1 = -pinSpacing; +// break; +// case _270: +// dx1 = pinSpacing; +// dy1 = 0; +// break; +// default: +// throw new RuntimeException("Unexpected orientation: " + orientation); +// } +// controlPoints[1] = new Point(firstPoint.x + dx1, firstPoint.y + dy1); +// } +// +// public Area[] getBody() { +// if (body == null) { +// body = new Area[2]; +// int x = controlPoints[0].x; +// int y = controlPoints[0].y; +// int smdLength = (int) LENGTH.convertToPixels(); +// int smdWidth = (int) WIDTH.convertToPixels(); +// int pinSize = (int) PIN_SIZE.convertToPixels(); +// int width; +// int height; +// +// // create main body +// switch (orientation) { +// case DEFAULT: +// width = smdWidth; +// height = smdLength; +// x = controlPoints[0].x - smdWidth / 2; +// y = controlPoints[0].y - pinSize / 2; +// break; +// case _90: +// width = smdLength; +// height = smdWidth; +// x = controlPoints[1].x - pinSize / 2; +// y = controlPoints[1].y - smdWidth / 2; +// break; +// case _180: +// width = smdWidth; +// height = smdLength; +// x = controlPoints[1].x - smdWidth / 2; +// y = controlPoints[1].y - pinSize / 2; +// break; +// case _270: +// width = smdLength; +// height = smdWidth; +// x = controlPoints[0].x - pinSize / 2; +// y = controlPoints[0].y - smdWidth / 2; +// break; +// default: +// throw new RuntimeException("Unexpected orientation: " + orientation); +// } +// Area mainArea = new Area(new RoundRectangle2D.Double(x, y, width, height, EDGE_RADIUS, EDGE_RADIUS)); +// +// // create contact area +// Area contactArea = new Area(); +// if (width > height) { +// contactArea.add(new Area(new Rectangle2D.Double(x, y, pinSize, height))); +// contactArea.add(new Area(new Rectangle2D.Double(x + width - pinSize, y, pinSize, height))); +// } else { +// contactArea.add(new Area(new Rectangle2D.Double(x, y, width, pinSize))); +// contactArea.add(new Area(new Rectangle2D.Double(x, y + height - pinSize, width, pinSize))); +// } +// contactArea.intersect(mainArea); +// +// mainArea.subtract(contactArea); +// body[0] = mainArea; +// body[1] = contactArea; +// +// } +// return body; +// } +// +// @Override +// public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, +// IDrawingObserver drawingObserver) { +// if (checkPointsClipped(g2d.getClip())) { +// return; +// } +// +// // draw main area +// Area mainArea = getBody()[0]; +// 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)); +// g2d.draw(mainArea); +// +// +// // draw contact area +// Area contactArea = getBody()[1]; +// if (!outlineMode) { +// g2d.setColor(PIN_COLOR); +// if (alpha < MAX_ALPHA) { +// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); +// } +// g2d.fill(contactArea); +// g2d.setComposite(oldComposite); +// } +// +// 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 +// : PIN_BORDER_COLOR; +// } +// g2d.setColor(finalBorderColor); +// g2d.draw(contactArea); +// +// // Draw label. +// g2d.setFont(LABEL_FONT); +// 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 = ""; +// label = (getDisplay() == Display.NAME) ? getName() : getValue().toString(); +// if (getDisplay() == Display.NONE) { +// label = ""; +// } +// if (getDisplay() == Display.BOTH) { +// label = getName() + " " + (getValue() == null ? "" : getValue().toString()); +// } +// +// Rectangle textTarget = mainArea.getBounds(); +// int length = textTarget.height > textTarget.width ? textTarget.height : textTarget.width; +// +// Rectangle2D rect = fontMetrics.getStringBounds(label, g2d); +// int textHeight = (int) (rect.getHeight()); +// int textWidth = (int) (rect.getWidth()); +// +// do { +// g2d.setFont(g2d.getFont().deriveFont(g2d.getFont().getSize2D() - 1)); +// fontMetrics = g2d.getFontMetrics(g2d.getFont()); +// rect = fontMetrics.getStringBounds(label, g2d); +// textHeight = (int) (rect.getHeight()); +// textWidth = (int) (rect.getWidth()); +// } while (textWidth > length && g2d.getFont().getSize2D() > 2); +// +// double centerX = textTarget.getX() + textTarget.getWidth() / 2; +// double centerY = textTarget.getY() + textTarget.getHeight() / 2; +// g2d.translate(centerX, centerY); +// +// switch (orientation) { +// case DEFAULT: +// g2d.rotate(Math.PI / 2); +// break; +// case _90: +// g2d.rotate(Math.PI); +// break; +// case _180: +// g2d.rotate(Math.PI * 3 / 2); +// break; +// case _270: +// break; +// default: +// throw new RuntimeException("Unexpected orientation: " + orientation); +// } +// +// // Center text horizontally and vertically +// int x = -textWidth / 2; +// int y = -textHeight / 2 + fontMetrics.getAscent() - 1; +// g2d.drawString(label, x, y); +// } +// +// @Override +// public void drawIcon(Graphics2D g2d, int width, int height) { +// int radius = 4 * width / 32; +// int contactSize = 4 * width / 32; +// int thickness = getClosestOdd(width / 2); +// g2d.rotate(Math.PI / 4, width / 2, height / 2); +// RoundRectangle2D rect = +// new RoundRectangle2D.Double((width - thickness) / 2, 4 * width / 32, thickness, height - 8 * width / 32, +// radius, radius); +// g2d.setColor(getBodyColor()); +// g2d.fill(rect); +// g2d.setColor(getBorderColor()); +// g2d.draw(rect); +// Area contactArea = new Area(); +// contactArea.add(new Area(new Rectangle2D.Double((width - thickness) / 2, 4 * width / 32, thickness, contactSize))); +// contactArea.add(new Area(new Rectangle2D.Double((width - thickness) / 2, height - 8 * width / 32, thickness, +// contactSize))); +// contactArea.intersect(new Area(rect)); +// g2d.setColor(PIN_COLOR); +// g2d.fill(contactArea); +// } +// +// @EditableProperty(name = "Body") +// public Color getBodyColor() { +// return bodyColor; +// } +// +// public void setBodyColor(Color bodyColor) { +// this.bodyColor = bodyColor; +// } +// +// @EditableProperty(name = "Border") +// public Color getBorderColor() { +// 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; +// } +// +// public static enum SOT23Variation { +// +// _3, _5, _6, _8; +// +// @Override +// public String toString() { +// return name().replace("_", ""); +// } +// +// public int getValue() { +// return Integer.parseInt(toString()); +// } +// } +//} diff --git a/diylc/diylc-library/src/org/diylc/components/transform/TubeSymbolTransformer.java b/diylc/diylc-library/src/org/diylc/components/transform/TubeSymbolTransformer.java new file mode 100644 index 00000000..715ded70 --- /dev/null +++ b/diylc/diylc-library/src/org/diylc/components/transform/TubeSymbolTransformer.java @@ -0,0 +1,103 @@ +package org.diylc.components.transform; + +import java.awt.Point; +import java.awt.geom.AffineTransform; + +import org.diylc.common.IComponentTransformer; +import org.diylc.common.Orientation; +import org.diylc.components.tube.AbstractTubeSymbol; +import org.diylc.core.IDIYComponent; + +public class TubeSymbolTransformer implements IComponentTransformer { + + @Override + public boolean canRotate(IDIYComponent component) { + return AbstractTubeSymbol.class.isAssignableFrom(component.getClass()); + } + + @Override + public boolean canMirror(IDIYComponent component) { + return AbstractTubeSymbol.class.isAssignableFrom(component.getClass()); + } + + @Override + public boolean mirroringChangesCircuit() { + return false; + } + + @Override + public void rotate(IDIYComponent component, Point center, int direction) { + AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2 * direction, center.x, center.y); + for (int index = 0; index < component.getControlPointCount(); index++) { + Point p = new Point(component.getControlPoint(index)); + rotate.transform(p, p); + component.setControlPoint(p, index); + } + + AbstractTubeSymbol tube = (AbstractTubeSymbol) component; + Orientation o = tube.getOrientation(); + int oValue = o.ordinal(); + oValue += direction; + if (oValue < 0) + oValue = Orientation.values().length - 1; + if (oValue >= Orientation.values().length) + oValue = 0; + o = Orientation.values()[oValue]; + tube.setOrientation(o); + } + + @Override + public void mirror(IDIYComponent component, Point center, int direction) { + AbstractTubeSymbol tube = (AbstractTubeSymbol) component; + + if (direction == IComponentTransformer.HORIZONTAL) { + int dx = 2 * (center.x - tube.getControlPoint(0).x); + int dy = 0; + + Orientation o = tube.getOrientation(); + switch (o) { + case DEFAULT: + o = Orientation._180; + break; + case _90: + break; + case _180: + o = Orientation.DEFAULT; + break; + case _270: + break; + } + + for (int i = 0; i < tube.getControlPointCount(); i++) { + Point p = tube.getControlPoint(i); + tube.setControlPoint(new Point(p.x + dx, p.y + dy), i); + } + + tube.setOrientation(o); + } else { + int dx = 0; + int dy = 2 * (center.y - tube.getControlPoint(0).y); + + Orientation o = tube.getOrientation(); + switch (o) { + case DEFAULT: + break; + case _90: + o = Orientation._270; + break; + case _180: + break; + case _270: + o = Orientation._90; + break; + } + + for (int i = 0; i < tube.getControlPointCount(); i++) { + Point p = tube.getControlPoint(i); + tube.setControlPoint(new Point(p.x + dx, p.y + dy), i); + } + + tube.setOrientation(o); + } + } +} diff --git a/diylc/diylc-library/src/org/diylc/components/tube/AbstractTubeSymbol.java b/diylc/diylc-library/src/org/diylc/components/tube/AbstractTubeSymbol.java index 1c6eb60f..3b7d3388 100644 --- a/diylc/diylc-library/src/org/diylc/components/tube/AbstractTubeSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/tube/AbstractTubeSymbol.java @@ -15,6 +15,7 @@ import org.diylc.common.ObjectCache; import org.diylc.common.Orientation; import org.diylc.common.VerticalAlignment; import org.diylc.components.AbstractComponent; +import org.diylc.components.semiconductors.SymbolFlipping; import org.diylc.core.ComponentState; import org.diylc.core.IDrawingObserver; import org.diylc.core.Project; @@ -38,6 +39,7 @@ public abstract class AbstractTubeSymbol extends AbstractComponent { transient protected Shape[] body; protected boolean showHeaters; protected Orientation orientation = Orientation.DEFAULT; + protected SymbolFlipping flip = SymbolFlipping.NONE; protected Point[] controlPoints; @Override @@ -87,9 +89,9 @@ public abstract class AbstractTubeSymbol extends AbstractComponent { : LABEL_COLOR; } g2d.setColor(finalLabelColor); - + Rectangle rect = body[2] != null ? body[2].getBounds() : body[1].getBounds(); - + String label = ""; label = display == Display.VALUE ? getValue() : getName(); if (display == Display.NONE) { @@ -98,9 +100,10 @@ public abstract class AbstractTubeSymbol extends AbstractComponent { if (display == Display.BOTH) { label = getName() + " " + (getValue() == null ? "" : getValue().toString()); } - drawCenteredText(g2d, label, rect.x + rect.width, rect.y + rect.height, HorizontalAlignment.RIGHT, VerticalAlignment.BOTTOM); + drawCenteredText(g2d, label, rect.x + rect.width, rect.y + rect.height, HorizontalAlignment.RIGHT, + VerticalAlignment.BOTTOM); } - + @Override public Point getControlPoint(int index) { return controlPoints[index]; @@ -110,12 +113,13 @@ public abstract class AbstractTubeSymbol extends AbstractComponent { public int getControlPointCount() { return controlPoints.length; } - + @Override public void setControlPoint(Point point, int index) { controlPoints[index].setLocation(point); - - refreshDrawing(); + + if (index == controlPoints.length - 1) + this.body = null; } @EditableProperty @@ -155,28 +159,112 @@ public abstract class AbstractTubeSymbol extends AbstractComponent { public void setShowHeaters(boolean showHeaters) { this.showHeaters = showHeaters; - refreshDrawing(); + this.body = null; } @EditableProperty public Orientation getOrientation() { if (orientation == null) orientation = Orientation.DEFAULT; - + return orientation; } public void setOrientation(Orientation orientation) { this.orientation = orientation; - refreshDrawing(); + updateControlPoints(); + this.body = null; } - protected void refreshDrawing() { + @EditableProperty + public SymbolFlipping getFlip() { + if (flip == null) + flip = SymbolFlipping.NONE; + return flip; + } + + public void setFlip(SymbolFlipping flip) { + this.flip = flip; + updateControlPoints(); - // make sure we have a new drawing - body = null; - getBody(); + this.body = null; + } + + /** + * Returns transistor shape consisting of 3 parts, in this order: electrodes, connectors, bulb. + * + * @return + */ + protected abstract Shape[] initializeBody(); + + protected Shape[] getBody() { + if (this.body == null) { + Shape[] newBody = initializeBody(); + +// int pinSpacing = (int) PIN_SPACING.convertToPixels(); + int centerX = this.controlPoints[0].x;// + pinSpacing * 3; + int centerY = this.controlPoints[0].y; + + if (getFlip() == SymbolFlipping.X) { + AffineTransform tx = AffineTransform.getScaleInstance(-1, 1); + tx.concatenate(AffineTransform.getTranslateInstance(-2 * centerX, 0)); + if (newBody != null) { + for (int i = 0; i < newBody.length; i++) { + newBody[i] = tx.createTransformedShape(newBody[i]); + } + } + } else if (getFlip() == SymbolFlipping.Y) { + AffineTransform tx = AffineTransform.getScaleInstance(1, -1); + tx.concatenate(AffineTransform.getTranslateInstance(0, -2 * centerY)); + if (newBody != null) { + for (int i = 0; i < newBody.length; i++) { + newBody[i] = tx.createTransformedShape(newBody[i]); + } + } + } + + if (getOrientation() != Orientation.DEFAULT) { + + Point first = this.controlPoints[0]; + double angle = Double.parseDouble(getOrientation().name().replace("_", "")); + AffineTransform rotate = AffineTransform.getRotateInstance(Math.toRadians(angle), first.x, first.y); + if (newBody != null) { + for (int i = 0; i < newBody.length; i++) { + newBody[i] = rotate.createTransformedShape(newBody[i]); + } + } + } + + this.body = newBody; + } + + return this.body; + } + + protected abstract Point[] initializeControlPoints(Point first); + + protected void updateControlPoints() { + Point[] newPoints = initializeControlPoints(this.controlPoints[0]); + this.controlPoints = newPoints; + +// int pinSpacing = (int) PIN_SPACING.convertToPixels(); + int centerX = this.controlPoints[0].x;// + pinSpacing * 3; + int centerY = this.controlPoints[0].y; + + if (getFlip() == SymbolFlipping.X) { + AffineTransform tx = AffineTransform.getScaleInstance(-1, 1); + tx.concatenate(AffineTransform.getTranslateInstance(-2 * centerX, 0)); + for (int i = 0; i < this.controlPoints.length; i++) { + tx.transform(this.controlPoints[i], this.controlPoints[i]); + } + } else if (getFlip() == SymbolFlipping.Y) { + AffineTransform tx = AffineTransform.getScaleInstance(1, -1); + tx.concatenate(AffineTransform.getTranslateInstance(0, -2 * centerY)); + for (int i = 0; i < this.controlPoints.length; i++) { + tx.transform(this.controlPoints[i], this.controlPoints[i]); + } + } if (getOrientation() == Orientation.DEFAULT) return; @@ -187,19 +275,5 @@ public abstract class AbstractTubeSymbol extends AbstractComponent { for (int i = 1; i < this.controlPoints.length; i++) { rotate.transform(this.controlPoints[i], this.controlPoints[i]); } - if (this.body != null) { - for (int i = 0; i < this.body.length; i++) { - this.body[i] = rotate.createTransformedShape(this.body[i]); - } - } } - - /** - * Returns transistor shape consisting of 3 parts, in this order: electrodes, connectors, bulb. - * - * @return - */ - protected abstract Shape[] getBody(); - - protected abstract void updateControlPoints(); } 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 7e306b39..63fcadf5 100644 --- a/diylc/diylc-library/src/org/diylc/components/tube/DiodeSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/tube/DiodeSymbol.java @@ -7,6 +7,7 @@ import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import org.diylc.common.ObjectCache; +import org.diylc.components.transform.TubeSymbolTransformer; import org.diylc.core.IDIYComponent; import org.diylc.core.IPropertyValidator; import org.diylc.core.ValidationException; @@ -17,7 +18,7 @@ import org.diylc.core.annotations.KeywordPolicy; @ComponentDescriptor(name = "Diode (symbol)", author = "Branislav Stojkovic", category = "Schematics", instanceNamePrefix = "V", description = "Diode tube symbol", stretchable = false, zOrder = IDIYComponent.COMPONENT, - keywordPolicy = KeywordPolicy.SHOW_VALUE) + keywordPolicy = KeywordPolicy.SHOW_VALUE, transformer = TubeSymbolTransformer.class) public class DiodeSymbol extends AbstractTubeSymbol { private static final long serialVersionUID = 1L; @@ -31,8 +32,10 @@ public class DiodeSymbol extends AbstractTubeSymbol { updateControlPoints(); } - public Shape[] getBody() { + public Shape[] initializeBody() { if (body == null) { + Point[] controlPoints = initializeControlPoints(this.controlPoints[0]); + body = new Shape[3]; int x = controlPoints[0].x; int y = controlPoints[0].y; @@ -110,23 +113,27 @@ public class DiodeSymbol extends AbstractTubeSymbol { } @Override - protected void updateControlPoints() { + protected Point[] initializeControlPoints(Point first) { int pinSpacing = (int) PIN_SPACING.convertToPixels(); // Update control points. - int x = controlPoints[0].x; - int y = controlPoints[0].y; + int x = first.x; + int y = first.y; - controlPoints[1].x = x + pinSpacing * 3; - controlPoints[1].y = y - pinSpacing * 3; + Point[] newPoints = new Point[] {first, new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0)}; - controlPoints[2].x = x + pinSpacing * 2; - controlPoints[2].y = y + pinSpacing * 3; + newPoints[1].x = x + pinSpacing * 3; + newPoints[1].y = y - pinSpacing * 3; - controlPoints[3].x = x + pinSpacing * 3; - controlPoints[3].y = y + pinSpacing * 3; + newPoints[2].x = x + pinSpacing * 2; + newPoints[2].y = y + pinSpacing * 3; - controlPoints[4].x = x + pinSpacing * 4; - controlPoints[4].y = y + pinSpacing * 3; + newPoints[3].x = x + pinSpacing * 3; + newPoints[3].y = y + pinSpacing * 3; + + newPoints[4].x = x + pinSpacing * 4; + newPoints[4].y = y + pinSpacing * 3; + + return newPoints; } @Override @@ -159,7 +166,7 @@ public class DiodeSymbol extends AbstractTubeSymbol { public void setDirectlyHeated(boolean directlyHeated) { this.directlyHeated = directlyHeated; - refreshDrawing(); + this.body = null; } public class HeaterValidator implements IPropertyValidator { diff --git a/diylc/diylc-library/src/org/diylc/components/tube/PentodeSymbol.java b/diylc/diylc-library/src/org/diylc/components/tube/PentodeSymbol.java index c8d93708..d9efec10 100644 --- a/diylc/diylc-library/src/org/diylc/components/tube/PentodeSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/tube/PentodeSymbol.java @@ -8,6 +8,7 @@ import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import org.diylc.common.ObjectCache; +import org.diylc.components.transform.TubeSymbolTransformer; import org.diylc.core.IDIYComponent; import org.diylc.core.VisibilityPolicy; import org.diylc.core.annotations.ComponentDescriptor; @@ -16,7 +17,8 @@ import org.diylc.core.annotations.KeywordPolicy; @ComponentDescriptor(name = "Pentode (symbol)", author = "Branislav Stojkovic", category = "Schematics", instanceNamePrefix = "V", description = "Pentode tube symbol", stretchable = false, - zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE) + zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, + transformer = TubeSymbolTransformer.class) public class PentodeSymbol extends AbstractTubeSymbol { private static final long serialVersionUID = 1L; @@ -31,8 +33,10 @@ public class PentodeSymbol extends AbstractTubeSymbol { updateControlPoints(); } - public Shape[] getBody() { + public Shape[] initializeBody() { if (body == null) { + Point[] controlPoints = initializeControlPoints(this.controlPoints[0]); + body = new Shape[3]; int x = controlPoints[0].x; int y = controlPoints[0].y; @@ -156,29 +160,35 @@ public class PentodeSymbol extends AbstractTubeSymbol { g2d.drawLine(width / 8, height * 5 / 8, width * 7 / 8, height * 5 / 8); } - protected void updateControlPoints() { + protected Point[] initializeControlPoints(Point first) { int pinSpacing = (int) PIN_SPACING.convertToPixels(); // Update control points. - int x = controlPoints[0].x; - int y = controlPoints[0].y; + int x = first.x; + int y = first.y; - controlPoints[1].x = x + pinSpacing * 3; - controlPoints[1].y = y - pinSpacing * 4; + Point[] newPoints = + new Point[] {first, new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0), + new Point(0, 0)}; - controlPoints[2].x = x + pinSpacing * 2; - controlPoints[2].y = y + pinSpacing * 2; + newPoints[1].x = x + pinSpacing * 3; + newPoints[1].y = y - pinSpacing * 4; - controlPoints[3].x = x + pinSpacing * 6; - controlPoints[3].y = y - pinSpacing; + newPoints[2].x = x + pinSpacing * 2; + newPoints[2].y = y + pinSpacing * 2; - controlPoints[4].x = x; - controlPoints[4].y = y - pinSpacing * 2; + newPoints[3].x = x + pinSpacing * 6; + newPoints[3].y = y - pinSpacing; - controlPoints[5].x = x + pinSpacing * 3; - controlPoints[5].y = y + pinSpacing * 2; + newPoints[4].x = x; + newPoints[4].y = y - pinSpacing * 2; - controlPoints[6].x = x + pinSpacing * 4; - controlPoints[6].y = y + pinSpacing * 2; + newPoints[5].x = x + pinSpacing * 3; + newPoints[5].y = y + pinSpacing * 2; + + newPoints[6].x = x + pinSpacing * 4; + newPoints[6].y = y + pinSpacing * 2; + + return newPoints; } @Override @@ -208,6 +218,6 @@ public class PentodeSymbol extends AbstractTubeSymbol { public void setExposeSuppressorGrid(boolean exposeSuppressorGrid) { this.exposeSuppressorGrid = exposeSuppressorGrid; - refreshDrawing(); + this.body = null; } } diff --git a/diylc/diylc-library/src/org/diylc/components/tube/TriodeSymbol.java b/diylc/diylc-library/src/org/diylc/components/tube/TriodeSymbol.java index 96de7d1a..decb50b9 100644 --- a/diylc/diylc-library/src/org/diylc/components/tube/TriodeSymbol.java +++ b/diylc/diylc-library/src/org/diylc/components/tube/TriodeSymbol.java @@ -8,6 +8,7 @@ import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import org.diylc.common.ObjectCache; +import org.diylc.components.transform.TubeSymbolTransformer; import org.diylc.core.IDIYComponent; import org.diylc.core.VisibilityPolicy; import org.diylc.core.annotations.ComponentDescriptor; @@ -16,7 +17,8 @@ import org.diylc.core.annotations.KeywordPolicy; @ComponentDescriptor(name = "Triode (symbol)", author = "Branislav Stojkovic", category = "Schematics", instanceNamePrefix = "V", description = "Triode tube symbol", stretchable = false, - zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE) + zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, + transformer = TubeSymbolTransformer.class) public class TriodeSymbol extends AbstractTubeSymbol { private static final long serialVersionUID = 1L; @@ -30,8 +32,10 @@ public class TriodeSymbol extends AbstractTubeSymbol { updateControlPoints(); } - public Shape[] getBody() { + public Shape[] initializeBody() { if (body == null) { + Point[] controlPoints = initializeControlPoints(this.controlPoints[0]); + body = new Shape[3]; int x = controlPoints[0].x; int y = controlPoints[0].y; @@ -126,23 +130,27 @@ public class TriodeSymbol extends AbstractTubeSymbol { g2d.drawLine(width / 8, height / 2, width * 7 / 8, height / 2); } - protected void updateControlPoints() { + protected Point[] initializeControlPoints(Point first) { int pinSpacing = (int) PIN_SPACING.convertToPixels(); // Update control points. - int x = controlPoints[0].x; - int y = controlPoints[0].y; + int x = first.x; + int y = first.y; - controlPoints[1].x = x + pinSpacing * 3; - controlPoints[1].y = y - pinSpacing * 3; + Point[] newPoints = new Point[] {first, new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0)}; - controlPoints[2].x = x + pinSpacing * 2; - controlPoints[2].y = y + pinSpacing * 3; + newPoints[1].x = x + pinSpacing * 3; + newPoints[1].y = y - pinSpacing * 3; - controlPoints[3].x = x + pinSpacing * 3; - controlPoints[3].y = y + pinSpacing * 3; + newPoints[2].x = x + pinSpacing * 2; + newPoints[2].y = y + pinSpacing * 3; - controlPoints[4].x = x + pinSpacing * 4; - controlPoints[4].y = y + pinSpacing * 3; + newPoints[3].x = x + pinSpacing * 3; + newPoints[3].y = y + pinSpacing * 3; + + newPoints[4].x = x + pinSpacing * 4; + newPoints[4].y = y + pinSpacing * 3; + + return newPoints; } @Override @@ -175,6 +183,6 @@ public class TriodeSymbol extends AbstractTubeSymbol { public void setDirectlyHeated(boolean directlyHeated) { this.directlyHeated = directlyHeated; - refreshDrawing(); + this.body = null; } } diff --git a/diylc/diylc-swing/build.xml b/diylc/diylc-swing/build.xml index dd608ce8..200ecedd 100644 --- a/diylc/diylc-swing/build.xml +++ b/diylc/diylc-swing/build.xml @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@ Compile with JDK ${java.runtime.version} - + diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index 92b6a30c8fb4c3e0eecd852131e8dc3ca54c7805..81f34ce0fef122a615e8e1febd55642f321a5bc5 100644 GIT binary patch delta 4668 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 delta 4668 zcmXw5d0dvo7XD@qiztgAn?Fh*gD^<*VyFQIii)79$R?|xpaL2SDhMH~f{H93@d7Go zxnYYG<#&}#Q&ZB4tXrw6_v*Dw%`2oS7rA+7&YABIe$O*!dCr+L@65;jqt^G2T3gKv z2a};X-4LDb=cLK?R$g#fz@&!~^y8Q-;(X@G#j=1+kZ_3kfQZ#!V=p7x@>dZf_=|{z z+z+vUx#)YiGx9^sMJu*r=6XvQiiVN!5=zffSOC5h2$K=-LLj2I$vDI$6CY8#bBjqG zm-wvtbyI;2RySowzgi7S<4x;xOk&4yW+JiEej~2^9Xl}Tp7SciMJ}U3`YT7d;d;MY zCt~90P>kRA{1n7rJu;b9(&Vt*tHr-H=ybaCI(?sqvp(F*LJLZUVfyM9c1js9uNn+D zj2X!+Mfk1hGhVwY!ejNl9wW7hDPXU+@cvCi>K}Ly$b|boFPKSm_N~LjgA<$(PrVX} z=rr+L#M_hVv9BWkIf&;2|3Ew*)Qq@r+G51drvG6&TonHC$7ft`aGma`sZQsm|J>eQ zTfZ2bI`4+x!?4Q{Zn*8i`819XqKeS&6I);^&P8AEp$3J zdwp=_XstaRY&v_F*IS@-qTN7LnypS3;fc}@R!Eko*j0m&4-Gj2Gp(HlFeYy!m1&DMymt%teX;I1WJ2iA+pR*63keP7!MEj|+* z^i?}6<#cV@E}+`K+vZUrzul=sTHi4lDhIyn{S`O?n-70N-QPORux{_iBXK><@FFEl zI#NvJNY_U)wvXGyK|VI;`Yt7aFCk&Rk#D-8kub8{cb|qs?(L(9qfX&qP~CG#k#H zwP72;&JdT+x+!;bAq%67oMLvE*qAalhFEkZD@3Mk4C2oj{;XoF$&tC0Inor%>(~~u z*)|$Cb6sQYWUJZE9#Wx-Ha3%N-|S}dX)gC3%v{$e=JLCCXeM_ygzRBvBs%8+dxlu{ zd+aP7jo&fWLsCOdu-n8Qo)pK5yPO`_e{P770@#AC zeaw#7s)t7D^N(31+1#G6B4Tg-#TFAY<=l;!mnrvR*nVAyMMkeUq`P=XhBanfeXbQ2 z+?;~9S@Ko1C7(}Uc*$OLX(RVK(%>u?i|2gvS>8tFX?caV?C|~4SZJXHA zfz4oRFmvIzXo9`Z@={94bLVf6{<}#xGAe}r1{#^82XCT~LtgwovE4r6XBt1bYvcF_ z3|Z}Xol!r)4~qY=v2T3T9}ZX7g{+S-XO77=g^Tl)I7Kgfc#c z*rIYiidbm{{|?_pL(C?AmTYd-d@en5*ur}lzR@d> z?D6_axZBBXI8wvu*)_D(@>Y`dYv7*~8))R`iFIo{$_ATr-On%EBOC1EJE-C9J-m+^ zslC8Q;}5OjlN&sQatCkn!^A$h#X0T&=pDX-qADWn&%2twt$c@gAEv`(dd(o-qlkV^69X@s$9WN%NS zz8Ct6>3JOmbE2tHUDOGe_IFVdx}IA7>V@=ZQWMKYoQLXgB4h|4Km`wNuLJtOg5uSyge$*J|? z^2uPELX{pY!D-rq;!K){?bTnOH}ahHR5H-Edg%~++CvDyj7y+=U1xsU0$l%>@gCT zGSyvHnUe1;gPExFzcM8sQm$NE%azWha+r@XFI9-+mEDzBsF?E=D$A}?1*cR(IL5qh zv(cwH>=?8&8md$78Sg3i;CH`MYVdzNG5DmGc4JvV$K?gb&cvLp+>phu2JdY zi0DgsWt(ypZBwo@+f*BlwJIj1R=L`1)kpNORw)P9i4NrtKy{rs0!gmcsf!;_5AkSe zsaKZ%dUemE8Xy&2e{X>2t{BNg4PsEIPE%L^j;0=ipk{G>W%CWqkbtDOS+zR5MLi+ATU7Al7WFWMwJNf+ rRrT|qR;3)eT^x!OY}_usC`oP@En|0x(Me0;4mGi!9V*>zC(Qjnwsn7# diff --git a/diylc/diylc-swing/update.xml b/diylc/diylc-swing/update.xml index 8a600e7a..d374ab01 100644 --- a/diylc/diylc-swing/update.xml +++ b/diylc/diylc-swing/update.xml @@ -1572,8 +1572,12 @@ IMPROVEMENT - Ability to rotate tube sockets for arbitrary angle and to change color + Ability to rotate tube sockets for arbitrary angle and change color + + IMPROVEMENT + Flip tube schematic symbols + IMPROVEMENT Renamed "template" to "variant" as it is describes the meaning more closely