Angle editor added

This commit is contained in:
Bane Stojkovic
2022-09-25 14:06:08 +02:00
parent d2adb49ccf
commit 3b12788eff
10 changed files with 432 additions and 191 deletions
@@ -0,0 +1,52 @@
package org.diylc.core;
import java.util.HashMap;
import java.util.Map;
public class Angle {
private int value;
private Angle(int value) {
super();
this.value = value;
}
public int getValue() {
return value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + value;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Angle other = (Angle) obj;
if (value != other.value)
return false;
return true;
}
@Override
public String toString() {
return Integer.toString(value);
}
private static Map<Integer, Angle> valueCache = new HashMap<Integer, Angle>();
public synchronized static Angle of(int angle) {
valueCache.computeIfAbsent(angle, (value) -> new Angle(value));
return valueCache.get(angle);
}
}
@@ -3937,5 +3937,33 @@
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>4</major>
<minor>28</minor>
<build>0</build>
</versionNumber>
<releaseDate>2022-09-25 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added '4-pin Jumbo Tube Socket' component for 211, 805 and 845 tubes</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>More convenient way of editing angle of rotation of all tube sockets</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Ability to rotate all tube sockets through the 'Transform Selection' feature or keyboard shortcut</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Tube socket pin designations are not rendered until property editor dialog is opened and closed</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
</a>
</java.util.Arrays_-ArrayList>
Binary file not shown.
@@ -0,0 +1,66 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package org.diylc.components.transform;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import org.diylc.common.IComponentTransformer;
import org.diylc.components.tube.TubeSocket;
import org.diylc.core.Angle;
import org.diylc.core.IDIYComponent;
public class TubeSocketTransformer implements IComponentTransformer {
@Override
public boolean canRotate(IDIYComponent<?> component) {
return TubeSocket.class.isAssignableFrom(component.getClass());
}
@Override
public boolean canMirror(IDIYComponent<?> component) {
return false;
}
@Override
public boolean mirroringChangesCircuit() {
return false;
}
@Override
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2 * direction, center.getX(), center.getY());
for (int index = 0; index < component.getControlPointCount(); index++) {
Point2D p = new Point2D.Double();
rotate.transform(component.getControlPoint(index), p);
component.setControlPoint(p, index);
}
TubeSocket tube = (TubeSocket) component;
Angle angle = tube.getAngle();
Angle newAngle = Angle.of(angle.getValue() + direction * 90);
tube.setAngle(newAngle);
}
@Override
public void mirror(IDIYComponent<?> component, Point2D center, int direction) {
}
}
@@ -1,86 +1,89 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/*
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 <http://www.gnu.org/licenses/>.
*/
package org.diylc.components.tube;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
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 org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.awt.StringUtils;
import org.diylc.common.HorizontalAlignment;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.common.Orientation;
import org.diylc.common.VerticalAlignment;
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.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.Constants;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
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 org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.awt.StringUtils;
import org.diylc.common.HorizontalAlignment;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.common.Orientation;
import org.diylc.common.VerticalAlignment;
import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.transform.TubeSocketTransformer;
import org.diylc.core.Angle;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.Theme;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.Constants;
@ComponentDescriptor(name = "Tube Socket", author = "Branislav Stojkovic", category = "Tubes",
instanceNamePrefix = "V", description = "Various types of tube/valve sockets",
zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, enableCache = true)
zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_VALUE, enableCache = true,
transformer = TubeSocketTransformer.class)
public class TubeSocket extends AbstractTransparentComponent<String> {
private static final Size B9A_PIN_SPACING_CHASSIS = new Size(12.5d, SizeUnit.mm);
private static final Size B9A_PIN_SPACING_PCB = new Size(21d, SizeUnit.mm);
private static final Size OCTAL_PIN_SPACING = new Size(17.5d, SizeUnit.mm);
private static final Size B7G_PIN_SPACING = new Size(12d, SizeUnit.mm);
private static final Size B7G_CUTOUT_DIAMETER = new Size(4d, SizeUnit.mm);
private static final Size B9A_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
private static final Size B12C_HOLE_SIZE = new Size(10d, SizeUnit.mm);
private static final Size B12C_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
private static final Size B12C_PIN_SPACING_PCB = new Size(25d, SizeUnit.mm);
private static final Size B12C_PIN_SPACING_CHASSIS = new Size(22d, SizeUnit.mm);
private static final Size OCTAL_DIAMETER = new Size(25d, SizeUnit.mm);
private static final Size B9A_DIAMETER = new Size(3 / 4d, SizeUnit.in);
private static final Size B7G_DIAMETER = new Size(17d, SizeUnit.mm);
private static final Size B12C_DIAMETER = new Size(30d, SizeUnit.mm);
private static final Size B9A_PIN_SPACING_CHASSIS = new Size(12.5d, SizeUnit.mm);
private static final Size B9A_PIN_SPACING_PCB = new Size(21d, SizeUnit.mm);
private static final Size OCTAL_PIN_SPACING = new Size(17.5d, SizeUnit.mm);
private static final Size B7G_PIN_SPACING = new Size(12d, SizeUnit.mm);
private static final Size B7G_CUTOUT_DIAMETER = new Size(4d, SizeUnit.mm);
private static final Size B9A_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
private static final Size B12C_HOLE_SIZE = new Size(10d, SizeUnit.mm);
private static final Size B12C_CUTOUT_DIAMETER = new Size(5.5d, SizeUnit.mm);
private static final Size B12C_PIN_SPACING_PCB = new Size(25d, SizeUnit.mm);
private static final Size B12C_PIN_SPACING_CHASSIS = new Size(22d, SizeUnit.mm);
private static final Size OCTAL_DIAMETER = new Size(25d, SizeUnit.mm);
private static final Size B9A_DIAMETER = new Size(3 / 4d, SizeUnit.in);
private static final Size B7G_DIAMETER = new Size(17d, SizeUnit.mm);
private static final Size B12C_DIAMETER = new Size(30d, SizeUnit.mm);
private static final long serialVersionUID = 1L;
private static Color BODY_COLOR = Color.decode("#F7F7EF");
private static Color BODY_COLOR = Color.decode("#F7F7EF");
private static Color LABEL_COLOR = BODY_COLOR.darker();
public static Color PIN_COLOR = Color.decode("#00B2EE");
public static Color PIN_BORDER_COLOR = PIN_COLOR.darker();
public static Size PIN_DIAMETER = new Size(1d, SizeUnit.mm);
private static Size PIN_WIDTH = new Size(0.08d, SizeUnit.in);
public static Size PIN_DIAMETER = new Size(1d, SizeUnit.mm);
private static Size PIN_WIDTH = new Size(0.08d, SizeUnit.in);
private static Size PIN_THICKNESS = new Size(0.02d, SizeUnit.in);
public static Size HOLE_SIZE = new Size(5d, SizeUnit.mm);
public static Size OCTAL_TICK_SIZE = new Size(2d, SizeUnit.mm);
@@ -91,9 +94,9 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
private Orientation orientation;
// private Mount mount = Mount.CHASSIS;
private int angle;
private Color color = BODY_COLOR;
private String electrodeLabels = null;
private Mount mount = Mount.CHASSIS;
private Color color = BODY_COLOR;
private String electrodeLabels = null;
private Mount mount = Mount.CHASSIS;
private Color labelColor = LABEL_COLOR;
private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
@@ -119,7 +122,7 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
@EditableProperty
@SuppressWarnings("incomplete-switch")
public int getAngle() {
public Angle getAngle() {
if (orientation != null) {
switch (orientation) {
case _90:
@@ -134,11 +137,11 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
}
orientation = null;
}
return angle;
return Angle.of(angle);
}
public void setAngle(int angle) {
this.angle = angle;
public void setAngle(Angle angle) {
this.angle = angle.getValue();
updateControlPoints();
// Reset body shape
body = null;
@@ -185,11 +188,11 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
pinCount = 9;
pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B9A_PIN_SPACING_PCB.convertToPixels() : B9A_PIN_SPACING_CHASSIS.convertToPixels());
hasEmptySpace = true;
break;
case B12C:
pinCount = 12;
pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B12C_PIN_SPACING_PCB.convertToPixels() : B12C_PIN_SPACING_CHASSIS.convertToPixels());
hasEmptySpace = true;
break;
case B12C:
pinCount = 12;
pinSpacing = getClosestOdd(getMount() == Mount.PCB ? B12C_PIN_SPACING_PCB.convertToPixels() : B12C_PIN_SPACING_CHASSIS.convertToPixels());
hasEmptySpace = true;
break;
default:
throw new RuntimeException("Unexpected base: " + base);
@@ -198,7 +201,7 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
double initialAngleOffset = hasEmptySpace ? angleIncrement : (angleIncrement / 2);
controlPoints = new Point2D[pinCount + 1];
double theta = initialAngleOffset + Math.toRadians(getAngle());
double theta = initialAngleOffset + Math.toRadians(getAngle().getValue());
controlPoints[0] = firstPoint;
for (int i = 0; i < pinCount; i++) {
controlPoints[i + 1] =
@@ -220,13 +223,13 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
break;
case OCTAL:
bodyDiameter = getClosestOdd(OCTAL_DIAMETER.convertToPixels());
break;
case B12C:
bodyDiameter = getClosestOdd(B12C_DIAMETER.convertToPixels());
break;
case B12C:
bodyDiameter = getClosestOdd(B12C_DIAMETER.convertToPixels());
break;
default:
throw new RuntimeException("Unexpected base: " + base);
}
}
body =
new Ellipse2D.Double(controlPoints[0].getX() - bodyDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2,
@@ -234,28 +237,28 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
Area bodyArea = new Area(body);
int holeSize = getClosestOdd(base == Base.B12C ? B12C_HOLE_SIZE.convertToPixels() : HOLE_SIZE.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - holeSize / 2, controlPoints[0].getY() - holeSize
/ 2, holeSize, holeSize)));
/ 2, holeSize, holeSize)));
if (base == Base.OCTAL) {
int tickSize = getClosestOdd(OCTAL_TICK_SIZE.convertToPixels());
double theta = Math.toRadians(getAngle());
double theta = Math.toRadians(getAngle().getValue());
int centerX = (int) (controlPoints[0].getX() + Math.cos(theta) * holeSize / 2);
int centerY = (int) (controlPoints[0].getY() + Math.sin(theta) * holeSize / 2);
bodyArea.subtract(new Area(new Ellipse2D.Double(centerX - tickSize / 2, centerY - tickSize / 2, tickSize,
tickSize)));
} else if (base == Base.B9A && getMount() == Mount.CHASSIS) {
double cutoutDiameter = getClosestOdd(B9A_CUTOUT_DIAMETER.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
} else if (base == Base.B7G && getMount() == Mount.CHASSIS) {
double cutoutDiameter = getClosestOdd(B7G_CUTOUT_DIAMETER.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
} else if (base == Base.B12C && getMount() == Mount.CHASSIS) {
double cutoutDiameter = getClosestOdd(B12C_CUTOUT_DIAMETER.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
}
} else if (base == Base.B9A && getMount() == Mount.CHASSIS) {
double cutoutDiameter = getClosestOdd(B9A_CUTOUT_DIAMETER.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
} else if (base == Base.B7G && getMount() == Mount.CHASSIS) {
double cutoutDiameter = getClosestOdd(B7G_CUTOUT_DIAMETER.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
} else if (base == Base.B12C && getMount() == Mount.CHASSIS) {
double cutoutDiameter = getClosestOdd(B12C_CUTOUT_DIAMETER.convertToPixels());
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() - bodyDiameter / 2 - cutoutDiameter * 3 / 4, cutoutDiameter, cutoutDiameter)));
bodyArea.subtract(new Area(new Ellipse2D.Double(controlPoints[0].getX() - cutoutDiameter / 2, controlPoints[0].getY() + bodyDiameter / 2 - cutoutDiameter / 4, cutoutDiameter, cutoutDiameter)));
}
body = bodyArea;
}
@@ -264,7 +267,7 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) {
IDrawingObserver drawingObserver) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
@@ -292,48 +295,48 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
: getColor().darker();
}
g2d.setColor(finalBorderColor);
g2d.draw(body);
drawingObserver.stopTracking();
g2d.draw(body);
drawingObserver.stopTracking();
// Draw pins
if (!outlineMode) {
for (int i = 1; i < controlPoints.length; i++) {
Shape pinShape;
if (getMount() == Mount.PCB) {
int pinSize = getClosestOdd(PIN_DIAMETER.convertToPixels());
pinShape = new Ellipse2D.Double(controlPoints[i].getX() - pinSize / 2, controlPoints[i].getY() - pinSize / 2, pinSize, pinSize);
} else {
int pinWidth = getClosestOdd(PIN_WIDTH.convertToPixels());
int pinThickness = getClosestOdd(PIN_THICKNESS.convertToPixels());
pinShape = new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2, controlPoints[i].getY() - pinThickness / 2, pinWidth, pinThickness);
double theta = Math.atan2(controlPoints[i].getY() - controlPoints[0].getY(), controlPoints[i].getX() - controlPoints[0].getX()) + Math.PI / 2;
Area rotatedPin = new Area(pinShape);
rotatedPin.transform(AffineTransform.getRotateInstance(theta, controlPoints[i].getX(), controlPoints[i].getY()));
pinShape = rotatedPin;
for (int i = 1; i < controlPoints.length; i++) {
Shape pinShape;
if (getMount() == Mount.PCB) {
int pinSize = getClosestOdd(PIN_DIAMETER.convertToPixels());
pinShape = new Ellipse2D.Double(controlPoints[i].getX() - pinSize / 2, controlPoints[i].getY() - pinSize / 2, pinSize, pinSize);
} else {
int pinWidth = getClosestOdd(PIN_WIDTH.convertToPixels());
int pinThickness = getClosestOdd(PIN_THICKNESS.convertToPixels());
pinShape = new Rectangle2D.Double(controlPoints[i].getX() - pinWidth / 2, controlPoints[i].getY() - pinThickness / 2, pinWidth, pinThickness);
double theta = Math.atan2(controlPoints[i].getY() - controlPoints[0].getY(), controlPoints[i].getX() - controlPoints[0].getX()) + Math.PI / 2;
Area rotatedPin = new Area(pinShape);
rotatedPin.transform(AffineTransform.getRotateInstance(theta, controlPoints[i].getX(), controlPoints[i].getY()));
pinShape = rotatedPin;
}
g2d.setColor(PIN_COLOR);
g2d.fill(pinShape);
g2d.setColor(PIN_BORDER_COLOR);
g2d.fill(pinShape);
}
}
// draw electrode labels
if (electrodeLabels != null) {
g2d.setColor(getLabelColor());
g2d.setFont(project.getFont().deriveFont((float) (project.getFont().getSize2D() * 0.8)));
String[] labels = electrodeLabels.split(",");
double electrodeLabelOffset = project.getFont().getSize2D() * (getBase() == Base.B9A && getMount() == Mount.PCB ? 1.5 : 1);
for (int i = 0; i < labels.length; i++) {
if (i < controlPoints.length - 1) {
String label = labels[i];
double theta = Math.atan2(controlPoints[i + 1].getY() - controlPoints[0].getY(), controlPoints[i + 1].getX() - controlPoints[0].getX());
double x = controlPoints[i + 1].getX() - Math.cos(theta) * electrodeLabelOffset;
double y = controlPoints[i + 1].getY() - Math.sin(theta) * electrodeLabelOffset;
StringUtils.drawCenteredText(g2d, label, (int)x, (int)y, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
}
}
}
// draw electrode labels
if (getElectrodeLabels() != null) {
g2d.setColor(getLabelColor());
g2d.setFont(project.getFont().deriveFont((float) (project.getFont().getSize2D() * 0.8)));
String[] labels = getElectrodeLabels().split(",");
double electrodeLabelOffset = project.getFont().getSize2D() * (getBase() == Base.B9A && getMount() == Mount.PCB ? 1.5 : 1);
for (int i = 0; i < labels.length; i++) {
if (i < controlPoints.length - 1) {
String label = labels[i];
double theta = Math.atan2(controlPoints[i + 1].getY() - controlPoints[0].getY(), controlPoints[i + 1].getX() - controlPoints[0].getX());
double x = controlPoints[i + 1].getX() - Math.cos(theta) * electrodeLabelOffset;
double y = controlPoints[i + 1].getY() - Math.sin(theta) * electrodeLabelOffset;
StringUtils.drawCenteredText(g2d, label, (int)x, (int)y, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
}
}
}
}
@@ -374,7 +377,7 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
}
@Override
@EditableProperty(name = "Type")
@EditableProperty(name = "Designation")
public String getValue() {
return type;
}
@@ -391,58 +394,64 @@ public class TubeSocket extends AbstractTransparentComponent<String> {
@Override
public void setControlPoint(Point2D point, int index) {
controlPoints[index].setLocation(point);
controlPoints[index].setLocation(point);
body = null;
}
@Override
public boolean canPointMoveFreely(int pointIndex) {
return false;
}
@EditableProperty(name = "Electrode Labels")
public String getElectrodeLabels() {
if (electrodeLabels == null)
electrodeLabels = "1,2,3,4,5,6,7,8,9,10,11,12";
return electrodeLabels;
}
public void setElectrodeLabels(String electrodeLabels) {
this.electrodeLabels = electrodeLabels;
}
@EditableProperty(name = "Label")
public Color getLabelColor() {
if (labelColor == null)
labelColor = LABEL_COLOR;
return labelColor;
}
public void setLabelColor(Color labelColor) {
this.labelColor = labelColor;
}
@EditableProperty(name = "Mount")
public Mount getMount() {
if (mount == null)
mount = Mount.CHASSIS;
return mount;
}
public void setMount(Mount mount) {
this.mount = mount;
updateControlPoints();
// Reset body shape
body = null;
}
@Override
public Rectangle2D getCachingBounds() {
Rectangle2D rect = getBody().getBounds2D();
int margin = 40; // to catch the pins that are outside the body, if needed
return new Rectangle2D.Double(rect.getX() - margin, rect.getY() - margin, rect.getWidth() + 2 * margin, rect.getHeight() + 2 * margin);
}
@Override
public boolean canPointMoveFreely(int pointIndex) {
return false;
}
@EditableProperty(name = "Electrode Labels")
public String getElectrodeLabels() {
if (electrodeLabels == null)
electrodeLabels = "1,2,3,4,5,6,7,8,9,10,11,12";
return electrodeLabels;
}
public void setElectrodeLabels(String electrodeLabels) {
this.electrodeLabels = electrodeLabels;
}
@EditableProperty(name = "Label")
public Color getLabelColor() {
if (labelColor == null)
labelColor = LABEL_COLOR;
return labelColor;
}
public void setLabelColor(Color labelColor) {
this.labelColor = labelColor;
}
@EditableProperty(name = "Mount")
public Mount getMount() {
if (mount == null)
mount = Mount.CHASSIS;
return mount;
}
public void setMount(Mount mount) {
this.mount = mount;
updateControlPoints();
// Reset body shape
body = null;
}
@Override
public String getControlPointNodeName(int index) {
String[] labels = getElectrodeLabels().split(",");
return index > 0 && index <= labels.length ? labels[index - 1] : null;
}
@Override
public Rectangle2D getCachingBounds() {
Rectangle2D rect = getBody().getBounds2D();
int margin = 40; // to catch the pins that are outside the body, if needed
return new Rectangle2D.Double(rect.getX() - margin, rect.getY() - margin, rect.getWidth() + 2 * margin, rect.getHeight() + 2 * margin);
}
public static enum Base {
@@ -69,6 +69,7 @@ import org.diylc.components.tube.PentodeSymbol;
import org.diylc.components.tube.TriodeSymbol;
import org.diylc.components.tube.TubeSocket;
import org.diylc.components.tube.TubeSocket.Base;
import org.diylc.core.Angle;
import org.diylc.core.Project;
import org.diylc.core.measures.Capacitance;
import org.diylc.core.measures.CapacitanceUnit;
@@ -926,7 +927,7 @@ public class V2FileParser implements IOldFileParser {
ts.setAlpha((byte) transparency);
if (value_s != "")
ts.setValue(value_s);
ts.setAngle((int) angle);
ts.setAngle(Angle.of((int) angle));
ts.setControlPoint(tacke.get(0), 0);
ts.setBase(Base.B9A);
project.getComponents().add(ts);
@@ -962,7 +963,7 @@ public class V2FileParser implements IOldFileParser {
ts.setAlpha((byte) transparency);
if (value_s != "")
ts.setValue(value_s);
ts.setAngle((int) angle);
ts.setAngle(Angle.of((int) angle));
ts.setControlPoint(tacke.get(0), 0);
ts.setBase(Base.OCTAL);
project.getComponents().add(ts);
@@ -975,7 +976,7 @@ public class V2FileParser implements IOldFileParser {
ts.setAlpha((byte) transparency);
if (value_s != "")
ts.setValue(value_s);
ts.setAngle((int) angle);
ts.setAngle(Angle.of((int)angle));
ts.setControlPoint(tacke.get(0), 0);
ts.setBase(Base.B7G);
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,80 @@
/*
*
* 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
* <http://www.gnu.org/licenses/>.
*
*/
package org.diylc.swing.gui.editor;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JList;
import org.diylc.common.PropertyWrapper;
import org.diylc.core.Angle;
import org.diylc.lang.LangUtil;
import org.diylc.utils.Constants;
public class AngleEditor extends JComboBox<Integer> {
private static final long serialVersionUID = 1L;
private Color oldBg = getBackground();
private final PropertyWrapper property;
public AngleEditor(final PropertyWrapper property) {
this.property = property;
if (property.isReadOnly())
setEnabled(false);
setEditable(true);
setModel(new DefaultComboBoxModel<Integer>(new Integer[] {30, 45, 90, 135, 180, 270}));
setRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
// TODO Auto-generated method stub
return super.getListCellRendererComponent(list,
value == null ? null : LangUtil.translate(value.toString()), index, isSelected,
cellHasFocus);
}
});
setSelectedItem(((Angle) (property.getValue())).getValue());
addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
property.setChanged(true);
setBackground(oldBg);
AngleEditor.this.property.setValue(Angle.of((Integer) e.getItem()));
}
}
});
if (!property.isUnique()) {
setBackground(Constants.MULTI_VALUE_COLOR);
}
}
}
@@ -28,6 +28,7 @@ import javax.swing.JLabel;
import org.apache.log4j.Logger;
import org.diylc.common.PropertyWrapper;
import org.diylc.components.misc.LoadlineEntity;
import org.diylc.core.Angle;
import org.diylc.core.annotations.ByteArrayProperty;
import org.diylc.core.annotations.DynamicList;
import org.diylc.core.annotations.MultiLineText;
@@ -112,6 +113,10 @@ public class FieldEditorFactory {
if (LoadlineEntity.class.isAssignableFrom(property.getType())) {
LoadlineEditor editor = new LoadlineEditor(property);
return editor;
}
if (Angle.class.isAssignableFrom(property.getType())) {
AngleEditor editor = new AngleEditor(property);
return editor;
}
LOG.error("Unrecognized parameter type: " + property.getType().getName());
return new JLabel("Unrecognized");