This commit is contained in:
Bane Stojkovic
2026-08-16 12:27:09 +02:00
parent 7641d7bb38
commit e895cc13c3
10 changed files with 193 additions and 142 deletions
@@ -195,13 +195,78 @@ public abstract class AbstractMakerBoard extends AbstractTransparentComponent<Vo
}
}
/**
* Helper to draw a complete PCB terminal block (green body + inner compartment lines + screw lugs)
* that matches the visuals of the PCBTerminalBlock component.
*
* @param g2d Graphics2D context
* @param startIndex First control point index
* @param count Number of positions in this terminal block
* @param isHorizontal true if terminal block runs horizontally (along X), false if vertically (along Y)
* @param wireEntryOffset Direction/offset from pins to the wire entry edge (positive or negative)
* @param blockDepth Total depth of the green body (e.g. 50.0px for 5.08mm blocks, or 35.0px for compact)
* @param outlineMode Outline mode flag
* @param drawingObserver Observer
*/
protected void drawTerminalBlock(Graphics2D g2d, int startIndex, int count, boolean isHorizontal,
double wireEntryOffset, double blockDepth, boolean outlineMode, IDrawingObserver drawingObserver) {
if (outlineMode) return;
if (count <= 0 || startIndex < 0 || startIndex >= controlPoints.length) return;
Point2D p0 = controlPoints[startIndex];
Point2D pLast = controlPoints[Math.min(startIndex + count - 1, controlPoints.length - 1)];
double pitchPx = count > 1 ?
(isHorizontal ? Math.abs(pLast.getX() - p0.getX()) / (count - 1) : Math.abs(pLast.getY() - p0.getY()) / (count - 1))
: new Size(5.08d, SizeUnit.mm).convertToPixels();
if (pitchPx <= 0) {
pitchPx = new Size(5.08d, SizeUnit.mm).convertToPixels();
}
double minX = Math.min(p0.getX(), pLast.getX());
double minY = Math.min(p0.getY(), pLast.getY());
double maxX = Math.max(p0.getX(), pLast.getX());
double maxY = Math.max(p0.getY(), pLast.getY());
Rectangle2D outerBody;
Rectangle2D innerCompartment;
if (isHorizontal) {
double bx = minX - pitchPx / 2.0;
double bw = (maxX - minX) + pitchPx;
double by = wireEntryOffset >= 0 ? minY - (blockDepth - pitchPx) / 2.0 : minY - (blockDepth - pitchPx / 2.0);
double bh = blockDepth;
outerBody = new Rectangle2D.Double(bx, by, bw, bh);
innerCompartment = new Rectangle2D.Double(bx, minY - pitchPx / 2.0, bw, pitchPx);
} else {
double by = minY - pitchPx / 2.0;
double bh = (maxY - minY) + pitchPx;
double bx = wireEntryOffset >= 0 ? minX - (blockDepth - pitchPx) / 2.0 : minX - (blockDepth - pitchPx / 2.0);
double bw = blockDepth;
outerBody = new Rectangle2D.Double(bx, by, bw, bh);
innerCompartment = new Rectangle2D.Double(minX - pitchPx / 2.0, by, pitchPx, bh);
}
// Draw green body and compartment
g2d.setColor(SCREW_TERMINAL_COLOR);
g2d.fill(outerBody);
g2d.setColor(SCREW_TERMINAL_BORDER);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.draw(innerCompartment);
g2d.draw(outerBody);
// Draw screw contacts
drawScrewTerminals(g2d, startIndex, count, pitchPx, outlineMode, drawingObserver);
}
/**
* Helper to draw screw terminal block contacts at given control points.
* Visuals match the PCBTerminalBlock component: green body, light metal screw circles with diagonal slot.
* Visuals match the PCBTerminalBlock component: light metal screw circles with diagonal slot.
*/
protected void drawScrewTerminals(Graphics2D g2d, int startIndex, int count, double pitchPx, boolean outlineMode, IDrawingObserver drawingObserver) {
if (outlineMode) return;
int circleDiameter = getClosestOdd((int) (PIN_SPACING.convertToPixels() * 3d / 5));
double effectivePitch = pitchPx > 0 ? pitchPx : PIN_SPACING.convertToPixels();
int circleDiameter = getClosestOdd((int) (effectivePitch * 3d / 5));
drawingObserver.startTrackingContinuityArea(true);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2f));
@@ -209,14 +274,14 @@ public abstract class AbstractMakerBoard extends AbstractTransparentComponent<Vo
Point2D p = controlPoints[i];
// Light metal screw head circle
g2d.setColor(SCREW_CIRCLE_COLOR);
g2d.fillOval((int) Math.round(p.getX() - circleDiameter / 2), (int) Math.round(p.getY() - circleDiameter / 2),
g2d.fillOval((int) Math.round(p.getX() - circleDiameter / 2.0), (int) Math.round(p.getY() - circleDiameter / 2.0),
circleDiameter, circleDiameter);
// Diagonal screw slot line
g2d.setColor(SCREW_CIRCLE_COLOR.darker());
g2d.drawLine((int) (p.getX() + Math.cos(Math.PI / 4) * circleDiameter / 2),
(int) (p.getY() + Math.sin(Math.PI / 4) * circleDiameter / 2),
(int) (p.getX() + Math.cos(5 * Math.PI / 4) * circleDiameter / 2),
(int) (p.getY() + Math.sin(5 * Math.PI / 4) * circleDiameter / 2));
g2d.drawLine((int) (p.getX() + Math.cos(Math.PI / 4) * circleDiameter / 2.0),
(int) (p.getY() + Math.sin(Math.PI / 4) * circleDiameter / 2.0),
(int) (p.getX() + Math.cos(5 * Math.PI / 4) * circleDiameter / 2.0),
(int) (p.getY() + Math.sin(5 * Math.PI / 4) * circleDiameter / 2.0));
}
drawingObserver.stopTrackingContinuityArea();
}
@@ -64,8 +64,6 @@ public class WS2812BStick extends AbstractMakerBoard {
public static Color LED_DIFFUSER = Color.decode("#EAECEE");
public static Color DIFFUSER_BORDER = Color.decode("#BDC3C7");
public static Color CHIP_DOT_COLOR = Color.decode("#333333");
public static Color CAP_CERAMIC_COLOR = Color.decode("#B87333");
public static Color CAP_METAL_COLOR = Color.decode("#D5D8DC");
public static Font PIN_LABEL_FONT = new Font("SansSerif", Font.BOLD, 9);
@@ -184,19 +182,6 @@ public class WS2812BStick extends AbstractMakerBoard {
// Internal tiny IC dot
g2d.setColor(CHIP_DOT_COLOR);
g2d.fill(new Rectangle2D.Double(lx - 2.5, ly - 2.5, 5, 5));
// Decoupling capacitor between LEDs (0805 SMD capacitor with silver end caps)
if (i < 7) {
double capX = lx + ledPitch / 2.0 - 4;
double capY = ly - 12;
// Ceramic body
g2d.setColor(CAP_CERAMIC_COLOR);
g2d.fill(new Rectangle2D.Double(capX, capY, 8, 4));
// Silver endcaps
g2d.setColor(CAP_METAL_COLOR);
g2d.fillRect((int) capX, (int) capY, 2, 4);
g2d.fillRect((int) (capX + 6), (int) capY, 2, 4);
}
}
// Silk Screen Pin Labels — all 4 pins labeled on both sides with clean spacing
@@ -89,7 +89,7 @@ public class ArduinoNano extends AbstractMakerBoard {
protected void updateControlPoints() {
Point2D firstPoint = controlPoints[0];
double spacing = PIN_SPACING.convertToPixels(); // 20px (0.1")
double rowSpacing = new Size(0.7d, SizeUnit.in).convertToPixels(); // 140px (0.7")
double rowSpacing = new Size(0.6d, SizeUnit.in).convertToPixels(); // 120px (0.6")
double[][] relativeOffsets = new double[PIN_NAMES.length][2];
@@ -121,7 +121,7 @@ public class ArduinoNano extends AbstractMakerBoard {
Point2D p0 = controlPoints[0];
double x = p0.getX();
double y = p0.getY();
double rowSpacing = new Size(0.7d, SizeUnit.in).convertToPixels();
double rowSpacing = new Size(0.6d, SizeUnit.in).convertToPixels();
double boardW = rowSpacing + 20;
double boardH = 16 * PIN_SPACING.convertToPixels();
double boardX = x - 10;
@@ -145,7 +145,7 @@ public class ArduinoNano extends AbstractMakerBoard {
g2d.rotate(orientation.toRadians(), x, y);
}
double rowSpacing = new Size(0.7d, SizeUnit.in).convertToPixels();
double rowSpacing = new Size(0.6d, SizeUnit.in).convertToPixels();
double boardW = rowSpacing + 20;
double boardH = 16 * PIN_SPACING.convertToPixels();
double boardX = x - 10;
@@ -167,17 +167,17 @@ public class ArduinoNano extends AbstractMakerBoard {
if (!outlineMode) {
// Mini USB Jack
drawMetalConnector(g2d, boardX + (boardW - 60) / 2.0, boardY - 8, 60, 45, "USB");
drawMetalConnector(g2d, boardX + (boardW - 50) / 2.0, boardY - 8, 50, 42, "USB");
// ATmega328P TQFP square chip
drawChip(g2d, boardX + (boardW - 55) / 2.0, boardY + 90, 55, 55, "m328P");
drawChip(g2d, boardX + (boardW - 48) / 2.0, boardY + 90, 48, 48, "m328P");
// Reset Button
g2d.setColor(Color.decode("#CC3333"));
g2d.fill(new RoundRectangle2D.Double(boardX + (boardW - 25) / 2.0, boardY + 50, 25, 20, 4, 4));
g2d.fill(new RoundRectangle2D.Double(boardX + (boardW - 22) / 2.0, boardY + 50, 22, 18, 4, 4));
g2d.setColor(Color.WHITE);
g2d.setFont(SILK_FONT_SMALL);
StringUtils.drawCenteredText(g2d, "RST", boardX + boardW / 2.0, boardY + 60, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "RST", boardX + boardW / 2.0, boardY + 59, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
// Silkscreen
g2d.setFont(SILK_FONT);
@@ -187,19 +187,6 @@ public class L298NMotorDriver extends AbstractMakerBoard {
// L298 Multiwatt IC mounted to heatsink
drawChip(g2d, hsX + (hsW - 100) / 2.0, hsY + hsH - 15, 100, 30, "L298N");
// Green screw terminal block bodies
g2d.setColor(SCREW_TERMINAL_COLOR);
RoundRectangle2D tb1 = new RoundRectangle2D.Double(x - 15, y - 25, 120, 35, 3, 3);
RoundRectangle2D tb2 = new RoundRectangle2D.Double(boardX + 5, y - 195, 35, 75, 3, 3);
RoundRectangle2D tb3 = new RoundRectangle2D.Double(boardX + boardSizePx - 40, y - 195, 35, 75, 3, 3);
g2d.fill(tb1);
g2d.fill(tb2);
g2d.fill(tb3);
g2d.setColor(SCREW_TERMINAL_BORDER);
g2d.draw(tb1);
g2d.draw(tb2);
g2d.draw(tb3);
// Logic header black block
g2d.setColor(HEADER_BODY_COLOR);
g2d.fill(new RoundRectangle2D.Double(x + 130, y - 10, 128, 20, 2, 2));
@@ -218,8 +205,12 @@ public class L298NMotorDriver extends AbstractMakerBoard {
g2d.setTransform(oldTx);
// Draw terminals and logic header pins
drawScrewTerminals(g2d, 0, 7, 40, outlineMode, drawingObserver);
// Draw terminal blocks matching PCBTerminalBlock style
drawTerminalBlock(g2d, 0, 3, true, -1, 38.0, outlineMode, drawingObserver);
drawTerminalBlock(g2d, 3, 2, false, -1, 38.0, outlineMode, drawingObserver);
drawTerminalBlock(g2d, 5, 2, false, 1, 38.0, outlineMode, drawingObserver);
// Draw logic header pins
drawPins(g2d, 7, 6, false, outlineMode, drawingObserver);
g2d.setComposite(oldComposite);
@@ -84,20 +84,23 @@ public class LM2596BuckConverter extends AbstractMakerBoard {
return Integer.toString(index + 1);
}
private static final Size TERMINAL_PITCH = new Size(5.08d, SizeUnit.mm);
private static final double PAD_MARGIN_X = 16.0;
@Override
protected void updateControlPoints() {
Point2D firstPoint = controlPoints[0];
double h = BOARD_HEIGHT.convertToPixels();
double termSpacing = TERMINAL_PITCH.convertToPixels();
double w = BOARD_WIDTH.convertToPixels();
// 4 Solder / Screw terminal pads:
// 4 Solder / Screw terminal pads (5.08mm pitch, centered vertically on left and right edges):
// Input (Left): 0 = IN+, 1 = IN-
// Output (Right): 2 = OUT+, 3 = OUT-
double[][] relativeOffsets = new double[][] {
{ 0, 0 }, // Pin 0: IN+
{ 0, h - 20 }, // Pin 1: IN-
{ w - 20, 0 }, // Pin 2: OUT+
{ w - 20, h - 20 } // Pin 3: OUT-
{ 0, 0 }, // Pin 0: IN+
{ 0, termSpacing }, // Pin 1: IN-
{ w - 2 * PAD_MARGIN_X, 0 }, // Pin 2: OUT+
{ w - 2 * PAD_MARGIN_X, termSpacing } // Pin 3: OUT-
};
rotatePoints(firstPoint, relativeOffsets);
@@ -110,7 +113,10 @@ public class LM2596BuckConverter extends AbstractMakerBoard {
double y = p0.getY();
double boardW = BOARD_WIDTH.convertToPixels();
double boardH = BOARD_HEIGHT.convertToPixels();
return new RoundRectangle2D.Double(x - 10, y - 10, boardW, boardH, 6, 6);
double termSpacing = TERMINAL_PITCH.convertToPixels();
double boardX = x - PAD_MARGIN_X;
double boardY = y - (boardH - termSpacing) / 2.0;
return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6);
}
@Override
@@ -131,8 +137,9 @@ public class LM2596BuckConverter extends AbstractMakerBoard {
double boardW = BOARD_WIDTH.convertToPixels();
double boardH = BOARD_HEIGHT.convertToPixels();
double boardX = x - 10;
double boardY = y - 10;
double termSpacing = TERMINAL_PITCH.convertToPixels();
double boardX = x - PAD_MARGIN_X;
double boardY = y - (boardH - termSpacing) / 2.0;
Shape boardShape = getBodyShape();
@@ -149,59 +156,60 @@ public class LM2596BuckConverter extends AbstractMakerBoard {
if (!outlineMode) {
// 2 Diagonal Mounting holes
drawMountingHole(g2d, boardX + 45, boardY + 16, 16);
drawMountingHole(g2d, boardX + boardW - 45, boardY + boardH - 16, 16);
drawMountingHole(g2d, boardX + 50, boardY + 16, 16);
drawMountingHole(g2d, boardX + boardW - 50, boardY + boardH - 16, 16);
// Input Capacitor (Left)
g2d.setColor(Color.LIGHT_GRAY);
g2d.fill(new Ellipse2D.Double(boardX + 22, boardY + boardH / 2.0 - 18, 36, 36));
g2d.fill(new Ellipse2D.Double(boardX + 38, boardY + boardH / 2.0 - 18, 34, 34));
g2d.setColor(Color.DARK_GRAY);
g2d.draw(new Ellipse2D.Double(boardX + 22, boardY + boardH / 2.0 - 18, 36, 36));
g2d.draw(new Ellipse2D.Double(boardX + 38, boardY + boardH / 2.0 - 18, 34, 34));
// Output Capacitor (Right)
g2d.setColor(Color.LIGHT_GRAY);
g2d.fill(new Ellipse2D.Double(boardX + boardW - 58, boardY + boardH / 2.0 - 18, 36, 36));
g2d.fill(new Ellipse2D.Double(boardX + boardW - 72, boardY + boardH / 2.0 - 18, 34, 34));
g2d.setColor(Color.DARK_GRAY);
g2d.draw(new Ellipse2D.Double(boardX + boardW - 58, boardY + boardH / 2.0 - 18, 36, 36));
g2d.draw(new Ellipse2D.Double(boardX + boardW - 72, boardY + boardH / 2.0 - 18, 34, 34));
// LM2596 IC (Center Left) with tab
g2d.setColor(IC_TAB_BODY);
g2d.fill(new RoundRectangle2D.Double(boardX + 70, boardY + 15, 38, 48, 3, 3));
g2d.fill(new RoundRectangle2D.Double(boardX + 80, boardY + 16, 38, 48, 3, 3));
g2d.setColor(IC_TAB_METAL);
g2d.fill(new RoundRectangle2D.Double(boardX + 70, boardY + 12, 38, 10, 2, 2));
g2d.fill(new RoundRectangle2D.Double(boardX + 80, boardY + 12, 38, 10, 2, 2));
g2d.setColor(Color.WHITE);
g2d.setFont(SILK_FONT_SMALL);
StringUtils.drawCenteredText(g2d, "LM2596", boardX + 89, boardY + 38, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "LM2596", boardX + 99, boardY + 38, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
// Toroidal Power Inductor (Center Right)
g2d.setColor(INDUCTOR_CORE);
g2d.fill(new Ellipse2D.Double(boardX + 120, boardY + boardH / 2.0 - 24, 48, 48));
g2d.fill(new Ellipse2D.Double(boardX + 130, boardY + boardH / 2.0 - 24, 48, 48));
g2d.setColor(COPPER_COIL);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
g2d.draw(new Ellipse2D.Double(boardX + 124, boardY + boardH / 2.0 - 20, 40, 40));
g2d.draw(new Ellipse2D.Double(boardX + 134, boardY + boardH / 2.0 - 20, 40, 40));
// Blue 3296W Trimmer Potentiometer (Top Center)
g2d.setColor(POT_BLUE);
g2d.fill(new RoundRectangle2D.Double(boardX + 185, boardY + 15, 45, 26, 3, 3));
g2d.fill(new RoundRectangle2D.Double(boardX + 190, boardY + 16, 45, 26, 3, 3));
// Brass screw head
g2d.setColor(POT_SCREW_BRASS);
g2d.fill(new Ellipse2D.Double(boardX + 190, boardY + 22, 12, 12));
g2d.fill(new Ellipse2D.Double(boardX + 195, boardY + 23, 12, 12));
g2d.setColor(Color.BLACK);
g2d.drawLine((int)(boardX + 192), (int)(boardY + 28), (int)(boardX + 200), (int)(boardY + 28));
g2d.drawLine((int)(boardX + 197), (int)(boardY + 29), (int)(boardX + 205), (int)(boardY + 29));
// Silk Screen Text
g2d.setColor(Color.WHITE);
g2d.setFont(SILK_FONT_SMALL);
StringUtils.drawCenteredText(g2d, "IN+", boardX + 14, boardY + 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "IN-", boardX + 14, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT+", boardX + boardW - 14, boardY + 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT-", boardX + boardW - 14, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "IN+", boardX + 38, y - 8, HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "IN-", boardX + 38, y + termSpacing + 8, HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT+", boardX + boardW - 38, y - 8, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT-", boardX + boardW - 38, y + termSpacing + 8, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
}
g2d.setTransform(oldTx);
// Draw connection pads
drawScrewTerminals(g2d, 0, controlPoints.length, 0, outlineMode, drawingObserver);
// Draw Input and Output terminal blocks matching PCBTerminalBlock style
drawTerminalBlock(g2d, 0, 2, false, -1, 35.0, outlineMode, drawingObserver);
drawTerminalBlock(g2d, 2, 2, false, 1, 35.0, outlineMode, drawingObserver);
g2d.setComposite(oldComposite);
}
@@ -78,25 +78,33 @@ public class MOSFETSwitchModule extends AbstractMakerBoard {
return Integer.toString(index + 1);
}
private static final Size TERMINAL_PITCH = new Size(5.08d, SizeUnit.mm);
private static final double PAD_MARGIN_X = 15.0;
@Override
protected void updateControlPoints() {
Point2D firstPoint = controlPoints[0];
double spacing = PIN_SPACING.convertToPixels();
double termSpacing = TERMINAL_PITCH.convertToPixels();
double w = BOARD_WIDTH.convertToPixels();
double h = BOARD_HEIGHT.convertToPixels();
// 7 pins total:
// Pin 0..2: Control header (SIG, VCC, GND on left)
// Pin 3, 4: VIN, GND (Power in screw terminal, top right)
// Pin 5, 6: V+, V- (Load out screw terminal, bottom right)
// Pin 0..2: Control header (SIG, VCC, GND on left, 2.54mm pitch)
// Pin 3, 4: VIN, GND (Power in screw terminal, top right, 5.08mm pitch)
// Pin 5, 6: V+, V- (Load out screw terminal, bottom right, 5.08mm pitch)
double rightX = w - PAD_MARGIN_X - 18.0;
double topTermY = 18.0;
double btmTermY = h - 18.0 - termSpacing;
double[][] relativeOffsets = new double[][] {
{ 0, 0 },
{ 0, spacing },
{ 0, spacing * 2 },
{ w - 30, -spacing * 1.5 },
{ w - 30, -spacing * 0.5 },
{ w - 30, spacing * 1.5 },
{ w - 30, spacing * 2.5 }
{ 0, 0 }, // Pin 0: SIG
{ 0, spacing }, // Pin 1: VCC
{ 0, spacing * 2 }, // Pin 2: GND
{ rightX, topTermY - (h - 2 * spacing) / 2.0 }, // Pin 3: VIN
{ rightX, topTermY + termSpacing - (h - 2 * spacing) / 2.0 }, // Pin 4: GND (Power)
{ rightX, btmTermY - (h - 2 * spacing) / 2.0 }, // Pin 5: V+
{ rightX, btmTermY + termSpacing - (h - 2 * spacing) / 2.0 } // Pin 6: V-
};
rotatePoints(firstPoint, relativeOffsets);
@@ -109,7 +117,7 @@ public class MOSFETSwitchModule extends AbstractMakerBoard {
double y = p0.getY();
double boardW = BOARD_WIDTH.convertToPixels();
double boardH = BOARD_HEIGHT.convertToPixels();
double boardX = x - 15;
double boardX = x - PAD_MARGIN_X;
double boardY = y - (boardH - 2 * PIN_SPACING.convertToPixels()) / 2.0;
return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6);
}
@@ -132,7 +140,7 @@ public class MOSFETSwitchModule extends AbstractMakerBoard {
double boardW = BOARD_WIDTH.convertToPixels();
double boardH = BOARD_HEIGHT.convertToPixels();
double boardX = x - 15;
double boardX = x - PAD_MARGIN_X;
double boardY = y - (boardH - 2 * PIN_SPACING.convertToPixels()) / 2.0;
Shape boardShape = getBodyShape();
@@ -165,17 +173,6 @@ public class MOSFETSwitchModule extends AbstractMakerBoard {
g2d.setFont(SILK_FONT_SMALL);
StringUtils.drawCenteredText(g2d, "IRF520", mosX + 18, mosY + 24, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
// Dual Screw Terminal Blocks (Right side)
double stX = boardX + boardW - 48;
RoundRectangle2D stb1 = new RoundRectangle2D.Double(stX, boardY + 8, 42, 35, 3, 3);
RoundRectangle2D stb2 = new RoundRectangle2D.Double(stX, boardY + boardH - 43, 42, 35, 3, 3);
g2d.setColor(SCREW_TERMINAL_COLOR);
g2d.fill(stb1);
g2d.fill(stb2);
g2d.setColor(SCREW_TERMINAL_BORDER);
g2d.draw(stb1);
g2d.draw(stb2);
// Gate Trigger Status LED (Red)
g2d.setColor(Color.RED);
g2d.fill(new RoundRectangle2D.Double(boardX + 32, boardY + boardH / 2.0 - 5, 10, 10, 2, 2));
@@ -188,15 +185,19 @@ public class MOSFETSwitchModule extends AbstractMakerBoard {
for (int i = 0; i < 3; i++) {
StringUtils.drawCenteredText(g2d, labels[i], x + 16, y + i * spacing, HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
}
StringUtils.drawCenteredText(g2d, "VIN", stX - 10, boardY + 24, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT", stX - 10, boardY + boardH - 26, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
double termX = boardX + boardW - 42;
StringUtils.drawCenteredText(g2d, "VIN", termX - 6, boardY + 36, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT", termX - 6, boardY + boardH - 36, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
}
g2d.setTransform(oldTx);
// Draw control header pins and terminal contacts
// Draw control header pins on left
drawPins(g2d, 0, 3, false, outlineMode, drawingObserver);
drawScrewTerminals(g2d, 3, 4, 0, outlineMode, drawingObserver);
// Draw dual terminal blocks on right matching PCBTerminalBlock style
drawTerminalBlock(g2d, 3, 2, false, 1, 38.0, outlineMode, drawingObserver);
drawTerminalBlock(g2d, 5, 2, false, 1, 38.0, outlineMode, drawingObserver);
g2d.setComposite(oldComposite);
}
@@ -268,11 +268,6 @@ public class PCA9685ServoDriver extends AbstractMakerBoard {
double termH = 34.0;
double termX = centerX - termW / 2.0;
double termY = boardY + 8.0;
RoundRectangle2D termBody = new RoundRectangle2D.Double(termX, termY, termW, termH, 4, 4);
g2d.setColor(SCREW_TERMINAL_COLOR);
g2d.fill(termBody);
g2d.setColor(SCREW_TERMINAL_BORDER);
g2d.draw(termBody);
// Terminal Silk labels (V+ on left, GND on right of the terminal block)
g2d.setColor(Color.WHITE);
@@ -398,8 +393,8 @@ public class PCA9685ServoDriver extends AbstractMakerBoard {
drawPins(g2d, 0, 6, false, outlineMode, drawingObserver);
drawPins(g2d, 6, 6, false, outlineMode, drawingObserver);
// Draw screw terminal contacts (V+, GND)
drawScrewTerminals(g2d, 12, 2, 0, outlineMode, drawingObserver);
// Draw screw terminal block matching PCBTerminalBlock style (V+, GND)
drawTerminalBlock(g2d, 12, 2, true, -1, 34.0, outlineMode, drawingObserver);
// Draw all 48 servo channel pins
drawPins(g2d, 14, 48, false, outlineMode, drawingObserver);
@@ -218,13 +218,6 @@ public class RelayModule extends AbstractMakerBoard {
double ry = boardY + 20 + ch * relayH;
double rx = boardX + 55;
// Terminal block
RoundRectangle2D tb = new RoundRectangle2D.Double(boardX + 5, ry + 2, 45, relayH - 4, 3, 3);
g2d.setColor(SCREW_TERMINAL_COLOR);
g2d.fill(tb);
g2d.setColor(SCREW_TERMINAL_BORDER);
g2d.draw(tb);
// Blue Relay cube
g2d.setColor(RELAY_CUBE_BLUE);
g2d.fill(new RoundRectangle2D.Double(rx, ry + 2, relayW, relayH - 4, 4, 4));
@@ -244,9 +237,13 @@ public class RelayModule extends AbstractMakerBoard {
g2d.setTransform(oldTx);
// Draw terminals and control pins
// Draw terminal blocks matching PCBTerminalBlock style for each channel
int chCount = channels.getCount();
drawScrewTerminals(g2d, 0, chCount * 3, 40, outlineMode, drawingObserver);
for (int ch = 0; ch < chCount; ch++) {
drawTerminalBlock(g2d, ch * 3, 3, false, -1, 40.0, outlineMode, drawingObserver);
}
// Draw control pins on right
drawPins(g2d, chCount * 3, 2 + chCount, false, outlineMode, drawingObserver);
g2d.setComposite(oldComposite);
@@ -164,10 +164,6 @@ public class RotaryEncoderKY040 extends AbstractMakerBoard {
g2d.setColor(METAL_SHAFT);
g2d.fillRect((int)(cx + 4), (int)(cy - 14), 10, 28);
// SMD Pull-up Resistors (10k)
drawChip(g2d, boardX + 145, boardY + 25, 12, 18, "");
drawChip(g2d, boardX + 145, boardY + boardH - 43, 12, 18, "");
// Silk Screen Pin Labels
g2d.setColor(Color.WHITE);
g2d.setFont(SILK_FONT_SMALL);
@@ -77,6 +77,9 @@ public class TP4056Charger extends AbstractMakerBoard {
return Integer.toString(index + 1);
}
private static final double PAD_MARGIN_X = 14.0;
private static final double PAD_MARGIN_Y = 14.0;
@Override
protected void updateControlPoints() {
Point2D firstPoint = controlPoints[0];
@@ -85,15 +88,19 @@ public class TP4056Charger extends AbstractMakerBoard {
double w = BOARD_WIDTH.convertToPixels();
// 6 Solder pads:
// Input (Left): 0 = IN+, 1 = IN-
// Output (Right): 2 = OUT+, 3 = B+, 4 = B-, 5 = OUT-
// Input (Left): 0 = IN+ (Top-Left), 1 = IN- (Bottom-Left)
// Output (Right): 2 = OUT+ (Top-Right), 3 = B+, 4 = B-, 5 = OUT- (Bottom-Right)
double rightX = w - 2 * PAD_MARGIN_X;
double padSpanY = h - 2 * PAD_MARGIN_Y;
double rightSpacing = Math.min(spacing, padSpanY / 3.0);
double[][] relativeOffsets = new double[][] {
{ 0, 0 }, // Pin 0: IN+ (Top-Left)
{ 0, h - 20 }, // Pin 1: IN- (Bottom-Left)
{ w - 20, 0 }, // Pin 2: OUT+ (Top-Right)
{ w - 20, spacing }, // Pin 3: B+
{ w - 20, h - 20 - spacing }, // Pin 4: B-
{ w - 20, h - 20 } // Pin 5: OUT- (Bottom-Right)
{ 0, 0 }, // Pin 0: IN+ (Top-Left)
{ 0, padSpanY }, // Pin 1: IN- (Bottom-Left)
{ rightX, 0 }, // Pin 2: OUT+ (Top-Right)
{ rightX, rightSpacing }, // Pin 3: B+
{ rightX, padSpanY - rightSpacing }, // Pin 4: B-
{ rightX, padSpanY } // Pin 5: OUT- (Bottom-Right)
};
rotatePoints(firstPoint, relativeOffsets);
@@ -106,7 +113,9 @@ public class TP4056Charger extends AbstractMakerBoard {
double y = p0.getY();
double boardW = BOARD_WIDTH.convertToPixels();
double boardH = BOARD_HEIGHT.convertToPixels();
return new RoundRectangle2D.Double(x - 10, y - 10, boardW, boardH, 6, 6);
double boardX = x - PAD_MARGIN_X;
double boardY = y - PAD_MARGIN_Y;
return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6);
}
@Override
@@ -127,8 +136,8 @@ public class TP4056Charger extends AbstractMakerBoard {
double boardW = BOARD_WIDTH.convertToPixels();
double boardH = BOARD_HEIGHT.convertToPixels();
double boardX = x - 10;
double boardY = y - 10;
double boardX = x - PAD_MARGIN_X;
double boardY = y - PAD_MARGIN_Y;
Shape boardShape = getBodyShape();
@@ -156,25 +165,29 @@ public class TP4056Charger extends AbstractMakerBoard {
// Dual Status LEDs (Red = CHRG, Blue = STDBY)
g2d.setColor(Color.RED);
g2d.fill(new RoundRectangle2D.Double(boardX + 45, boardY + 16, 8, 12, 2, 2));
g2d.fill(new RoundRectangle2D.Double(boardX + 42, boardY + 18, 8, 12, 2, 2));
g2d.setColor(Color.CYAN);
g2d.fill(new RoundRectangle2D.Double(boardX + 45, boardY + boardH - 28, 8, 12, 2, 2));
g2d.fill(new RoundRectangle2D.Double(boardX + 42, boardY + boardH - 30, 8, 12, 2, 2));
// Silk Screen Labels
// Silk Screen Labels (cleanly positioned beside pads)
g2d.setColor(Color.WHITE);
g2d.setFont(SILK_FONT_SMALL);
StringUtils.drawCenteredText(g2d, "IN+", boardX + 18, boardY + 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "IN-", boardX + 18, boardY + boardH - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT+", boardX + boardW - 22, boardY + 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "B+", boardX + boardW - 22, boardY + 32, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "B-", boardX + boardW - 22, boardY + boardH - 32, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT-", boardX + boardW - 22, boardY + boardH - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "IN+", x + 16, y, HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "IN-", x + 16, y + boardH - 2 * PAD_MARGIN_Y, HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
double rightX = x + boardW - 2 * PAD_MARGIN_X;
double padSpanY = boardH - 2 * PAD_MARGIN_Y;
double rightSpacing = Math.min(PIN_SPACING.convertToPixels(), padSpanY / 3.0);
StringUtils.drawCenteredText(g2d, "OUT+", rightX - 16, y, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "B+", rightX - 16, y + rightSpacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "B-", rightX - 16, y + padSpanY - rightSpacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
StringUtils.drawCenteredText(g2d, "OUT-", rightX - 16, y + padSpanY, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
}
g2d.setTransform(oldTx);
// Draw solder pads
drawScrewTerminals(g2d, 0, controlPoints.length, 0, outlineMode, drawingObserver);
// Draw tinned solder pads
drawSolderPads(g2d, 0, controlPoints.length, outlineMode, drawingObserver);
g2d.setComposite(oldComposite);
}