diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..c5f3f6b9
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.configuration.updateBuildConfiguration": "interactive"
+}
\ No newline at end of file
diff --git a/diylc/.run/DIYLCStarter.run.xml b/diylc/.run/DIYLCStarter.run.xml
new file mode 100644
index 00000000..b9dca84e
--- /dev/null
+++ b/diylc/.run/DIYLCStarter.run.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/diylc/diylc-core/config.properties b/diylc/diylc-core/config.properties
deleted file mode 100644
index c6abd215..00000000
--- a/diylc/diylc-core/config.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-#org.diylc.utils.Constants.CANVAS_COLOR=#005D96
-#org.diylc.utils.Constants.GRID_COLOR=#FFFFFF
\ No newline at end of file
diff --git a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java
index 69458fa4..983eb7d0 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractCurvedComponent.java
@@ -76,7 +76,7 @@ public abstract class AbstractCurvedComponent extends AbstractTransparentComp
* @param curve
* @param g2d
* @param componentState
- * @param theme
+ * @param drawingObserver
*/
protected abstract void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
IDrawingObserver drawingObserver);
diff --git a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java
index 78a9615d..52b18e84 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/components/AbstractTransparentComponent.java
@@ -29,10 +29,13 @@ public abstract class AbstractTransparentComponent extends AbstractComponent<
public static byte MAX_ALPHA = 127;
- protected byte alpha = MAX_ALPHA;
+ protected Byte alpha = MAX_ALPHA;
@EditableProperty
public Byte getAlpha() {
+ if (alpha == null) {
+ alpha = MAX_ALPHA;
+ }
return alpha;
}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/BoardUndersideDisplay.java b/diylc/diylc-core/src/main/java/org/diylc/core/BoardUndersideDisplay.java
new file mode 100644
index 00000000..1c402bb0
--- /dev/null
+++ b/diylc/diylc-core/src/main/java/org/diylc/core/BoardUndersideDisplay.java
@@ -0,0 +1,10 @@
+package org.diylc.core;
+
+public enum BoardUndersideDisplay {
+ NONE, ABOVE, BELOW, LEFT, RIGHT;
+
+ @Override
+ public String toString() {
+ return super.toString().charAt(0) + super.toString().substring(1).toLowerCase();
+ }
+}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/IBoard.java b/diylc/diylc-core/src/main/java/org/diylc/core/IBoard.java
new file mode 100644
index 00000000..302547d3
--- /dev/null
+++ b/diylc/diylc-core/src/main/java/org/diylc/core/IBoard.java
@@ -0,0 +1,16 @@
+package org.diylc.core;
+
+import org.diylc.core.measures.Size;
+
+import java.awt.geom.Rectangle2D;
+
+public interface IBoard {
+
+ Rectangle2D getBoardRectangle();
+
+ BoardUndersideDisplay getBoardUndersideDisplay();
+
+ Size getUndersideOffset();
+
+ boolean shouldExportToGerber();
+}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/gerber/GerberExporter.java b/diylc/diylc-core/src/main/java/org/diylc/core/gerber/GerberExporter.java
index 066254c7..e041e9e2 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/core/gerber/GerberExporter.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/core/gerber/GerberExporter.java
@@ -17,6 +17,7 @@ import org.apache.log4j.Logger;
import com.bancika.gerberwriter.DataLayer;
import org.diylc.core.ComponentState;
+import org.diylc.core.IBoard;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IView;
import org.diylc.core.Project;
@@ -30,44 +31,47 @@ public class GerberExporter {
private static final Logger LOG = Logger.getLogger(GerberExporter.class);
public static void exportGerber(String fileNameBase, Project currentProject, IView view,
- Graphics2D graphics2d, String diylcVersion) {
- List gerberBoards =
- currentProject.getComponents().stream().filter(c -> c instanceof IGerberBoard)
- .map(x -> (IGerberBoard) x).collect(Collectors.toList());
+ Graphics2D graphics2d, String diylcVersion) {
- Map>> boardComponentMap =
- new HashMap>>();
+ List gerberBoards =
+ currentProject.getComponents().stream()
+ .filter(IBoard.class::isInstance)
+ .map(IBoard.class::cast)
+ .filter(IBoard::shouldExportToGerber).collect(Collectors.toList());
+
+ Map>> boardComponentMap =
+ new HashMap>>();
// DefaultGerberBoard defaultGerberBoard = new DefaultGerberBoard();
List> componentsWithoutBoard = new ArrayList>();
currentProject.getComponents().stream().filter(c -> c instanceof IGerberComponent)
- .forEach(c -> {
- Point2D firstPoint = c.getControlPoint(0);
- IGerberBoard board = gerberBoards.stream()
- .filter(b -> b.getBoardRectangle().contains(firstPoint)).findFirst().orElse(null);
- if (board == null) {
- componentsWithoutBoard.add(c);
- } else {
- boardComponentMap.computeIfAbsent(board, k -> new ArrayList>()).add(c);
- }
- });
+ .forEach(c -> {
+ Point2D firstPoint = c.getControlPoint(0);
+ IBoard board = gerberBoards.stream()
+ .filter(b -> b.getBoardRectangle().contains(firstPoint)).findFirst().orElse(null);
+ if (board == null) {
+ componentsWithoutBoard.add(c);
+ } else {
+ boardComponentMap.computeIfAbsent(board, k -> new ArrayList>()).add(c);
+ }
+ });
// defaultGerberBoard.setComponents(boardComponentMap.get(defaultGerberBoard));
if (boardComponentMap.isEmpty()) {
view.showMessage(LangUtil.translate("Nothing to export."),
- LangUtil.translate("Gerber Export"), IView.WARNING_MESSAGE);
+ LangUtil.translate("Gerber Export"), IView.WARNING_MESSAGE);
return;
}
if (componentsWithoutBoard.size() > 0) {
if (view.showConfirmDialog(String.format(
- LangUtil.translate("There are some components that are outside of the bounds of boards.%s"
- + "They will be ignored unless you add a board component underneath them.%sDo you want to continue?"),
- "\n", "\n"), LangUtil.translate("Gerber Export"), IView.YES_NO_OPTION,
- IView.WARNING_MESSAGE) != IView.YES_OPTION) {
+ LangUtil.translate("There are some components that are outside of the bounds of boards.%s"
+ + "They will be ignored unless you add a board component underneath them.%sDo you want to continue?"),
+ "\n", "\n"), LangUtil.translate("Gerber Export"), IView.YES_NO_OPTION,
+ IView.WARNING_MESSAGE) != IView.YES_OPTION) {
return;
}
}
@@ -88,15 +92,15 @@ public class GerberExporter {
String fileNameOutline = GerberLayer.Outline.formatFileName(fileNameBase, boardComponent.getName());
try {
LOG.info(String.format(LangUtil.translate("Exporting outline for board %s to file %s"),
- boardComponent.getName(), fileNameOutline));
+ boardComponent.getName(), fileNameOutline));
outlineLayer.dumpGerberToFile(fileNameOutline);
generatedFiles.add(fileNameOutline);
} catch (IOException e) {
LOG.error("Error writing gerber file: " + e.getMessage());
view.showMessage(
- LangUtil.translate(
- "Failed to export the project to gerber. Please check the log for details"),
- LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
+ LangUtil.translate(
+ "Failed to export the project to gerber. Please check the log for details"),
+ LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
return;
}
@@ -119,30 +123,30 @@ public class GerberExporter {
try {
String fileName = layer.formatFileName(fileNameBase, boardComponent.getName());
LOG.info("Exporting layer: " + layer + " for board " + boardComponent.getName()
- + " to file: " + fileName);
+ + " to file: " + fileName);
dataLayer.dumpGerberToFile(fileName);
generatedFiles.add(fileName);
} catch (IOException e) {
LOG.error("Error writing gerber file: " + e.getMessage());
view.showMessage(
- LangUtil.translate(
- "Failed to export the project to gerber. Please check the log for details"),
- LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
+ LangUtil.translate(
+ "Failed to export the project to gerber. Please check the log for details"),
+ LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
return;
}
});
});
view.showMessage(
- String.format(
- LangUtil.translate(
- "Gerber export completed successfully. The following files were created:%s"),
- "\n\n" + String.join("\n", generatedFiles)),
- LangUtil.translate("Gerber Export"), IView.INFORMATION_MESSAGE);
+ String.format(
+ LangUtil.translate(
+ "Gerber export completed successfully. The following files were created:%s"),
+ "\n\n" + String.join("\n", generatedFiles)),
+ LangUtil.translate("Gerber Export"), IView.INFORMATION_MESSAGE);
LOG.info("Completed export to gerber");
}
-
+
private static void drawComponent(Project currentProject, GerberG2DWrapper g2d,
- IDIYComponent> c, boolean outlineMode) {
+ IDIYComponent> c, boolean outlineMode) {
IGerberComponent gerberComponent = (IGerberComponent) c;
g2d.startedDrawingComponent();
if (gerberComponent instanceof IGerberComponentCustom) {
@@ -151,9 +155,9 @@ public class GerberExporter {
} else if (gerberComponent instanceof IGerberComponentSimple) {
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
g2d.startGerberOutput(gerberComponentSimple.getGerberLayer(),
- gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
+ gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
g2d.stopGerberOutput();
}
}
-}
+}
\ No newline at end of file
diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/gerber/IGerberBoard.java b/diylc/diylc-core/src/main/java/org/diylc/core/gerber/IGerberBoard.java
deleted file mode 100644
index 76474d71..00000000
--- a/diylc/diylc-core/src/main/java/org/diylc/core/gerber/IGerberBoard.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.diylc.core.gerber;
-
-import java.awt.geom.Rectangle2D;
-
-public interface IGerberBoard {
-
- Rectangle2D getBoardRectangle();
-}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/lang/LangUtil.java b/diylc/diylc-core/src/main/java/org/diylc/lang/LangUtil.java
index 55b3824e..6312f093 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/lang/LangUtil.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/lang/LangUtil.java
@@ -125,25 +125,28 @@ public class LangUtil {
public static List getAvailableLanguages() {
List res = new ArrayList();
- List files = ResourceUtils.getResourceFiles(LANG_DIR);
+ Map langContents = ResourceUtils.getResourceContents(LANG_DIR);
try {
- for (File file : files) {
- String key = file.getName().replaceFirst("[.][^.]+$", "");
- Map details = new HashMap();
- try (Stream stream = Files.lines(
- Paths.get(file.getAbsolutePath()), StandardCharsets.UTF_8)) {
- stream.forEach(s -> {
- if (s.contains("=")) {
- String[] parts = s.split("=");
- if (parts.length == 2)
- details.put(parts[0].toLowerCase().trim(), parts[1].trim());
+ langContents.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(entry -> {
+ String key = entry.getKey().replaceFirst("[.][^.]+$", "");
+ Map details = new HashMap();
+ try {
+ String content = entry.getValue();
+ String[] lines = content.split("\n");
+ for (String line : lines) {
+ if (line.contains("=")) {
+ String[] parts = line.split("=");
+ if (parts.length == 2)
+ details.put(parts[0].toLowerCase().trim(), parts[1].trim());
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Error loading language file", e);
}
+ res.add(new Language(key, details));
});
- } catch (IOException e) {
- LOG.error("Error loading language file", e);
- }
- res.add(new Language(key, details));
- }
Collections.sort(res);
return res;
} catch (Exception e) {
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/BuildingBlockManager.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/BuildingBlockManager.java
index 45484187..1685f568 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/BuildingBlockManager.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/BuildingBlockManager.java
@@ -18,7 +18,6 @@
package org.diylc.presenter;
import java.io.*;
-import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -42,7 +41,7 @@ import org.diylc.serialization.ProjectFileManager;
public class BuildingBlockManager {
- private static final String BLOCKS_FILE_NAME = "blocks.xml";
+ private static final String BLOCKS_FILE_NAME = "import-defaults/blocks.xml";
private static final Logger LOG = Logger.getLogger(VariantManager.class);
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/ComponentProcessor.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/ComponentProcessor.java
index 7503354c..4a7c1409 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/ComponentProcessor.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/ComponentProcessor.java
@@ -26,12 +26,8 @@ import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.lang.reflect.Modifier;
+import java.util.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.apache.log4j.Logger;
@@ -52,6 +48,11 @@ import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
import org.diylc.lang.LangUtil;
+import org.reflections.Reflections;
+import org.reflections.util.ConfigurationBuilder;
+import org.reflections.util.FilterBuilder;
+
+import static org.reflections.scanners.Scanners.TypesAnnotated;
/**
* Utility class with component processing methods.
@@ -68,6 +69,7 @@ public class ComponentProcessor {
private Map propertyValidatorCache;
private Map componentTypeMap;
private Map componentTransformerMap;
+ private Map> componentTypes;
public static ComponentProcessor getInstance() {
if (instance == null) {
@@ -138,6 +140,10 @@ public class ComponentProcessor {
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
// g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
// RenderingHints.VALUE_STROKE_PURE);
componentInstance.drawIcon(g2d, Presenter.ICON_SIZE, Presenter.ICON_SIZE);
@@ -225,6 +231,50 @@ public class ComponentProcessor {
return result;
}
+ public Map> getComponentTypes() {
+ if (componentTypes == null) {
+ LOG.info("Loading component types.");
+ componentTypes = new HashMap>();
+ Reflections reflections = new Reflections(
+ new ConfigurationBuilder()
+ .forPackage("org.diylc")
+ .filterInputsBy(new FilterBuilder().includePackage("org.diylc.components"))
+ .setScanners(TypesAnnotated));
+ Set> componentTypeClasses = null;
+ try {
+ componentTypeClasses = reflections.getTypesAnnotatedWith(ComponentDescriptor.class, false);
+
+ for (Class> clazz : componentTypeClasses) {
+ if (!Modifier.isAbstract(clazz.getModifiers()) && IDIYComponent.class.isAssignableFrom(clazz)) {
+ ComponentType componentType =
+ ComponentProcessor.getInstance().extractComponentTypeFrom((Class extends IDIYComponent>>) clazz);
+ if (componentType == null)
+ continue;
+
+ // just to store in the cache
+ ComponentProcessor.getInstance().extractProperties(clazz);
+
+ List nestedList;
+ if (componentTypes.containsKey(componentType.getCategory())) {
+ nestedList = componentTypes.get(componentType.getCategory());
+ } else {
+ nestedList = new ArrayList();
+ componentTypes.put(componentType.getCategory(), nestedList);
+ }
+ nestedList.add(componentType);
+ }
+ }
+
+ for (Map.Entry> e : componentTypes.entrySet()) {
+ LOG.debug(e.getKey() + ": " + e.getValue());
+ }
+ } catch (Exception e) {
+ LOG.error("Error loading component types", e);
+ }
+ }
+ return componentTypes;
+ }
+
/**
* Returns properties that have the same value for all the selected components.
*
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/DatasheetService.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/DatasheetService.java
index abff8506..7dc1812e 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/DatasheetService.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/DatasheetService.java
@@ -17,10 +17,7 @@
*/
package org.diylc.presenter;
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.*;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
@@ -55,16 +52,15 @@ public class DatasheetService {
private DatasheetService() {}
public List loadDatasheet(Class> clazz) {
- ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return datasheetCache.computeIfAbsent(clazz.getCanonicalName(), key -> {
String fileName = clazz.getSimpleName() + ".datasheet";
LOG.info("Loading datasheet file for " + fileName);
- URL resource = classloader.getResource(fileName);
- if (resource == null) {
+ InputStream inputStream = clazz.getResourceAsStream("/datasheets/" + fileName);
+ if (inputStream == null) {
LOG.warn("Datasheet file not found: " + fileName);
return null;
}
- try (BufferedInputStream in = new BufferedInputStream(resource.openStream())) {
+ try (BufferedInputStream in = new BufferedInputStream(inputStream)) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
List types =
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java
index f2920b1d..c272692e 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingManager.java
@@ -49,20 +49,9 @@ import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.appframework.simplemq.MessageDispatcher;
-import org.diylc.common.DrawOption;
-import org.diylc.common.EventType;
-import org.diylc.common.GridType;
-import org.diylc.common.IComponentFilter;
-import org.diylc.common.IPlugInPort;
-import org.diylc.common.ObjectCache;
-import org.diylc.core.ComponentForRender;
-import org.diylc.core.ComponentState;
-import org.diylc.core.IContinuity;
-import org.diylc.core.IDIYComponent;
-import org.diylc.core.ILayeredComponent;
-import org.diylc.core.Project;
-import org.diylc.core.Theme;
-import org.diylc.core.VisibilityPolicy;
+import org.diylc.common.*;
+import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.core.*;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.netlist.ContinuityGraph;
@@ -78,6 +67,7 @@ import org.diylc.utils.Constants;
public class DrawingManager {
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
+ public static final byte MIRROR_ALPHA = 64;
public static int CONTROL_POINT_SIZE = 7;
public static double EXTRA_SPACE = 0.25;
@@ -195,38 +185,35 @@ public class DrawingManager {
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
- if (drawOptions.contains(DrawOption.ANTIALIASING)) {
- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- } else {
- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
- g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ configureRenderingHints(g2d, drawOptions);
+
+ // group components with boards that contain them
+ Map>> boardMap = project.getComponents().stream()
+ .filter(IBoard.class::isInstance)
+ .map(IBoard.class::cast)
+ .filter(b -> b.getBoardUndersideDisplay() != BoardUndersideDisplay.NONE)
+ .collect(Collectors.toMap(x -> x, x -> new ArrayList>()));
+ Map, Set> componentBoardMap = new HashMap, Set>();
+
+ for (IBoard board : boardMap.keySet()) {
+ Rectangle2D boardRect = board.getBoardRectangle();
+ for (IDIYComponent> c : project.getComponents()) {
+ if (c == board) {
+ continue;
+ }
+ boolean include = true;
+ for (int i = 0; i < c.getControlPointCount(); i++) {
+ if (!boardRect.contains(c.getControlPoint(i))) {
+ include = false;
+ break;
+ }
+ }
+ if (include) {
+ boardMap.get(board).add(c);
+ componentBoardMap.computeIfAbsent(c, key -> new HashSet()).add(board);
+ }
+ }
}
- if (configManager.readBoolean(IPlugInPort.HI_QUALITY_RENDER_KEY, false)) {
- g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
- RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
- g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
- RenderingHints.VALUE_COLOR_RENDER_QUALITY);
- g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
- g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
- g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
- // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
- // RenderingHints.VALUE_STROKE_PURE);
- } else {
- g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
- RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
- g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
- RenderingHints.VALUE_COLOR_RENDER_SPEED);
- g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
- g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
- g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
- }
- g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
- RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
// AffineTransform initialTx = g2d.getTransform();
Dimension canvasDimension =
@@ -297,7 +284,7 @@ public class DrawingManager {
// drawn in the same state.
boolean trackArea = lastDrawnStateMap.get(component) != state;
- synchronized (g2d) {
+ synchronized (this) {
g2dWrapper.startedDrawingComponent(i);
if (!trackArea) {
g2dWrapper.stopTracking();
@@ -312,11 +299,7 @@ public class DrawingManager {
long componentStart = System.nanoTime();
try {
- if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
- DrawingCache.Instance.draw(component, g2dWrapper, state,
- drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect);
- else // go straight to the wrapper
- component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
+ drawComponent(project, drawOptions, scaleFactor, visibleRect, component, g2dWrapper, state, zoom, i, outlineMode);
if (g2dWrapper.isTrackingContinuityArea()) {
LOG.info("Component " + component.getName() + " of type "
@@ -349,6 +332,29 @@ public class DrawingManager {
componentAreaMap.put(component, area);
lastDrawnStateMap.put(component, state);
}
+
+ // Mirror components that belong to boards that need to be mirrored
+ if (componentBoardMap.containsKey(component)) {
+ @SuppressWarnings("unchecked")
+ ComponentType componentType = ComponentProcessor.getInstance()
+ .extractComponentTypeFrom((Class extends IDIYComponent>>) component.getClass());
+ if (componentType.getTransformer() != null) {
+ Set boards = componentBoardMap.get(component);
+ for (IBoard board : boards) {
+ drawMirroredComponent(project, board, component, componentType, g2dWrapper, state, outlineMode);
+ }
+ }
+ }
+
+ // if a component itself is a board that needs to be mirrored, do it
+ if (IBoard.class.isInstance(component) && componentBoardMap.values().stream()
+ .anyMatch(boards -> boards.contains(component))) {
+ ComponentType componentType = ComponentProcessor.getInstance()
+ .extractComponentTypeFrom((Class extends IDIYComponent>>) component.getClass());
+ if (componentType.getTransformer() != null) {
+ drawMirroredComponent(project, (IBoard) component, component, componentType, g2dWrapper, state, outlineMode);
+ }
+ }
}
}
@@ -510,6 +516,86 @@ public class DrawingManager {
return failedComponents;
}
+ private static void drawMirroredComponent(Project project, IBoard board, IDIYComponent> component,
+ ComponentType componentType, G2DWrapper g2dWrapper, ComponentState state, boolean outlineMode) {
+ double offset = board.getUndersideOffset().convertToPixels();
+ Rectangle2D boardRectangle = board.getBoardRectangle();
+ try {
+ IDIYComponent> clonedComponent = component.clone();
+ int direction = 0;
+ Point2D pivotPoint = new Point2D.Double();
+ switch (board.getBoardUndersideDisplay()) {
+ case ABOVE:
+ direction = IComponentTransformer.VERTICAL;
+ pivotPoint.setLocation(boardRectangle.getMinX(), boardRectangle.getMinY() - offset / 2);
+ break;
+ case BELOW:
+ direction = IComponentTransformer.VERTICAL;
+ pivotPoint.setLocation(boardRectangle.getMinX(), boardRectangle.getMaxY() + offset / 2);
+ break;
+ case LEFT:
+ direction = IComponentTransformer.HORIZONTAL;
+ pivotPoint.setLocation(boardRectangle.getMinX() - offset / 2, boardRectangle.getMinY());
+ break;
+ case RIGHT:
+ direction = IComponentTransformer.HORIZONTAL;
+ pivotPoint.setLocation(boardRectangle.getMaxX() + offset / 2, boardRectangle.getMinY());
+ break;
+ }
+ componentType.getTransformer().mirror(clonedComponent, pivotPoint, direction);
+ if (AbstractTransparentComponent.class.isInstance(clonedComponent)) {
+ AbstractTransparentComponent> transparentComponent = (AbstractTransparentComponent>) clonedComponent;
+ transparentComponent.setAlpha(MIRROR_ALPHA);
+ }
+ clonedComponent.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void drawComponent(Project project, Set drawOptions, Double scaleFactor, Rectangle2D visibleRect, IDIYComponent> component, G2DWrapper g2dWrapper, ComponentState state, double zoom, int i, boolean outlineMode) {
+ if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
+ DrawingCache.Instance.draw(component, g2dWrapper, state,
+ drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect);
+ else // go straight to the wrapper
+ component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
+ }
+
+ private void configureRenderingHints(Graphics2D g2d, Set drawOptions) {
+ if (drawOptions.contains(DrawOption.ANTIALIASING)) {
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ } else {
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ }
+ if (configManager.readBoolean(IPlugInPort.HI_QUALITY_RENDER_KEY, false)) {
+ g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
+ RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
+ RenderingHints.VALUE_COLOR_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
+ // RenderingHints.VALUE_STROKE_PURE);
+ } else {
+ g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
+ RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
+ g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
+ RenderingHints.VALUE_COLOR_RENDER_SPEED);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
+ g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ }
+ g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
+ }
+
private double zoomCached = 0;
private Dimension canvasDimensionCached;
private double extraSpaceCached;
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java
index b6e6587e..a0c13fda 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java
@@ -78,7 +78,6 @@ import org.diylc.core.Project;
import org.diylc.core.Template;
import org.diylc.core.Theme;
import org.diylc.core.VisibilityPolicy;
-import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.IAutoCreator;
import org.diylc.core.gerber.GerberExporter;
import org.diylc.core.measures.Size;
@@ -94,11 +93,6 @@ import org.diylc.test.DIYTest;
import org.diylc.test.Snapshot;
import org.diylc.utils.Constants;
import org.diylc.utils.ReflectionUtils;
-import org.reflections.Reflections;
-import org.reflections.util.ConfigurationBuilder;
-import org.reflections.util.FilterBuilder;
-
-import static org.reflections.scanners.Scanners.TypesAnnotated;
/**
* The main presenter class, contains core app logic and drawing routines.
@@ -135,6 +129,9 @@ public class Presenter implements IPlugInPort, IConfigListener {
private static final Logger LOG = Logger.getLogger(Presenter.class);
+ public static final Double[] ZOOM_LEVELS =
+ {0.25d, 0.3333d, 0.5d, 0.6667d, 0.75d, 1d, 1.25d, 1.5d, 2d, 2.5d, 3d};
+
public static VersionNumber CURRENT_VERSION = null;
private static List RECENT_VERSIONS = null;
@@ -147,7 +144,6 @@ public class Presenter implements IPlugInPort, IConfigListener {
private static final int MAX_RECENT_FILES = 20;
private Project currentProject;
- private Map> componentTypes;
// Maps component class names to ComponentType objects.
private List plugIns;
@@ -242,7 +238,7 @@ public class Presenter implements IPlugInPort, IConfigListener {
@Override
public java.lang.Double[] getAvailableZoomLevels() {
- return new java.lang.Double[] {0.25d, 0.3333d, 0.5d, 0.6667d, 0.75d, 1d, 1.25d, 1.5d, 2d, 2.5d, 3d};
+ return ZOOM_LEVELS;
}
@Override
@@ -424,47 +420,7 @@ public class Presenter implements IPlugInPort, IConfigListener {
@SuppressWarnings("unchecked")
@Override
public Map> getComponentTypes() {
- if (componentTypes == null) {
- LOG.info("Loading component types.");
- componentTypes = new HashMap>();
- Reflections reflections = new Reflections(
- new ConfigurationBuilder()
- .forPackage("org.diylc")
- .filterInputsBy(new FilterBuilder().includePackage("org.diylc.components"))
- .setScanners(TypesAnnotated));
- Set> componentTypeClasses = null;
- try {
- componentTypeClasses = reflections.getTypesAnnotatedWith(ComponentDescriptor.class, false);
-
- for (Class> clazz : componentTypeClasses) {
- if (!Modifier.isAbstract(clazz.getModifiers()) && IDIYComponent.class.isAssignableFrom(clazz)) {
- ComponentType componentType =
- ComponentProcessor.getInstance().extractComponentTypeFrom((Class extends IDIYComponent>>) clazz);
- if (componentType == null)
- continue;
-
- // just to store in the cache
- ComponentProcessor.getInstance().extractProperties(clazz);
-
- List nestedList;
- if (componentTypes.containsKey(componentType.getCategory())) {
- nestedList = componentTypes.get(componentType.getCategory());
- } else {
- nestedList = new ArrayList();
- componentTypes.put(componentType.getCategory(), nestedList);
- }
- nestedList.add(componentType);
- }
- }
-
- for (Map.Entry> e : componentTypes.entrySet()) {
- LOG.debug(e.getKey() + ": " + e.getValue());
- }
- } catch (Exception e) {
- LOG.error("Error loading component types", e);
- }
- }
- return componentTypes;
+ return ComponentProcessor.getInstance().getComponentTypes();
}
@SuppressWarnings({"unchecked"})
@@ -2559,7 +2515,8 @@ public class Presenter implements IPlugInPort, IConfigListener {
}
}
try {
- BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("variants.xml"));
+ BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(
+ "import-defaults/variants.xml"));
XStream xStream = new XStream(new DomDriver());
xStream.addPermission(AnyTypePermission.ANY);
ProjectFileManager.xStreamSerializer.toXML(defaultVariantMap, out);
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/VariantManager.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/VariantManager.java
index 4761b4e4..6e857688 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/VariantManager.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/VariantManager.java
@@ -21,7 +21,6 @@ import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
@@ -46,7 +45,7 @@ import org.diylc.serialization.ProjectFileManager;
public class VariantManager {
- private static final String VARIANTS_FILE_NAME = "variants.xml";
+ private static final String VARIANTS_FILE_NAME = "import-defaults/variants.xml";
private static final Logger LOG = Logger.getLogger(VariantManager.class);
diff --git a/diylc/diylc-core/src/main/java/org/diylc/utils/ResourceUtils.java b/diylc/diylc-core/src/main/java/org/diylc/utils/ResourceUtils.java
index 6a1cbb25..2b3d32f1 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/utils/ResourceUtils.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/utils/ResourceUtils.java
@@ -24,36 +24,78 @@ package org.diylc.utils;
import org.apache.log4j.Logger;
import org.diylc.lang.LangUtil;
-import java.io.File;
import java.io.IOException;
-import java.net.URISyntaxException;
+import java.io.InputStream;
import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
public class ResourceUtils {
- private static final Logger LOG = Logger.getLogger(LangUtil.class);
+ private static final Logger LOG = Logger.getLogger(ResourceUtils.class);
- public static List getResourceFiles(String dir) {
- List files = new ArrayList<>();
- URL url = LangUtil.class.getResource("/" + dir);
- Path path = null;
+ public static Map getResourceContents(String dir) {
+ Map contents = new HashMap<>();
+
try {
- path = Paths.get(url.toURI());
- Files.walk(path, 5).forEach(p -> {
- if (!p.toFile().isDirectory()) {
- files.add(p.toFile());
+ // Get all resources in the directory
+ URL dirUrl = ResourceUtils.class.getClassLoader().getResource(dir);
+ if (dirUrl != null) {
+ if (dirUrl.getProtocol().equals("jar")) {
+ // Running from JAR
+ String jarPath = dirUrl.getPath();
+ // Remove the "file:" prefix and decode the URL
+ jarPath = URLDecoder.decode(jarPath.substring(5, jarPath.indexOf("!")), StandardCharsets.UTF_8);
+ JarFile jarFile = new JarFile(jarPath);
+ try {
+ jarFile.stream()
+ .filter(entry -> entry.getName().startsWith(dir + "/") && !entry.isDirectory())
+ .forEach(entry -> {
+ try {
+ String relativePath = entry.getName().substring(dir.length() + 1);
+ // Read the entire file content as string
+ String content = new String(jarFile.getInputStream(entry).readAllBytes(), StandardCharsets.UTF_8);
+ contents.put(relativePath, content);
+ } catch (IOException e) {
+ LOG.warn("Could not read resource: " + entry.getName(), e);
+ }
+ });
+ } finally {
+ try {
+ jarFile.close();
+ } catch (IOException e) {
+ LOG.warn("Could not close JAR file", e);
+ }
+ }
+ } else {
+ // Running from filesystem
+ java.io.File dirFile = new java.io.File(dirUrl.toURI());
+ if (dirFile.exists() && dirFile.isDirectory()) {
+ java.io.File[] files = dirFile.listFiles();
+ if (files != null) {
+ for (java.io.File file : files) {
+ if (file.isFile()) {
+ try {
+ String relativePath = file.getName();
+ String content = new String(java.nio.file.Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
+ contents.put(relativePath, content);
+ } catch (IOException e) {
+ LOG.warn("Could not read file: " + file, e);
+ }
+ }
+ }
+ }
+ }
}
- });
- } catch (URISyntaxException e) {
- LOG.error("Error loading language file", e);
- } catch (IOException e) {
- LOG.error("Error loading language file", e);
+ }
+ } catch (Exception e) {
+ LOG.error("Error loading resources from directory: " + dir, e);
}
- return files;
+
+ return contents;
}
}
diff --git a/diylc/diylc-core/src/main/resources/blocks.xml b/diylc/diylc-core/src/main/resources/import-defaults/blocks.xml
similarity index 100%
rename from diylc/diylc-core/src/main/resources/blocks.xml
rename to diylc/diylc-core/src/main/resources/import-defaults/blocks.xml
diff --git a/diylc/diylc-core/src/main/resources/variants.xml b/diylc/diylc-core/src/main/resources/import-defaults/variants.xml
similarity index 100%
rename from diylc/diylc-core/src/main/resources/variants.xml
rename to diylc/diylc-core/src/main/resources/import-defaults/variants.xml
diff --git a/diylc/diylc-core/src/main/resources/themes/Gray.xml b/diylc/diylc-core/src/main/resources/themes/Gray.xml
new file mode 100644
index 00000000..1f5966e0
--- /dev/null
+++ b/diylc/diylc-core/src/main/resources/themes/Gray.xml
@@ -0,0 +1,27 @@
+
+ Gray
+
+ 170
+ 170
+ 170
+ 255
+
+
+ 150
+ 150
+ 150
+ 255
+
+
+ 100
+ 100
+ 100
+ 255
+
+
+ 0
+ 0
+ 0
+ 255
+
+
\ No newline at end of file
diff --git a/diylc/diylc-core/src/main/resources/update.xml b/diylc/diylc-core/src/main/resources/update.xml
index 967e8b2a..a4f2bed2 100644
--- a/diylc/diylc-core/src/main/resources/update.xml
+++ b/diylc/diylc-core/src/main/resources/update.xml
@@ -246,9 +246,13 @@
1
0
- 2025-03-09 00:00:00.000 CET
+ 2025-03-24 00:00:00.000 CET
+
+ NEW_FEATURE
+ Added ability to render the underside of boards along with the top side for easier validation, building and debugging
+
NEW_FEATURE
Configurable 'High DPI Rendering' feature which makes the diagram smoother on high-resolution displays but can affect performance
@@ -257,6 +261,10 @@
IMPROVEMENT
Significantly improved rendering performance
+
+ IMPROVEMENT
+ Increased initial memory allocation to 1GB for smoother performance
+
IMPROVEMENT
Upgraded source code structure to modern standards and introduced Maven
@@ -271,7 +279,7 @@
IMPROVEMENT
- Updated the windows installer to avoid false positive virus detection
+ Updated the windows installer (hopefully) to avoid false positive anti-virus detection
BUG_FIX
@@ -281,6 +289,10 @@
BUG_FIX
Rotating selected components sometimes wacks the alignment off the grid
+
+ BUG_FIX
+ Ctrl+X (Command+X) shortcut for Cut action doesn't work because 'Project Explorer' steals the focus on X key press
+
https://github.com/bancika/diy-layout-creator/releases
diff --git a/diylc/diylc-core/src/test/java/org/diylc/presenter/DatasheetServiceTest.java b/diylc/diylc-core/src/test/java/org/diylc/presenter/DatasheetServiceTest.java
index 08fdb8ee..d68a8e64 100644
--- a/diylc/diylc-core/src/test/java/org/diylc/presenter/DatasheetServiceTest.java
+++ b/diylc/diylc-core/src/test/java/org/diylc/presenter/DatasheetServiceTest.java
@@ -1,266 +1,80 @@
package org.diylc.presenter;
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.List;
-
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-@RunWith(MockitoJUnitRunner.class)
+import java.util.List;
+
+import static org.junit.Assert.*;
+
public class DatasheetServiceTest {
-
private DatasheetService service;
-
- @Mock
- private ClassLoader mockClassLoader;
-
+ private static final Class> TEST_CLASS = DatasheetServiceTest.class;
+
@Before
public void setUp() {
service = DatasheetService.getInstance();
- service.clearCache(); // Clear cache before each test
- Thread.currentThread().setContextClassLoader(mockClassLoader);
+ service.clearCache();
}
-
+
@Test
- public void testLoadDatasheet() throws Exception {
- // Create a mock datasheet content
- String datasheetContent =
- "1N4001,50V,1A,1.1V\n" +
- "1N4002,100V,1A,1.1V\n" +
- "1N4003,200V,1A,1.1V";
-
- // Create a mock URL that returns our test content
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
-
- // Setup the mock ClassLoader to return our mock URL
- when(mockClassLoader.getResource("TestComponent.datasheet"))
- .thenReturn(mockUrl);
-
- // Test loading the datasheet
- List result = service.loadDatasheet(TestComponent.class);
-
- // Verify results
- assertNotNull("Datasheet should not be null", result);
- assertEquals("Should have 3 entries", 3, result.size());
-
- // Verify first entry
- String[] firstEntry = result.get(0);
- assertEquals("1N4001", firstEntry[0]);
- assertEquals("50V", firstEntry[1]);
- assertEquals("1A", firstEntry[2]);
- assertEquals("1.1V", firstEntry[3]);
-
- // Verify second entry
- String[] secondEntry = result.get(1);
- assertEquals("1N4002", secondEntry[0]);
- assertEquals("100V", secondEntry[1]);
-
- // Verify third entry
- String[] thirdEntry = result.get(2);
- assertEquals("1N4003", thirdEntry[0]);
- assertEquals("200V", thirdEntry[1]);
+ public void testLoadDatasheet() {
+ List result = service.loadDatasheet(TEST_CLASS);
+ assertNotNull(result);
+ assertEquals(4, result.size());
+ assertArrayEquals(new String[]{"TEST", "KEY", "10.0", "20.0"}, result.get(0));
}
-
+
@Test
public void testLoadDatasheetFileNotFound() {
- // Setup the mock ClassLoader to return null (file not found)
- when(mockClassLoader.getResource("TestComponent.datasheet"))
- .thenReturn(null);
-
- List result = service.loadDatasheet(TestComponent.class);
-
- assertNull("Result should be null when file is not found", result);
+ List result = service.loadDatasheet(String.class);
+ assertNull(result);
}
-
+
@Test
- public void testLookupExactMatch() throws Exception {
- // Create a mock datasheet content
- String datasheetContent =
- "TEST,KEY,10.0\n" +
- "TEST,KEY,20.0\n" +
- "TEST,OTHER,15.0\n" +
- "OTHER,KEY,10.0";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("DatasheetServiceTest.datasheet"))
- .thenReturn(mockUrl);
-
- // Create test data
- String[] result = service.lookup(
- DatasheetServiceTest.class, // Using test class itself as component class
- 0.1, // 0.1% tolerance
- "TEST|KEY", // Key to look up
- 10.0 // Value to match
- );
-
- assertNotNull("Should find matching entry", result);
- assertEquals("TEST", result[0]);
- assertEquals("KEY", result[1]);
+ public void testLookupExactMatch() {
+ String[] result = service.lookup(TEST_CLASS, 0.0, "TEST|KEY", 10.0);
+ assertNotNull(result);
assertEquals("10.0", result[2]);
}
-
+
@Test
- public void testLookupWithinTolerance() throws Exception {
- // Create a mock datasheet content
- String datasheetContent =
- "TEST,KEY,10.0\n" +
- "TEST,KEY,20.0\n" +
- "TEST,OTHER,15.0\n" +
- "OTHER,KEY,10.0";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("DatasheetServiceTest.datasheet"))
- .thenReturn(mockUrl);
-
- // Should match 10.0 with 5% tolerance when looking for 10.2
- String[] result = service.lookup(
- DatasheetServiceTest.class,
- 5.0, // 5% tolerance
- "TEST|KEY",
- 10.2 // Should match 10.0 within 5% tolerance
- );
-
- assertNotNull("Should find matching entry within tolerance", result);
+ public void testLookupWithinTolerance() {
+ String[] result = service.lookup(TEST_CLASS, 5.0, "TEST|KEY", 10.5);
+ assertNotNull(result);
assertEquals("10.0", result[2]);
}
-
+
@Test
- public void testLookupNoMatch() throws Exception {
- // Create a mock datasheet content
- String datasheetContent =
- "TEST,KEY,10.0\n" +
- "TEST,KEY,20.0\n" +
- "TEST,OTHER,15.0\n" +
- "OTHER,KEY,10.0";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("DatasheetServiceTest.datasheet"))
- .thenReturn(mockUrl);
-
- // Should not match when value is outside tolerance
- String[] result = service.lookup(
- DatasheetServiceTest.class,
- 1.0, // 1% tolerance
- "TEST|KEY",
- 15.0 // No value close enough to match
- );
-
- assertNull("Should not find matching entry", result);
+ public void testLookupOutsideTolerance() {
+ String[] result = service.lookup(TEST_CLASS, 5.0, "TEST|KEY", 12.0);
+ assertNull(result);
}
-
+
@Test
- public void testLookupNonexistentKey() throws Exception {
- // Create a mock datasheet content
- String datasheetContent =
- "TEST,KEY,10.0\n" +
- "TEST,KEY,20.0\n" +
- "TEST,OTHER,15.0\n" +
- "OTHER,KEY,10.0";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("DatasheetServiceTest.datasheet"))
- .thenReturn(mockUrl);
-
- String[] result = service.lookup(
- DatasheetServiceTest.class,
- 0.1,
- "NONEXISTENT|KEY", // Key that doesn't exist in datasheet
- 10.0
- );
-
- assertNull("Should not find matching entry for nonexistent key", result);
+ public void testLookupNoMatch() {
+ String[] result = service.lookup(TEST_CLASS, 0.0, "TEST,KEY", 30.0);
+ assertNull(result);
}
-
+
@Test
- public void testLookupWithTolerance() throws Exception {
- // Create a mock datasheet content with resistor values
- String datasheetContent =
- "0805,1%,100,0.125W\n" +
- "0805,1%,220,0.125W\n" +
- "0805,1%,470,0.125W";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("TestComponent.datasheet"))
- .thenReturn(mockUrl);
-
- // Test lookup with 5% tolerance (should match 220 when looking for 225)
- String[] result = service.lookup(TestComponent.class, 5.0, "0805|1%", 225.0);
-
- assertNotNull("Should find matching entry within tolerance", result);
- assertEquals("0805", result[0]);
- assertEquals("1%", result[1]);
- assertEquals("220", result[2]);
+ public void testLookupNonexistentKey() {
+ String[] result = service.lookup(TEST_CLASS, 0.0, "NONEXISTENT,KEY", 10.0);
+ assertNull(result);
}
-
+
@Test
- public void testLookupOutsideTolerance() throws Exception {
- // Create a mock datasheet content
- String datasheetContent =
- "0805,1%,100,0.125W\n" +
- "0805,1%,220,0.125W\n" +
- "0805,1%,470,0.125W";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("TestComponent.datasheet"))
- .thenReturn(mockUrl);
-
- // Test lookup with value outside tolerance
- String[] result = service.lookup(TestComponent.class, 1.0, "0805|1%", 250.0);
-
- assertNull("Should not find matching entry outside tolerance", result);
+ public void testLookupWithTolerance() {
+ String[] result = service.lookup(TEST_CLASS, 50.0, "TEST|KEY", 15.0);
+ assertNotNull(result);
+ assertEquals("10.0", result[2]);
}
-
+
@Test
- public void testLookupMultipleValues() throws Exception {
- // Create a mock datasheet content with multiple value matches
- String datasheetContent =
- "TO220,NPN,50,5,0.7\n" + // Vce, Ic, Vbe
- "TO220,NPN,60,8,0.7\n" +
- "TO220,NPN,100,10,0.7";
-
- URL mockUrl = mock(URL.class);
- when(mockUrl.openStream()).thenReturn(
- new ByteArrayInputStream(datasheetContent.getBytes()));
- when(mockClassLoader.getResource("TestComponent.datasheet"))
- .thenReturn(mockUrl);
-
- // Test lookup matching multiple values within tolerance
- String[] result = service.lookup(TestComponent.class, 5.0, "TO220|NPN",
- 98.0, 9.8, 0.71);
-
- assertNotNull("Should find matching entry for multiple values", result);
- assertEquals("TO220", result[0]);
- assertEquals("NPN", result[1]);
- assertEquals("100", result[2]);
- assertEquals("10", result[3]);
- assertEquals("0.7", result[4]);
+ public void testLookupMultipleValues() {
+ String[] result = service.lookup(TEST_CLASS, 0.0, "TEST|KEY", 10.0, 20.0);
+ assertNotNull(result);
+ assertEquals("10.0", result[2]);
+ assertEquals("20.0", result[3]);
}
-
- // Test component class
- private static class TestComponent {
- // Empty class just for testing
- }
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-core/src/test/resources/datasheets/DatasheetServiceTest.datasheet b/diylc/diylc-core/src/test/resources/datasheets/DatasheetServiceTest.datasheet
new file mode 100644
index 00000000..2712a0d2
--- /dev/null
+++ b/diylc/diylc-core/src/test/resources/datasheets/DatasheetServiceTest.datasheet
@@ -0,0 +1,4 @@
+TEST,KEY,10.0,20.0
+TEST,KEY,20.0,30.0
+TEST,OTHER,15.0,25.0
+OTHER,KEY,10.0,20.0
\ No newline at end of file
diff --git a/diylc/diylc-core/src/test/resources/org/diylc/presenter/DatasheetServiceTest.datasheet b/diylc/diylc-core/src/test/resources/org/diylc/presenter/DatasheetServiceTest.datasheet
deleted file mode 100644
index 5249c552..00000000
--- a/diylc/diylc-core/src/test/resources/org/diylc/presenter/DatasheetServiceTest.datasheet
+++ /dev/null
@@ -1,4 +0,0 @@
-TEST,KEY,10.0 mm
-TEST,KEY,20.0 mm
-TEST,OTHER,15.0 mm
-OTHER,KEY,10.0 mm
\ No newline at end of file
diff --git a/diylc/diylc-library/.classpath b/diylc/diylc-library/.classpath
deleted file mode 100644
index 05a589ec..00000000
--- a/diylc/diylc-library/.classpath
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/diylc/diylc-library/.project b/diylc/diylc-library/.project
deleted file mode 100644
index 0f0c953c..00000000
--- a/diylc/diylc-library/.project
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- diylc-library
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.m2e.core.maven2Nature
- org.eclipse.jdt.core.javanature
-
-
-
- 1741597247360
-
- 30
-
- org.eclipse.core.resources.regexFilterMatcher
- node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
-
-
-
-
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java b/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java
index cdb8d891..fe9d7d3f 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/AbstractLeadedComponent.java
@@ -441,7 +441,11 @@ public abstract class AbstractLeadedComponent extends AbstractLabeledComponen
stroke = ObjectCache.getInstance().fetchStroke(thickness, new float[] {thickness / 4, thickness * 4}, 0, BasicStroke.CAP_ROUND);
break;
}
-
+
+ Composite oldComposite = g2d.getComposite();
+ if (getAlpha() < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
+ }
if (shouldShadeLeads()) {
Shape lineShape = stroke.createStrokedShape(line);
@@ -463,6 +467,7 @@ public abstract class AbstractLeadedComponent extends AbstractLabeledComponen
if (isCopperArea)
observer.stopTrackingContinuityArea();
}
+ g2d.setComposite(oldComposite);
}
protected LineStyle getStyle() {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java
index e64effa2..8a2d1ddb 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/AbstractBoard.java
@@ -35,7 +35,9 @@ import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.common.VerticalAlignment;
import org.diylc.components.AbstractTransparentComponent;
+import org.diylc.core.BoardUndersideDisplay;
import org.diylc.core.ComponentState;
+import org.diylc.core.IBoard;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
@@ -43,9 +45,10 @@ import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
-public abstract class AbstractBoard extends AbstractTransparentComponent {
+public abstract class AbstractBoard extends AbstractTransparentComponent implements IBoard {
private static final long serialVersionUID = 1L;
+ public static final Size DEFAULT_UNDERSIDE_OFFSET = new Size(0.1, SizeUnit.in);
public static Color BORDER_COLOR = PHENOLIC_COLOR.darker();
public static Color COORDINATE_COLOR = Color.gray.brighter();
@@ -56,7 +59,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
protected String value = "";
// two control points used for controlling the position
protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0),
- new Point2D.Double(DEFAULT_WIDTH.convertToPixels(), DEFAULT_HEIGHT.convertToPixels())};
+ new Point2D.Double(DEFAULT_WIDTH.convertToPixels(), DEFAULT_HEIGHT.convertToPixels())};
// top-left and bottom-right points
protected Point2D.Double firstPoint = new Point2D.Double();
protected Point2D.Double secondPoint = new Point2D.Double();
@@ -69,17 +72,20 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
protected CoordinateOrigin coordinateOrigin = CoordinateOrigin.Top_Left;
protected CoordinateDisplay coordinateDisplay = CoordinateDisplay.One_Side;
protected CoordinateType yType = CoordinateType.Letters;
-
+
protected Size length;
protected Size width;
protected BoardSizingMode mode = BoardSizingMode.TwoPoints;
+ protected BoardUndersideDisplay boardUndersideDisplay = BoardUndersideDisplay.NONE;
+ protected Size undersideOffset = DEFAULT_UNDERSIDE_OFFSET;
+
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
+ IDrawingObserver drawingObserver) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
-
- Point2D finalSecondPoint = getFinalSecondPoint();
+
+ Point2D finalSecondPoint = getFinalSecondPoint();
Composite oldComposite = g2d.getComposite();
// render as transparent when dragging
@@ -90,64 +96,64 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
g2d.setColor(boardColor);
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
g2d.setComposite(oldComposite);
-
+
// Do not track any changes that follow because the whole board has been
// tracked so far.
drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor);
+ : borderColor);
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
}
-
+
protected Point2D getFinalSecondPoint() {
Point2D finalSecondPoint;
if (getMode() == BoardSizingMode.TwoPoints)
finalSecondPoint = secondPoint;
else
- finalSecondPoint = new Point2D.Double(firstPoint.getX() + getLength().convertToPixels(),
- firstPoint.getY() + getWidth().convertToPixels());
+ finalSecondPoint = new Point2D.Double(firstPoint.getX() + getLength().convertToPixels(),
+ firstPoint.getY() + getWidth().convertToPixels());
return finalSecondPoint;
}
protected void drawCoordinates(Graphics2D g2d, double spacing, Project project) {
g2d.setColor(coordinateColor);
g2d.setFont(project.getFont().deriveFont(COORDINATE_FONT_SIZE));
-
+
// The half space is used to do rounding when calculating the range.
double halfSpace = spacing / 2;
CoordinateOrigin origin = getCoordinateOrigin();
-
+
Point2D finalSecondPoint = getFinalSecondPoint();
-
+
if (getCoordinateDisplay() != CoordinateDisplay.None) {
int range;
double yOffset;
CoordinateType yType = getyType();
double y = firstPoint.getY();
-
+
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Top_Right) {
- range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
- yOffset = spacing;
+ range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
+ yOffset = spacing;
} else {
- range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
- yOffset = -spacing;
- y = finalSecondPoint.getY();
+ range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
+ yOffset = -spacing;
+ y = finalSecondPoint.getY();
}
-
+
for (int c = 1; c < range; c++) {
- int xOffset = (yType == CoordinateType.Numbers && c >= 10) || (yType == CoordinateType.Letters && c >= 27) ? 0 : 2;
- String label = yType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
-
- y += yOffset;
-
- StringUtils.drawCenteredText(g2d, label,
- firstPoint.getX() + xOffset, y,
- HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
- if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
- StringUtils.drawCenteredText(g2d, label,
- finalSecondPoint.getX() - xOffset, y,
- HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
- }
+ int xOffset = (yType == CoordinateType.Numbers && c >= 10) || (yType == CoordinateType.Letters && c >= 27) ? 0 : 2;
+ String label = yType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
+
+ y += yOffset;
+
+ StringUtils.drawCenteredText(g2d, label,
+ firstPoint.getX() + xOffset, y,
+ HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
+ if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
+ StringUtils.drawCenteredText(g2d, label,
+ finalSecondPoint.getX() - xOffset, y,
+ HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
+ }
}
}
@@ -155,8 +161,8 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
int range;
double xOffset;
CoordinateType xType = getxType();
- double x = firstPoint.getX();
-
+ double x = firstPoint.getX();
+
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Bottom_Left) {
range = (int) ((finalSecondPoint.getX() - firstPoint.getX() + halfSpace) / spacing);
xOffset = spacing;
@@ -165,19 +171,19 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
xOffset = -spacing;
x = finalSecondPoint.getX();
}
-
+
for (int c = 1; c < range; c++) {
String label = xType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
-
+
x += xOffset;
-
- StringUtils.drawCenteredText(g2d, label,
- x, firstPoint.getY() + 2,
- HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
+
+ StringUtils.drawCenteredText(g2d, label,
+ x, firstPoint.getY() + 2,
+ HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
- StringUtils.drawCenteredText(g2d, label,
- x, (int) (finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
- HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
+ StringUtils.drawCenteredText(g2d, label,
+ x, (int) (finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
+ HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
}
}
}
@@ -225,7 +231,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
public void setBorderColor(Color borderColor) {
this.borderColor = borderColor;
}
-
+
@EditableProperty(name = "X")
public CoordinateType getxType() {
if (xType == null)
@@ -250,15 +256,15 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
@EditableProperty(name = "Coordinate Origin")
public CoordinateOrigin getCoordinateOrigin() {
- if (coordinateOrigin == null)
- coordinateOrigin = CoordinateOrigin.Top_Left;
- return coordinateOrigin;
+ if (coordinateOrigin == null)
+ coordinateOrigin = CoordinateOrigin.Top_Left;
+ return coordinateOrigin;
}
-
+
public void setCoordinateOrigin(CoordinateOrigin coordinateOrigin) {
- this.coordinateOrigin = coordinateOrigin;
+ this.coordinateOrigin = coordinateOrigin;
}
-
+
@EditableProperty(name = "Y")
public CoordinateType getyType() {
if (yType == null)
@@ -294,9 +300,9 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
public void setControlPoint(Point2D point, int index) {
controlPoints[index].setLocation(point);
firstPoint.setLocation(Math.min(controlPoints[0].getX(), controlPoints[1].getX()),
- Math.min(controlPoints[0].getY(), controlPoints[1].getY()));
+ Math.min(controlPoints[0].getY(), controlPoints[1].getY()));
secondPoint.setLocation(Math.max(controlPoints[0].getX(), controlPoints[1].getX()),
- Math.max(controlPoints[0].getY(), controlPoints[1].getY()));
+ Math.max(controlPoints[0].getY(), controlPoints[1].getY()));
}
@EditableProperty
@@ -309,13 +315,13 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
public void setValue(String value) {
this.value = value;
}
-
+
private SizeUnit getDefaultUnit() {
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.METRIC_KEY, true))
return SizeUnit.mm;
- return SizeUnit.in;
+ return SizeUnit.in;
}
-
+
@EditableProperty(name = "Explicit Length", validatorClass = BoardModeValidator.class)
public Size getLength() {
if (getMode() == BoardSizingMode.TwoPoints) {
@@ -327,12 +333,12 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
public void setLength(Size length) {
if (getMode() == BoardSizingMode.Explicit && length != null && width != null) {
- setControlPoint(firstPoint, 0);
+ setControlPoint(firstPoint, 0);
Point2D second = new Point2D.Double(firstPoint.getX() + length.convertToPixels(),
- firstPoint.getY() + width.convertToPixels());
- setControlPoint(second, 1);
+ firstPoint.getY() + width.convertToPixels());
+ setControlPoint(second, 1);
}
- this.length = length;
+ this.length = length;
}
@EditableProperty(name = "Explicit Width", validatorClass = BoardModeValidator.class)
@@ -352,7 +358,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
}
this.width = width;
}
-
+
@EditableProperty(name = "Dimension Mode")
public BoardSizingMode getMode() {
if (mode == null)
@@ -363,27 +369,66 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
public void setMode(BoardSizingMode mode) {
this.mode = mode;
}
-
+
+ @EditableProperty(name = "Underside Display")
+ @Override
+ public BoardUndersideDisplay getBoardUndersideDisplay() {
+ if (this.boardUndersideDisplay == null) {
+ this.boardUndersideDisplay = BoardUndersideDisplay.NONE;
+ }
+ return this.boardUndersideDisplay;
+ }
+
+ public void setBoardUndersideDisplay(BoardUndersideDisplay boardUndersideDisplay) {
+ this.boardUndersideDisplay = boardUndersideDisplay;
+ }
+
+ @EditableProperty(name = "Underside Offset")
+ @Override
+ public Size getUndersideOffset() {
+ if (undersideOffset == null) {
+ undersideOffset = DEFAULT_UNDERSIDE_OFFSET;
+ }
+ return undersideOffset;
+ }
+
+ public void setUndersideOffset(Size undersideOffset) {
+ this.undersideOffset = undersideOffset;
+ }
+
+ @Override
+ public Rectangle2D getBoardRectangle() {
+ Point2D finalSecondPoint = getFinalSecondPoint();
+
+ return new Rectangle2D.Double(firstPoint.getX(), firstPoint.getY(),
+ finalSecondPoint.getX() - firstPoint.getX(), finalSecondPoint.getY() - firstPoint.getY());
+ }
+
+ @Override
+ public boolean shouldExportToGerber() {
+ return false;
+ }
+
@Override
public Rectangle2D getCachingBounds() {
- Point2D finalSecondPoint = getFinalSecondPoint();
- return new Rectangle2D.Double(Math.min(firstPoint.getX(), finalSecondPoint.getX()) - 2, Math.min(firstPoint.getY(), finalSecondPoint.getY()) - 2,
- Math.abs(finalSecondPoint.getX() - firstPoint.getX()) + 4, Math.abs(finalSecondPoint.getY() - firstPoint.getY()) + 4);
+ Point2D finalSecondPoint = getFinalSecondPoint();
+ return new Rectangle2D.Double(Math.min(firstPoint.getX(), finalSecondPoint.getX()) - 2, Math.min(firstPoint.getY(), finalSecondPoint.getY()) - 2,
+ Math.abs(finalSecondPoint.getX() - firstPoint.getX()) + 4, Math.abs(finalSecondPoint.getY() - firstPoint.getY()) + 4);
}
public static enum CoordinateType {
Letters, Numbers
}
-
+
public static enum CoordinateDisplay {
None, One_Side, Both_Sides;
-
+
@Override
public String toString() {
return super.toString().replace('_', ' ');
};
}
-
+
public static enum CoordinateOrigin {
Top_Left, Top_Right, Bottom_Right, Bottom_Left;
@@ -392,19 +437,19 @@ public abstract class AbstractBoard extends AbstractTransparentComponent
return super.toString().replace('_', ' ');
};
}
-
+
public static enum BoardSizingMode {
TwoPoints("Opposing Points"), Explicit("Explicit Dimensions");
-
+
private String label;
private BoardSizingMode(String label) {
this.label = label;
}
-
+
@Override
public String toString() {
return label;
}
- }
-}
+ }
+}
\ No newline at end of file
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java b/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java
index 5fda6b2c..2cbbe0be 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/boards/BlankBoard.java
@@ -38,12 +38,11 @@ import org.diylc.core.Project;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
-import org.diylc.core.gerber.IGerberBoard;
@ComponentDescriptor(name = "Blank Board", category = "Boards", author = "Branislav Stojkovic",
- zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board", description = "Blank circuit board",
- bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, transformer = SimpleComponentTransformer.class)
-public class BlankBoard extends AbstractBoard implements IGerberBoard {
+ zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board", description = "Blank circuit board",
+ bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, transformer = SimpleComponentTransformer.class)
+public class BlankBoard extends AbstractBoard {
private static final long serialVersionUID = 1L;
@@ -60,14 +59,14 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
- IDrawingObserver drawingObserver) {
- Point2D finalSecondPoint = getFinalSecondPoint();
-
+ IDrawingObserver drawingObserver) {
+ Point2D finalSecondPoint = getFinalSecondPoint();
+
Shape clip = g2d.getClip();
if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
- && !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
+ && !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
return;
- }
+ }
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
if (componentState != ComponentState.DRAGGING) {
@@ -86,13 +85,13 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
// tracked so far.
drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
- : borderColor);
+ : borderColor);
if (getType() == Type.SQUARE)
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
else
g2d.drawOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
}
-
+
@Override
public CoordinateType getxType() {
// Override to prevent editing.
@@ -128,12 +127,17 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
public void setType(Type type) {
this.type = type;
}
-
+
@Override
public String getControlPointNodeName(int index) {
return null;
}
+ @Override
+ public boolean shouldExportToGerber() {
+ return true;
+ }
+
static enum Type {
ROUND, SQUARE;
@@ -142,12 +146,4 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
-
- @Override
- public Rectangle2D getBoardRectangle() {
- Point2D finalSecondPoint = getFinalSecondPoint();
-
- return new Rectangle2D.Double(firstPoint.getX(), firstPoint.getY(),
- finalSecondPoint.getX() - firstPoint.getX(), finalSecondPoint.getY() - firstPoint.getY());
- }
-}
+}
\ No newline at end of file
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CopperTrace.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CopperTrace.java
index baff2381..f0862538 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CopperTrace.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CopperTrace.java
@@ -133,11 +133,6 @@ public class CopperTrace extends AbstractLeadedComponent implements ILayer
return super.getBorderColor();
}
- @Override
- public Byte getAlpha() {
- return super.getAlpha();
- }
-
@Override
public Size getLength() {
return super.getLength();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java
index 56a3608a..0b35f1df 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CurvedTrace.java
@@ -111,11 +111,6 @@ public class CurvedTrace extends AbstractCurvedComponent implements ILayer
@Override
public void setValue(Void value) {}
- @Override
- public Byte getAlpha() {
- return super.getAlpha();
- }
-
@Override
public void setAlpha(Byte alpha) {
super.setAlpha(alpha);
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java
index c202a7db..3e74d70c 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Eyelet.java
@@ -21,13 +21,13 @@
*/
package org.diylc.components.connectivity;
-import java.awt.Color;
-import java.awt.Graphics2D;
+import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.common.ObjectCache;
import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -49,7 +49,7 @@ import org.diylc.utils.Constants;
zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class,
enableCache = true)
-public class Eyelet extends AbstractComponent {
+public class Eyelet extends AbstractTransparentComponent {
private static final long serialVersionUID = 1L;
@@ -71,6 +71,12 @@ public class Eyelet extends AbstractComponent {
}
int diameter = getClosestOdd((int) size.convertToPixels());
int holeDiameter = getClosestOdd((int) holeSize.convertToPixels());
+
+ Composite oldComposite = g2d.getComposite();
+ if (getAlpha() < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
+ }
+
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
g2d.setColor(color);
drawingObserver.startTrackingContinuityArea(true);
@@ -84,6 +90,8 @@ public class Eyelet extends AbstractComponent {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker());
g2d.drawOval((int)(point.getX() - holeDiameter / 2), (int)(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
+
+ g2d.setComposite(oldComposite);
}
@Override
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java
index 0db6d4ac..ac6d255f 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/GroundFill.java
@@ -21,8 +21,7 @@
*/
package org.diylc.components.connectivity;
-import java.awt.Color;
-import java.awt.Graphics2D;
+import java.awt.*;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.EnumSet;
@@ -33,6 +32,7 @@ import com.bancika.gerberwriter.GerberFunctions;
import org.diylc.common.ObjectCache;
import org.diylc.common.PCBLayer;
import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -52,7 +52,8 @@ import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Ground Fill", author = "Branislav Stojkovic", category = "Connectivity",
instanceNamePrefix = "GF", description = "Polygonal ground fill area", zOrder = IDIYComponent.TRACE,
bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
-public class GroundFill extends AbstractComponent implements ILayeredComponent, IGerberComponentSimple {
+public class GroundFill extends AbstractTransparentComponent
+ implements ILayeredComponent, IGerberComponentSimple {
private static final long serialVersionUID = 1L;
@@ -83,7 +84,12 @@ public class GroundFill extends AbstractComponent implements ILayeredCompo
yPoints[i] = (int)controlPoints[i].getY();
}
drawingObserver.startTrackingContinuityArea(true);
+ Composite oldComposite = g2d.getComposite();
+ if (getAlpha() < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
+ }
g2d.fillPolygon(xPoints, yPoints, controlPoints.length);
+ g2d.setComposite(oldComposite);
drawingObserver.stopTrackingContinuityArea();
// Do not track any changes that follow because the whole board has been
// tracked so far.
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Jumper.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Jumper.java
index 2f69dd61..61d281cf 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Jumper.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Jumper.java
@@ -103,11 +103,6 @@ public class Jumper extends AbstractLeadedComponent implements IContinuity
return super.getBorderColor();
}
- @Override
- public Byte getAlpha() {
- return super.getAlpha();
- }
-
@Override
public Size getLength() {
return super.getLength();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Line.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Line.java
index 0b0234d2..9da327a5 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Line.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Line.java
@@ -233,11 +233,6 @@ public class Line extends AbstractLeadedComponent {
return super.getBorderColor();
}
- @Override
- public Byte getAlpha() {
- return super.getAlpha();
- }
-
@Override
public Size getLength() {
return super.getLength();
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
index e734cca6..ebd05240 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
@@ -17,8 +17,7 @@
*/
package org.diylc.components.connectivity;
-import java.awt.Color;
-import java.awt.Graphics2D;
+import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -29,6 +28,7 @@ import com.bancika.gerberwriter.GerberFunctions;
import org.diylc.common.PCBLayer;
import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -55,7 +55,8 @@ import org.diylc.utils.Constants;
zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB",
transformer = SimpleComponentTransformer.class, enableCache = true)
-public class SolderPad extends AbstractComponent implements ILayeredComponent, IGerberComponentCustom {
+public class SolderPad extends AbstractTransparentComponent
+ implements ILayeredComponent, IGerberComponentCustom {
private static final long serialVersionUID = 1L;
@@ -90,6 +91,11 @@ public class SolderPad extends AbstractComponent implements ILayeredCompon
gerberDrawingObserver.startGerberOutput(gerberCopperLayer, GerberFunctions.CONNECTOR_PAD, false);
gerberDrawingObserver.startGerberOutput(org.diylc.core.gerber.GerberLayer.SolderMaskBot, "Material", false);
}
+ Composite oldComposite = g2d.getComposite();
+ if (getAlpha() < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
+ }
+
if (type == Type.ROUND) {
g2d.fill(new Ellipse2D.Double(point.getX() - diameter / 2, point.getY() - diameter / 2,
diameter, diameter));
@@ -116,6 +122,7 @@ public class SolderPad extends AbstractComponent implements ILayeredCompon
g2d.fill(new Ellipse2D.Double(point.getX() - holeDiameter / 2,
point.getY() - holeDiameter / 2, holeDiameter, holeDiameter));
}
+ g2d.setComposite(oldComposite);
if (gerberDrawingObserver != null)
gerberDrawingObserver.stopGerberOutput();
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java
index 3bc979a3..4cc3964f 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/TraceCut.java
@@ -21,14 +21,14 @@
*/
package org.diylc.components.connectivity;
-import java.awt.Color;
-import java.awt.Graphics2D;
+import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.common.ObjectCache;
import org.diylc.common.OrientationHV;
import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.boards.AbstractBoard;
import org.diylc.components.boards.VeroBoard;
import org.diylc.components.transform.SimpleComponentTransformer;
@@ -49,7 +49,7 @@ import org.diylc.utils.Constants;
description = "Designates the place where a trace on the vero board needs to be cut", instanceNamePrefix = "Cut",
zOrder = IDIYComponent.BOARD + 1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
transformer = SimpleComponentTransformer.class, enableCache = true)
-public class TraceCut extends AbstractComponent implements ILayeredComponent {
+public class TraceCut extends AbstractTransparentComponent implements ILayeredComponent {
private static final long serialVersionUID = 1L;
@@ -79,6 +79,10 @@ public class TraceCut extends AbstractComponent implements ILayeredCompone
if (checkPointsClipped(g2d.getClip())) {
return;
}
+ Composite oldComposite = g2d.getComposite();
+ if (getAlpha() < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
+ }
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(1f));
int size = getClosestOdd((int) this.size.convertToPixels());
int cutWidth = getClosestOdd((int) CUT_WIDTH.convertToPixels());
@@ -105,6 +109,7 @@ public class TraceCut extends AbstractComponent implements ILayeredCompone
g2d.setColor(getBoardColor().darker());
g2d.drawOval((int)(point.getX() - holeSize / 2), (int)(point.getY() - holeSize / 2), holeSize, holeSize);
}
+ g2d.setComposite(oldComposite);
}
@Override
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java
index bd5c21f7..9400d75c 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Turret.java
@@ -21,13 +21,13 @@
*/
package org.diylc.components.connectivity;
-import java.awt.Color;
-import java.awt.Graphics2D;
+import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.common.ObjectCache;
import org.diylc.components.AbstractComponent;
+import org.diylc.components.AbstractTransparentComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -47,7 +47,7 @@ import org.diylc.utils.Constants;
zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false,
keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class,
enableCache = true)
-public class Turret extends AbstractComponent {
+public class Turret extends AbstractTransparentComponent {
private static final long serialVersionUID = 1L;
@@ -67,6 +67,10 @@ public class Turret extends AbstractComponent {
if (checkPointsClipped(g2d.getClip())) {
return;
}
+ Composite oldComposite = g2d.getComposite();
+ if (getAlpha() < MAX_ALPHA) {
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * getAlpha() / MAX_ALPHA));
+ }
int diameter = getClosestOdd((int) size.convertToPixels());
int holeDiameter = getClosestOdd((int) holeSize.convertToPixels());
g2d.setColor(color);
@@ -82,6 +86,7 @@ public class Turret extends AbstractComponent {
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: color.darker());
g2d.drawOval((int)(point.getX() - holeDiameter / 2), (int)(point.getY() - holeDiameter / 2), holeDiameter, holeDiameter);
+ g2d.setComposite(oldComposite);
}
@Override
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java
index 253ae23d..142b4499 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/guitar/Freeway3x3_03.java
@@ -304,7 +304,8 @@ public class Freeway3x3_03 extends AbstractTransparentComponent implements
if (svgDiagram == null) {
try {
byte[] data =
- IOUtils.toByteArray(Freeway3x3_03.class.getResourceAsStream("/freeway_3x3-03.svg"));
+ IOUtils.toByteArray(Freeway3x3_03.class.getResourceAsStream(
+ "/component-drawings/freeway_3x3-03.svg"));
ByteArrayInputStream bis = new ByteArrayInputStream(data);
SVGUniverse universe = new SVGUniverse();
URI url = universe.loadSVG(bis,
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java b/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java
index 1e67dd13..2527a4cc 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/misc/Image.java
@@ -40,7 +40,6 @@ import org.diylc.awt.ImageUtils;
import org.diylc.common.ObjectCache;
import org.diylc.common.Orientation;
import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.boards.AbstractBoard;
import org.diylc.components.transform.ImageTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
@@ -72,7 +71,7 @@ public class Image extends AbstractTransparentComponent {
private Orientation orientation;
static {
- String name = "/image.png";
+ String name = "/diylc-library-images/image.png";
try (InputStream inputStream = Image.class.getResourceAsStream(name)) {
if (inputStream != null) {
ICON = new ImageIcon(inputStream.readAllBytes(), name);
@@ -99,7 +98,7 @@ public class Image extends AbstractTransparentComponent {
public Image() {
try {
- data = IOUtils.toByteArray(Image.class.getResourceAsStream("/image.png"));
+ data = IOUtils.toByteArray(Image.class.getResourceAsStream("/diylc-library-images/image.png"));
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java b/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java
index 91610df6..739d16f0 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/misc/SVGImage.java
@@ -81,7 +81,8 @@ public class SVGImage extends AbstractTransparentComponent {
public SVGImage() {
try {
- data = IOUtils.toByteArray(SVGImage.class.getResourceAsStream("/diylc.svg"));
+ data = IOUtils.toByteArray(SVGImage.class.getResourceAsStream(
+ "/diylc-library-images/diylc.svg"));
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/transform/CliffJackTransformer.java b/diylc/diylc-library/src/main/java/org/diylc/components/transform/CliffJackTransformer.java
index 816f668d..687545e1 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/transform/CliffJackTransformer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/transform/CliffJackTransformer.java
@@ -43,7 +43,7 @@ public class CliffJackTransformer implements IComponentTransformer {
@Override
public boolean mirroringChangesCircuit() {
- return true;
+ return false;
}
@Override
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/transform/MiniToggleSwitchTransformer.java b/diylc/diylc-library/src/main/java/org/diylc/components/transform/MiniToggleSwitchTransformer.java
index 21da24ee..f347f9f2 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/transform/MiniToggleSwitchTransformer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/transform/MiniToggleSwitchTransformer.java
@@ -48,14 +48,26 @@ public class MiniToggleSwitchTransformer implements IComponentTransformer {
@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);
- }
-
MiniToggleSwitch sw = (MiniToggleSwitch) component;
+
+ // Calculate center of all control points
+ double sumX = 0, sumY = 0;
+ for (int i = 0; i < sw.getControlPointCount(); i++) {
+ Point2D p = sw.getControlPoint(i);
+ sumX += p.getX();
+ sumY += p.getY();
+ }
+ Point2D controlCenter = new Point2D.Double(
+ sumX / sw.getControlPointCount(),
+ sumY / sw.getControlPointCount()
+ );
+
+ // Calculate where control center should end up after rotation
+ Point2D targetCenter = new Point2D.Double();
+ AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2 * direction, center.getX(), center.getY());
+ rotate.transform(controlCenter, targetCenter);
+
+ // Update orientation first - this will rotate points around first point
OrientationHV o = sw.getOrientation();
int oValue = o.ordinal();
oValue += direction;
@@ -65,6 +77,29 @@ public class MiniToggleSwitchTransformer implements IComponentTransformer {
oValue = 0;
o = OrientationHV.values()[oValue];
sw.setOrientation(o);
+
+ // Recalculate current control center after orientation change
+ sumX = 0;
+ sumY = 0;
+ for (int i = 0; i < sw.getControlPointCount(); i++) {
+ Point2D p = sw.getControlPoint(i);
+ sumX += p.getX();
+ sumY += p.getY();
+ }
+ Point2D newControlCenter = new Point2D.Double(
+ sumX / sw.getControlPointCount(),
+ sumY / sw.getControlPointCount()
+ );
+
+ // Calculate and apply translation to move control center to target position
+ double dx = targetCenter.getX() - newControlCenter.getX();
+ double dy = targetCenter.getY() - newControlCenter.getY();
+
+ // Apply translation to all points
+ for (int i = 0; i < sw.getControlPointCount(); i++) {
+ Point2D p = sw.getControlPoint(i);
+ sw.setControlPoint(new Point2D.Double(p.getX() + dx, p.getY() + dy), i);
+ }
}
@Override
diff --git a/diylc/diylc-library/src/main/resources/freeway_3x3-03.svg b/diylc/diylc-library/src/main/resources/component-drawings/freeway_3x3-03.svg
similarity index 100%
rename from diylc/diylc-library/src/main/resources/freeway_3x3-03.svg
rename to diylc/diylc-library/src/main/resources/component-drawings/freeway_3x3-03.svg
diff --git a/diylc/diylc-library/src/main/resources/AxialElectrolyticCapacitor.datasheet b/diylc/diylc-library/src/main/resources/datasheets/AxialElectrolyticCapacitor.datasheet
similarity index 100%
rename from diylc/diylc-library/src/main/resources/AxialElectrolyticCapacitor.datasheet
rename to diylc/diylc-library/src/main/resources/datasheets/AxialElectrolyticCapacitor.datasheet
diff --git a/diylc/diylc-library/src/main/resources/AxialFilmCapacitor.datasheet b/diylc/diylc-library/src/main/resources/datasheets/AxialFilmCapacitor.datasheet
similarity index 100%
rename from diylc/diylc-library/src/main/resources/AxialFilmCapacitor.datasheet
rename to diylc/diylc-library/src/main/resources/datasheets/AxialFilmCapacitor.datasheet
diff --git a/diylc/diylc-library/src/main/resources/RadialElectrolytic.datasheet b/diylc/diylc-library/src/main/resources/datasheets/RadialElectrolytic.datasheet
similarity index 100%
rename from diylc/diylc-library/src/main/resources/RadialElectrolytic.datasheet
rename to diylc/diylc-library/src/main/resources/datasheets/RadialElectrolytic.datasheet
diff --git a/diylc/diylc-library/src/main/resources/RadialFilmCapacitor.datasheet b/diylc/diylc-library/src/main/resources/datasheets/RadialFilmCapacitor.datasheet
similarity index 100%
rename from diylc/diylc-library/src/main/resources/RadialFilmCapacitor.datasheet
rename to diylc/diylc-library/src/main/resources/datasheets/RadialFilmCapacitor.datasheet
diff --git a/diylc/diylc-library/src/main/resources/RadialMicaCapacitor.datasheet b/diylc/diylc-library/src/main/resources/datasheets/RadialMicaCapacitor.datasheet
similarity index 100%
rename from diylc/diylc-library/src/main/resources/RadialMicaCapacitor.datasheet
rename to diylc/diylc-library/src/main/resources/datasheets/RadialMicaCapacitor.datasheet
diff --git a/diylc/diylc-library/src/main/resources/diylc.svg b/diylc/diylc-library/src/main/resources/diylc-library-images/diylc.svg
similarity index 100%
rename from diylc/diylc-library/src/main/resources/diylc.svg
rename to diylc/diylc-library/src/main/resources/diylc-library-images/diylc.svg
diff --git a/diylc/diylc-library/src/main/resources/image.png b/diylc/diylc-library/src/main/resources/diylc-library-images/image.png
similarity index 100%
rename from diylc/diylc-library/src/main/resources/image.png
rename to diylc/diylc-library/src/main/resources/diylc-library-images/image.png
diff --git a/diylc/diylc-swing/.classpath b/diylc/diylc-swing/.classpath
deleted file mode 100644
index cd173d6f..00000000
--- a/diylc/diylc-swing/.classpath
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/diylc/diylc-swing/.project b/diylc/diylc-swing/.project
deleted file mode 100644
index 33001697..00000000
--- a/diylc/diylc-swing/.project
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- diylc-swing
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.m2e.core.maven2Nature
- org.eclipse.jdt.core.javanature
-
-
-
- 1741597247368
-
- 30
-
- org.eclipse.core.resources.regexFilterMatcher
- node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
-
-
-
-
diff --git a/diylc/diylc-swing/deploy/linux/appimage/diylc.sh b/diylc/diylc-swing/deploy/linux/appimage/diylc.sh
index 07214765..1f2138b2 100644
--- a/diylc/diylc-swing/deploy/linux/appimage/diylc.sh
+++ b/diylc/diylc-swing/deploy/linux/appimage/diylc.sh
@@ -1,26 +1,25 @@
#!/bin/bash
#set -x # Enable debug mode
-HERE="$(dirname "$(readlink -f "$0")")"
+# Get the AppImage directory
+if [ -n "$APPDIR" ]; then
+ HERE="$APPDIR/usr/bin"
+else
+ HERE="$(cd "$(dirname "$0")" && pwd)"
+fi
+
echo "diylc.sh: Running from directory: $HERE"
-# Check if Java is available
-if [ -d "$HERE/jre" ]; then
- export JAVA_HOME="$HERE/jre"
- export PATH="$JAVA_HOME/bin:$PATH"
- JAVA="$JAVA_HOME/bin/java"
- echo "diylc.sh: Using bundled JRE: $JAVA"
-else
- JAVA="$(which java)"
- echo "diylc.sh: Using system Java: $JAVA"
-fi
-
-# Debug: Check Java existence
-if [ ! -x "$JAVA" ]; then
- echo "diylc.sh: ERROR - Java binary not found or not executable!"
+# Use system Java
+JAVA="$(which java)"
+if [ -z "$JAVA" ] || [ ! -x "$JAVA" ]; then
+ echo "diylc.sh: ERROR - System Java not found or not executable!"
+ echo "diylc.sh: Please install Java 17 or later"
exit 1
fi
+echo "diylc.sh: Using system Java: $JAVA"
+
cd "$HERE"
echo "diylc.sh: Current working directory: $(pwd)"
@@ -28,11 +27,9 @@ echo "diylc.sh: Current working directory: $(pwd)"
echo "diylc.sh: Executing DIYLCStarter with Java"
exec "$JAVA" \
- -Xms512m \
+ -Xms1024m \
-Xmx4096m \
- -cp "$HERE/../lib/diylc.jar" \
- --add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED \
- --add-exports java.desktop/com.apple.eio=ALL-UNNAMED \
+ -cp "$APPDIR/usr/lib/diylc.jar" \
--add-opens java.base/java.util=ALL-UNNAMED \
--add-opens java.base/java.lang=ALL-UNNAMED \
--add-opens java.base/java.text=ALL-UNNAMED \
diff --git a/diylc/diylc-swing/deploy/linux/run.sh b/diylc/diylc-swing/deploy/linux/run.sh
index 7f78069a..943efe7f 100755
--- a/diylc/diylc-swing/deploy/linux/run.sh
+++ b/diylc/diylc-swing/deploy/linux/run.sh
@@ -2,4 +2,19 @@
JAVA_BIN="$(which java)"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
CLASS_PATH="${DIR}/diylc.jar"
-exec java -Xms512m -Xmx4096m -Dorg.diylc.scriptRun=true -Dfile.encoding=UTF-8 -cp "$CLASS_PATH" --add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED --add-exports java.desktop/com.apple.eio=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.desktop/java.awt.geom=ALL-UNNAMED org.diylc.DIYLCStarter "$@"
\ No newline at end of file
+
+exec java \
+ -Xms1024m \
+ -Xmx4096m \
+ -Dorg.diylc.scriptRun=true \
+ -Dfile.encoding=UTF-8 \
+ -cp "$CLASS_PATH" \
+ --add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED \
+ --add-exports java.desktop/com.apple.eio=ALL-UNNAMED \
+ --add-opens java.base/java.util=ALL-UNNAMED \
+ --add-opens java.base/java.lang=ALL-UNNAMED \
+ --add-opens java.base/java.text=ALL-UNNAMED \
+ --add-opens java.desktop/java.awt=ALL-UNNAMED \
+ --add-opens java.desktop/java.awt.font=ALL-UNNAMED \
+ --add-opens java.desktop/java.awt.geom=ALL-UNNAMED \
+ org.diylc.DIYLCStarter "$@"
\ No newline at end of file
diff --git a/diylc/diylc-swing/deploy/linux/test-appimage.sh b/diylc/diylc-swing/deploy/linux/test-appimage.sh
new file mode 100755
index 00000000..b8de95c5
--- /dev/null
+++ b/diylc/diylc-swing/deploy/linux/test-appimage.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+# Build the AppImage
+echo "Building AppImage..."
+cd ../..
+#mvn clean package -P linux-appimage
+
+# Check if build was successful
+if [ $? -ne 0 ]; then
+ echo "Build failed!"
+ exit 1
+fi
+
+# Get the AppImage path
+APPIMAGE="target/DIYLayoutCreator-5.1.0-x86_64.AppImage"
+ZIP_FILE="target/diylc-5.1.0-linux.zip"
+
+# Check if files exist
+if [ ! -f "$APPIMAGE" ]; then
+ echo "AppImage not found at $APPIMAGE"
+ exit 1
+fi
+
+if [ ! -f "$ZIP_FILE" ]; then
+ echo "Zip file not found at $ZIP_FILE"
+ exit 1
+fi
+
+# Create test directory
+TEST_DIR="target/appimage-test"
+rm -rf "$TEST_DIR"
+mkdir -p "$TEST_DIR"
+
+# Copy files to test directory
+echo "Copying files to test directory..."
+cp "$APPIMAGE" "$TEST_DIR/"
+cp "$ZIP_FILE" "$TEST_DIR/"
+
+# Extract zip file
+echo "Extracting zip file..."
+cd "$TEST_DIR"
+unzip "diylc-5.1.0-linux.zip"
+
+# Make AppImage executable
+chmod +x "DIYLayoutCreator-5.1.0-x86_64.AppImage"
+
+# Test AppImage structure
+echo "Testing AppImage structure..."
+if [ -f "DIYLayoutCreator-5.1.0-x86_64.AppImage" ]; then
+ echo "AppImage file exists and is executable"
+ echo "AppImage size: $(ls -lh DIYLayoutCreator-5.1.0-x86_64.AppImage | awk '{print $5}')"
+ echo "AppImage permissions: $(ls -l DIYLayoutCreator-5.1.0-x86_64.AppImage | awk '{print $1}')"
+
+ # Check if AppImage has the correct magic number
+ if file "DIYLayoutCreator-5.1.0-x86_64.AppImage" | grep -q "ELF 64-bit LSB executable"; then
+ echo "AppImage has correct ELF format"
+ else
+ echo "Warning: AppImage might not have correct ELF format"
+ fi
+
+ # Check if AppImage has the correct AppImage magic bytes
+ if dd if="DIYLayoutCreator-5.1.0-x86_64.AppImage" bs=8 count=1 2>/dev/null | grep -q "AI"; then
+ echo "AppImage has correct AppImage magic bytes"
+ else
+ echo "Warning: AppImage might not have correct AppImage magic bytes"
+ fi
+
+ echo "AppImage structure test completed successfully!"
+else
+ echo "AppImage file not found in test directory!"
+ exit 1
+fi
\ No newline at end of file
diff --git a/diylc/diylc-swing/deploy/print_version.sh b/diylc/diylc-swing/deploy/print_version.sh
new file mode 100755
index 00000000..2b6cdea0
--- /dev/null
+++ b/diylc/diylc-swing/deploy/print_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Get the directory where this script is located
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# Set DEBUG environment variable
+export DEBUG=true
+
+# Run the VersionReader class
+java -cp "../target/diylc.jar" --add-opens java.base/java.util=ALL-UNNAMED \
+ --add-opens java.base/java.lang=ALL-UNNAMED \
+ --add-opens java.base/java.text=ALL-UNNAMED \
+ --add-opens java.desktop/java.awt=ALL-UNNAMED \
+ --add-opens java.desktop/java.awt.font=ALL-UNNAMED \
+ --add-opens java.desktop/java.awt.geom=ALL-UNNAMED \
+ org.diylc.utils.VersionReader "$SCRIPT_DIR/../"
diff --git a/diylc/diylc-swing/deploy/upload_version.sh b/diylc/diylc-swing/deploy/upload_version.sh
new file mode 100755
index 00000000..7e2376b8
--- /dev/null
+++ b/diylc/diylc-swing/deploy/upload_version.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# Get the directory where this script is located
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# FTP settings
+FTP_USER="diylc_deploy@diy-fever.com"
+FTP_HOST="ftp.diy-fever.com"
+
+# Check if password is set
+if [ -z "$DIYLC_DEPLOY_PWD" ]; then
+ echo "Error: DIYLC_DEPLOY_PWD environment variable is not set"
+ exit 1
+fi
+
+# Source file path
+SOURCE_FILE="$SCRIPT_DIR/../../diylc-core/src/main/resources/update.xml"
+
+# Check if source file exists
+if [ ! -f "$SOURCE_FILE" ]; then
+ echo "Error: update.xml not found at $SOURCE_FILE"
+ exit 1
+fi
+
+# Upload using FTP
+echo "Uploading update.xml to $FTP_USER@$FTP_HOST..."
+ftp -n "$FTP_HOST" << EOF
+user $FTP_USER $DIYLC_DEPLOY_PWD
+binary
+put "$SOURCE_FILE" update.xml
+quit
+EOF
+
+# Check FTP exit status
+if [ $? -eq 0 ]; then
+ echo "Upload successful"
+else
+ echo "Upload failed"
+ exit 1
+fi
diff --git a/diylc/diylc-swing/deploy/win/launch4j-x64.xml b/diylc/diylc-swing/deploy/win/launch4j-x64.xml
index aa8e8e3a..d2740d62 100644
--- a/diylc/diylc-swing/deploy/win/launch4j-x64.xml
+++ b/diylc/diylc-swing/deploy/win/launch4j-x64.xml
@@ -24,7 +24,7 @@
true
17
- 512
+ 1024
4096
-Dorg.diylc.scriptRun=true
-Dfile.encoding=UTF-8
diff --git a/diylc/diylc-swing/dict.txt b/diylc/diylc-swing/dict.txt
index ee8cc2d2..712013cd 100644
--- a/diylc/diylc-swing/dict.txt
+++ b/diylc/diylc-swing/dict.txt
@@ -74,6 +74,7 @@ And
Angle
Angle Offset
Anti-Aliasing
+Apply Model
Arrow Size
Author
Auto-Create Pads
@@ -85,6 +86,8 @@ Below
Board
Board Color
Board Width
+Board1
+Board2
Boards
Bobbin 1
Bobbin 2
@@ -588,6 +591,8 @@ Tubular Beveled
Two
Type
Ultra-miniature
+Underside Display
+Underside Offset
Underside Pad Color
Underside Trace Color
Undo
diff --git a/diylc/diylc-swing/pom.xml b/diylc/diylc-swing/pom.xml
index 95c2456b..ec9dac10 100644
--- a/diylc/diylc-swing/pom.xml
+++ b/diylc/diylc-swing/pom.xml
@@ -260,47 +260,6 @@
-
- sign-jar-launcher
- package
-
- run
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -328,7 +287,7 @@
single
- diylc-${project.version}
+ diylc-${project.version}-universal
false
@@ -391,39 +350,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- JAVA_HOME="$APPDIR/usr/lib/jre"
- JAVA_HOME="$APPDIR/usr/bin/jre"
-
-
@@ -539,9 +465,17 @@
-
+
+
+
+
+
+
+
+
+
-
+
@@ -703,6 +637,49 @@
+
+
+ sign-jar-launcher
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
create-mac-bundle
@@ -740,7 +717,7 @@
-
+
@@ -760,13 +737,6 @@
-
-
-
-
-
-
-
@@ -776,6 +746,13 @@
+
+
+
+
+
+
+
@@ -973,6 +950,49 @@
+
+
+ sign-jar-launcher
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
create-mac-bundle
@@ -1011,7 +1031,7 @@
-
+
@@ -1031,13 +1051,6 @@
-
-
-
-
-
-
-
@@ -1047,6 +1060,13 @@
+
+
+
+
+
+
+
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CopyAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CopyAction.java
index 4ade138c..43c7c7a3 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CopyAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CopyAction.java
@@ -28,7 +28,7 @@ public class CopyAction extends AbstractAction {
this.clipboardOwner = clipboardOwner;
putValue(AbstractAction.NAME, "Copy");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.Copy.getIcon());
}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CutAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CutAction.java
index 714c6eda..048caabe 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CutAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/CutAction.java
@@ -28,7 +28,7 @@ public class CutAction extends AbstractAction {
this.clipboardOwner = clipboardOwner;
putValue(AbstractAction.NAME, "Cut");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.Cut.getIcon());
}
@@ -40,4 +40,4 @@ public class CutAction extends AbstractAction {
clipboardOwner);
plugInPort.deleteSelectedComponents();
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/DuplicateAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/DuplicateAction.java
index f2c59d2e..df8fcd78 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/DuplicateAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/DuplicateAction.java
@@ -21,7 +21,7 @@ public class DuplicateAction extends AbstractAction {
this.plugInPort = plugInPort;
putValue(AbstractAction.NAME, "Duplicate");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_D,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.DocumentsGear.getIcon());
}
@@ -34,4 +34,4 @@ public class DuplicateAction extends AbstractAction {
ActionFactory.LOG.error("Coule not duplicate.", ex);
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/EditSelectionAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/EditSelectionAction.java
index 26a1dd26..667a78e6 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/EditSelectionAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/EditSelectionAction.java
@@ -23,7 +23,7 @@ public class EditSelectionAction extends AbstractAction {
this.plugInPort = plugInPort;
putValue(AbstractAction.NAME, "Edit Selection");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.EditComponent.getIcon());
}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/GroupAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/GroupAction.java
index 69c556cf..14508884 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/GroupAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/GroupAction.java
@@ -21,7 +21,7 @@ public class GroupAction extends AbstractAction {
this.plugInPort = plugInPort;
putValue(AbstractAction.NAME, "Group Selection");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_G,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.Group.getIcon());
}
@@ -30,4 +30,4 @@ public class GroupAction extends AbstractAction {
ActionFactory.LOG.info("Group Selection triggered");
plugInPort.groupSelectedComponents();
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/NudgeAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/NudgeAction.java
index d1a9d92a..b052d964 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/NudgeAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/NudgeAction.java
@@ -32,7 +32,7 @@ public class NudgeAction extends AbstractAction {
putValue(AbstractAction.NAME, "Nudge");
putValue(AbstractAction.SMALL_ICON, IconLoader.FitToSize.getIcon());
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
}
@Override
@@ -56,4 +56,4 @@ public class NudgeAction extends AbstractAction {
plugInPort.nudgeSelection(n.getxOffset(), n.getyOffset(), n.getAffectStuckComponents());
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/PasteAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/PasteAction.java
index 15366fab..24187a85 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/PasteAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/PasteAction.java
@@ -27,7 +27,7 @@ public class PasteAction extends AbstractAction {
this.clipboard = clipboard;
putValue(AbstractAction.NAME, "Paste");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.Paste.getIcon());
}
@@ -43,4 +43,4 @@ public class PasteAction extends AbstractAction {
ActionFactory.LOG.error("Coule not paste.", ex);
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/SelectAllAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/SelectAllAction.java
index c5397742..8df6a8f1 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/SelectAllAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/SelectAllAction.java
@@ -21,7 +21,7 @@ public class SelectAllAction extends AbstractAction {
this.plugInPort = plugInPort;
putValue(AbstractAction.NAME, "Select All");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.Selection.getIcon());
}
@@ -30,4 +30,4 @@ public class SelectAllAction extends AbstractAction {
ActionFactory.LOG.info("Select All triggered");
plugInPort.selectAll(0);
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/UngroupAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/UngroupAction.java
index 4d1f34b7..88bc3af9 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/UngroupAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/edit/UngroupAction.java
@@ -21,7 +21,7 @@ public class UngroupAction extends AbstractAction {
this.plugInPort = plugInPort;
putValue(AbstractAction.NAME, "Ungroup Selection");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_U,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.Ungroup.getIcon());
}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/ImportAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/ImportAction.java
index 1133157e..f2f07987 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/ImportAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/ImportAction.java
@@ -66,7 +66,7 @@ public class ImportAction extends AbstractAction {
}, InMemoryConfigurationManager.getInstance());
putValue(AbstractAction.NAME, "Import");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_I,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.ElementInto.getIcon());
}
@@ -107,4 +107,4 @@ public class ImportAction extends AbstractAction {
}, true);
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/NewAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/NewAction.java
index a254e1bf..60b2dde2 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/NewAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/NewAction.java
@@ -28,7 +28,7 @@ public class NewAction extends AbstractAction {
this.plugInPort = plugInPort;
putValue(AbstractAction.NAME, "New");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.DocumentPlain.getIcon());
}
@@ -54,4 +54,4 @@ public class NewAction extends AbstractAction {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/OpenAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/OpenAction.java
index 650d7e2c..ab257edc 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/OpenAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/OpenAction.java
@@ -28,7 +28,7 @@ public class OpenAction extends AbstractAction {
this.swingUI = swingUI;
putValue(AbstractAction.NAME, "Open");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.FolderOut.getIcon());
}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAction.java
index 56a55153..fea6a5c2 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAction.java
@@ -28,7 +28,7 @@ public class SaveAction extends AbstractAction {
this.swingUI = swingUI;
putValue(AbstractAction.NAME, "Save");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
putValue(AbstractAction.SMALL_ICON, IconLoader.DiskBlue.getIcon());
}
@@ -79,4 +79,4 @@ public class SaveAction extends AbstractAction {
}, true);
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAsAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAsAction.java
index 4509101f..bda4a0b8 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAsAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/file/SaveAsAction.java
@@ -29,7 +29,7 @@ public class SaveAsAction extends AbstractAction {
this.swingUI = swingUI;
putValue(AbstractAction.NAME, "Save As");
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | ActionEvent.SHIFT_MASK));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() | ActionEvent.SHIFT_MASK));
putValue(AbstractAction.SMALL_ICON, IconLoader.DiskBlue.getIcon());
}
@@ -63,4 +63,4 @@ public class SaveAsAction extends AbstractAction {
}, true);
}
}
-}
\ No newline at end of file
+}
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/config/ConfigPlugin.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/config/ConfigPlugin.java
index 204af055..ba5c9df9 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/config/ConfigPlugin.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/config/ConfigPlugin.java
@@ -22,6 +22,7 @@ import java.io.FileInputStream;
import java.io.InputStream;
import java.util.EnumSet;
import java.util.List;
+import java.util.Map;
import javax.swing.Icon;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager;
@@ -174,23 +175,24 @@ public class ConfigPlugin implements IPlugIn {
ActionFactory.getInstance()
.createConfigAction(plugInPort, "Sticky Points", IPlugInPort.STICKY_POINTS_KEY, true), CONFIG_MENU);
- List themeFiles = ResourceUtils.getResourceFiles(THEMES_DIR);
- if (!themeFiles.isEmpty()) {
+ Map themeContents = ResourceUtils.getResourceContents(THEMES_DIR);
+ if (!themeContents.isEmpty()) {
XStream xStream = new XStream(new DomDriver());
xStream.addPermission(AnyTypePermission.ANY);
swingUI.injectSubmenu(THEME_MENU, IconLoader.Pens.getIcon(), CONFIG_MENU);
- for (File file : themeFiles) {
- if (file.getName().toLowerCase().endsWith(".xml")) {
- try {
- InputStream in = new FileInputStream(file);
- Theme theme = (Theme) xStream.fromXML(in);
- LOG.debug("Found theme: " + theme.getName());
- swingUI.injectMenuAction(ActionFactory.getInstance().createThemeAction(plugInPort, theme), THEME_MENU);
- } catch (Exception e) {
- LOG.error("Could not load theme file " + file.getName(), e);
- }
- }
- }
+ themeContents.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(entry -> {
+ if (entry.getKey().toLowerCase().endsWith(".xml")) {
+ try {
+ Theme theme = (Theme) xStream.fromXML(entry.getValue());
+ LOG.debug("Found theme: " + theme.getName());
+ swingUI.injectMenuAction(ActionFactory.getInstance().createThemeAction(plugInPort, theme), THEME_MENU);
+ } catch (Exception e) {
+ LOG.error("Could not load theme file " + entry.getKey(), e);
+ }
+ }
+ });
}
swingUI.injectSubmenu(COMPONENT_BROWSER_MENU, IconLoader.Hammer.getIcon(), CONFIG_MENU);
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/explorer/ExplorerPlugin.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/explorer/ExplorerPlugin.java
index e50f8bc0..b12ff860 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/explorer/ExplorerPlugin.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/explorer/ExplorerPlugin.java
@@ -90,8 +90,7 @@ public class ExplorerPlugin implements IPlugIn {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
- if ((canvasPanel.hasFocus() || explorerPane.hasFocus())
- && e.getKeyChar() == 'x'
+ if (e.getKeyChar() == 'x' && e.getModifiersEx() == 0
&& ConfigurationManager.getInstance()
.readBoolean(ConfigPlugin.PROJECT_EXPLORER, true)) {
explorerPane.getSearchField().requestFocusInWindow();
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/file/FileMenuPlugin.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/file/FileMenuPlugin.java
index afc13691..9c2047c2 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/file/FileMenuPlugin.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/file/FileMenuPlugin.java
@@ -86,7 +86,7 @@ public class FileMenuPlugin implements IPlugIn, IDynamicSubmenuHandler {
swingUI.injectMenuAction(
actionFactory.createExportGerberAction(plugInPort, swingUI), EXPORT_TITLE);
swingUI.injectMenuAction(actionFactory.createPrintAction(drawingProvider, swingUI,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), FILE_TITLE);
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()), FILE_TITLE);
swingUI.injectSubmenu(TRACE_MASK_TITLE, IconLoader.TraceMask.getIcon(), FILE_TITLE);
swingUI.injectMenuAction(actionFactory.createExportPDFAction(plugInPort,
traceMaskDrawingProvider, swingUI, " (mask)"), TRACE_MASK_TITLE);
@@ -94,7 +94,7 @@ public class FileMenuPlugin implements IPlugIn, IDynamicSubmenuHandler {
traceMaskDrawingProvider, swingUI, " (mask)"), TRACE_MASK_TITLE);
swingUI.injectMenuAction(
actionFactory.createPrintAction(traceMaskDrawingProvider, swingUI,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | KeyEvent.SHIFT_DOWN_MASK),
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() | KeyEvent.SHIFT_DOWN_MASK),
TRACE_MASK_TITLE);
swingUI.injectSubmenu(ANALYZE_TITLE, IconLoader.Scientist.getIcon(), FILE_TITLE);
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/layers/LayersMenuPlugin.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/layers/LayersMenuPlugin.java
index a4079c5c..9f315e9e 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/layers/LayersMenuPlugin.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/layers/LayersMenuPlugin.java
@@ -79,7 +79,7 @@ public class LayersMenuPlugin implements IPlugIn {
};
visibleAction.putValue(IView.CHECK_BOX_MENU_ITEM, true);
visibleAction.putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_0 + zOrder,
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));
visibleActionMap.put(layer, visibleAction);
AbstractAction selectAllAction = new AbstractAction("Select All") {
diff --git a/diylc/pom.xml b/diylc/pom.xml
index 0a778581..8f852003 100644
--- a/diylc/pom.xml
+++ b/diylc/pom.xml
@@ -23,7 +23,7 @@
17
17
1.2.15
- 1.4.19
+ 1.4.21
@@ -61,7 +61,7 @@
junit
junit
- 4.7
+ 4.13.1
test