mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 17:22:09 +10:00
mirror
This commit is contained in:
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -13,16 +13,15 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.bancika.gerberwriter.DataLayer;
|
|
||||||
|
|
||||||
import org.diylc.core.ComponentState;
|
import org.diylc.core.ComponentState;
|
||||||
|
import org.diylc.core.IBoard;
|
||||||
import org.diylc.core.IDIYComponent;
|
import org.diylc.core.IDIYComponent;
|
||||||
import org.diylc.core.IView;
|
import org.diylc.core.IView;
|
||||||
import org.diylc.core.Project;
|
import org.diylc.core.Project;
|
||||||
import org.diylc.core.measures.Size;
|
import org.diylc.core.measures.Size;
|
||||||
import org.diylc.core.measures.SizeUnit;
|
import org.diylc.core.measures.SizeUnit;
|
||||||
import org.diylc.lang.LangUtil;
|
import org.diylc.lang.LangUtil;
|
||||||
|
import com.bancika.gerberwriter.DataLayer;
|
||||||
|
|
||||||
public class GerberExporter {
|
public class GerberExporter {
|
||||||
|
|
||||||
@@ -30,44 +29,47 @@ public class GerberExporter {
|
|||||||
private static final Logger LOG = Logger.getLogger(GerberExporter.class);
|
private static final Logger LOG = Logger.getLogger(GerberExporter.class);
|
||||||
|
|
||||||
public static void exportGerber(String fileNameBase, Project currentProject, IView view,
|
public static void exportGerber(String fileNameBase, Project currentProject, IView view,
|
||||||
Graphics2D graphics2d, String diylcVersion) {
|
Graphics2D graphics2d, String diylcVersion) {
|
||||||
List<IGerberBoard> gerberBoards =
|
|
||||||
currentProject.getComponents().stream().filter(c -> c instanceof IGerberBoard)
|
|
||||||
.map(x -> (IGerberBoard) x).collect(Collectors.toList());
|
|
||||||
|
|
||||||
Map<IGerberBoard, List<IDIYComponent<?>>> boardComponentMap =
|
List<IBoard> gerberBoards =
|
||||||
new HashMap<IGerberBoard, List<IDIYComponent<?>>>();
|
currentProject.getComponents().stream()
|
||||||
|
.filter(IBoard.class::isInstance)
|
||||||
|
.map(IBoard.class::cast)
|
||||||
|
.filter(IBoard::shouldExportToGerber).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Map<IBoard, List<IDIYComponent<?>>> boardComponentMap =
|
||||||
|
new HashMap<IBoard, List<IDIYComponent<?>>>();
|
||||||
|
|
||||||
// DefaultGerberBoard defaultGerberBoard = new DefaultGerberBoard();
|
// DefaultGerberBoard defaultGerberBoard = new DefaultGerberBoard();
|
||||||
|
|
||||||
List<IDIYComponent<?>> componentsWithoutBoard = new ArrayList<IDIYComponent<?>>();
|
List<IDIYComponent<?>> componentsWithoutBoard = new ArrayList<IDIYComponent<?>>();
|
||||||
|
|
||||||
currentProject.getComponents().stream().filter(c -> c instanceof IGerberComponent)
|
currentProject.getComponents().stream().filter(c -> c instanceof IGerberComponent)
|
||||||
.forEach(c -> {
|
.forEach(c -> {
|
||||||
Point2D firstPoint = c.getControlPoint(0);
|
Point2D firstPoint = c.getControlPoint(0);
|
||||||
IGerberBoard board = gerberBoards.stream()
|
IBoard board = gerberBoards.stream()
|
||||||
.filter(b -> b.getBoardRectangle().contains(firstPoint)).findFirst().orElse(null);
|
.filter(b -> b.getBoardRectangle().contains(firstPoint)).findFirst().orElse(null);
|
||||||
if (board == null) {
|
if (board == null) {
|
||||||
componentsWithoutBoard.add(c);
|
componentsWithoutBoard.add(c);
|
||||||
} else {
|
} else {
|
||||||
boardComponentMap.computeIfAbsent(board, k -> new ArrayList<IDIYComponent<?>>()).add(c);
|
boardComponentMap.computeIfAbsent(board, k -> new ArrayList<IDIYComponent<?>>()).add(c);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// defaultGerberBoard.setComponents(boardComponentMap.get(defaultGerberBoard));
|
// defaultGerberBoard.setComponents(boardComponentMap.get(defaultGerberBoard));
|
||||||
|
|
||||||
if (boardComponentMap.isEmpty()) {
|
if (boardComponentMap.isEmpty()) {
|
||||||
view.showMessage(LangUtil.translate("Nothing to export."),
|
view.showMessage(LangUtil.translate("Nothing to export."),
|
||||||
LangUtil.translate("Gerber Export"), IView.WARNING_MESSAGE);
|
LangUtil.translate("Gerber Export"), IView.WARNING_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentsWithoutBoard.size() > 0) {
|
if (componentsWithoutBoard.size() > 0) {
|
||||||
if (view.showConfirmDialog(String.format(
|
if (view.showConfirmDialog(String.format(
|
||||||
LangUtil.translate("There are some components that are outside of the bounds of boards.%s"
|
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?"),
|
+ "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,
|
"\n", "\n"), LangUtil.translate("Gerber Export"), IView.YES_NO_OPTION,
|
||||||
IView.WARNING_MESSAGE) != IView.YES_OPTION) {
|
IView.WARNING_MESSAGE) != IView.YES_OPTION) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,15 +90,15 @@ public class GerberExporter {
|
|||||||
String fileNameOutline = GerberLayer.Outline.formatFileName(fileNameBase, boardComponent.getName());
|
String fileNameOutline = GerberLayer.Outline.formatFileName(fileNameBase, boardComponent.getName());
|
||||||
try {
|
try {
|
||||||
LOG.info(String.format(LangUtil.translate("Exporting outline for board %s to file %s"),
|
LOG.info(String.format(LangUtil.translate("Exporting outline for board %s to file %s"),
|
||||||
boardComponent.getName(), fileNameOutline));
|
boardComponent.getName(), fileNameOutline));
|
||||||
outlineLayer.dumpGerberToFile(fileNameOutline);
|
outlineLayer.dumpGerberToFile(fileNameOutline);
|
||||||
generatedFiles.add(fileNameOutline);
|
generatedFiles.add(fileNameOutline);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error writing gerber file: " + e.getMessage());
|
LOG.error("Error writing gerber file: " + e.getMessage());
|
||||||
view.showMessage(
|
view.showMessage(
|
||||||
LangUtil.translate(
|
LangUtil.translate(
|
||||||
"Failed to export the project to gerber. Please check the log for details"),
|
"Failed to export the project to gerber. Please check the log for details"),
|
||||||
LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
|
LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,30 +121,30 @@ public class GerberExporter {
|
|||||||
try {
|
try {
|
||||||
String fileName = layer.formatFileName(fileNameBase, boardComponent.getName());
|
String fileName = layer.formatFileName(fileNameBase, boardComponent.getName());
|
||||||
LOG.info("Exporting layer: " + layer + " for board " + boardComponent.getName()
|
LOG.info("Exporting layer: " + layer + " for board " + boardComponent.getName()
|
||||||
+ " to file: " + fileName);
|
+ " to file: " + fileName);
|
||||||
dataLayer.dumpGerberToFile(fileName);
|
dataLayer.dumpGerberToFile(fileName);
|
||||||
generatedFiles.add(fileName);
|
generatedFiles.add(fileName);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error writing gerber file: " + e.getMessage());
|
LOG.error("Error writing gerber file: " + e.getMessage());
|
||||||
view.showMessage(
|
view.showMessage(
|
||||||
LangUtil.translate(
|
LangUtil.translate(
|
||||||
"Failed to export the project to gerber. Please check the log for details"),
|
"Failed to export the project to gerber. Please check the log for details"),
|
||||||
LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
|
LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
view.showMessage(
|
view.showMessage(
|
||||||
String.format(
|
String.format(
|
||||||
LangUtil.translate(
|
LangUtil.translate(
|
||||||
"Gerber export completed successfully. The following files were created:%s"),
|
"Gerber export completed successfully. The following files were created:%s"),
|
||||||
"\n\n" + String.join("\n", generatedFiles)),
|
"\n\n" + String.join("\n", generatedFiles)),
|
||||||
LangUtil.translate("Gerber Export"), IView.INFORMATION_MESSAGE);
|
LangUtil.translate("Gerber Export"), IView.INFORMATION_MESSAGE);
|
||||||
LOG.info("Completed export to gerber");
|
LOG.info("Completed export to gerber");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawComponent(Project currentProject, GerberG2DWrapper g2d,
|
private static void drawComponent(Project currentProject, GerberG2DWrapper g2d,
|
||||||
IDIYComponent<?> c, boolean outlineMode) {
|
IDIYComponent<?> c, boolean outlineMode) {
|
||||||
IGerberComponent gerberComponent = (IGerberComponent) c;
|
IGerberComponent gerberComponent = (IGerberComponent) c;
|
||||||
g2d.startedDrawingComponent();
|
g2d.startedDrawingComponent();
|
||||||
if (gerberComponent instanceof IGerberComponentCustom) {
|
if (gerberComponent instanceof IGerberComponentCustom) {
|
||||||
@@ -151,9 +153,9 @@ public class GerberExporter {
|
|||||||
} else if (gerberComponent instanceof IGerberComponentSimple) {
|
} else if (gerberComponent instanceof IGerberComponentSimple) {
|
||||||
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
|
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
|
||||||
g2d.startGerberOutput(gerberComponentSimple.getGerberLayer(),
|
g2d.startGerberOutput(gerberComponentSimple.getGerberLayer(),
|
||||||
gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
|
gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
|
||||||
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
|
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
|
||||||
g2d.stopGerberOutput();
|
g2d.stopGerberOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package org.diylc.core.gerber;
|
|
||||||
|
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
|
|
||||||
public interface IGerberBoard {
|
|
||||||
|
|
||||||
Rectangle2D getBoardRectangle();
|
|
||||||
}
|
|
||||||
@@ -74,7 +74,7 @@ public class DrawingCache {
|
|||||||
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) x.getComponent().getClass());
|
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) x.getComponent().getClass());
|
||||||
|
|
||||||
if (type != null && type.getEnableCache()) {
|
if (type != null && type.getEnableCache()) {
|
||||||
renderAndCache(x.getComponent(), g2d, x.getState(), outlineMode, project, zoom, scaleFactor, x.getZOrder());
|
renderAndCache(x.getComponent(), g2d, x.getState(), outlineMode, project, zoom, scaleFactor, x.getZOrder(), false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -89,10 +89,14 @@ public class DrawingCache {
|
|||||||
* @param outlineMode
|
* @param outlineMode
|
||||||
* @param project
|
* @param project
|
||||||
* @param zoom
|
* @param zoom
|
||||||
|
* @param scaleFactor
|
||||||
|
* @param zOrder
|
||||||
|
* @param mirrored
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void draw(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
|
public void draw(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
|
||||||
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder, Rectangle2D visibleRect) {
|
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder, Rectangle2D visibleRect,
|
||||||
|
boolean mirrored) {
|
||||||
ComponentType type = ComponentProcessor.getInstance()
|
ComponentType type = ComponentProcessor.getInstance()
|
||||||
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
|
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
|
||||||
|
|
||||||
@@ -100,7 +104,7 @@ public class DrawingCache {
|
|||||||
// if we need to apply caching
|
// if we need to apply caching
|
||||||
Point2D firstPoint = component.getControlPoint(0);
|
Point2D firstPoint = component.getControlPoint(0);
|
||||||
|
|
||||||
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom, scaleFactor, zOrder);
|
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom, scaleFactor, zOrder, mirrored);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return;
|
return;
|
||||||
@@ -180,7 +184,7 @@ public class DrawingCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CacheValue renderAndCache(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
|
private CacheValue renderAndCache(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
|
||||||
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder) {
|
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder, boolean mirrored) {
|
||||||
// if we need to apply caching
|
// if we need to apply caching
|
||||||
Point2D firstPoint = component.getControlPoint(0);
|
Point2D firstPoint = component.getControlPoint(0);
|
||||||
|
|
||||||
@@ -196,7 +200,7 @@ public class DrawingCache {
|
|||||||
// only honor the cache if the component hasn't changed in the meantime
|
// only honor the cache if the component hasn't changed in the meantime
|
||||||
if (value == null || !value.getComponent().equalsTo(component)
|
if (value == null || !value.getComponent().equalsTo(component)
|
||||||
|| value.getState() != componentState || value.getZoom() != zoom || value.getOutlineMode() != outlineMode
|
|| value.getState() != componentState || value.getZoom() != zoom || value.getOutlineMode() != outlineMode
|
||||||
|| value.getScaleFactor() != scaleFactor) {
|
|| value.getScaleFactor() != scaleFactor || value.isMirrored() != mirrored) {
|
||||||
// figure out size and placement of buffer image
|
// figure out size and placement of buffer image
|
||||||
Rectangle2D rect = component.getCachingBounds();
|
Rectangle2D rect = component.getCachingBounds();
|
||||||
int width = (int)Math.round(rect.getWidth() * zoom);
|
int width = (int)Math.round(rect.getWidth() * zoom);
|
||||||
@@ -270,7 +274,7 @@ public class DrawingCache {
|
|||||||
|
|
||||||
// add to the cache
|
// add to the cache
|
||||||
value = new CacheValue(component, image, wrapper.getCurrentArea(), wrapper.getContinuityPositiveAreas(),
|
value = new CacheValue(component, image, wrapper.getCurrentArea(), wrapper.getContinuityPositiveAreas(),
|
||||||
wrapper.getContinuityNegativeAreas(), componentState, outlineMode, zoom, scaleFactor, dx, dy, rect);
|
wrapper.getContinuityNegativeAreas(), componentState, outlineMode, zoom, scaleFactor, dx, dy, rect, mirrored);
|
||||||
imageCache.put(component, new SoftReference<DrawingCache.CacheValue>(value));
|
imageCache.put(component, new SoftReference<DrawingCache.CacheValue>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,6 +291,7 @@ public class DrawingCache {
|
|||||||
boolean outlineMode;
|
boolean outlineMode;
|
||||||
double zoom;
|
double zoom;
|
||||||
double scaleFactor;
|
double scaleFactor;
|
||||||
|
boolean mirrored;
|
||||||
int dx;
|
int dx;
|
||||||
int dy;
|
int dy;
|
||||||
Rectangle2D cacheBounds;
|
Rectangle2D cacheBounds;
|
||||||
@@ -294,7 +299,7 @@ public class DrawingCache {
|
|||||||
public CacheValue(IDIYComponent<?> component, BufferedImage image, Area currentArea,
|
public CacheValue(IDIYComponent<?> component, BufferedImage image, Area currentArea,
|
||||||
Map<String, Area> continuityPositiveAreas, Map<String, Area> continuityNegativeAreas,
|
Map<String, Area> continuityPositiveAreas, Map<String, Area> continuityNegativeAreas,
|
||||||
ComponentState state, boolean outlineMode, double zoom, double scaleFactor, int dx, int dy,
|
ComponentState state, boolean outlineMode, double zoom, double scaleFactor, int dx, int dy,
|
||||||
Rectangle2D cacheBounds) {
|
Rectangle2D cacheBounds, boolean mirrored) {
|
||||||
super();
|
super();
|
||||||
this.cacheBounds = cacheBounds;
|
this.cacheBounds = cacheBounds;
|
||||||
// take a copy of the component, so we can check if it changed in the meantime
|
// take a copy of the component, so we can check if it changed in the meantime
|
||||||
@@ -309,6 +314,7 @@ public class DrawingCache {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
this.outlineMode = outlineMode;
|
this.outlineMode = outlineMode;
|
||||||
this.zoom = zoom;
|
this.zoom = zoom;
|
||||||
|
this.scaleFactor = scaleFactor;
|
||||||
this.dx = dx;
|
this.dx = dx;
|
||||||
this.dy = dy;
|
this.dy = dy;
|
||||||
}
|
}
|
||||||
@@ -349,6 +355,10 @@ public class DrawingCache {
|
|||||||
return scaleFactor;
|
return scaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMirrored() {
|
||||||
|
return mirrored;
|
||||||
|
}
|
||||||
|
|
||||||
public int getDx() {
|
public int getDx() {
|
||||||
return dx;
|
return dx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||||
*
|
*
|
||||||
* This file is part of DIYLC.
|
* This file is part of DIYLC.
|
||||||
*
|
*
|
||||||
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
* License, or (at your option) any later version.
|
* License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
* Public License for more details.
|
* Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
||||||
* <http://www.gnu.org/licenses/>.
|
* <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -46,17 +46,20 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
import org.checkerframework.checker.units.qual.A;
|
||||||
import org.diylc.appframework.miscutils.IConfigurationManager;
|
import org.diylc.appframework.miscutils.IConfigurationManager;
|
||||||
import org.diylc.appframework.simplemq.MessageDispatcher;
|
import org.diylc.appframework.simplemq.MessageDispatcher;
|
||||||
|
|
||||||
import org.diylc.common.DrawOption;
|
import org.diylc.common.DrawOption;
|
||||||
import org.diylc.common.EventType;
|
import org.diylc.common.EventType;
|
||||||
import org.diylc.common.GridType;
|
import org.diylc.common.GridType;
|
||||||
import org.diylc.common.IComponentFilter;
|
import org.diylc.common.IComponentFilter;
|
||||||
import org.diylc.common.IPlugInPort;
|
import org.diylc.common.IPlugInPort;
|
||||||
import org.diylc.common.ObjectCache;
|
import org.diylc.common.ObjectCache;
|
||||||
|
import org.diylc.components.AbstractTransparentComponent;
|
||||||
|
import org.diylc.core.BoardUndersideDisplay;
|
||||||
import org.diylc.core.ComponentForRender;
|
import org.diylc.core.ComponentForRender;
|
||||||
import org.diylc.core.ComponentState;
|
import org.diylc.core.ComponentState;
|
||||||
|
import org.diylc.core.IBoard;
|
||||||
import org.diylc.core.IContinuity;
|
import org.diylc.core.IContinuity;
|
||||||
import org.diylc.core.IDIYComponent;
|
import org.diylc.core.IDIYComponent;
|
||||||
import org.diylc.core.ILayeredComponent;
|
import org.diylc.core.ILayeredComponent;
|
||||||
@@ -72,7 +75,7 @@ import org.diylc.utils.Constants;
|
|||||||
/**
|
/**
|
||||||
* Utility that deals with painting {@link Project} on the {@link Graphics2D} and keeps areas taken
|
* Utility that deals with painting {@link Project} on the {@link Graphics2D} and keeps areas taken
|
||||||
* by each drawn component.
|
* by each drawn component.
|
||||||
*
|
*
|
||||||
* @author Branislav Stojkovic
|
* @author Branislav Stojkovic
|
||||||
*/
|
*/
|
||||||
public class DrawingManager {
|
public class DrawingManager {
|
||||||
@@ -92,6 +95,8 @@ public class DrawingManager {
|
|||||||
public static Color CONTROL_POINT_COLOR = Color.blue;
|
public static Color CONTROL_POINT_COLOR = Color.blue;
|
||||||
public static Color SELECTED_CONTROL_POINT_COLOR = Color.green;
|
public static Color SELECTED_CONTROL_POINT_COLOR = Color.green;
|
||||||
|
|
||||||
|
private static final Byte MIRRORED_ALPHA = 64;
|
||||||
|
|
||||||
private Theme theme;
|
private Theme theme;
|
||||||
|
|
||||||
// Maps keyed by object reference.
|
// Maps keyed by object reference.
|
||||||
@@ -127,7 +132,7 @@ public class DrawingManager {
|
|||||||
private List<Area> proximityMarkers = null;
|
private List<Area> proximityMarkers = null;
|
||||||
|
|
||||||
public DrawingManager(MessageDispatcher<EventType> messageDispatcher,
|
public DrawingManager(MessageDispatcher<EventType> messageDispatcher,
|
||||||
IConfigurationManager<?> configManager) {
|
IConfigurationManager<?> configManager) {
|
||||||
super();
|
super();
|
||||||
this.messageDispatcher = messageDispatcher;
|
this.messageDispatcher = messageDispatcher;
|
||||||
this.configManager = configManager;
|
this.configManager = configManager;
|
||||||
@@ -145,16 +150,16 @@ public class DrawingManager {
|
|||||||
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
|
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
|
||||||
String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS);
|
String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS);
|
||||||
debugComponentAreas =
|
debugComponentAreas =
|
||||||
debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true");
|
debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true");
|
||||||
|
|
||||||
String debugContinuityAreasStr = System.getProperty(DEBUG_CONTINUITY_AREAS);
|
String debugContinuityAreasStr = System.getProperty(DEBUG_CONTINUITY_AREAS);
|
||||||
debugContinuityAreas =
|
debugContinuityAreas =
|
||||||
debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true");
|
debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the project onto the canvas and returns the list of components that failed to draw.
|
* Paints the project onto the canvas and returns the list of components that failed to draw.
|
||||||
*
|
*
|
||||||
* @param g2d
|
* @param g2d
|
||||||
* @param project
|
* @param project
|
||||||
* @param drawOptions
|
* @param drawOptions
|
||||||
@@ -167,16 +172,18 @@ public class DrawingManager {
|
|||||||
* @param componentSlot
|
* @param componentSlot
|
||||||
* @param dragInProgress
|
* @param dragInProgress
|
||||||
* @param externalZoom
|
* @param externalZoom
|
||||||
* @param scaleFactor
|
* @param scaleFactor
|
||||||
* @param visibleRect
|
* @param visibleRect
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unlikely-arg-type")
|
||||||
public List<IDIYComponent<?>> drawProject(Graphics2D g2d, Project project,
|
public List<IDIYComponent<?>> drawProject(Graphics2D g2d, Project project,
|
||||||
Set<DrawOption> drawOptions, IComponentFilter filter, Rectangle selectionRect,
|
Set<DrawOption> drawOptions, IComponentFilter filter, Rectangle selectionRect,
|
||||||
Collection<IDIYComponent<?>> selectedComponents, Set<IDIYComponent<?>> lockedComponents,
|
Collection<IDIYComponent<?>> selectedComponents, Set<IDIYComponent<?>> lockedComponents,
|
||||||
Set<IDIYComponent<?>> groupedComponents, List<Point2D> controlPointSlot,
|
Set<IDIYComponent<?>> groupedComponents, List<Point2D> controlPointSlot,
|
||||||
List<IDIYComponent<?>> componentSlot, boolean dragInProgress, Double externalZoom,
|
List<IDIYComponent<?>> componentSlot, boolean dragInProgress, Double externalZoom,
|
||||||
Double scaleFactor, Rectangle2D visibleRect) {
|
Double scaleFactor, Rectangle2D visibleRect) {
|
||||||
|
|
||||||
long totalStartTime = System.nanoTime();
|
long totalStartTime = System.nanoTime();
|
||||||
failedComponents.clear();
|
failedComponents.clear();
|
||||||
if (project == null) {
|
if (project == null) {
|
||||||
@@ -195,42 +202,39 @@ public class DrawingManager {
|
|||||||
|
|
||||||
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
|
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
|
||||||
|
|
||||||
if (drawOptions.contains(DrawOption.ANTIALIASING)) {
|
configureG2D(g2d, drawOptions);
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
// group components with boards that contain them
|
||||||
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
Map<IBoard, List<IDIYComponent<?>>> boardMap = project.getComponents().stream()
|
||||||
} else {
|
.filter(IBoard.class::isInstance)
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
|
.map(IBoard.class::cast)
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
.filter(b -> b.getBoardUndersideDisplay() != BoardUndersideDisplay.NONE)
|
||||||
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
.collect(Collectors.toMap(x -> x, x -> new ArrayList<IDIYComponent<?>>()));
|
||||||
|
Map<IDIYComponent<?>, List<IBoard>> componentBoardMap = new HashMap<IDIYComponent<?>, List<IBoard>>();
|
||||||
|
|
||||||
|
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 ArrayList<IBoard>()).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();
|
// AffineTransform initialTx = g2d.getTransform();
|
||||||
Dimension canvasDimension =
|
Dimension canvasDimension =
|
||||||
getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE));
|
getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE));
|
||||||
|
|
||||||
g2dWrapper.setColor(theme.getBgColor());
|
g2dWrapper.setColor(theme.getBgColor());
|
||||||
g2dWrapper.fillRect(0, 0, canvasDimension.width, canvasDimension.height);
|
g2dWrapper.fillRect(0, 0, canvasDimension.width, canvasDimension.height);
|
||||||
@@ -243,14 +247,14 @@ public class DrawingManager {
|
|||||||
double extraSpace = getExtraSpace(project) * zoom;
|
double extraSpace = getExtraSpace(project) * zoom;
|
||||||
|
|
||||||
drawGrid(project, g2d, zoom, extraSpace, canvasDimension, visibleRect, drawOptions,
|
drawGrid(project, g2d, zoom, extraSpace, canvasDimension, visibleRect, drawOptions,
|
||||||
extraSpaceRect, extraSpaceTx);
|
extraSpaceRect, extraSpaceTx);
|
||||||
|
|
||||||
// apply zoom
|
// apply zoom
|
||||||
if (Math.abs(1.0 - zoom) > 1e-4) {
|
if (Math.abs(1.0 - zoom) > 1e-4) {
|
||||||
g2dWrapper.scale(zoom, zoom);
|
g2dWrapper.scale(zoom, zoom);
|
||||||
if (visibleRect != null)
|
if (visibleRect != null)
|
||||||
visibleRect.setRect(visibleRect.getX() / zoom, visibleRect.getY() / zoom,
|
visibleRect.setRect(visibleRect.getX() / zoom, visibleRect.getY() / zoom,
|
||||||
visibleRect.getWidth() / zoom, visibleRect.getHeight() / zoom);
|
visibleRect.getWidth() / zoom, visibleRect.getHeight() / zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Composite mainComposite = g2d.getComposite();
|
// Composite mainComposite = g2d.getComposite();
|
||||||
@@ -263,7 +267,7 @@ public class DrawingManager {
|
|||||||
Map<IDIYComponent<?>, ComponentState> componentStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
|
Map<IDIYComponent<?>, ComponentState> componentStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
|
||||||
List<ComponentForRender> componentForRenderList = new ArrayList<ComponentForRender>();
|
List<ComponentForRender> componentForRenderList = new ArrayList<ComponentForRender>();
|
||||||
for (int i = 0; i < project.getComponents().size(); i++) {
|
for (int i = 0; i < project.getComponents().size(); i++) {
|
||||||
IDIYComponent<?> component = project.getComponents().get(i);
|
IDIYComponent<?> component = project.getComponents().get(i);
|
||||||
ComponentState state = ComponentState.NORMAL;
|
ComponentState state = ComponentState.NORMAL;
|
||||||
if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) {
|
if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) {
|
||||||
if (dragInProgress) {
|
if (dragInProgress) {
|
||||||
@@ -287,17 +291,18 @@ public class DrawingManager {
|
|||||||
|
|
||||||
for (int i = 0; i < project.getComponents().size(); i++) {
|
for (int i = 0; i < project.getComponents().size(); i++) {
|
||||||
IDIYComponent<?> component = project.getComponents().get(i);
|
IDIYComponent<?> component = project.getComponents().get(i);
|
||||||
|
|
||||||
// Do not draw the component if it's filtered out.
|
// Do not draw the component if it's filtered out.
|
||||||
if (filter != null && !filter.testComponent(component)) {
|
if (filter != null && !filter.testComponent(component)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentState state = componentStateMap.get(component);
|
ComponentState state = componentStateMap.get(component);
|
||||||
// Do not track the area if component is not invalidated and was
|
// Do not track the area if component is not invalidated and was
|
||||||
// drawn in the same state.
|
// drawn in the same state.
|
||||||
boolean trackArea = lastDrawnStateMap.get(component) != state;
|
boolean trackArea = lastDrawnStateMap.get(component) != state;
|
||||||
|
|
||||||
synchronized (g2d) {
|
synchronized (this) {
|
||||||
g2dWrapper.startedDrawingComponent(i);
|
g2dWrapper.startedDrawingComponent(i);
|
||||||
if (!trackArea) {
|
if (!trackArea) {
|
||||||
g2dWrapper.stopTracking();
|
g2dWrapper.stopTracking();
|
||||||
@@ -312,15 +317,26 @@ public class DrawingManager {
|
|||||||
long componentStart = System.nanoTime();
|
long componentStart = System.nanoTime();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
|
AffineTransform txBefore = new AffineTransform(g2d.getTransform());
|
||||||
DrawingCache.Instance.draw(component, g2dWrapper, state,
|
drawComponent(project, drawOptions, scaleFactor, visibleRect, zoom, g2dWrapper,
|
||||||
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect);
|
outlineMode, i, component, state, false);
|
||||||
else // go straight to the wrapper
|
g2dWrapper.setTransform(txBefore);
|
||||||
component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
|
|
||||||
|
|
||||||
if (g2dWrapper.isTrackingContinuityArea()) {
|
// find one or more boards that contain the component and mirror the component to all
|
||||||
LOG.info("Component " + component.getName() + " of type "
|
List<IBoard> boards = componentBoardMap.get(component);
|
||||||
+ component.getClass().getName() + " did not stop tracking continuity area.");
|
if (boards != null) {
|
||||||
|
for (IBoard board : boards) {
|
||||||
|
double boardMirrorSpacing = board.getUndersideOffset().convertToPixels();
|
||||||
|
drawMirroredComponent(project, drawOptions, scaleFactor, visibleRect, zoom,
|
||||||
|
g2dWrapper, outlineMode, i, state, boardMirrorSpacing, component, board);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the component is the board itself, mirror it
|
||||||
|
if (boardMap.keySet().contains(component)) {
|
||||||
|
IBoard board = (IBoard) component;
|
||||||
|
double boardMirrorSpacing = board.getUndersideOffset().convertToPixels();
|
||||||
|
drawMirroredComponent(project, drawOptions, scaleFactor, visibleRect, zoom,
|
||||||
|
g2dWrapper, outlineMode, i, state, boardMirrorSpacing, component, (IBoard)component);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error drawing " + component.getName(), e);
|
LOG.error("Error drawing " + component.getName(), e);
|
||||||
@@ -362,17 +378,17 @@ public class DrawingManager {
|
|||||||
continue;
|
continue;
|
||||||
VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i);
|
VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i);
|
||||||
if ((groupedComponents.contains(component)
|
if ((groupedComponents.contains(component)
|
||||||
&& (visibilityPolicy == VisibilityPolicy.ALWAYS
|
&& (visibilityPolicy == VisibilityPolicy.ALWAYS
|
||||||
|| (selectedComponents.contains(component)
|
|| (selectedComponents.contains(component)
|
||||||
&& visibilityPolicy == VisibilityPolicy.WHEN_SELECTED))
|
&& visibilityPolicy == VisibilityPolicy.WHEN_SELECTED))
|
||||||
|| (!groupedComponents.contains(component)
|
|| (!groupedComponents.contains(component)
|
||||||
&& !selectedComponents.contains(component)
|
&& !selectedComponents.contains(component)
|
||||||
&& component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) {
|
&& component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) {
|
||||||
g2dWrapper.setColor(CONTROL_POINT_COLOR);
|
g2dWrapper.setColor(CONTROL_POINT_COLOR);
|
||||||
Point2D controlPoint = component.getControlPoint(i);
|
Point2D controlPoint = component.getControlPoint(i);
|
||||||
int pointSize = CONTROL_POINT_SIZE - 2;
|
int pointSize = CONTROL_POINT_SIZE - 2;
|
||||||
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2),
|
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2),
|
||||||
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize);
|
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,7 +397,7 @@ public class DrawingManager {
|
|||||||
for (IDIYComponent<?> component : selectedComponents) {
|
for (IDIYComponent<?> component : selectedComponents) {
|
||||||
for (int i = 0; i < component.getControlPointCount(); i++) {
|
for (int i = 0; i < component.getControlPointCount(); i++) {
|
||||||
if (!groupedComponents.contains(component)
|
if (!groupedComponents.contains(component)
|
||||||
&& (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED
|
&& (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED
|
||||||
|| component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) {
|
|| component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) {
|
||||||
|
|
||||||
Point2D controlPoint = component.getControlPoint(i);
|
Point2D controlPoint = component.getControlPoint(i);
|
||||||
@@ -389,11 +405,11 @@ public class DrawingManager {
|
|||||||
|
|
||||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
|
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
|
||||||
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2),
|
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2),
|
||||||
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize);
|
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize);
|
||||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
|
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
|
||||||
g2dWrapper.fillOval((int) (controlPoint.getX() - CONTROL_POINT_SIZE / 2 + 1),
|
g2dWrapper.fillOval((int) (controlPoint.getX() - CONTROL_POINT_SIZE / 2 + 1),
|
||||||
(int) (controlPoint.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
|
(int) (controlPoint.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
|
||||||
CONTROL_POINT_SIZE - 2);
|
CONTROL_POINT_SIZE - 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,7 +423,7 @@ public class DrawingManager {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
component.draw(g2dWrapper, ComponentState.NORMAL,
|
component.draw(g2dWrapper, ComponentState.NORMAL,
|
||||||
drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper);
|
drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error drawing " + component.getName(), e);
|
LOG.error("Error drawing " + component.getName(), e);
|
||||||
@@ -423,12 +439,12 @@ public class DrawingManager {
|
|||||||
if (point != null) {
|
if (point != null) {
|
||||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
|
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
|
||||||
g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2),
|
g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2),
|
||||||
(int) (point.getY() - CONTROL_POINT_SIZE / 2), CONTROL_POINT_SIZE,
|
(int) (point.getY() - CONTROL_POINT_SIZE / 2), CONTROL_POINT_SIZE,
|
||||||
CONTROL_POINT_SIZE);
|
CONTROL_POINT_SIZE);
|
||||||
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
|
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
|
||||||
g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2 + 1),
|
g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2 + 1),
|
||||||
(int) (point.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
|
(int) (point.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
|
||||||
CONTROL_POINT_SIZE - 2);
|
CONTROL_POINT_SIZE - 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +509,7 @@ public class DrawingManager {
|
|||||||
// shade extra space
|
// shade extra space
|
||||||
if (drawOptions.contains(DrawOption.EXTRA_SPACE) && SHADE_EXTRA_SPACE && extraSpaceRect != null) {
|
if (drawOptions.contains(DrawOption.EXTRA_SPACE) && SHADE_EXTRA_SPACE && extraSpaceRect != null) {
|
||||||
Area extraSpaceArea = new Area(
|
Area extraSpaceArea = new Area(
|
||||||
new Rectangle2D.Double(0, 0, canvasDimension.getWidth(), canvasDimension.getHeight()));
|
new Rectangle2D.Double(0, 0, canvasDimension.getWidth(), canvasDimension.getHeight()));
|
||||||
extraSpaceArea.subtract(new Area(extraSpaceRect));
|
extraSpaceArea.subtract(new Area(extraSpaceRect));
|
||||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.05f));
|
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.05f));
|
||||||
g2d.setTransform(extraSpaceTx);
|
g2d.setTransform(extraSpaceTx);
|
||||||
@@ -510,6 +526,123 @@ public class DrawingManager {
|
|||||||
return failedComponents;
|
return failedComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void drawMirroredComponent(Project project, Set<DrawOption> drawOptions,
|
||||||
|
Double scaleFactor, Rectangle2D visibleRect, double zoom, G2DWrapper g2dWrapper,
|
||||||
|
boolean outlineMode, int i, ComponentState state, double boardMirrorSpacing,
|
||||||
|
IDIYComponent<?> componentToDraw, IBoard board) {
|
||||||
|
Rectangle2D boardRectangle = board.getBoardRectangle();
|
||||||
|
AffineTransform mirrorTx = null;
|
||||||
|
switch (board.getBoardUndersideDisplay()) {
|
||||||
|
case ABOVE:
|
||||||
|
mirrorTx = new AffineTransform();
|
||||||
|
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMinY());
|
||||||
|
mirrorTx.scale(1, -1);
|
||||||
|
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMinY());
|
||||||
|
mirrorTx.translate(0, boardMirrorSpacing);
|
||||||
|
break;
|
||||||
|
case BELOW:
|
||||||
|
mirrorTx = new AffineTransform();
|
||||||
|
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMaxY());
|
||||||
|
mirrorTx.scale(1, -1);
|
||||||
|
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMaxY());
|
||||||
|
mirrorTx.translate(0, -boardMirrorSpacing);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
mirrorTx = new AffineTransform();
|
||||||
|
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMinY());
|
||||||
|
mirrorTx.scale(-1, 1);
|
||||||
|
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMinY());
|
||||||
|
mirrorTx.translate(boardMirrorSpacing, 0);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
mirrorTx = new AffineTransform();
|
||||||
|
mirrorTx.translate(boardRectangle.getMaxX(), boardRectangle.getMinY());
|
||||||
|
mirrorTx.scale(-1, 1);
|
||||||
|
mirrorTx.translate(-boardRectangle.getMaxX(), -boardRectangle.getMinY());
|
||||||
|
mirrorTx.translate(-boardMirrorSpacing, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.warn("Unexpected board underside display: " + board.getBoardUndersideDisplay());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
AffineTransform txBefore = new AffineTransform(g2dWrapper.getTransform());
|
||||||
|
byte alphaBefore = 0;
|
||||||
|
if (AbstractTransparentComponent.class.isInstance(componentToDraw)) {
|
||||||
|
alphaBefore = ((AbstractTransparentComponent<?>)componentToDraw).getAlpha();
|
||||||
|
((AbstractTransparentComponent<?>)componentToDraw).setAlpha(MIRRORED_ALPHA);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
g2dWrapper.setMirrorTransform(mirrorTx);
|
||||||
|
g2dWrapper.transform(mirrorTx);
|
||||||
|
|
||||||
|
drawComponent(project, drawOptions, scaleFactor, visibleRect, zoom, g2dWrapper, outlineMode, i, componentToDraw, state, true);
|
||||||
|
|
||||||
|
// componentToDraw.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
|
||||||
|
} finally {
|
||||||
|
g2dWrapper.setTransform(txBefore);
|
||||||
|
g2dWrapper.setMirrorTransform(null);
|
||||||
|
if (AbstractTransparentComponent.class.isInstance(componentToDraw)) {
|
||||||
|
((AbstractTransparentComponent<?>)componentToDraw).setAlpha(alphaBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawComponent(Project project, Set<DrawOption> drawOptions, Double scaleFactor,
|
||||||
|
Rectangle2D visibleRect, double zoom, G2DWrapper g2dWrapper, boolean outlineMode, int i,
|
||||||
|
IDIYComponent<?> component, ComponentState state, boolean mirrored) {
|
||||||
|
|
||||||
|
AffineTransform txBefore = new AffineTransform(g2dWrapper.getTransform());
|
||||||
|
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, mirrored);
|
||||||
|
else // go straight to the wrapper
|
||||||
|
component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
|
||||||
|
|
||||||
|
if (g2dWrapper.isTrackingContinuityArea()) {
|
||||||
|
LOG.debug("Component " + component.getName() + " of type "
|
||||||
|
+ component.getClass().getName() + " did not stop tracking continuity area.");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
g2dWrapper.setTransform(txBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureG2D(Graphics2D g2d, Set<DrawOption> 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 double zoomCached = 0;
|
||||||
private Dimension canvasDimensionCached;
|
private Dimension canvasDimensionCached;
|
||||||
private double extraSpaceCached;
|
private double extraSpaceCached;
|
||||||
@@ -517,8 +650,8 @@ public class DrawingManager {
|
|||||||
private BufferedImage cachedGridImage;
|
private BufferedImage cachedGridImage;
|
||||||
|
|
||||||
private void drawGrid(Project project, Graphics2D g2dIn, double zoom, double extraSpace,
|
private void drawGrid(Project project, Graphics2D g2dIn, double zoom, double extraSpace,
|
||||||
Dimension canvasDimension, Rectangle2D visibleRect, Set<DrawOption> drawOptions,
|
Dimension canvasDimension, Rectangle2D visibleRect, Set<DrawOption> drawOptions,
|
||||||
Rectangle2D extraSpaceRect, AffineTransform extraSpaceTx) {
|
Rectangle2D extraSpaceRect, AffineTransform extraSpaceTx) {
|
||||||
|
|
||||||
GridType gridType = GridType.LINES;
|
GridType gridType = GridType.LINES;
|
||||||
|
|
||||||
@@ -526,10 +659,10 @@ public class DrawingManager {
|
|||||||
|
|
||||||
// draw from cache
|
// draw from cache
|
||||||
if (zoom != zoomCached || !canvasDimension.equals(canvasDimensionCached)
|
if (zoom != zoomCached || !canvasDimension.equals(canvasDimensionCached)
|
||||||
|| extraSpace != extraSpaceCached || gridType != gridTypeCached) {
|
|| extraSpace != extraSpaceCached || gridType != gridTypeCached) {
|
||||||
try {
|
try {
|
||||||
cachedGridImage = new BufferedImage((int) canvasDimension.getWidth(),
|
cachedGridImage = new BufferedImage((int) canvasDimension.getWidth(),
|
||||||
(int) canvasDimension.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
(int) canvasDimension.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||||
// create graphics
|
// create graphics
|
||||||
Graphics2D g2d = cachedGridImage.createGraphics();
|
Graphics2D g2d = cachedGridImage.createGraphics();
|
||||||
|
|
||||||
@@ -538,11 +671,11 @@ public class DrawingManager {
|
|||||||
float gridThickness = (float) (1f * (zoom > 1 ? 1 : zoom));
|
float gridThickness = (float) (1f * (zoom > 1 ? 1 : zoom));
|
||||||
if (gridType == GridType.CROSSHAIR) {
|
if (gridType == GridType.CROSSHAIR) {
|
||||||
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT,
|
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT,
|
||||||
BasicStroke.JOIN_MITER, 10f,
|
BasicStroke.JOIN_MITER, 10f,
|
||||||
new float[] {(float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4));
|
new float[] {(float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4));
|
||||||
} else if (gridType == GridType.DOT) {
|
} else if (gridType == GridType.DOT) {
|
||||||
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT,
|
g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT,
|
||||||
BasicStroke.JOIN_MITER, 10f, new float[] {1f, (float) zoomStep - 1}, 0f));
|
BasicStroke.JOIN_MITER, 10f, new float[] {1f, (float) zoomStep - 1}, 0f));
|
||||||
} else {
|
} else {
|
||||||
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness));
|
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness));
|
||||||
}
|
}
|
||||||
@@ -559,9 +692,9 @@ public class DrawingManager {
|
|||||||
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness * 3));
|
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness * 3));
|
||||||
g2d.setColor(theme.getDotColor());
|
g2d.setColor(theme.getDotColor());
|
||||||
for (double i = extraSpace + zoomStep * project.getDotSpacing(); i < extraSpace
|
for (double i = extraSpace + zoomStep * project.getDotSpacing(); i < extraSpace
|
||||||
+ innerCanvasDimension.width; i += zoomStep * project.getDotSpacing())
|
+ innerCanvasDimension.width; i += zoomStep * project.getDotSpacing())
|
||||||
for (double j = extraSpace + zoomStep * project.getDotSpacing(); j < extraSpace
|
for (double j = extraSpace + zoomStep * project.getDotSpacing(); j < extraSpace
|
||||||
+ innerCanvasDimension.height; j += zoomStep * project.getDotSpacing()) {
|
+ innerCanvasDimension.height; j += zoomStep * project.getDotSpacing()) {
|
||||||
g2d.fillOval((int) Math.round(i - 1), (int) Math.round(j - 1), 3, 3);
|
g2d.fillOval((int) Math.round(i - 1), (int) Math.round(j - 1), 3, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,12 +706,12 @@ public class DrawingManager {
|
|||||||
gridTypeCached = gridType;
|
gridTypeCached = gridType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedGridImage == null) {
|
if (cachedGridImage == null) {
|
||||||
LOG.warn("Cached grid image is null!");
|
LOG.warn("Cached grid image is null!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) {
|
if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) {
|
||||||
g2dIn.drawImage(cachedGridImage, 0, 0, null);
|
g2dIn.drawImage(cachedGridImage, 0, 0, null);
|
||||||
}
|
}
|
||||||
@@ -587,10 +720,10 @@ public class DrawingManager {
|
|||||||
if (drawOptions.contains(DrawOption.EXTRA_SPACE)) {
|
if (drawOptions.contains(DrawOption.EXTRA_SPACE)) {
|
||||||
float borderThickness = (float) (3f * (zoom > 1 ? 1 : zoom));
|
float borderThickness = (float) (3f * (zoom > 1 ? 1 : zoom));
|
||||||
g2dIn.setStroke(ObjectCache.getInstance().fetchStroke(borderThickness,
|
g2dIn.setStroke(ObjectCache.getInstance().fetchStroke(borderThickness,
|
||||||
new float[] {borderThickness * 4, borderThickness * 4,}, 0, BasicStroke.CAP_BUTT));
|
new float[] {borderThickness * 4, borderThickness * 4,}, 0, BasicStroke.CAP_BUTT));
|
||||||
g2dIn.setColor(theme.getOutlineColor());
|
g2dIn.setColor(theme.getOutlineColor());
|
||||||
extraSpaceRect.setRect(new Rectangle2D.Double(extraSpace, extraSpace,
|
extraSpaceRect.setRect(new Rectangle2D.Double(extraSpace, extraSpace,
|
||||||
innerCanvasDimension.getWidth(), innerCanvasDimension.getHeight()));
|
innerCanvasDimension.getWidth(), innerCanvasDimension.getHeight()));
|
||||||
g2dIn.draw(extraSpaceRect);
|
g2dIn.draw(extraSpaceRect);
|
||||||
extraSpaceTx.setTransform(g2dIn.getTransform());
|
extraSpaceTx.setTransform(g2dIn.getTransform());
|
||||||
|
|
||||||
@@ -598,7 +731,7 @@ public class DrawingManager {
|
|||||||
g2dIn.transform(AffineTransform.getTranslateInstance(extraSpace, extraSpace));
|
g2dIn.transform(AffineTransform.getTranslateInstance(extraSpace, extraSpace));
|
||||||
if (visibleRect != null)
|
if (visibleRect != null)
|
||||||
visibleRect.setRect(visibleRect.getX() - extraSpace, visibleRect.getY() - extraSpace,
|
visibleRect.setRect(visibleRect.getX() - extraSpace, visibleRect.getY() - extraSpace,
|
||||||
visibleRect.getWidth(), visibleRect.getHeight());
|
visibleRect.getWidth(), visibleRect.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,9 +740,9 @@ public class DrawingManager {
|
|||||||
if (System.currentTimeMillis() - lastStatsReportedTime > statReportFrequencyMs) {
|
if (System.currentTimeMillis() - lastStatsReportedTime > statReportFrequencyMs) {
|
||||||
lastStatsReportedTime = System.currentTimeMillis();
|
lastStatsReportedTime = System.currentTimeMillis();
|
||||||
String mapAsString = renderStatsByType.entrySet().stream()
|
String mapAsString = renderStatsByType.entrySet().stream()
|
||||||
.sorted(
|
.sorted(
|
||||||
(e1, e2) -> -Long.compare(e1.getValue().getNanoTime(), e2.getValue().getNanoTime()))
|
(e1, e2) -> -Long.compare(e1.getValue().getNanoTime(), e2.getValue().getNanoTime()))
|
||||||
.map(e -> e.toString()).collect(Collectors.joining("; ", "{", "}"));
|
.map(e -> e.toString()).collect(Collectors.joining("; ", "{", "}"));
|
||||||
LOG.debug("Render stats: " + mapAsString);
|
LOG.debug("Render stats: " + mapAsString);
|
||||||
LOG.debug("Page stats: " + totalStats.toAvgString());
|
LOG.debug("Page stats: " + totalStats.toAvgString());
|
||||||
DrawingCache.Instance.logStats();
|
DrawingCache.Instance.logStats();
|
||||||
@@ -664,11 +797,11 @@ public class DrawingManager {
|
|||||||
double height = project.getHeight().convertToPixels();
|
double height = project.getHeight().convertToPixels();
|
||||||
double targetExtraSpace = EXTRA_SPACE * Math.max(width, height);
|
double targetExtraSpace = EXTRA_SPACE * Math.max(width, height);
|
||||||
return CalcUtils.roundToGrid(targetExtraSpace,
|
return CalcUtils.roundToGrid(targetExtraSpace,
|
||||||
project.getGridSpacing().scale(project.getDotSpacing()));
|
project.getGridSpacing().scale(project.getDotSpacing()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dimension getCanvasDimensions(Project project, Double zoomLevel,
|
public Dimension getCanvasDimensions(Project project, Double zoomLevel,
|
||||||
boolean includeExtraSpace) {
|
boolean includeExtraSpace) {
|
||||||
double width = project.getWidth().convertToPixels();
|
double width = project.getWidth().convertToPixels();
|
||||||
double height = project.getHeight().convertToPixels();
|
double height = project.getHeight().convertToPixels();
|
||||||
|
|
||||||
@@ -705,7 +838,7 @@ public class DrawingManager {
|
|||||||
|
|
||||||
currentContinuityAreas = continuityGraphCache.findAreasFor(p);
|
currentContinuityAreas = continuityGraphCache.findAreasFor(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ContinuityArea> getContinuityAreas() {
|
public List<ContinuityArea> getContinuityAreas() {
|
||||||
// Find all individual continuity areas for all components
|
// Find all individual continuity areas for all components
|
||||||
List<ContinuityArea> preliminaryAreas = new ArrayList<ContinuityArea>();
|
List<ContinuityArea> preliminaryAreas = new ArrayList<ContinuityArea>();
|
||||||
@@ -716,17 +849,17 @@ public class DrawingManager {
|
|||||||
|
|
||||||
if (a == null || a.getOutlineArea() == null)
|
if (a == null || a.getOutlineArea() == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
IDIYComponent<?> component = entry.getKey();
|
IDIYComponent<?> component = entry.getKey();
|
||||||
|
|
||||||
int layerId;
|
int layerId;
|
||||||
|
|
||||||
if (component instanceof ILayeredComponent) {
|
if (component instanceof ILayeredComponent) {
|
||||||
layerId = ((ILayeredComponent)component).getLayerId();
|
layerId = ((ILayeredComponent)component).getLayerId();
|
||||||
} else {
|
} else {
|
||||||
layerId = 0;
|
layerId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<Area> positiveAreas = a.getContinuityPositiveAreas();
|
Collection<Area> positiveAreas = a.getContinuityPositiveAreas();
|
||||||
if (positiveAreas != null) {
|
if (positiveAreas != null) {
|
||||||
for (Area a1 : positiveAreas) {
|
for (Area a1 : positiveAreas) {
|
||||||
@@ -734,7 +867,7 @@ public class DrawingManager {
|
|||||||
checkBreakout.add(false);
|
checkBreakout.add(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<Area> negativeAreas = a.getContinuityNegativeAreas();
|
Collection<Area> negativeAreas = a.getContinuityNegativeAreas();
|
||||||
if (negativeAreas != null) {
|
if (negativeAreas != null) {
|
||||||
for (Area na : negativeAreas) {
|
for (Area na : negativeAreas) {
|
||||||
@@ -759,9 +892,9 @@ public class DrawingManager {
|
|||||||
areas.add(a);
|
areas.add(a);
|
||||||
} else {
|
} else {
|
||||||
areas.addAll(breakoutAreas.stream()
|
areas.addAll(breakoutAreas.stream()
|
||||||
.map(area -> new ContinuityArea(a.getLayerId(), area))
|
.map(area -> new ContinuityArea(a.getLayerId(), area))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
areas.add(a);
|
areas.add(a);
|
||||||
}
|
}
|
||||||
@@ -781,7 +914,7 @@ public class DrawingManager {
|
|||||||
}
|
}
|
||||||
z++;
|
z++;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ContinuityArea> areas = getContinuityAreas();
|
List<ContinuityArea> areas = getContinuityAreas();
|
||||||
|
|
||||||
return NetlistBuilder.buildContinuityGraph(areas, connections);
|
return NetlistBuilder.buildContinuityGraph(areas, connections);
|
||||||
@@ -790,9 +923,9 @@ public class DrawingManager {
|
|||||||
public List<Area> getContinuityAreaProximity(float threshold) {
|
public List<Area> getContinuityAreaProximity(float threshold) {
|
||||||
List<ContinuityArea> continuityAreas = getContinuityAreas();
|
List<ContinuityArea> continuityAreas = getContinuityAreas();
|
||||||
Stroke s = ObjectCache.getInstance().fetchBasicStroke(threshold - 1); // value eyeballed for
|
Stroke s = ObjectCache.getInstance().fetchBasicStroke(threshold - 1); // value eyeballed for
|
||||||
// approx good results
|
// approx good results
|
||||||
List<Area> expanded = continuityAreas.parallelStream()
|
List<Area> expanded = continuityAreas.parallelStream()
|
||||||
.map((a) -> new Area(s.createStrokedShape(a.getArea()))).collect(Collectors.toList());
|
.map((a) -> new Area(s.createStrokedShape(a.getArea()))).collect(Collectors.toList());
|
||||||
List<Area> intersections = new ArrayList<Area>();
|
List<Area> intersections = new ArrayList<Area>();
|
||||||
for (int i = 0; i < expanded.size() - 1; i++) {
|
for (int i = 0; i < expanded.size() - 1; i++) {
|
||||||
for (int j = i + 1; j < expanded.size(); j++) {
|
for (int j = i + 1; j < expanded.size(); j++) {
|
||||||
@@ -812,13 +945,13 @@ public class DrawingManager {
|
|||||||
Rectangle2D bounds2d = a.getBounds2D();
|
Rectangle2D bounds2d = a.getBounds2D();
|
||||||
if (bounds2d.getWidth() < minSize)
|
if (bounds2d.getWidth() < minSize)
|
||||||
bounds2d = new Rectangle2D.Double(bounds2d.getCenterX() - minSize / 2, bounds2d.getY(),
|
bounds2d = new Rectangle2D.Double(bounds2d.getCenterX() - minSize / 2, bounds2d.getY(),
|
||||||
minSize, bounds2d.getHeight());
|
minSize, bounds2d.getHeight());
|
||||||
if (bounds2d.getHeight() < minSize)
|
if (bounds2d.getHeight() < minSize)
|
||||||
bounds2d = new Rectangle2D.Double(bounds2d.getX(), bounds2d.getCenterY() - minSize / 2,
|
bounds2d = new Rectangle2D.Double(bounds2d.getX(), bounds2d.getCenterY() - minSize / 2,
|
||||||
bounds2d.getWidth(), minSize);
|
bounds2d.getWidth(), minSize);
|
||||||
|
|
||||||
shapes.add(new Area(new Ellipse2D.Double(bounds2d.getX(), bounds2d.getY(),
|
shapes.add(new Area(new Ellipse2D.Double(bounds2d.getX(), bounds2d.getY(),
|
||||||
bounds2d.getWidth(), bounds2d.getHeight())));
|
bounds2d.getWidth(), bounds2d.getHeight())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// AreaUtils.crunchAreas(shapes, null);
|
// AreaUtils.crunchAreas(shapes, null);
|
||||||
@@ -827,4 +960,4 @@ public class DrawingManager {
|
|||||||
|
|
||||||
return shapes;
|
return shapes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||||
*
|
*
|
||||||
* This file is part of DIYLC.
|
* This file is part of DIYLC.
|
||||||
*
|
*
|
||||||
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
* License, or (at your option) any later version.
|
* License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
* Public License for more details.
|
* Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
|
||||||
* <http://www.gnu.org/licenses/>.
|
* <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -62,7 +62,6 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.diylc.common.ObjectCache;
|
import org.diylc.common.ObjectCache;
|
||||||
import org.diylc.common.ZoomableStroke;
|
import org.diylc.common.ZoomableStroke;
|
||||||
import org.diylc.core.IDrawingObserver;
|
import org.diylc.core.IDrawingObserver;
|
||||||
@@ -70,24 +69,24 @@ import org.diylc.core.IDrawingObserver;
|
|||||||
/**
|
/**
|
||||||
* {@link Graphics2D} wrapper that keeps track of all drawing actions and creates an {@link Area}
|
* {@link Graphics2D} wrapper that keeps track of all drawing actions and creates an {@link Area}
|
||||||
* that corresponds to drawn objects. Before each component is drawn,
|
* that corresponds to drawn objects. Before each component is drawn,
|
||||||
* {@link #startedDrawingComponent()} should be called. After the component is drawn, area may be
|
* {@link #startedDrawingComponent(int)} ()} should be called. After the component is drawn, area may be
|
||||||
* retrieved using {@link #finishedDrawingComponent()}. Graphics configuration (color, font, etc) is
|
* retrieved using {@link #finishedDrawingComponent()}. Graphics configuration (color, font, etc) is
|
||||||
* reset between each two components.
|
* reset between each two components.
|
||||||
*
|
*
|
||||||
* @author Branislav Stojkovic
|
* @author Branislav Stojkovic
|
||||||
*/
|
*/
|
||||||
class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
||||||
|
|
||||||
public static int LINE_SENSITIVITY_MARGIN = 2;
|
public static int LINE_SENSITIVITY_MARGIN = 2;
|
||||||
public static int CURVE_SENSITIVITY = 6;
|
public static int CURVE_SENSITIVITY = 6;
|
||||||
|
|
||||||
private boolean drawingComponent = false;
|
private boolean drawingComponent = false;
|
||||||
private boolean trackingAllowed = true;
|
private boolean trackingAllowed = true;
|
||||||
private boolean trackingContinuityAllowed = false;
|
private boolean trackingContinuityAllowed = false;
|
||||||
private boolean trackingContinuityPositive = true;
|
private boolean trackingContinuityPositive = true;
|
||||||
|
|
||||||
private HashMap<String, Integer> trackingStacks = new HashMap<String, Integer>();
|
private HashMap<String, Integer> trackingStacks = new HashMap<String, Integer>();
|
||||||
|
|
||||||
private int uniqueCounter = 0;
|
private int uniqueCounter = 0;
|
||||||
|
|
||||||
private Graphics2D canvasGraphics;
|
private Graphics2D canvasGraphics;
|
||||||
@@ -105,11 +104,13 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
private Shape lastShape;
|
private Shape lastShape;
|
||||||
|
|
||||||
private double zoom;
|
private double zoom;
|
||||||
private int zOrder;
|
private int zOrder;
|
||||||
|
|
||||||
|
private AffineTransform mirrorTransform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a wrapper around specified {@link Graphics2D} object.
|
* Creates a wrapper around specified {@link Graphics2D} object.
|
||||||
*
|
*
|
||||||
* @param canvasGraphics
|
* @param canvasGraphics
|
||||||
*/
|
*/
|
||||||
public G2DWrapper(Graphics2D canvasGraphics, double zoom) {
|
public G2DWrapper(Graphics2D canvasGraphics, double zoom) {
|
||||||
@@ -122,14 +123,14 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
continuityMarker = null;
|
continuityMarker = null;
|
||||||
currentTx = new AffineTransform();
|
currentTx = new AffineTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Graphics2D getCanvasGraphics() {
|
public Graphics2D getCanvasGraphics() {
|
||||||
return canvasGraphics;
|
return canvasGraphics;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears out the current area and caches canvas settings.
|
* Clears out the current area and caches canvas settings.
|
||||||
*
|
*
|
||||||
* @param zOrder
|
* @param zOrder
|
||||||
*/
|
*/
|
||||||
public void startedDrawingComponent(int zOrder) {
|
public void startedDrawingComponent(int zOrder) {
|
||||||
@@ -153,7 +154,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts {@link Graphics2D} settings and returns area drawn by component in the meantime.
|
* Reverts {@link Graphics2D} settings and returns area drawn by component in the meantime.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public ComponentArea finishedDrawingComponent() {
|
public ComponentArea finishedDrawingComponent() {
|
||||||
@@ -163,27 +164,27 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
canvasGraphics.setTransform(originalTx);
|
canvasGraphics.setTransform(originalTx);
|
||||||
canvasGraphics.setComposite(originalComposite);
|
canvasGraphics.setComposite(originalComposite);
|
||||||
canvasGraphics.setFont(originalFont);
|
canvasGraphics.setFont(originalFont);
|
||||||
// Map<String, Integer> sorted = sortByComparator(trackingStacks, false);
|
// Map<String, Integer> sorted = sortByComparator(trackingStacks, false);
|
||||||
return new ComponentArea(zOrder,currentArea, new ArrayList<Area>(continuityPositiveAreas.values()),
|
return new ComponentArea(zOrder,currentArea, new ArrayList<Area>(continuityPositiveAreas.values()),
|
||||||
new ArrayList<Area>(continuityNegativeAreas.values()));
|
new ArrayList<Area>(continuityNegativeAreas.values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// start - used for caching
|
// start - used for caching
|
||||||
|
|
||||||
public Area getCurrentArea() {
|
public Area getCurrentArea() {
|
||||||
return currentArea;
|
return currentArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Area> getContinuityPositiveAreas() {
|
public Map<String, Area> getContinuityPositiveAreas() {
|
||||||
return continuityPositiveAreas;
|
return continuityPositiveAreas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Area> getContinuityNegativeAreas() {
|
public Map<String, Area> getContinuityNegativeAreas() {
|
||||||
return continuityNegativeAreas;
|
return continuityNegativeAreas;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end - used for caching
|
// end - used for caching
|
||||||
|
|
||||||
public void merge(Area currentArea, Map<String, Area> continuityPositiveAreas, Map<String, Area> continuityNegativeAreas) {
|
public void merge(Area currentArea, Map<String, Area> continuityPositiveAreas, Map<String, Area> continuityNegativeAreas) {
|
||||||
this.currentArea = currentArea;
|
this.currentArea = currentArea;
|
||||||
this.continuityPositiveAreas = continuityPositiveAreas;
|
this.continuityPositiveAreas = continuityPositiveAreas;
|
||||||
@@ -212,18 +213,22 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrackingContinuityArea() {
|
public boolean isTrackingContinuityArea() {
|
||||||
return trackingContinuityAllowed;
|
return trackingContinuityAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setContinuityMarker(String marker) {
|
public void setContinuityMarker(String marker) {
|
||||||
continuityMarker = marker;
|
continuityMarker = marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMirrorTransform(AffineTransform mirrorTransform) {
|
||||||
|
this.mirrorTransform = mirrorTransform;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends shape interior to the current component area.
|
* Appends shape interior to the current component area.
|
||||||
*
|
*
|
||||||
* @param s
|
* @param s
|
||||||
*/
|
*/
|
||||||
private void appendShape(Shape s) {
|
private void appendShape(Shape s) {
|
||||||
@@ -237,7 +242,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
area.transform(currentTx);
|
area.transform(currentTx);
|
||||||
|
|
||||||
if (trackingAllowed)
|
if (trackingAllowed)
|
||||||
currentArea.add(area);
|
currentArea.add(area);
|
||||||
|
|
||||||
Map<String, Area> toAdd;
|
Map<String, Area> toAdd;
|
||||||
if (trackingContinuityAllowed) {
|
if (trackingContinuityAllowed) {
|
||||||
@@ -250,18 +255,18 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
toAdd.put(marker, area);
|
toAdd.put(marker, area);
|
||||||
// markStack();
|
// markStack();
|
||||||
} else {
|
} else {
|
||||||
Area current = toAdd.getOrDefault(marker, null);
|
Area current = toAdd.getOrDefault(marker, null);
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
toAdd.put(marker, area);
|
toAdd.put(marker, area);
|
||||||
// markStack();
|
// markStack();
|
||||||
} else
|
} else
|
||||||
current.add(area);
|
current.add(area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastShape = s;
|
lastShape = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private void markStack() {
|
private void markStack() {
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
@@ -275,7 +280,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends shape outline to the current component area.
|
* Appends shape outline to the current component area.
|
||||||
*
|
*
|
||||||
* @param s
|
* @param s
|
||||||
*/
|
*/
|
||||||
private void appendShapeOutline(Shape s) {
|
private void appendShapeOutline(Shape s) {
|
||||||
@@ -345,22 +350,73 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawString(String str, int x, int y) {
|
public void drawString(String str, int x, int y) {
|
||||||
canvasGraphics.drawString(str, x, y);
|
this.drawString(str, (float)x, (float)y);
|
||||||
if (drawingComponent && trackingAllowed) {
|
|
||||||
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
|
|
||||||
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
|
|
||||||
Point2D point = new Point2D.Double(x, y);
|
|
||||||
// currentTx.transform(point, point);
|
|
||||||
Rectangle2D finalRec =
|
|
||||||
new Rectangle2D.Double(rect.getX() + point.getX(), rect.getY() + point.getY(), rect.getWidth(),
|
|
||||||
rect.getHeight());
|
|
||||||
appendShape(finalRec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawString(String str, float x, float y) {
|
public void drawString(String str, float x, float y) {
|
||||||
canvasGraphics.drawString(str, x, y);
|
if (this.mirrorTransform == null) {
|
||||||
|
canvasGraphics.drawString(str, x, y);
|
||||||
|
} else {
|
||||||
|
drawStringUnmirrored(str, x, y);
|
||||||
|
}
|
||||||
|
handleDrawString(str, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawStringUnmirrored(String str, float x, float y) {
|
||||||
|
// Save the current transform (T), which includes the mirror.
|
||||||
|
AffineTransform originalTransform = new AffineTransform(getTransform());
|
||||||
|
|
||||||
|
// Compute the non-mirrored transform A by "canceling" the mirror:
|
||||||
|
// Since T = A ? M and M is self-inverse, we have A = T ? M.
|
||||||
|
AffineTransform nonMirroredTransform = new AffineTransform(originalTransform);
|
||||||
|
nonMirroredTransform.concatenate(mirrorTransform);
|
||||||
|
|
||||||
|
GlyphVector gv = getFont().createGlyphVector(this.getFontRenderContext(), str);
|
||||||
|
Rectangle2D visualBounds = gv.getVisualBounds();
|
||||||
|
// Use a temporary Graphics2D (with transform A) to obtain correct FontMetrics.
|
||||||
|
Graphics2D gTemp = (Graphics2D) canvasGraphics.create();
|
||||||
|
gTemp.setTransform(nonMirroredTransform);
|
||||||
|
FontMetrics fm = gTemp.getFontMetrics();
|
||||||
|
double textWidth = fm.stringWidth(str);
|
||||||
|
// Use ascent + descent as the bounding box height.
|
||||||
|
double textHeight = visualBounds.getHeight();//fm.getAscent() + fm.getDescent();
|
||||||
|
double ascent = fm.getAscent();
|
||||||
|
gTemp.dispose();
|
||||||
|
|
||||||
|
// 1. Compute the center of the text?s bounding box in the mirrored (T) space.
|
||||||
|
Point2D centerMirrored = new Point2D.Double(x + textWidth / 2.0,
|
||||||
|
y + textHeight / 2.0);
|
||||||
|
|
||||||
|
// 2. Convert that center to screen coordinates using the original transform T.
|
||||||
|
Point2D centerScreen = originalTransform.transform(centerMirrored, null);
|
||||||
|
|
||||||
|
// 3. Map the screen coordinate into the non-mirrored coordinate system (A).
|
||||||
|
Point2D centerNonMirrored;
|
||||||
|
try {
|
||||||
|
centerNonMirrored = nonMirroredTransform.createInverse().transform(centerScreen, null);
|
||||||
|
} catch (NoninvertibleTransformException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
centerNonMirrored = centerMirrored; // Fallback if inversion fails.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Compute the new top-left in A so that the bounding box (width x height)
|
||||||
|
// remains centered at centerNonMirrored.
|
||||||
|
double newTopLeftX = centerNonMirrored.getX() - textWidth / 2.0;
|
||||||
|
double newTopLeftY = centerNonMirrored.getY() - textHeight / 2.0;
|
||||||
|
// Adjust for the baseline (drawString uses the baseline for y)
|
||||||
|
float drawX = (float) newTopLeftX;
|
||||||
|
float drawY = (float) (newTopLeftY + ascent);
|
||||||
|
|
||||||
|
// 5. Set the transform to the non-mirrored transform (A) so that mirror is canceled.
|
||||||
|
canvasGraphics.setTransform(nonMirroredTransform);
|
||||||
|
canvasGraphics.drawString(str, drawX, drawY);
|
||||||
|
|
||||||
|
// 6. Restore the original transform.
|
||||||
|
setTransform(originalTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDrawString(String str, float x, float y) {
|
||||||
if (drawingComponent && trackingAllowed) {
|
if (drawingComponent && trackingAllowed) {
|
||||||
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
|
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
|
||||||
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
|
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
|
||||||
@@ -569,7 +625,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
canvasGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
|
canvasGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
|
||||||
if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
|
if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
|
||||||
appendShapeOutline(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN));
|
appendShapeOutline(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -599,14 +655,14 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
|
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
|
||||||
ImageObserver observer) {
|
ImageObserver observer) {
|
||||||
// FIXME: map
|
// FIXME: map
|
||||||
return canvasGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
|
return canvasGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
|
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
|
||||||
Color bgcolor, ImageObserver observer) {
|
Color bgcolor, ImageObserver observer) {
|
||||||
// FIXME: map
|
// FIXME: map
|
||||||
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
|
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
|
||||||
}
|
}
|
||||||
@@ -757,12 +813,12 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
public void setXORMode(Color c1) {
|
public void setXORMode(Color c1) {
|
||||||
canvasGraphics.setXORMode(c1);
|
canvasGraphics.setXORMode(c1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap,
|
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap,
|
||||||
final boolean order) {
|
final boolean order) {
|
||||||
List<Entry<String, Integer>> list =
|
List<Entry<String, Integer>> list =
|
||||||
new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
|
new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
|
||||||
|
|
||||||
// Sorting the list based on values
|
// Sorting the list based on values
|
||||||
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
|
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
|
||||||
@@ -784,4 +840,4 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
|
|
||||||
return sortedMap;
|
return sortedMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,14 +28,15 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import org.diylc.appframework.miscutils.ConfigurationManager;
|
import org.diylc.appframework.miscutils.ConfigurationManager;
|
||||||
|
|
||||||
import org.diylc.awt.StringUtils;
|
import org.diylc.awt.StringUtils;
|
||||||
import org.diylc.common.HorizontalAlignment;
|
import org.diylc.common.HorizontalAlignment;
|
||||||
import org.diylc.common.IPlugInPort;
|
import org.diylc.common.IPlugInPort;
|
||||||
import org.diylc.common.ObjectCache;
|
import org.diylc.common.ObjectCache;
|
||||||
import org.diylc.common.VerticalAlignment;
|
import org.diylc.common.VerticalAlignment;
|
||||||
import org.diylc.components.AbstractTransparentComponent;
|
import org.diylc.components.AbstractTransparentComponent;
|
||||||
|
import org.diylc.core.BoardUndersideDisplay;
|
||||||
import org.diylc.core.ComponentState;
|
import org.diylc.core.ComponentState;
|
||||||
|
import org.diylc.core.IBoard;
|
||||||
import org.diylc.core.IDrawingObserver;
|
import org.diylc.core.IDrawingObserver;
|
||||||
import org.diylc.core.Project;
|
import org.diylc.core.Project;
|
||||||
import org.diylc.core.VisibilityPolicy;
|
import org.diylc.core.VisibilityPolicy;
|
||||||
@@ -43,9 +44,10 @@ import org.diylc.core.annotations.EditableProperty;
|
|||||||
import org.diylc.core.measures.Size;
|
import org.diylc.core.measures.Size;
|
||||||
import org.diylc.core.measures.SizeUnit;
|
import org.diylc.core.measures.SizeUnit;
|
||||||
|
|
||||||
public abstract class AbstractBoard extends AbstractTransparentComponent<String> {
|
public abstract class AbstractBoard extends AbstractTransparentComponent<String> implements IBoard {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
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 BORDER_COLOR = PHENOLIC_COLOR.darker();
|
||||||
public static Color COORDINATE_COLOR = Color.gray.brighter();
|
public static Color COORDINATE_COLOR = Color.gray.brighter();
|
||||||
@@ -56,7 +58,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
protected String value = "";
|
protected String value = "";
|
||||||
// two control points used for controlling the position
|
// two control points used for controlling the position
|
||||||
protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0),
|
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
|
// top-left and bottom-right points
|
||||||
protected Point2D.Double firstPoint = new Point2D.Double();
|
protected Point2D.Double firstPoint = new Point2D.Double();
|
||||||
protected Point2D.Double secondPoint = new Point2D.Double();
|
protected Point2D.Double secondPoint = new Point2D.Double();
|
||||||
@@ -69,17 +71,20 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
protected CoordinateOrigin coordinateOrigin = CoordinateOrigin.Top_Left;
|
protected CoordinateOrigin coordinateOrigin = CoordinateOrigin.Top_Left;
|
||||||
protected CoordinateDisplay coordinateDisplay = CoordinateDisplay.One_Side;
|
protected CoordinateDisplay coordinateDisplay = CoordinateDisplay.One_Side;
|
||||||
protected CoordinateType yType = CoordinateType.Letters;
|
protected CoordinateType yType = CoordinateType.Letters;
|
||||||
|
|
||||||
protected Size length;
|
protected Size length;
|
||||||
protected Size width;
|
protected Size width;
|
||||||
protected BoardSizingMode mode = BoardSizingMode.TwoPoints;
|
protected BoardSizingMode mode = BoardSizingMode.TwoPoints;
|
||||||
|
|
||||||
|
protected BoardUndersideDisplay boardUndersideDisplay = BoardUndersideDisplay.NONE;
|
||||||
|
protected Size undersideOffset = DEFAULT_UNDERSIDE_OFFSET;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||||
IDrawingObserver drawingObserver) {
|
IDrawingObserver drawingObserver) {
|
||||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||||
|
|
||||||
Point2D finalSecondPoint = getFinalSecondPoint();
|
Point2D finalSecondPoint = getFinalSecondPoint();
|
||||||
|
|
||||||
Composite oldComposite = g2d.getComposite();
|
Composite oldComposite = g2d.getComposite();
|
||||||
// render as transparent when dragging
|
// render as transparent when dragging
|
||||||
@@ -90,64 +95,64 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
g2d.setColor(boardColor);
|
g2d.setColor(boardColor);
|
||||||
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
g2d.fillRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
||||||
g2d.setComposite(oldComposite);
|
g2d.setComposite(oldComposite);
|
||||||
|
|
||||||
// Do not track any changes that follow because the whole board has been
|
// Do not track any changes that follow because the whole board has been
|
||||||
// tracked so far.
|
// tracked so far.
|
||||||
drawingObserver.stopTracking();
|
drawingObserver.stopTracking();
|
||||||
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
|
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()));
|
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Point2D getFinalSecondPoint() {
|
protected Point2D getFinalSecondPoint() {
|
||||||
Point2D finalSecondPoint;
|
Point2D finalSecondPoint;
|
||||||
if (getMode() == BoardSizingMode.TwoPoints)
|
if (getMode() == BoardSizingMode.TwoPoints)
|
||||||
finalSecondPoint = secondPoint;
|
finalSecondPoint = secondPoint;
|
||||||
else
|
else
|
||||||
finalSecondPoint = new Point2D.Double(firstPoint.getX() + getLength().convertToPixels(),
|
finalSecondPoint = new Point2D.Double(firstPoint.getX() + getLength().convertToPixels(),
|
||||||
firstPoint.getY() + getWidth().convertToPixels());
|
firstPoint.getY() + getWidth().convertToPixels());
|
||||||
return finalSecondPoint;
|
return finalSecondPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void drawCoordinates(Graphics2D g2d, double spacing, Project project) {
|
protected void drawCoordinates(Graphics2D g2d, double spacing, Project project) {
|
||||||
g2d.setColor(coordinateColor);
|
g2d.setColor(coordinateColor);
|
||||||
g2d.setFont(project.getFont().deriveFont(COORDINATE_FONT_SIZE));
|
g2d.setFont(project.getFont().deriveFont(COORDINATE_FONT_SIZE));
|
||||||
|
|
||||||
// The half space is used to do rounding when calculating the range.
|
// The half space is used to do rounding when calculating the range.
|
||||||
double halfSpace = spacing / 2;
|
double halfSpace = spacing / 2;
|
||||||
CoordinateOrigin origin = getCoordinateOrigin();
|
CoordinateOrigin origin = getCoordinateOrigin();
|
||||||
|
|
||||||
Point2D finalSecondPoint = getFinalSecondPoint();
|
Point2D finalSecondPoint = getFinalSecondPoint();
|
||||||
|
|
||||||
if (getCoordinateDisplay() != CoordinateDisplay.None) {
|
if (getCoordinateDisplay() != CoordinateDisplay.None) {
|
||||||
int range;
|
int range;
|
||||||
double yOffset;
|
double yOffset;
|
||||||
CoordinateType yType = getyType();
|
CoordinateType yType = getyType();
|
||||||
double y = firstPoint.getY();
|
double y = firstPoint.getY();
|
||||||
|
|
||||||
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Top_Right) {
|
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Top_Right) {
|
||||||
range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
|
range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
|
||||||
yOffset = spacing;
|
yOffset = spacing;
|
||||||
} else {
|
} else {
|
||||||
range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
|
range = (int) ((finalSecondPoint.getY() - firstPoint.getY() + halfSpace) / spacing);
|
||||||
yOffset = -spacing;
|
yOffset = -spacing;
|
||||||
y = finalSecondPoint.getY();
|
y = finalSecondPoint.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int c = 1; c < range; c++) {
|
for (int c = 1; c < range; c++) {
|
||||||
int xOffset = (yType == CoordinateType.Numbers && c >= 10) || (yType == CoordinateType.Letters && c >= 27) ? 0 : 2;
|
int xOffset = (yType == CoordinateType.Numbers && c >= 10) || (yType == CoordinateType.Letters && c >= 27) ? 0 : 2;
|
||||||
String label = yType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
|
String label = yType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
|
||||||
|
|
||||||
y += yOffset;
|
y += yOffset;
|
||||||
|
|
||||||
StringUtils.drawCenteredText(g2d, label,
|
StringUtils.drawCenteredText(g2d, label,
|
||||||
firstPoint.getX() + xOffset, y,
|
firstPoint.getX() + xOffset, y,
|
||||||
HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
|
HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
|
||||||
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
|
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
|
||||||
StringUtils.drawCenteredText(g2d, label,
|
StringUtils.drawCenteredText(g2d, label,
|
||||||
finalSecondPoint.getX() - xOffset, y,
|
finalSecondPoint.getX() - xOffset, y,
|
||||||
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
|
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,8 +160,8 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
int range;
|
int range;
|
||||||
double xOffset;
|
double xOffset;
|
||||||
CoordinateType xType = getxType();
|
CoordinateType xType = getxType();
|
||||||
double x = firstPoint.getX();
|
double x = firstPoint.getX();
|
||||||
|
|
||||||
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Bottom_Left) {
|
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Bottom_Left) {
|
||||||
range = (int) ((finalSecondPoint.getX() - firstPoint.getX() + halfSpace) / spacing);
|
range = (int) ((finalSecondPoint.getX() - firstPoint.getX() + halfSpace) / spacing);
|
||||||
xOffset = spacing;
|
xOffset = spacing;
|
||||||
@@ -165,19 +170,19 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
xOffset = -spacing;
|
xOffset = -spacing;
|
||||||
x = finalSecondPoint.getX();
|
x = finalSecondPoint.getX();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int c = 1; c < range; c++) {
|
for (int c = 1; c < range; c++) {
|
||||||
String label = xType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
|
String label = xType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
|
||||||
|
|
||||||
x += xOffset;
|
x += xOffset;
|
||||||
|
|
||||||
StringUtils.drawCenteredText(g2d, label,
|
StringUtils.drawCenteredText(g2d, label,
|
||||||
x, firstPoint.getY() + 2,
|
x, firstPoint.getY() + 2,
|
||||||
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
|
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
|
||||||
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
|
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
|
||||||
StringUtils.drawCenteredText(g2d, label,
|
StringUtils.drawCenteredText(g2d, label,
|
||||||
x, (int) (finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
|
x, (int) (finalSecondPoint.getY() - COORDINATE_FONT_SIZE),
|
||||||
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
|
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +230,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
public void setBorderColor(Color borderColor) {
|
public void setBorderColor(Color borderColor) {
|
||||||
this.borderColor = borderColor;
|
this.borderColor = borderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EditableProperty(name = "X")
|
@EditableProperty(name = "X")
|
||||||
public CoordinateType getxType() {
|
public CoordinateType getxType() {
|
||||||
if (xType == null)
|
if (xType == null)
|
||||||
@@ -250,15 +255,15 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
|
|
||||||
@EditableProperty(name = "Coordinate Origin")
|
@EditableProperty(name = "Coordinate Origin")
|
||||||
public CoordinateOrigin getCoordinateOrigin() {
|
public CoordinateOrigin getCoordinateOrigin() {
|
||||||
if (coordinateOrigin == null)
|
if (coordinateOrigin == null)
|
||||||
coordinateOrigin = CoordinateOrigin.Top_Left;
|
coordinateOrigin = CoordinateOrigin.Top_Left;
|
||||||
return coordinateOrigin;
|
return coordinateOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCoordinateOrigin(CoordinateOrigin coordinateOrigin) {
|
public void setCoordinateOrigin(CoordinateOrigin coordinateOrigin) {
|
||||||
this.coordinateOrigin = coordinateOrigin;
|
this.coordinateOrigin = coordinateOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EditableProperty(name = "Y")
|
@EditableProperty(name = "Y")
|
||||||
public CoordinateType getyType() {
|
public CoordinateType getyType() {
|
||||||
if (yType == null)
|
if (yType == null)
|
||||||
@@ -294,9 +299,9 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
public void setControlPoint(Point2D point, int index) {
|
public void setControlPoint(Point2D point, int index) {
|
||||||
controlPoints[index].setLocation(point);
|
controlPoints[index].setLocation(point);
|
||||||
firstPoint.setLocation(Math.min(controlPoints[0].getX(), controlPoints[1].getX()),
|
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()),
|
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
|
@EditableProperty
|
||||||
@@ -309,13 +314,13 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
public void setValue(String value) {
|
public void setValue(String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SizeUnit getDefaultUnit() {
|
private SizeUnit getDefaultUnit() {
|
||||||
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.METRIC_KEY, true))
|
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.METRIC_KEY, true))
|
||||||
return SizeUnit.mm;
|
return SizeUnit.mm;
|
||||||
return SizeUnit.in;
|
return SizeUnit.in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EditableProperty(name = "Explicit Length", validatorClass = BoardModeValidator.class)
|
@EditableProperty(name = "Explicit Length", validatorClass = BoardModeValidator.class)
|
||||||
public Size getLength() {
|
public Size getLength() {
|
||||||
if (getMode() == BoardSizingMode.TwoPoints) {
|
if (getMode() == BoardSizingMode.TwoPoints) {
|
||||||
@@ -327,12 +332,12 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
|
|
||||||
public void setLength(Size length) {
|
public void setLength(Size length) {
|
||||||
if (getMode() == BoardSizingMode.Explicit && length != null && width != null) {
|
if (getMode() == BoardSizingMode.Explicit && length != null && width != null) {
|
||||||
setControlPoint(firstPoint, 0);
|
setControlPoint(firstPoint, 0);
|
||||||
Point2D second = new Point2D.Double(firstPoint.getX() + length.convertToPixels(),
|
Point2D second = new Point2D.Double(firstPoint.getX() + length.convertToPixels(),
|
||||||
firstPoint.getY() + width.convertToPixels());
|
firstPoint.getY() + width.convertToPixels());
|
||||||
setControlPoint(second, 1);
|
setControlPoint(second, 1);
|
||||||
}
|
}
|
||||||
this.length = length;
|
this.length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EditableProperty(name = "Explicit Width", validatorClass = BoardModeValidator.class)
|
@EditableProperty(name = "Explicit Width", validatorClass = BoardModeValidator.class)
|
||||||
@@ -352,7 +357,7 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
}
|
}
|
||||||
this.width = width;
|
this.width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EditableProperty(name = "Dimension Mode")
|
@EditableProperty(name = "Dimension Mode")
|
||||||
public BoardSizingMode getMode() {
|
public BoardSizingMode getMode() {
|
||||||
if (mode == null)
|
if (mode == null)
|
||||||
@@ -363,27 +368,66 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
public void setMode(BoardSizingMode mode) {
|
public void setMode(BoardSizingMode mode) {
|
||||||
this.mode = 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
|
@Override
|
||||||
public Rectangle2D getCachingBounds() {
|
public Rectangle2D getCachingBounds() {
|
||||||
Point2D finalSecondPoint = getFinalSecondPoint();
|
Point2D finalSecondPoint = getFinalSecondPoint();
|
||||||
return new Rectangle2D.Double(Math.min(firstPoint.getX(), finalSecondPoint.getX()) - 2, Math.min(firstPoint.getY(), finalSecondPoint.getY()) - 2,
|
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);
|
Math.abs(finalSecondPoint.getX() - firstPoint.getX()) + 4, Math.abs(finalSecondPoint.getY() - firstPoint.getY()) + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum CoordinateType {
|
public static enum CoordinateType {
|
||||||
Letters, Numbers
|
Letters, Numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum CoordinateDisplay {
|
public static enum CoordinateDisplay {
|
||||||
None, One_Side, Both_Sides;
|
None, One_Side, Both_Sides;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString().replace('_', ' ');
|
return super.toString().replace('_', ' ');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum CoordinateOrigin {
|
public static enum CoordinateOrigin {
|
||||||
Top_Left, Top_Right, Bottom_Right, Bottom_Left;
|
Top_Left, Top_Right, Bottom_Right, Bottom_Left;
|
||||||
|
|
||||||
@@ -392,19 +436,19 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
|
|||||||
return super.toString().replace('_', ' ');
|
return super.toString().replace('_', ' ');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum BoardSizingMode {
|
public static enum BoardSizingMode {
|
||||||
TwoPoints("Opposing Points"), Explicit("Explicit Dimensions");
|
TwoPoints("Opposing Points"), Explicit("Explicit Dimensions");
|
||||||
|
|
||||||
private String label;
|
private String label;
|
||||||
|
|
||||||
private BoardSizingMode(String label) {
|
private BoardSizingMode(String label) {
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,6 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
import org.diylc.common.ObjectCache;
|
import org.diylc.common.ObjectCache;
|
||||||
import org.diylc.components.transform.SimpleComponentTransformer;
|
import org.diylc.components.transform.SimpleComponentTransformer;
|
||||||
import org.diylc.core.ComponentState;
|
import org.diylc.core.ComponentState;
|
||||||
@@ -38,12 +37,11 @@ import org.diylc.core.Project;
|
|||||||
import org.diylc.core.annotations.BomPolicy;
|
import org.diylc.core.annotations.BomPolicy;
|
||||||
import org.diylc.core.annotations.ComponentDescriptor;
|
import org.diylc.core.annotations.ComponentDescriptor;
|
||||||
import org.diylc.core.annotations.EditableProperty;
|
import org.diylc.core.annotations.EditableProperty;
|
||||||
import org.diylc.core.gerber.IGerberBoard;
|
|
||||||
|
|
||||||
@ComponentDescriptor(name = "Blank Board", category = "Boards", author = "Branislav Stojkovic",
|
@ComponentDescriptor(name = "Blank Board", category = "Boards", author = "Branislav Stojkovic",
|
||||||
zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board", description = "Blank circuit board",
|
zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board", description = "Blank circuit board",
|
||||||
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, transformer = SimpleComponentTransformer.class)
|
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, transformer = SimpleComponentTransformer.class)
|
||||||
public class BlankBoard extends AbstractBoard implements IGerberBoard {
|
public class BlankBoard extends AbstractBoard {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -60,14 +58,14 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||||
IDrawingObserver drawingObserver) {
|
IDrawingObserver drawingObserver) {
|
||||||
Point2D finalSecondPoint = getFinalSecondPoint();
|
Point2D finalSecondPoint = getFinalSecondPoint();
|
||||||
|
|
||||||
Shape clip = g2d.getClip();
|
Shape clip = g2d.getClip();
|
||||||
if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
|
if (checkPointsClipped(clip) && !clip.contains(firstPoint.getX(), finalSecondPoint.getY())
|
||||||
&& !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
|
&& !clip.contains(finalSecondPoint.getX(), firstPoint.getY())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||||
if (componentState != ComponentState.DRAGGING) {
|
if (componentState != ComponentState.DRAGGING) {
|
||||||
@@ -86,13 +84,13 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
|
|||||||
// tracked so far.
|
// tracked so far.
|
||||||
drawingObserver.stopTracking();
|
drawingObserver.stopTracking();
|
||||||
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
|
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
|
||||||
: borderColor);
|
: borderColor);
|
||||||
if (getType() == Type.SQUARE)
|
if (getType() == Type.SQUARE)
|
||||||
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
g2d.drawRect((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
||||||
else
|
else
|
||||||
g2d.drawOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
g2d.drawOval((int)firstPoint.getX(), (int)firstPoint.getY(), (int)(finalSecondPoint.getX() - firstPoint.getX()), (int)(finalSecondPoint.getY() - firstPoint.getY()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CoordinateType getxType() {
|
public CoordinateType getxType() {
|
||||||
// Override to prevent editing.
|
// Override to prevent editing.
|
||||||
@@ -128,12 +126,17 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
|
|||||||
public void setType(Type type) {
|
public void setType(Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getControlPointNodeName(int index) {
|
public String getControlPointNodeName(int index) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldExportToGerber() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static enum Type {
|
static enum Type {
|
||||||
ROUND, SQUARE;
|
ROUND, SQUARE;
|
||||||
|
|
||||||
@@ -142,12 +145,4 @@ public class BlankBoard extends AbstractBoard implements IGerberBoard {
|
|||||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -583,6 +583,8 @@ Tubular Beveled
|
|||||||
Two
|
Two
|
||||||
Type
|
Type
|
||||||
Ultra-miniature
|
Ultra-miniature
|
||||||
|
Underside Display
|
||||||
|
Underside Offset
|
||||||
Underside Pad Color
|
Underside Pad Color
|
||||||
Underside Trace Color
|
Underside Trace Color
|
||||||
Undo
|
Undo
|
||||||
|
|||||||
Reference in New Issue
Block a user