mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 17:22:09 +10:00
mirror
This commit is contained in:
@@ -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(), false);
|
renderAndCache(x.getComponent(), g2d, x.getState(), outlineMode, project, zoom, scaleFactor, x.getZOrder());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -89,14 +89,10 @@ 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());
|
||||||
|
|
||||||
@@ -104,7 +100,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, mirrored);
|
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom, scaleFactor, zOrder);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return;
|
return;
|
||||||
@@ -184,7 +180,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 mirrored) {
|
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder) {
|
||||||
// if we need to apply caching
|
// if we need to apply caching
|
||||||
Point2D firstPoint = component.getControlPoint(0);
|
Point2D firstPoint = component.getControlPoint(0);
|
||||||
|
|
||||||
@@ -200,7 +196,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.isMirrored() != mirrored) {
|
|| value.getScaleFactor() != scaleFactor) {
|
||||||
// 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);
|
||||||
@@ -274,7 +270,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, mirrored);
|
wrapper.getContinuityNegativeAreas(), componentState, outlineMode, zoom, scaleFactor, dx, dy, rect);
|
||||||
imageCache.put(component, new SoftReference<DrawingCache.CacheValue>(value));
|
imageCache.put(component, new SoftReference<DrawingCache.CacheValue>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +287,6 @@ 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;
|
||||||
@@ -299,7 +294,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, boolean mirrored) {
|
Rectangle2D cacheBounds) {
|
||||||
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
|
||||||
@@ -314,7 +309,6 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -355,10 +349,6 @@ public class DrawingCache {
|
|||||||
return scaleFactor;
|
return scaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMirrored() {
|
|
||||||
return mirrored;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDx() {
|
public int getDx() {
|
||||||
return dx;
|
return dx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,26 +46,12 @@ 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.EventType;
|
import org.diylc.common.*;
|
||||||
import org.diylc.common.GridType;
|
|
||||||
import org.diylc.common.IComponentFilter;
|
|
||||||
import org.diylc.common.IPlugInPort;
|
|
||||||
import org.diylc.common.ObjectCache;
|
|
||||||
import org.diylc.components.AbstractTransparentComponent;
|
import org.diylc.components.AbstractTransparentComponent;
|
||||||
import org.diylc.core.BoardUndersideDisplay;
|
import org.diylc.core.*;
|
||||||
import org.diylc.core.ComponentForRender;
|
|
||||||
import org.diylc.core.ComponentState;
|
|
||||||
import org.diylc.core.IBoard;
|
|
||||||
import org.diylc.core.IContinuity;
|
|
||||||
import org.diylc.core.IDIYComponent;
|
|
||||||
import org.diylc.core.ILayeredComponent;
|
|
||||||
import org.diylc.core.Project;
|
|
||||||
import org.diylc.core.Theme;
|
|
||||||
import org.diylc.core.VisibilityPolicy;
|
|
||||||
import org.diylc.core.measures.Size;
|
import org.diylc.core.measures.Size;
|
||||||
import org.diylc.core.measures.SizeUnit;
|
import org.diylc.core.measures.SizeUnit;
|
||||||
import org.diylc.netlist.ContinuityGraph;
|
import org.diylc.netlist.ContinuityGraph;
|
||||||
@@ -81,6 +67,7 @@ import org.diylc.utils.Constants;
|
|||||||
public class DrawingManager {
|
public class DrawingManager {
|
||||||
|
|
||||||
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
|
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
|
||||||
|
public static final byte MIRROR_ALPHA = 64;
|
||||||
|
|
||||||
public static int CONTROL_POINT_SIZE = 7;
|
public static int CONTROL_POINT_SIZE = 7;
|
||||||
public static double EXTRA_SPACE = 0.25;
|
public static double EXTRA_SPACE = 0.25;
|
||||||
@@ -95,8 +82,6 @@ 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.
|
||||||
@@ -176,14 +161,12 @@ public class DrawingManager {
|
|||||||
* @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) {
|
||||||
@@ -202,7 +185,7 @@ public class DrawingManager {
|
|||||||
|
|
||||||
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
|
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
|
||||||
|
|
||||||
configureG2D(g2d, drawOptions);
|
configureRenderingHints(g2d, drawOptions);
|
||||||
|
|
||||||
// group components with boards that contain them
|
// group components with boards that contain them
|
||||||
Map<IBoard, List<IDIYComponent<?>>> boardMap = project.getComponents().stream()
|
Map<IBoard, List<IDIYComponent<?>>> boardMap = project.getComponents().stream()
|
||||||
@@ -210,7 +193,7 @@ public class DrawingManager {
|
|||||||
.map(IBoard.class::cast)
|
.map(IBoard.class::cast)
|
||||||
.filter(b -> b.getBoardUndersideDisplay() != BoardUndersideDisplay.NONE)
|
.filter(b -> b.getBoardUndersideDisplay() != BoardUndersideDisplay.NONE)
|
||||||
.collect(Collectors.toMap(x -> x, x -> new ArrayList<IDIYComponent<?>>()));
|
.collect(Collectors.toMap(x -> x, x -> new ArrayList<IDIYComponent<?>>()));
|
||||||
Map<IDIYComponent<?>, List<IBoard>> componentBoardMap = new HashMap<IDIYComponent<?>, List<IBoard>>();
|
Map<IDIYComponent<?>, Set<IBoard>> componentBoardMap = new HashMap<IDIYComponent<?>, Set<IBoard>>();
|
||||||
|
|
||||||
for (IBoard board : boardMap.keySet()) {
|
for (IBoard board : boardMap.keySet()) {
|
||||||
Rectangle2D boardRect = board.getBoardRectangle();
|
Rectangle2D boardRect = board.getBoardRectangle();
|
||||||
@@ -227,7 +210,7 @@ public class DrawingManager {
|
|||||||
}
|
}
|
||||||
if (include) {
|
if (include) {
|
||||||
boardMap.get(board).add(c);
|
boardMap.get(board).add(c);
|
||||||
componentBoardMap.computeIfAbsent(c, key -> new ArrayList<IBoard>()).add(board);
|
componentBoardMap.computeIfAbsent(c, key -> new HashSet<IBoard>()).add(board);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,7 +279,6 @@ public class DrawingManager {
|
|||||||
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.
|
||||||
@@ -317,26 +299,11 @@ public class DrawingManager {
|
|||||||
long componentStart = System.nanoTime();
|
long componentStart = System.nanoTime();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
AffineTransform txBefore = new AffineTransform(g2d.getTransform());
|
drawComponent(project, drawOptions, scaleFactor, visibleRect, component, g2dWrapper, state, zoom, i, outlineMode);
|
||||||
drawComponent(project, drawOptions, scaleFactor, visibleRect, zoom, g2dWrapper,
|
|
||||||
outlineMode, i, component, state, false);
|
|
||||||
g2dWrapper.setTransform(txBefore);
|
|
||||||
|
|
||||||
// find one or more boards that contain the component and mirror the component to all
|
if (g2dWrapper.isTrackingContinuityArea()) {
|
||||||
List<IBoard> boards = componentBoardMap.get(component);
|
LOG.info("Component " + component.getName() + " of type "
|
||||||
if (boards != null) {
|
+ component.getClass().getName() + " did not stop tracking continuity area.");
|
||||||
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);
|
||||||
@@ -365,6 +332,29 @@ public class DrawingManager {
|
|||||||
componentAreaMap.put(component, area);
|
componentAreaMap.put(component, area);
|
||||||
lastDrawnStateMap.put(component, state);
|
lastDrawnStateMap.put(component, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mirror components that belong to boards that need to be mirrored
|
||||||
|
if (componentBoardMap.containsKey(component)) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ComponentType componentType = ComponentProcessor.getInstance()
|
||||||
|
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
|
||||||
|
if (componentType.getTransformer() != null) {
|
||||||
|
Set<IBoard> boards = componentBoardMap.get(component);
|
||||||
|
for (IBoard board : boards) {
|
||||||
|
drawMirroredComponent(project, board, component, componentType, g2dWrapper, state, outlineMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a component itself is a board that needs to be mirrored, do it
|
||||||
|
if (IBoard.class.isInstance(component) && componentBoardMap.values().stream()
|
||||||
|
.anyMatch(boards -> boards.contains(component))) {
|
||||||
|
ComponentType componentType = ComponentProcessor.getInstance()
|
||||||
|
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
|
||||||
|
if (componentType.getTransformer() != null) {
|
||||||
|
drawMirroredComponent(project, (IBoard) component, component, componentType, g2dWrapper, state, outlineMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,89 +516,52 @@ public class DrawingManager {
|
|||||||
return failedComponents;
|
return failedComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawMirroredComponent(Project project, Set<DrawOption> drawOptions,
|
private static void drawMirroredComponent(Project project, IBoard board, IDIYComponent<?> component,
|
||||||
Double scaleFactor, Rectangle2D visibleRect, double zoom, G2DWrapper g2dWrapper,
|
ComponentType componentType, G2DWrapper g2dWrapper, ComponentState state, boolean outlineMode) {
|
||||||
boolean outlineMode, int i, ComponentState state, double boardMirrorSpacing,
|
double offset = board.getUndersideOffset().convertToPixels();
|
||||||
IDIYComponent<?> componentToDraw, IBoard board) {
|
|
||||||
Rectangle2D boardRectangle = board.getBoardRectangle();
|
Rectangle2D boardRectangle = board.getBoardRectangle();
|
||||||
AffineTransform mirrorTx = null;
|
try {
|
||||||
|
IDIYComponent<?> clonedComponent = component.clone();
|
||||||
|
int direction = 0;
|
||||||
|
Point2D pivotPoint = new Point2D.Double();
|
||||||
switch (board.getBoardUndersideDisplay()) {
|
switch (board.getBoardUndersideDisplay()) {
|
||||||
case ABOVE:
|
case ABOVE:
|
||||||
mirrorTx = new AffineTransform();
|
direction = IComponentTransformer.VERTICAL;
|
||||||
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMinY());
|
pivotPoint.setLocation(boardRectangle.getMinX(), boardRectangle.getMinY() - offset / 2);
|
||||||
mirrorTx.scale(1, -1);
|
|
||||||
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMinY());
|
|
||||||
mirrorTx.translate(0, boardMirrorSpacing);
|
|
||||||
break;
|
break;
|
||||||
case BELOW:
|
case BELOW:
|
||||||
mirrorTx = new AffineTransform();
|
direction = IComponentTransformer.VERTICAL;
|
||||||
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMaxY());
|
pivotPoint.setLocation(boardRectangle.getMinX(), boardRectangle.getMaxY() + offset / 2);
|
||||||
mirrorTx.scale(1, -1);
|
|
||||||
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMaxY());
|
|
||||||
mirrorTx.translate(0, -boardMirrorSpacing);
|
|
||||||
break;
|
break;
|
||||||
case LEFT:
|
case LEFT:
|
||||||
mirrorTx = new AffineTransform();
|
direction = IComponentTransformer.HORIZONTAL;
|
||||||
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMinY());
|
pivotPoint.setLocation(boardRectangle.getMinX() - offset / 2, boardRectangle.getMinY());
|
||||||
mirrorTx.scale(-1, 1);
|
|
||||||
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMinY());
|
|
||||||
mirrorTx.translate(boardMirrorSpacing, 0);
|
|
||||||
break;
|
break;
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
mirrorTx = new AffineTransform();
|
direction = IComponentTransformer.HORIZONTAL;
|
||||||
mirrorTx.translate(boardRectangle.getMaxX(), boardRectangle.getMinY());
|
pivotPoint.setLocation(boardRectangle.getMaxX() + offset / 2, 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;
|
break;
|
||||||
}
|
}
|
||||||
AffineTransform txBefore = new AffineTransform(g2dWrapper.getTransform());
|
componentType.getTransformer().mirror(clonedComponent, pivotPoint, direction);
|
||||||
byte alphaBefore = 0;
|
if (AbstractTransparentComponent.class.isInstance(clonedComponent)) {
|
||||||
if (AbstractTransparentComponent.class.isInstance(componentToDraw)) {
|
AbstractTransparentComponent<?> transparentComponent = (AbstractTransparentComponent<?>) clonedComponent;
|
||||||
alphaBefore = ((AbstractTransparentComponent<?>)componentToDraw).getAlpha();
|
transparentComponent.setAlpha(MIRROR_ALPHA);
|
||||||
((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);
|
|
||||||
}
|
}
|
||||||
|
clonedComponent.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawComponent(Project project, Set<DrawOption> drawOptions, Double scaleFactor,
|
private static void drawComponent(Project project, Set<DrawOption> drawOptions, Double scaleFactor, Rectangle2D visibleRect, IDIYComponent<?> component, G2DWrapper g2dWrapper, ComponentState state, double zoom, int i, boolean outlineMode) {
|
||||||
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
|
if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
|
||||||
DrawingCache.Instance.draw(component, g2dWrapper, state,
|
DrawingCache.Instance.draw(component, g2dWrapper, state,
|
||||||
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect, mirrored);
|
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect);
|
||||||
else // go straight to the wrapper
|
else // go straight to the wrapper
|
||||||
component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
|
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) {
|
private void configureRenderingHints(Graphics2D g2d, Set<DrawOption> drawOptions) {
|
||||||
if (drawOptions.contains(DrawOption.ANTIALIASING)) {
|
if (drawOptions.contains(DrawOption.ANTIALIASING)) {
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ 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;
|
||||||
@@ -69,7 +70,7 @@ 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(int)} ()} should be called. After the component is drawn, area may be
|
* {@link #startedDrawingComponent()} 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.
|
||||||
*
|
*
|
||||||
@@ -106,8 +107,6 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
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.
|
||||||
*
|
*
|
||||||
@@ -222,10 +221,6 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
|
|||||||
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.
|
||||||
*
|
*
|
||||||
@@ -350,73 +345,22 @@ 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) {
|
||||||
this.drawString(str, (float)x, (float)y);
|
canvasGraphics.drawString(str, x, 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) {
|
||||||
if (this.mirrorTransform == null) {
|
|
||||||
canvasGraphics.drawString(str, x, y);
|
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);
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ public class CliffJackTransformer implements IComponentTransformer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mirroringChangesCircuit() {
|
public boolean mirroringChangesCircuit() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ And
|
|||||||
Angle
|
Angle
|
||||||
Angle Offset
|
Angle Offset
|
||||||
Anti-Aliasing
|
Anti-Aliasing
|
||||||
|
Apply Model
|
||||||
Arrow Size
|
Arrow Size
|
||||||
Author
|
Author
|
||||||
Auto-Create Pads
|
Auto-Create Pads
|
||||||
@@ -81,6 +82,8 @@ Below
|
|||||||
Board
|
Board
|
||||||
Board Color
|
Board Color
|
||||||
Board Width
|
Board Width
|
||||||
|
Board1
|
||||||
|
Board2
|
||||||
Boards
|
Boards
|
||||||
Bobbin 1
|
Bobbin 1
|
||||||
Bobbin 2
|
Bobbin 2
|
||||||
|
|||||||
Reference in New Issue
Block a user