chassis improvements

This commit is contained in:
Bane Stojkovic
2026-11-02 10:08:00 +01:00
parent b15a6e3f64
commit c5a462a385
23 changed files with 916 additions and 586 deletions
@@ -21,15 +21,17 @@
*/
package org.diylc.components.chassis;
import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.common.ObjectCache;
import org.diylc.components.shapes.AbstractShape;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDatasheetSupport;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.annotations.AiNote;
@@ -39,21 +41,83 @@ import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@AiNote("Each instance is one side of the chassis: an exploded view of a whole chassis takes five panels, while the top, front and back alone take three, which is typical for pedals and amplifiers. The top panel goes in the centre with the front panel against its upper edge and the back panel against its lower edge; in the five-panel view the left side panel goes against its left edge and the right side panel against its right edge")
@AiNote("The panel is not conductive in the netlist: jacks, pots and lugs drawn on it are not joined through it, so chassis ground points must be connected explicitly")
@ComponentDescriptor(name = "Chassis Panel", author = "Branislav Stojkovic", category = "Electro-Mechanical",
instanceNamePrefix = "CP", description = "One side of a chassis, with or withouth rounded edges",
@AiNote("The two control points are opposite corners of the enclosure's top panel. With 'Height' above zero the sides are unfolded around it as an exploded view, each as tall as 'Height' and set 'Spacing' apart from it: the front against the top panel's upper edge, the back against its lower edge and, when 'Sides' is All, the left and right sides against its left and right edges. The bottom is never drawn. With 'Sides' set to None, or 'Height' at zero, it is a single flat panel of any size, such as one side of a chassis drawn on its own")
@AiNote("The enclosure is not conductive in the netlist: jacks, pots and lugs drawn on it are not joined through it, so chassis ground points must be connected explicitly")
@AiNote("A datasheet model is a Hammond enclosure part number such as 1590BB, 1550B or 1444-32, or a generic size such as 125B, and is stored as 'Value'; it sets the top panel to the enclosure's length and width, upright for pedal-sized die-cast boxes up to 125 mm long and horizontal for bigger boxes and amplifier chassis and 'Height' to its wall height. 125B is a generic size sold by several makers; its Hammond equivalent is 1590N1")
@ComponentDescriptor(name = "Enclosure", author = "Branislav Stojkovic", category = "Hardware",
instanceNamePrefix = "ENC",
description = "Top panel of an enclosure or chassis, optionally with its sides unfolded",
zOrder = IDIYComponent.CHASSIS, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
transformer = SimpleComponentTransformer.class)
public class ChassisPanel extends AbstractShape {
transformer = SimpleComponentTransformer.class, enableDatasheet = true,
datasheetCreationStepCount = 2, datasheetModelColumn = 1)
public class ChassisPanel extends AbstractShape implements IDatasheetSupport {
private static final long serialVersionUID = 1L;
protected Size edgeRadius = new Size(0d, SizeUnit.mm);
// a new enclosure is a 125B, the most common pedal enclosure, upright as in its datasheet row
public static String DEFAULT_MODEL = "125B";
public static Size DEFAULT_TOP_WIDTH = new Size(66d, SizeUnit.mm);
public static Size DEFAULT_TOP_LENGTH = new Size(122d, SizeUnit.mm);
public static Size DEFAULT_WALL_HEIGHT = new Size(36d, SizeUnit.mm);
public static Size DEFAULT_RADIUS = new Size(0d, SizeUnit.mm);
public static Size DEFAULT_SPACING = new Size(0d, SizeUnit.mm);
protected Size edgeRadius = DEFAULT_RADIUS;
private Size height = DEFAULT_WALL_HEIGHT;
private Sides sides = Sides.ALL;
private Size spacing = DEFAULT_SPACING;
public ChassisPanel() {
this.color = LIGHT_METAL_COLOR;
this.borderColor = LIGHT_METAL_COLOR.darker();
this.value = DEFAULT_MODEL;
setControlPoint(new Point2D.Double(DEFAULT_TOP_WIDTH.convertToPixels(),
DEFAULT_TOP_LENGTH.convertToPixels()), 1);
}
public ChassisPanel(String[] model) {
this();
applyModel(model);
}
// columns: group, model, top panel size along x and along y, wall height. The wall height leaves out the lid, which is the bottom left out of the view. Pedal-sized boxes
// are listed upright, as pedals use them, and the bigger ones horizontal
@Override
public void applyModel(String[] model) {
setModel(model[1]);
setHeight(Size.parseSize(model[4]));
// the first control point stays put and the top panel keeps the direction it is drawn in
Point2D first = controlPoints[0];
Point2D second = controlPoints[1];
double x = Size.parseSize(model[2]).convertToPixels();
double y = Size.parseSize(model[3]).convertToPixels();
setControlPoint(new Point2D.Double(first.getX() + (second.getX() < first.getX() ? -x : x),
first.getY() + (second.getY() < first.getY() ? -y : y)), 1);
}
/**
* @return the side panels of the exploded view, folded out from the edges of the top panel:
* front, back and then, when all sides are shown, left and right. Empty when no sides are
* shown or the enclosure has no height.
*/
Rectangle2D[] getSidePanels() {
double h = getHeight() == null ? 0 : getHeight().convertToPixels();
if (h <= 0 || getSides() == Sides.NONE) {
return new Rectangle2D[0];
}
double s = getSpacing() == null ? 0 : getSpacing().convertToPixels();
double x = firstPoint.getX();
double y = firstPoint.getY();
double w = secondPoint.getX() - x;
double d = secondPoint.getY() - y;
Rectangle2D front = new Rectangle2D.Double(x, y - s - h, w, h);
Rectangle2D back = new Rectangle2D.Double(x, y + d + s, w, h);
if (getSides() == Sides.FRONT_AND_BACK) {
return new Rectangle2D[] {front, back};
}
return new Rectangle2D[] {front, back, new Rectangle2D.Double(x - s - h, y, h, d),
new Rectangle2D.Double(x + w + s, y, h, d)};
}
@Override
@@ -61,6 +125,7 @@ public class ChassisPanel extends AbstractShape {
IDrawingObserver drawingObserver) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((int) borderThickness.convertToPixels()));
int radius = (int) edgeRadius.convertToPixels();
Rectangle2D[] sidePanels = getSidePanels();
if (componentState != ComponentState.DRAGGING) {
Composite oldComposite = applyAlpha(g2d, componentState);
g2d.setColor(color);
@@ -73,6 +138,9 @@ public class ChassisPanel extends AbstractShape {
(int) (secondPoint.getX() - firstPoint.getX()),
(int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
}
for (Rectangle2D panel : sidePanels) {
g2d.fill(panel);
}
g2d.setComposite(oldComposite);
drawingObserver.stopTracking();
}
@@ -89,6 +157,9 @@ public class ChassisPanel extends AbstractShape {
(int) (secondPoint.getX() - firstPoint.getX()),
(int) (secondPoint.getY() - firstPoint.getY()), radius, radius);
}
for (Rectangle2D panel : sidePanels) {
g2d.draw(panel);
}
}
@EditableProperty(name = "Radius")
@@ -100,12 +171,84 @@ public class ChassisPanel extends AbstractShape {
this.edgeRadius = edgeRadius;
}
@EditableProperty(name = "Value")
public String getModel() {
return value;
}
public void setModel(String model) {
this.value = model;
}
@EditableProperty
public Size getHeight() {
return height;
}
public void setHeight(Size height) {
this.height = height;
}
@EditableProperty
public Sides getSides() {
if (sides == null) {
sides = Sides.ALL;
}
return sides;
}
public void setSides(Sides sides) {
this.sides = sides;
}
@EditableProperty
public Size getSpacing() {
if (spacing == null) {
spacing = DEFAULT_SPACING;
}
return spacing;
}
public void setSpacing(Size spacing) {
this.spacing = spacing;
}
@Override
public String getValueForDisplay() {
return value == null ? "" : value;
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
int factor = 32 / width;
g2d.setColor(LIGHT_METAL_COLOR);
g2d.fillRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
g2d.setColor(LIGHT_METAL_COLOR.darker());
g2d.drawRect(2 / factor, 4 / factor, width - 4 / factor, height - 8 / factor);
int flap = 6 / factor;
int left = 2 / factor + flap;
int top = 2 / factor + flap;
int topWidth = width - 2 * left;
int topHeight = height - 2 * top;
int[][] panels = {{left, top, topWidth, topHeight}, {left, top - flap, topWidth, flap},
{left, top + topHeight, topWidth, flap}, {left - flap, top, flap, topHeight},
{left + topWidth, top, flap, topHeight}};
for (int[] panel : panels) {
g2d.setColor(LIGHT_METAL_COLOR);
g2d.fillRect(panel[0], panel[1], panel[2], panel[3]);
g2d.setColor(LIGHT_METAL_COLOR.darker());
g2d.drawRect(panel[0], panel[1], panel[2], panel[3]);
}
}
public enum Sides {
ALL("All"), FRONT_AND_BACK("Front and Back"), NONE("None");
private final String label;
Sides(String label) {
this.label = label;
}
@Override
public String toString() {
return label;
}
}
}
@@ -42,7 +42,7 @@ import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Dial Scale", author = "Branislav Stojkovic", category = "Misc",
@ComponentDescriptor(name = "Dial Scale", author = "Branislav Stojkovic", category = "Hardware",
instanceNamePrefix = "DS", description = "Control panel dial scale", zOrder = IDIYComponent.CHASSIS + 0.1,
bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
public class DialScale extends AbstractComponent<String> {
@@ -31,7 +31,7 @@ import org.diylc.core.Project;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
@ComponentDescriptor(name = "Elliptical Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
@ComponentDescriptor(name = "Elliptical Cutout", author = "Branislav Stojkovic", category = "Hardware",
instanceNamePrefix = "ELC", description = "Elliptical chassis cutout", zOrder = IDIYComponent.CHASSIS + 0.1,
bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
public class EllipticalCutout extends AbstractShape {
@@ -35,7 +35,7 @@ import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
@ComponentDescriptor(name = "Polygonal Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
@ComponentDescriptor(name = "Polygonal Cutout", author = "Branislav Stojkovic", category = "Hardware",
instanceNamePrefix = "POLYC", description = "Polygonal chassis cutout", zOrder = IDIYComponent.CHASSIS + 0.1,
bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
public class PolygonalCutout extends AbstractShape {
@@ -34,7 +34,7 @@ import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Rectangular Cutout", author = "Branislav Stojkovic", category = "Electro-Mechanical",
@ComponentDescriptor(name = "Rectangular Cutout", author = "Branislav Stojkovic", category = "Hardware",
instanceNamePrefix = "RECTC", description = "Rectangular chassis cutout, with or without rounded edges",
zOrder = IDIYComponent.CHASSIS + 0.1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
transformer = SimpleComponentTransformer.class)
@@ -43,7 +43,7 @@ import org.diylc.core.gerber.IGerberDrawingObserver;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Drill Hole", category = "Electro-Mechanical", author = "Branislav Stojkovic",
@ComponentDescriptor(name = "Drill Hole", category = "Hardware", author = "Branislav Stojkovic",
description = "Drill hole marker for PCB, chassis or faceplate", instanceNamePrefix = "Hole",
zOrder = IDIYComponent.BOARD + 0.1, bomPolicy = BomPolicy.NEVER_SHOW,
keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB",
@@ -0,0 +1,132 @@
Diecast (1590),1590LLB,50.5 mm,50.5 mm,21 mm
Diecast (1590),1590LB,50.6 mm,50.55 mm,27 mm
Diecast (1590),1590H,38 mm,53 mm,27 mm
Diecast (1590),1590Y,92 mm,92 mm,38 mm
Diecast (1590),1590A,38.5 mm,92.6 mm,27 mm
Diecast (1590),1590G,50 mm,100 mm,21.5 mm
Diecast (1590),1590G2,50 mm,100 mm,27 mm
Diecast (1590),1590S,82.4 mm,110.5 mm,40 mm
Diecast (1590),1590B,60.5 mm,112.4 mm,27 mm
Diecast (1590),1590B2,60.5 mm,112.4 mm,33.5 mm
Diecast (1590),1590BS,60.5 mm,112 mm,38 mm
Diecast (1590),1590B3,77 mm,116 mm,33.5 mm
Diecast (1590),1590BB,94 mm,119.5 mm,30 mm
Diecast (1590),1590BB2,94 mm,119.5 mm,33.75 mm
Diecast (1590),1590BBS,94 mm,119.5 mm,38.1 mm
Diecast (1590),1590Q,120 mm,120 mm,30 mm
Diecast (1590),1590U,120 mm,120 mm,55 mm
Diecast (1590),1590V,120 mm,120 mm,90 mm
Diecast (1590),1590C,94 mm,119.5 mm,52.5 mm
Diecast (1590),1590T,80 mm,120 mm,55 mm
Diecast (1590),1590CE,100 mm,120 mm,61 mm
Diecast (1590),1590N1,65.5 mm,121.2 mm,35.8 mm
Diecast (1590),1590KK,125 mm,125 mm,53 mm
Diecast (1590),1590K,125 mm,125 mm,75 mm
Diecast (1590),1590J,145 mm,95 mm,45.1 mm
Diecast (1590),1590XX,145.2 mm,121.2 mm,35.2 mm
Diecast (1590),1590X,145.2 mm,121.2 mm,52.3 mm
Diecast (1590),1590P1,153 mm,83.1 mm,46.4 mm
Diecast (1590),1590D,187.75 mm,119.5 mm,52 mm
Diecast (1590),1590DD,188 mm,120 mm,33 mm
Diecast (1590),1590E,188 mm,120 mm,78 mm
Diecast (1590),1590F,188 mm,188 mm,63 mm
Diecast (1590),1590R1,192 mm,112 mm,57 mm
Diecast (1590),1590DE,200 mm,120 mm,60 mm
Diecast (1590),1590EE,200 mm,120 mm,81 mm
Diecast (1590),1590BX2,254 mm,70 mm,31 mm
Diecast (1590),1590BX,254 mm,70 mm,46 mm
Diecast (1550),1550Q,55 mm,60 mm,26 mm
Diecast (1550),1550P,55 mm,80 mm,21 mm
Diecast (1550),1550A,35 mm,89 mm,26 mm
Diecast (1550),1550B,64 mm,114.5 mm,26 mm
Diecast (1550),1550D,64 mm,115 mm,51 mm
Diecast (1550),1550C,90 mm,115 mm,51 mm
Diecast (1550),1550M,100 mm,120 mm,31 mm
Diecast (1550),1550K,140 mm,102 mm,73 mm
Diecast (1550),1550L,165 mm,127 mm,73 mm
Diecast (1550),1550E,171 mm,121 mm,51 mm
Diecast (1550),1550F,171 mm,121 mm,101 mm
Diecast (1550),1550G,222 mm,146 mm,51 mm
Diecast (1550),1550H,222 mm,146 mm,101 mm
Diecast (1550),1550N,250 mm,250 mm,97 mm
Diecast (1550),1550J,275 mm,175 mm,63 mm
Others,125B,66 mm,122 mm,36 mm
Chassis - Steel (1441),1441-9,8 in,4 in,1 in
Chassis - Steel (1441),1441-15,10 in,6 in,1 in
Chassis - Steel (1441),1441-6,4 in,4 in,2 in
Chassis - Steel (1441),1441-8,6 in,4 in,2 in
Chassis - Steel (1441),1441-12,7 in,5 in,2 in
Chassis - Steel (1441),1441-10,8 in,4 in,2 in
Chassis - Steel (1441),1441-14,9 in,5 in,2 in
Chassis - Steel (1441),1441-16,10 in,6 in,2 in
Chassis - Steel (1441),1441-22,12 in,8 in,2 in
Chassis - Steel (1441),1441-29,12 in,10 in,2 in
Chassis - Steel (1441),1441-18,13.5 in,5 in,2 in
Chassis - Steel (1441),1441-26,16 in,8 in,2 in
Chassis - Steel (1441),1441-30,17 in,10 in,2 in
Chassis - Steel (1441),1441-34,17 in,12 in,2 in
Chassis - Steel (1441),1441-24,12 in,8 in,3 in
Chassis - Steel (1441),1441-28,16 in,8 in,3 in
Chassis - Steel (1441),1441-20,17 in,4 in,3 in
Chassis - Steel (1441),1441-32,17 in,10 in,3 in
Chassis - Steel (1441),1441-36,17 in,12 in,3 in
Chassis - Steel (1441),1441-38,17 in,14 in,3 in
Chassis - Steel (1441),1441-33,17 in,10 in,4 in
Chassis - Steel (1441),1441-40,17 in,14 in,4 in
Chassis - Steel (1441),1441-42,17 in,14 in,5 in
Chassis - Aluminium (1444) 1-2 in,1444-45351,4.5 in,3.5 in,1 in
Chassis - Aluminium (1444) 1-2 in,1444-9,8 in,4 in,1 in
Chassis - Aluminium (1444) 1-2 in,1444-15,10 in,6 in,1 in
Chassis - Aluminium (1444) 1-2 in,1444-6415,6 in,4 in,1.5 in
Chassis - Aluminium (1444) 1-2 in,1444-84515,8 in,4.5 in,1.5 in
Chassis - Aluminium (1444) 1-2 in,1444-6,4 in,4 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-542,5 in,4 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-8,6 in,4 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-12,7 in,5 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-772,7 in,7 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-10,8 in,4 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-862,8 in,6 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-14,9 in,5 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-972,9 in,7 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-9552,9.5 in,5 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-16,10 in,6 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-1172,11 in,7 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-22,12 in,8 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-29,12 in,10 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-1372,13 in,7 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-18,13.5 in,5 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-26,16 in,8 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-30,17 in,10 in,2 in
Chassis - Aluminium (1444) 1-2 in,1444-17132,17 in,13 in,2 in
Chassis - Aluminium (1444) 2.5-3 in,1444-95525,9.5 in,5 in,2.5 in
Chassis - Aluminium (1444) 2.5-3 in,1444-10825,10 in,8 in,2.5 in
Chassis - Aluminium (1444) 2.5-3 in,1444-12825,12 in,8 in,2.5 in
Chassis - Aluminium (1444) 2.5-3 in,1444-643,6 in,4 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-753,7 in,5 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-9553,9.5 in,5 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1053,10 in,5 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1273,12 in,7 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-24,12 in,8 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-12103,12 in,10 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-12123,12 in,12 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1463,14 in,6 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-14103,14 in,10 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1573,15 in,7 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1593,15 in,9 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-28,16 in,8 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-20,17 in,4 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1763,17 in,6 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1773,17 in,7 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-1783,17 in,8 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-32,17 in,10 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-17123,17 in,12 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-17133,17 in,13 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-17143,17 in,14 in,3 in
Chassis - Aluminium (1444) 2.5-3 in,1444-17173,17 in,17 in,3 in
Chassis - Aluminium (1444) 4-6 in,1444-33,17 in,10 in,4 in
Chassis - Aluminium (1444) 4-6 in,1444-17134,17 in,13 in,4 in
Chassis - Aluminium (1444) 4-6 in,1444-17154,17 in,15 in,4 in
Chassis - Aluminium (1444) 4-6 in,1444-17174,17 in,17 in,4 in
Chassis - Aluminium (1444) 4-6 in,1444-17105,17 in,10 in,5 in
Chassis - Aluminium (1444) 4-6 in,1444-17135,17 in,13 in,5 in
Chassis - Aluminium (1444) 4-6 in,1444-17156,17 in,15 in,6 in
@@ -0,0 +1,241 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 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.chassis;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import org.diylc.components.chassis.ChassisPanel.Sides;
import org.diylc.core.IDIYComponent;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.presenter.DatasheetService;
import org.diylc.serialization.ProjectFileManager;
import org.diylc.utils.BomEntry;
import org.diylc.utils.BomMaker;
import org.junit.Assert;
import org.junit.Test;
public class ChassisPanelDatasheetTest {
private static final double TOLERANCE = 1e-6;
private static String[] row(String model) {
return DatasheetService.getInstance().loadDatasheet(ChassisPanel.class).stream()
.filter(row -> row[1].equals(model)).findFirst().get();
}
private static double mm(double value) {
return new Size(value, SizeUnit.mm).convertToPixels();
}
private static void assertRect(Rectangle2D expected, Rectangle2D actual) {
Assert.assertEquals(expected.getX(), actual.getX(), TOLERANCE);
Assert.assertEquals(expected.getY(), actual.getY(), TOLERANCE);
Assert.assertEquals(expected.getWidth(), actual.getWidth(), TOLERANCE);
Assert.assertEquals(expected.getHeight(), actual.getHeight(), TOLERANCE);
}
@Test
public void everyRowApplies() {
List<String[]> datasheet = DatasheetService.getInstance().loadDatasheet(ChassisPanel.class);
Assert.assertNotNull(datasheet);
Assert.assertFalse(datasheet.isEmpty());
for (String[] row : datasheet) {
Assert.assertEquals(String.join(",", row), 5, row.length);
ChassisPanel enclosure = new ChassisPanel(row);
Assert.assertEquals(row[1], enclosure.getModel());
Assert.assertEquals(row[1], Size.parseSize(row[4]), enclosure.getHeight());
Point2D first = enclosure.getControlPoint(0);
Point2D second = enclosure.getControlPoint(1);
Assert.assertEquals(row[1], Size.parseSize(row[2]).convertToPixels(),
second.getX() - first.getX(), TOLERANCE);
Assert.assertEquals(row[1], Size.parseSize(row[3]).convertToPixels(),
second.getY() - first.getY(), TOLERANCE);
}
}
@Test
public void aNewEnclosureIsA125BWithAllSides() {
ChassisPanel enclosure = new ChassisPanel();
ChassisPanel fromDatasheet = new ChassisPanel(row("125B"));
Assert.assertEquals(fromDatasheet.getModel(), enclosure.getModel());
Assert.assertEquals(fromDatasheet.getHeight(), enclosure.getHeight());
Assert.assertEquals(fromDatasheet.getEdgeRadius(), enclosure.getEdgeRadius());
Assert.assertEquals(fromDatasheet.getControlPoint(1), enclosure.getControlPoint(1));
Assert.assertEquals(Sides.ALL, enclosure.getSides());
Assert.assertEquals(4, enclosure.getSidePanels().length);
}
@Test
public void pedalSizedBoxesAreUprightAndBiggerOnesHorizontal() {
for (String model : new String[] {"125B", "1590A", "1590B", "1590BB", "1550B"}) {
Point2D second = new ChassisPanel(row(model)).getControlPoint(1);
Assert.assertTrue(model, second.getY() > second.getX());
}
for (String model : new String[] {"1590XX", "1590DD", "1441-10", "1444-32"}) {
Point2D second = new ChassisPanel(row(model)).getControlPoint(1);
Assert.assertTrue(model, second.getX() > second.getY());
}
}
@Test
public void modelNamesAreUnique() {
List<String[]> datasheet = DatasheetService.getInstance().loadDatasheet(ChassisPanel.class);
Assert.assertEquals(datasheet.size(),
datasheet.stream().map(row -> row[1]).distinct().count());
}
@Test
public void modelLeavesTheRadiusAlone() {
ChassisPanel enclosure = new ChassisPanel();
enclosure.setEdgeRadius(new Size(3d, SizeUnit.mm));
enclosure.applyModel(row("1590BB"));
Assert.assertEquals(new Size(3d, SizeUnit.mm), enclosure.getEdgeRadius());
}
@Test
public void inchRowsKeepTheirUnit() {
ChassisPanel enclosure = new ChassisPanel(row("1444-32"));
Assert.assertEquals(new Size(3d, SizeUnit.in), enclosure.getHeight());
Point2D first = enclosure.getControlPoint(0);
Point2D second = enclosure.getControlPoint(1);
Assert.assertEquals(new Size(17d, SizeUnit.in).convertToPixels(),
second.getX() - first.getX(), TOLERANCE);
Assert.assertEquals(new Size(10d, SizeUnit.in).convertToPixels(),
second.getY() - first.getY(), TOLERANCE);
}
@Test
public void sidesUnfoldAroundTheTopPanel() {
ChassisPanel enclosure = new ChassisPanel(row("1590BB"));
Rectangle2D[] panels = enclosure.getSidePanels();
Assert.assertEquals(4, panels.length);
assertRect(new Rectangle2D.Double(0, -mm(30), mm(94), mm(30)), panels[0]);
assertRect(new Rectangle2D.Double(0, mm(119.5), mm(94), mm(30)), panels[1]);
assertRect(new Rectangle2D.Double(-mm(30), 0, mm(30), mm(119.5)), panels[2]);
assertRect(new Rectangle2D.Double(mm(94), 0, mm(30), mm(119.5)), panels[3]);
}
@Test
public void spacingSetsTheSidesApart() {
ChassisPanel enclosure = new ChassisPanel(row("1590BB"));
enclosure.setSpacing(new Size(2d, SizeUnit.mm));
Rectangle2D[] panels = enclosure.getSidePanels();
assertRect(new Rectangle2D.Double(0, -mm(32), mm(94), mm(30)), panels[0]);
assertRect(new Rectangle2D.Double(0, mm(121.5), mm(94), mm(30)), panels[1]);
assertRect(new Rectangle2D.Double(-mm(32), 0, mm(30), mm(119.5)), panels[2]);
assertRect(new Rectangle2D.Double(mm(96), 0, mm(30), mm(119.5)), panels[3]);
}
@Test
public void frontAndBackOnly() {
ChassisPanel enclosure = new ChassisPanel(row("1590BB"));
enclosure.setSides(Sides.FRONT_AND_BACK);
Rectangle2D[] panels = enclosure.getSidePanels();
Assert.assertEquals(2, panels.length);
assertRect(new Rectangle2D.Double(0, -mm(30), mm(94), mm(30)), panels[0]);
assertRect(new Rectangle2D.Double(0, mm(119.5), mm(94), mm(30)), panels[1]);
}
@Test
public void noSidesKeepsTheModelButDrawsOnePanel() {
ChassisPanel enclosure = new ChassisPanel(row("1590BB"));
enclosure.setSides(Sides.NONE);
Assert.assertEquals(0, enclosure.getSidePanels().length);
Assert.assertEquals(new Size(30d, SizeUnit.mm), enclosure.getHeight());
}
@Test
public void sidesFollowTheTopPanelWhenItIsStretched() {
ChassisPanel enclosure = new ChassisPanel(row("1590BB"));
enclosure.setControlPoint(new Point2D.Double(mm(200), mm(100)), 1);
Rectangle2D[] panels = enclosure.getSidePanels();
assertRect(new Rectangle2D.Double(0, mm(100), mm(200), mm(30)), panels[1]);
assertRect(new Rectangle2D.Double(mm(200), 0, mm(30), mm(100)), panels[3]);
}
@Test
public void withoutHeightItIsASinglePanel() {
ChassisPanel enclosure = new ChassisPanel();
enclosure.setHeight(new Size(0d, SizeUnit.mm));
Assert.assertEquals(0, enclosure.getSidePanels().length);
enclosure.setHeight(null);
Assert.assertEquals(0, enclosure.getSidePanels().length);
}
@Test
public void panelFromAnOldFileIsASinglePanel() {
// a panel from before the datasheet: no model, a radius of 0 and a free-form size
ChassisPanel original = new ChassisPanel();
original.setModel("");
original.setEdgeRadius(new Size(0d, SizeUnit.mm));
original.setControlPoint(new Point2D.Double(20, 30), 1);
String xml = ProjectFileManager.xStreamSerializer.toXML(original)
.replaceAll("\\s*<height[^>]*/>", "").replaceAll("\\s*<height>.*?</height>", "")
.replaceAll("\\s*<sides>[^<]*</sides>", "")
.replaceAll("\\s*<spacing[^>]*/>", "").replaceAll("\\s*<spacing>.*?</spacing>", "");
Assert.assertFalse(xml, xml.contains("<height"));
Assert.assertFalse(xml, xml.contains("<sides>"));
Assert.assertFalse(xml, xml.contains("<spacing"));
ChassisPanel reloaded = (ChassisPanel) ProjectFileManager.xStreamSerializer.fromXML(xml);
Assert.assertNull(reloaded.getHeight());
Assert.assertEquals(Sides.ALL, reloaded.getSides());
Assert.assertEquals(new Size(0d, SizeUnit.mm), reloaded.getSpacing());
Assert.assertEquals(0, reloaded.getSidePanels().length);
Assert.assertEquals("", reloaded.getValueForDisplay());
Assert.assertEquals(new Size(0d, SizeUnit.mm), reloaded.getEdgeRadius());
Assert.assertEquals(new Point2D.Double(20, 30), reloaded.getControlPoint(1));
}
@Test
public void bomListsEnclosuresByModel() {
List<IDIYComponent<?>> components = new ArrayList<IDIYComponent<?>>();
components.add(new ChassisPanel(row("1590BB")));
components.add(new ChassisPanel(row("1590BB")));
components.add(new ChassisPanel(row("1590B")));
List<BomEntry> bom = BomMaker.getInstance().createBom(components);
Assert.assertEquals(2, bom.size());
BomEntry bb = bom.stream().filter(e -> "1590BB".equals(e.getValue())).findFirst().get();
Assert.assertEquals("Enclosure", bb.getType());
Assert.assertEquals(Integer.valueOf(2), bb.getQuantity());
}
}