diff --git a/diylc/diylc-core/pom.xml b/diylc/diylc-core/pom.xml
index a96995f3..2ee50f0d 100644
--- a/diylc/diylc-core/pom.xml
+++ b/diylc/diylc-core/pom.xml
@@ -62,6 +62,13 @@
junit
test
+
+
+ org.mockito
+ mockito-core
+ 5.11.0
+ test
+
diff --git a/diylc/diylc-core/src/main/java/org/diylc/common/IPlugInPort.java b/diylc/diylc-core/src/main/java/org/diylc/common/IPlugInPort.java
index f5c69b3f..9e76e511 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/common/IPlugInPort.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/common/IPlugInPort.java
@@ -61,6 +61,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
public static final String ANTI_ALIASING_KEY = "antiAliasing";
public static final String HI_QUALITY_RENDER_KEY = "hiQualityRender";
+ public static final String HIGH_DPI_RENDERING = "hiDpiRendering";
public static final String EXPORT_GRID_KEY = "exportGrid";
public static final String STICKY_POINTS_KEY = "stickyPoints";
public static final String METRIC_KEY = "metric";
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 24bc5ad0..abff8506 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
@@ -120,4 +120,10 @@ public class DatasheetService {
return null;
}
+
+ // Add method to clear cache for testing
+ public void clearCache() {
+ datasheetCache.clear();
+ lookupCache.clear();
+ }
}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingCache.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingCache.java
index e0aacfe2..88e9d789 100644
--- a/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingCache.java
+++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/DrawingCache.java
@@ -181,6 +181,11 @@ public class DrawingCache {
private CacheValue renderAndCache(IDIYComponent> component, G2DWrapper g2d, ComponentState componentState,
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder) {
+
+ if (!g2d.getClipBounds().intersects(component.getCachingBounds())) {
+ return null;
+ }
+
// if we need to apply caching
Point2D firstPoint = component.getControlPoint(0);
@@ -311,6 +316,7 @@ public class DrawingCache {
this.zoom = zoom;
this.dx = dx;
this.dy = dy;
+ this.scaleFactor = scaleFactor;
}
public IDIYComponent> getComponent() {
diff --git a/diylc/diylc-core/src/main/resources/update.xml b/diylc/diylc-core/src/main/resources/update.xml
index 4d285908..3ed8e068 100644
--- a/diylc/diylc-core/src/main/resources/update.xml
+++ b/diylc/diylc-core/src/main/resources/update.xml
@@ -249,6 +249,14 @@
2025-03-09 00:00:00.000 CET
+
+ NEW_FEATURE
+ Configurable 'High DPI Rendering' feature which makes the diagram smoother on high-resolution displays but can affect performance
+
+
+ IMPROVEMENT
+ Significantly improved rendering performance
+
IMPROVEMENT
Upgraded source code structure to modern standards and introduced Maven
diff --git a/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java b/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java
index 611162aa..00d1c46f 100644
--- a/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java
+++ b/diylc/diylc-core/src/test/java/org/diylc/presenter/CalcUtilsTest.java
@@ -1,27 +1,145 @@
package org.diylc.presenter;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
-import org.junit.Test;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+import java.util.List;
+import org.diylc.core.IDIYComponent;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
-import org.diylc.presenter.CalcUtils;
+import org.junit.Test;
public class CalcUtilsTest {
- @Test
- public void TestRoundToGrid() {
- Size spacing = new Size(1d, SizeUnit.mm);
- int value = 5;
- double s = spacing.convertToPixels();
- double targetPrev = (value - 1) * s;
- double target = value * s;
- double targetNext = (value + 1) * s;
- for (int i = -100; i <= 100; i++) {
- double rounded = CalcUtils.roundToGrid(target + i / 100.0 * s, spacing);
- double expected = i < -50 ? targetPrev : (i >= 50 ? targetNext : target);
- assertTrue("Failed at " + i + " rounded = " + rounded + "; expected = " + expected, Math.abs(rounded - expected) < 1e-10);
+ @Test
+ public void testRoundToGrid() {
+ Size gridSpacing = new Size(10.0, SizeUnit.px);
+
+ // Test exact grid points
+ assertEquals(10.0, CalcUtils.roundToGrid(10.0, gridSpacing), 0.001);
+ assertEquals(20.0, CalcUtils.roundToGrid(20.0, gridSpacing), 0.001);
+
+ // Test rounding up
+ assertEquals(10.0, CalcUtils.roundToGrid(8.0, gridSpacing), 0.001);
+ assertEquals(20.0, CalcUtils.roundToGrid(16.0, gridSpacing), 0.001);
+
+ // Test rounding down
+ assertEquals(10.0, CalcUtils.roundToGrid(12.0, gridSpacing), 0.001);
+ assertEquals(20.0, CalcUtils.roundToGrid(22.0, gridSpacing), 0.001);
+
+ // Test with different grid spacing
+ Size finerGrid = new Size(5.0, SizeUnit.px);
+ assertEquals(5.0, CalcUtils.roundToGrid(6.0, finerGrid), 0.001);
+ assertEquals(15.0, CalcUtils.roundToGrid(13.0, finerGrid), 0.001);
+ }
+
+ @Test
+ public void testSnapPointToGrid() {
+ Size gridSpacing = new Size(10.0, SizeUnit.px);
+ Point2D point = new Point2D.Double(12.0, 18.0);
+
+ CalcUtils.snapPointToGrid(point, gridSpacing);
+
+ assertEquals(10.0, point.getX(), 0.001);
+ assertEquals(20.0, point.getY(), 0.001);
+
+ // Test with point exactly on grid
+ point.setLocation(20.0, 30.0);
+ CalcUtils.snapPointToGrid(point, gridSpacing);
+ assertEquals(20.0, point.getX(), 0.001);
+ assertEquals(30.0, point.getY(), 0.001);
+
+ // Test with different grid spacing
+ Size finerGrid = new Size(5.0, SizeUnit.px);
+ point.setLocation(13.0, 28.0);
+ CalcUtils.snapPointToGrid(point, finerGrid);
+ assertEquals(15.0, point.getX(), 0.001);
+ assertEquals(30.0, point.getY(), 0.001);
+ }
+
+ @Test
+ public void testFindClosestMultiplierOf() {
+ Size factor = new Size(1.0, SizeUnit.mm);
+ Size target = new Size(3.5, SizeUnit.mm);
+ int step = 1;
+
+ Size result = CalcUtils.findClosestMultiplierOf(factor, target, step);
+ assertEquals(4.0, result.getValue(), 0.001);
+ assertEquals(SizeUnit.mm, result.getUnit());
+
+ // Test with different step
+ result = CalcUtils.findClosestMultiplierOf(factor, target, 2);
+ assertEquals(4.0, result.getValue(), 0.001);
+
+ // Test with different factor
+ factor = new Size(0.5, SizeUnit.mm);
+ result = CalcUtils.findClosestMultiplierOf(factor, target, step);
+ assertEquals(3.5, result.getValue(), 0.001);
+ }
+
+ @Test
+ public void testSnapPointToObjects() {
+ Size gridSpacing = new Size(10.0, SizeUnit.px);
+ Point2D point = new Point2D.Double(12.0, 18.0);
+
+ // Create mock components
+ IDIYComponent> component1 = mock(IDIYComponent.class);
+ IDIYComponent> component2 = mock(IDIYComponent.class);
+
+ // Setup component1 with a sticky point near our test point
+ when(component1.getControlPointCount()).thenReturn(1);
+ when(component1.isControlPointSticky(0)).thenReturn(true);
+ when(component1.getControlPoint(0)).thenReturn(new Point2D.Double(10.0, 20.0));
+
+ // Setup component2 with a non-sticky point
+ when(component2.getControlPointCount()).thenReturn(1);
+ when(component2.isControlPointSticky(0)).thenReturn(false);
+ when(component2.getControlPoint(0)).thenReturn(new Point2D.Double(11.0, 19.0));
+
+ List> components = Arrays.asList(component1, component2);
+
+ // Test snapping to sticky point
+ CalcUtils.snapPointToObjects(point, gridSpacing, null, components);
+ assertEquals(10.0, point.getX(), 0.001);
+ assertEquals(20.0, point.getY(), 0.001);
+
+ // Test not snapping when point is too far
+ point.setLocation(25.0, 25.0);
+ CalcUtils.snapPointToObjects(point, gridSpacing, null, components);
+ assertEquals(25.0, point.getX(), 0.001);
+ assertEquals(25.0, point.getY(), 0.001);
+
+ // Test not snapping to non-sticky points
+ point.setLocation(15.0, 23.0); // Changed coordinates to be further from sticky point
+ CalcUtils.snapPointToObjects(point, gridSpacing, null, components);
+ assertEquals(15.0, point.getX(), 0.001);
+ assertEquals(23.0, point.getY(), 0.001);
+ }
+
+ @Test
+ public void testPointsMatch() {
+ Point2D point1 = new Point2D.Double(10.0, 20.0);
+ Point2D point2 = new Point2D.Double(10.0, 20.0);
+
+ // Test exact match
+ assertTrue(CalcUtils.pointsMatch(point1, point2, 0.001));
+
+ // Test within delta
+ point2.setLocation(10.1, 20.1);
+ assertTrue(CalcUtils.pointsMatch(point1, point2, 0.2));
+
+ // Test outside delta
+ assertFalse(CalcUtils.pointsMatch(point1, point2, 0.05));
+
+ // Test x coordinate outside delta
+ point2.setLocation(11.0, 20.0);
+ assertFalse(CalcUtils.pointsMatch(point1, point2, 0.5));
+
+ // Test y coordinate outside delta
+ point2.setLocation(10.0, 21.0);
+ assertFalse(CalcUtils.pointsMatch(point1, point2, 0.5));
}
- }
}
diff --git a/diylc/diylc-core/src/test/java/org/diylc/presenter/ComponentProcessorTest.java b/diylc/diylc-core/src/test/java/org/diylc/presenter/ComponentProcessorTest.java
new file mode 100644
index 00000000..27c2b2c4
--- /dev/null
+++ b/diylc/diylc-core/src/test/java/org/diylc/presenter/ComponentProcessorTest.java
@@ -0,0 +1,219 @@
+package org.diylc.presenter;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.awt.Point;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+import java.util.List;
+
+import org.diylc.common.ComponentType;
+import org.diylc.common.IComponentTransformer;
+import org.diylc.common.PropertyWrapper;
+import org.diylc.components.AbstractComponent;
+import org.diylc.core.CreationMethod;
+import org.diylc.core.IDIYComponent;
+import org.diylc.core.VisibilityPolicy;
+import org.diylc.core.annotations.BomPolicy;
+import org.diylc.core.annotations.ComponentDescriptor;
+import org.diylc.core.annotations.EditableProperty;
+import org.diylc.core.annotations.KeywordPolicy;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ComponentProcessorTest {
+
+ private ComponentProcessor processor;
+
+ @Before
+ public void setUp() {
+ processor = ComponentProcessor.getInstance();
+ }
+
+ @ComponentDescriptor(
+ name = "Test Component",
+ category = "Test",
+ author = "Test Author",
+ description = "Test Description",
+ instanceNamePrefix = "TEST",
+ creationMethod = CreationMethod.POINT_BY_POINT,
+ zOrder = IDIYComponent.COMPONENT,
+ flexibleZOrder = false,
+ bomPolicy = BomPolicy.NEVER_SHOW,
+ autoEdit = false,
+ enableCache = true,
+ keywordPolicy = KeywordPolicy.SHOW_VALUE,
+ keywordTag = "",
+ enableDatasheet = false,
+ datasheetCreationStepCount = 0
+ )
+ public static class TestComponent extends AbstractComponent