From f21e591adbbe299e7cdf91df8e4bab2e124bd75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 29 Dec 2022 16:22:29 +0100 Subject: [PATCH] Hilight selected shape record --- .../flash/gui/GenericTagTreePanel.java | 49 +++++++++---- .../decompiler/flash/gui/ImagePanel.java | 67 +++++++++++++++++- .../decompiler/flash/gui/PreviewPanel.java | 68 ++++++++++++++++++- 3 files changed, 169 insertions(+), 15 deletions(-) diff --git a/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java b/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java index ddd498a1c..989f60e85 100644 --- a/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java @@ -95,11 +95,14 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; import javax.swing.plaf.basic.BasicLabelUI; import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; @@ -120,15 +123,23 @@ public class GenericTagTreePanel extends GenericTagPanel { private static final int FIELD_INDEX = 0; - private List listeners = new ArrayList<>(); + private List modelListeners = new ArrayList<>(); public void addTreeModelListener(TreeModelListener listener) { - listeners.add(listener); + modelListeners.add(listener); ((DefaultTreeModel) tree.getModel()).addTreeModelListener(listener); } + + public void addTreeSelectionListener(TreeSelectionListener listener) { + tree.addTreeSelectionListener(listener); + } + + public void removeTreeSelectionListener(TreeSelectionListener listener) { + tree.removeTreeSelectionListener(listener); + } public void removeTreeModelListener(TreeModelListener listener) { - listeners.remove(listener); + modelListeners.remove(listener); ((DefaultTreeModel) tree.getModel()).removeTreeModelListener(listener); } @@ -478,6 +489,11 @@ public class GenericTagTreePanel extends GenericTagPanel { tree.setRootVisible(false); tree.setShowsRootHandles(true); add(new FasterScrollPane(tree), BorderLayout.CENTER); + tree.addTreeSelectionListener(new TreeSelectionListener(){ + @Override + public void valueChanged(TreeSelectionEvent e) { + } + }); tree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { @@ -714,7 +730,7 @@ public class GenericTagTreePanel extends GenericTagPanel { } } - private static final class FieldNode extends DefaultMutableTreeNode { + public static final class FieldNode extends DefaultMutableTreeNode { private Tag tag; @@ -725,14 +741,21 @@ public class GenericTagTreePanel extends GenericTagPanel { private int index; private MyTreeModel model; - - public FieldNode(MyTreeModel model, Tag tag, Object obj, FieldSet fieldSet, int index) { + + private Object parentObject; + + public Object getParentObject() { + return parentObject; + } + + public FieldNode(Object parent, MyTreeModel model, Tag tag, Object obj, FieldSet fieldSet, int index) { this.tag = tag; this.obj = obj; this.fieldSet = fieldSet; this.index = index; - this.model = model; - + this.model = model; + this.parentObject = parent; + for (int i = 0; i < fieldSet.size(); i++) { if (getValue(i) == null) { try { @@ -1016,7 +1039,7 @@ public class GenericTagTreePanel extends GenericTagPanel { } } - private static class MyTreeModel extends DefaultTreeModel { + public static class MyTreeModel extends DefaultTreeModel { private final Tag mtroot; @@ -1107,15 +1130,15 @@ public class GenericTagTreePanel extends GenericTagPanel { private Object getChild(Object parent, int index, boolean limited) { if (parent == mtroot) { - return new FieldNode(this, mtroot, mtroot, filterFields(this, mtroot.getClass().getSimpleName(), mtroot.getClass(), limited, mtroot.getId()).get(index), -1); + return new FieldNode(null, this, mtroot, mtroot, filterFields(this, mtroot.getClass().getSimpleName(), mtroot.getClass(), limited, mtroot.getId()).get(index), -1); } FieldNode fnode = (FieldNode) parent; Field field = fnode.fieldSet.get(FIELD_INDEX); if (ReflectionTools.needsIndex(field) && (fnode.index == -1)) { //Arrays ot Lists - return new FieldNode(this, mtroot, fnode.obj, fnode.fieldSet, index); + return new FieldNode(parent, this, mtroot, fnode.obj, fnode.fieldSet, index); } parent = fnode.getValue(FIELD_INDEX); - return new FieldNode(this, mtroot, parent, filterFields(this, getNodePathName(fnode), parent.getClass(), limited, mtroot.getId()).get(index), -1); + return new FieldNode(parent, this, mtroot, parent, filterFields(this, getNodePathName(fnode), parent.getClass(), limited, mtroot.getId()).get(index), -1); } @Override @@ -1508,7 +1531,7 @@ public class GenericTagTreePanel extends GenericTagPanel { public void refreshTree() { View.refreshTree(tree, getModel()); - for (TreeModelListener listener:listeners) { + for (TreeModelListener listener:modelListeners) { ((DefaultTreeModel) tree.getModel()).addTreeModelListener(listener); } revalidate(); diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 6a2a35ce9..1765c58aa 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -111,7 +111,6 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.event.MouseInputAdapter; -import jsyntaxpane.util.SwingUtils; import org.pushingpixels.substance.api.ColorSchemeAssociationKind; import org.pushingpixels.substance.api.ComponentState; import org.pushingpixels.substance.api.DecorationAreaType; @@ -254,6 +253,11 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private DepthState depthStateUnderCursor = null; private List placeObjectSelectedListeners = new ArrayList<>(); + + private Point[] hilightedEdge = null; + + private int hilightEdgeColorStep = 10; + private int hilightEdgeColor = 0; private static Cursor loadCursor(String name, int x, int y) throws IOException { Toolkit toolkit = Toolkit.getDefaultToolkit(); @@ -265,6 +269,21 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private List boundsChangeListeners = new ArrayList<>(); + public void setHilightedEdge(Point[] hilightedEdge) { + this.hilightedEdge = hilightedEdge; + hilightEdgeColor = 255; + /*if (hilightedEdge == null) { + System.out.println("set no hilight edge"); + } else { + String s = ""; + for(Point p:hilightedEdge) { + s+="["+p.x+","+p.y+"]"; + } + System.out.println("set hilight edge " + s); + }*/ + redraw(); + } + public void addBoundsChangeListener(BoundsChangeListener listener) { boundsChangeListeners.add(listener); } @@ -617,6 +636,50 @@ public final class ImagePanel extends JPanel implements MediaDisplay { g2.drawImage(img.getBufferedImage(), x, y, x + img.getWidth(), y + img.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null); + if (hilightedEdge != null) { + hilightEdgeColor += hilightEdgeColorStep; + if (hilightEdgeColor < 100 || hilightEdgeColor > 255) { + hilightEdgeColorStep = -hilightEdgeColorStep; + hilightEdgeColor += hilightEdgeColorStep * 2; + } + RECT timRect = timelined.getRect(); + double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; + AffineTransform t = new AffineTransform(); + t.translate(offsetPoint.getX() - (int) (timRect.Xmin * zoomDouble / SWF.unitDivisor) + , offsetPoint.getY() - (int) (timRect.Ymin * zoomDouble / SWF.unitDivisor)); + t.scale(1/SWF.unitDivisor, 1/SWF.unitDivisor); + t.scale(zoomDouble, zoomDouble); + AffineTransform oldTransform = g2.getTransform(); + g2.setTransform(t); + g2.setStroke(new BasicStroke((float) (SWF.unitDivisor * 6 / zoomDouble))); + g2.setPaint(new Color(hilightEdgeColor, hilightEdgeColor, hilightEdgeColor)); + Point[] edge = hilightedEdge; + GeneralPath path = new GeneralPath(); + if (edge.length == 2) { + path.moveTo(edge[0].x, edge[0].y); + path.lineTo(edge[1].x, edge[1].y); + } + if (edge.length == 3) { + path.moveTo(edge[0].x, edge[0].y); + path.quadTo(edge[1].x, edge[1].y, edge[2].x, edge[2].y); + } + if (edge.length == 1) { + double crossSize = (SWF.unitDivisor * 10 / zoomDouble); + path.moveTo(edge[0].x - crossSize, edge[0].y); + path.lineTo(edge[0].x + crossSize, edge[0].y); + path.moveTo(edge[0].x, edge[0].y - crossSize); + path.lineTo(edge[0].x, edge[0].y + crossSize); + } + g2.draw(path); + + double pointSize = SWF.unitDivisor * 4 / zoomDouble; + + g2.setPaint(Color.red); + g2.fill(new Ellipse2D.Double(edge[edge.length - 1].x - pointSize, edge[edge.length - 1].y - pointSize, pointSize * 2, pointSize * 2)); + g2.setPaint(Color.green); + g2.fill(new Ellipse2D.Double(edge[0].x - pointSize, edge[0].y - pointSize, pointSize * 2, pointSize * 2)); + g2.setTransform(oldTransform); + } if (!(timelined instanceof SWF) && freeTransformDepth > -1) { int axisX = 0; @@ -1918,6 +1981,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { this.muted = muted; this.mutable = mutable; depthStateUnderCursor = null; + hilightedEdge = null; this.showObjectsUnderCursor = showObjectsUnderCursor; this.registrationPointPosition = RegistrationPointPosition.CENTER; centerImage(); @@ -1953,6 +2017,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { loaded = true; stillFrame = true; zoomAvailable = false; + hilightedEdge = null; iconPanel.setImg(image); drawReady = true; diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index ec4df982e..1405a6e6b 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -105,10 +105,15 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSplitPane; +import javax.swing.JTree; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.Transformer; @@ -772,6 +777,67 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel //placeSplitPane.setDividerLocation(800); placeTagCard.add(createPlaceTagButtonsPanel(), BorderLayout.SOUTH); + ((GenericTagTreePanel) displayEditGenericPanel).addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + JTree tree = (JTree) e.getSource(); + Object obj = e.getPath().getLastPathComponent(); + if (obj instanceof GenericTagTreePanel.FieldNode) { + GenericTagTreePanel.FieldNode fieldNode = (GenericTagTreePanel.FieldNode) obj; + Object val = fieldNode.getValue(0); + if (val instanceof SHAPERECORD) { + Object parent = fieldNode.getParentObject(); + if (parent == null) { + return; + } + int x = 0; + int y = 0; + TreeModel model = tree.getModel(); + for (int i = 0; i < model.getChildCount(parent); i++) { + Object child = model.getChild(parent, i); + GenericTagTreePanel.FieldNode childFN = (GenericTagTreePanel.FieldNode) child; + SHAPERECORD rec = (SHAPERECORD) childFN.getValue(0); + if (rec == val) { + if (rec instanceof StraightEdgeRecord) { + StraightEdgeRecord ser = (StraightEdgeRecord) rec; + Point point1 = new Point(x, y); + Point point2 = new Point(x + ser.deltaX, y + ser.deltaY); + Point[] hilightedPoint = new Point[]{point1, point2}; + displayEditImagePanel.setHilightedEdge(hilightedPoint); + } else if (rec instanceof CurvedEdgeRecord) { + CurvedEdgeRecord cer = (CurvedEdgeRecord) rec; + Point point1 = new Point(x, y); + Point point2 = new Point(x + cer.controlDeltaX, y + cer.controlDeltaY); + Point point3 = new Point(x + cer.controlDeltaX + cer.anchorDeltaX, y + cer.controlDeltaY + cer.anchorDeltaY); + Point[] hilightedPoint = new Point[]{point1, point2, point3}; + displayEditImagePanel.setHilightedEdge(hilightedPoint); + } else if (rec instanceof StyleChangeRecord) { + StyleChangeRecord scr = (StyleChangeRecord) rec; + if (scr.stateMoveTo) { + Point point1 = new Point(scr.moveDeltaX, scr.moveDeltaY); + Point[] hilightedPoint = new Point[]{point1}; + displayEditImagePanel.setHilightedEdge(hilightedPoint); + } else { + displayEditImagePanel.setHilightedEdge(null); + } + } else { + displayEditImagePanel.setHilightedEdge(null); + } + break; + } + x = rec.changeX(x); + y = rec.changeY(y); + } + } else { + displayEditImagePanel.setHilightedEdge(null); + } + + } else { + displayEditImagePanel.setHilightedEdge(null); + } + } + }); + return placeTagCard; } @@ -1468,7 +1534,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel (int) Math.round(edgeRect.yMax) ); } - shape.getSwf().clearShapeCache(); + shape.getSwf().clearShapeCache(); } displayEditTag.setModified(true); if (displayEditTag instanceof PlaceObjectTypeTag) {