Mercurial > hg > graal-compiler
view src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java @ 1552:c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
Summary: Change all the Sun copyrights to Oracle copyright
Reviewed-by: ohair
author | trims |
---|---|
date | Thu, 27 May 2010 19:08:38 -0700 |
parents | f4fe12e429a4 |
children | 53ddfe305645 |
line wrap: on
line source
/* * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ package com.sun.hotspot.igv.view; import com.sun.hotspot.igv.view.widgets.BlockWidget; import com.sun.hotspot.igv.view.widgets.LineWidget; import com.sun.hotspot.igv.util.DoubleClickAction; import com.sun.hotspot.igv.data.InputBlock; import com.sun.hotspot.igv.data.InputNode; import com.sun.hotspot.igv.graph.Connection; import com.sun.hotspot.igv.graph.Diagram; import com.sun.hotspot.igv.graph.Figure; import com.sun.hotspot.igv.graph.InputSlot; import com.sun.hotspot.igv.graph.OutputSlot; import com.sun.hotspot.igv.graph.Slot; import com.sun.hotspot.igv.hierarchicallayout.HierarchicalClusterLayoutManager; import com.sun.hotspot.igv.hierarchicallayout.OldHierarchicalLayoutManager; import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager; import com.sun.hotspot.igv.view.widgets.FigureWidget; import com.sun.hotspot.igv.view.widgets.InputSlotWidget; import com.sun.hotspot.igv.view.widgets.OutputSlotWidget; import com.sun.hotspot.igv.view.widgets.SlotWidget; import com.sun.hotspot.igv.layout.LayoutGraph; import com.sun.hotspot.igv.data.services.Scheduler; import com.sun.hotspot.igv.data.ChangedListener; import com.sun.hotspot.igv.graph.Block; import com.sun.hotspot.igv.util.ColorIcon; import com.sun.hotspot.igv.util.ExtendedSelectAction; import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.UndoableEditEvent; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import org.netbeans.api.visual.action.ActionFactory; import org.netbeans.api.visual.action.PopupMenuProvider; import org.netbeans.api.visual.action.RectangularSelectDecorator; import org.netbeans.api.visual.action.RectangularSelectProvider; import org.netbeans.api.visual.action.SelectProvider; import org.netbeans.api.visual.action.WidgetAction; import org.netbeans.api.visual.animator.SceneAnimator; import org.netbeans.api.visual.layout.LayoutFactory; import org.netbeans.api.visual.widget.ConnectionWidget; import org.netbeans.api.visual.widget.LayerWidget; import org.netbeans.api.visual.widget.Scene; import org.netbeans.api.visual.widget.Widget; import org.netbeans.api.visual.widget.LabelWidget; import org.openide.awt.UndoRedo; import org.openide.util.Lookup; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.InstanceContent; /** * * @author Thomas Wuerthinger */ public class DiagramScene extends Scene implements ChangedListener<DiagramViewModel> { private HashMap<Figure, FigureWidget> figureWidgets; private HashMap<Slot, SlotWidget> slotWidgets; private HashMap<Connection, ConnectionWidget> connectionWidgets; private HashMap<InputBlock, BlockWidget> blockWidgets; private Widget hoverWidget; private WidgetAction hoverAction; private List<FigureWidget> selectedWidgets; private Lookup lookup; private InstanceContent content; private Action[] actions; private LayerWidget connectionLayer; private JScrollPane scrollPane; private UndoRedo.Manager undoRedoManager; private LayerWidget mainLayer; private LayerWidget slotLayer; private LayerWidget blockLayer; private double realZoomFactor; private BoundedZoomAction zoomAction; private WidgetAction panAction; private Widget topLeft; private Widget bottomRight; private LayerWidget startLayer; private LabelWidget startLabel; private DiagramViewModel model; private DiagramViewModel modelCopy; public static final int AFTER = 1; public static final int BEFORE = 1; public static final float ALPHA = 0.4f; public static final int GRID_SIZE = 30; public static final int BORDER_SIZE = 20; public static final int UNDOREDO_LIMIT = 100; public static final int SCROLL_UNIT_INCREMENT = 80; public static final int SCROLL_BLOCK_INCREMENT = 400; public static final float ZOOM_MAX_FACTOR = 3.0f; public static final float ZOOM_MIN_FACTOR = 0.0f;//0.15f; public static final float ZOOM_INCREMENT = 1.5f; public static final int SLOT_OFFSET = 6; public static final int ANIMATION_LIMIT = 40; private PopupMenuProvider popupMenuProvider = new PopupMenuProvider() { public JPopupMenu getPopupMenu(Widget widget, Point localLocation) { return DiagramScene.this.createPopupMenu(); } }; private RectangularSelectDecorator rectangularSelectDecorator = new RectangularSelectDecorator() { public Widget createSelectionWidget() { Widget widget = new Widget(DiagramScene.this); widget.setBorder(BorderFactory.createLineBorder(Color.black, 2)); widget.setForeground(Color.red); return widget; } }; private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() { public void performSelection(Rectangle rectangle) { if (rectangle.width < 0) { rectangle.x += rectangle.width; rectangle.width *= -1; } if (rectangle.height < 0) { rectangle.y += rectangle.height; rectangle.height *= -1; } boolean updated = false; for (Figure f : getModel().getDiagramToView().getFigures()) { FigureWidget w = figureWidgets.get(f); Rectangle r = new Rectangle(w.getBounds()); r.setLocation(w.getLocation()); if (r.intersects(rectangle)) { if (!selectedWidgets.contains(w)) { addToSelection(w); updated = true; } } else { if (selectedWidgets.contains(w)) { selectedWidgets.remove(w); content.remove(w.getNode()); w.setState(w.getState().deriveSelected(false)); updated = true; } } } if (updated) { selectionUpdated(); } } }; private SelectProvider selectProvider = new SelectProvider() { public boolean isAimingAllowed(Widget widget, Point point, boolean b) { return false; } public boolean isSelectionAllowed(Widget widget, Point point, boolean b) { return widget instanceof FigureWidget || widget == DiagramScene.this; } public void select(Widget w, Point point, boolean change) { boolean updated = false; if (w == DiagramScene.this) { if (DiagramScene.this.selectedWidgets.size() != 0) { clearSelection(); selectionUpdated(); } return; } FigureWidget widget = (FigureWidget) w; if (change) { if (widget.getState().isSelected()) { assert selectedWidgets.contains(widget); widget.setState(widget.getState().deriveSelected(false)); selectedWidgets.remove(widget); content.remove(widget.getNode()); updated = true; } else { assert !selectedWidgets.contains(widget); addToSelection(widget); updated = true; assert widget.getState().isSelected(); } } else { if (widget.getState().isSelected()) { assert selectedWidgets.contains(widget); } else { assert !selectedWidgets.contains(widget); clearSelection(); addToSelection(widget); updated = true; assert widget.getState().isSelected(); } } if (updated) { selectionUpdated(); } } }; private FigureWidget getFigureWidget(Figure f) { return figureWidgets.get(f); } private FocusListener focusListener = new FocusListener() { public void focusGained(FocusEvent e) { DiagramScene.this.getView().requestFocus(); } public void focusLost(FocusEvent e) { } }; private MouseWheelListener mouseWheelListener = new MouseWheelListener() { public void mouseWheelMoved(MouseWheelEvent e) { DiagramScene.this.zoomAction.mouseWheelMoved(DiagramScene.this, new WidgetAction.WidgetMouseWheelEvent(0, e)); DiagramScene.this.validate(); } }; private MouseListener mouseListener = new MouseListener() { public void mouseClicked(MouseEvent e) { DiagramScene.this.panAction.mouseClicked(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e)); } public void mousePressed(MouseEvent e) { DiagramScene.this.panAction.mousePressed(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e)); } public void mouseReleased(MouseEvent e) { DiagramScene.this.panAction.mouseReleased(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e)); } public void mouseEntered(MouseEvent e) { DiagramScene.this.panAction.mouseEntered(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e)); } public void mouseExited(MouseEvent e) { DiagramScene.this.panAction.mouseExited(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e)); } }; private MouseMotionListener mouseMotionListener = new MouseMotionListener() { public void mouseDragged(MouseEvent e) { DiagramScene.this.panAction.mouseDragged(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e)); } public void mouseMoved(MouseEvent e) { } }; private ScrollChangeListener scrollChangeListener = new ScrollChangeListener(); private class ScrollChangeListener implements ChangeListener { private Map<Widget, Point> relativePositions = new HashMap<Widget, Point>(); private Point oldPosition; public void register(Widget w, Point p) { relativePositions.put(w, p); } public void unregister(Widget w) { relativePositions.remove(w); } public void stateChanged(ChangeEvent e) { Point p = DiagramScene.this.getScrollPane().getViewport().getViewPosition(); if (oldPosition == null || !p.equals(oldPosition)) { for (Widget w : relativePositions.keySet()) { Point curPoint = relativePositions.get(w); Point newPoint = new Point(p.x + curPoint.x, p.y + curPoint.y); w.setPreferredLocation(newPoint); DiagramScene.this.validate(); } oldPosition = p; } } } public Point getScrollPosition() { return getScrollPane().getViewport().getViewPosition(); } public void setScrollPosition(Point p) { getScrollPane().getViewport().setViewPosition(p); } public DiagramScene(Action[] actions, DiagramViewModel model) { this.actions = actions; selectedWidgets = new ArrayList<FigureWidget>(); content = new InstanceContent(); lookup = new AbstractLookup(content); this.setCheckClipping(true); this.getInputBindings().setZoomActionModifiers(0); JComponent comp = this.createView(); comp.setDoubleBuffered(true); comp.setBackground(Color.WHITE); comp.setOpaque(true); this.setBackground(Color.WHITE); this.setOpaque(true); scrollPane = new JScrollPane(comp); scrollPane.setBackground(Color.WHITE); scrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT); scrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT); scrollPane.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT); scrollPane.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT); scrollPane.getViewport().addChangeListener(scrollChangeListener); hoverAction = this.createWidgetHoverAction(); blockLayer = new LayerWidget(this); this.addChild(blockLayer); startLayer = new LayerWidget(this); this.addChild(startLayer); // TODO: String startLabelString = "Loading graph with " + originalDiagram.getFigures().size() + " figures and " + originalDiagram.getConnections().size() + " connections..."; String startLabelString = ""; LabelWidget w = new LabelWidget(this, startLabelString); scrollChangeListener.register(w, new Point(10, 10)); w.setAlignment(LabelWidget.Alignment.CENTER); startLabel = w; startLayer.addChild(w); mainLayer = new LayerWidget(this); this.addChild(mainLayer); topLeft = new Widget(this); topLeft.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE)); this.addChild(topLeft); bottomRight = new Widget(this); bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE)); this.addChild(bottomRight); slotLayer = new LayerWidget(this); this.addChild(slotLayer); connectionLayer = new LayerWidget(this); this.addChild(connectionLayer); LayerWidget selectionLayer = new LayerWidget(this); this.addChild(selectionLayer); this.setLayout(LayoutFactory.createAbsoluteLayout()); this.getActions().addAction(hoverAction); zoomAction = new BoundedZoomAction(1.1, false); zoomAction.setMaxFactor(ZOOM_MAX_FACTOR); zoomAction.setMinFactor(ZOOM_MIN_FACTOR); this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1)); panAction = new ExtendedPanAction(); this.getActions().addAction(panAction); this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider)); LayerWidget selectLayer = new LayerWidget(this); this.addChild(selectLayer); this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider)); blockWidgets = new HashMap<InputBlock, BlockWidget>(); boolean b = this.getUndoRedoEnabled(); this.setUndoRedoEnabled(false); this.setNewModel(model); this.setUndoRedoEnabled(b); } private void selectionUpdated() { getModel().setSelectedNodes(this.getSelectedNodes()); addUndo(); } public DiagramViewModel getModel() { return model; } public void setRealZoomFactor(double d) { this.realZoomFactor = d; } public double getRealZoomFactor() { if (realZoomFactor == 0.0) { return getZoomFactor(); } else { return realZoomFactor; } } public JScrollPane getScrollPane() { return scrollPane; } public boolean isAllVisible() { return getModel().getHiddenNodes().size() == 0; } public Action createGotoAction(final Figure f) { final DiagramScene diagramScene = this; Action a = new AbstractAction() { public void actionPerformed(ActionEvent e) { diagramScene.gotoFigure(f); } }; a.setEnabled(true); a.putValue(Action.SMALL_ICON, new ColorIcon(f.getColor())); String name = f.getLines()[0]; name += " ("; if (f.getCluster() != null) { name += "B" + f.getCluster().toString(); } if (!this.getFigureWidget(f).isVisible()) { if (f.getCluster() != null) { name += ", "; } name += "hidden"; } name += ")"; a.putValue(Action.NAME, name); return a; } public void setNewModel(DiagramViewModel model) { if (this.model != null) { this.model.getDiagramChangedEvent().removeListener(this); this.model.getViewPropertiesChangedEvent().removeListener(this); } this.model = model; if (this.model == null) { this.modelCopy = null; } else { this.modelCopy = this.model.copy(); } model.getDiagramChangedEvent().addListener(this); model.getViewPropertiesChangedEvent().addListener(this); update(); } private void update() { /*if (startLabel != null) { // Animate fade-out final LabelWidget labelWidget = this.startLabel; labelWidget.setVisible(true); RequestProcessor.getDefault().post(new Runnable() { public void run() { final int Sleep = 200; final int Progress = 10; for (int i = 0; i < 255 / Progress + 1; i++) { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { Color c = labelWidget.getForeground(); int v = c.getRed(); v += Progress; if (v > 255) { v = 255; } labelWidget.setForeground(new Color(v, v, v, 255 - v)); labelWidget.getScene().validate(); } }); } catch (InterruptedException ex) { } catch (InvocationTargetException ex) { } try { Thread.sleep(Sleep); } catch (InterruptedException ex) { } } labelWidget.setVisible(false); DiagramScene.this.scrollChangeListener.unregister(labelWidget); } }, 1000); startLabel = null; }*/ slotLayer.removeChildren(); mainLayer.removeChildren(); blockLayer.removeChildren(); blockWidgets.clear(); figureWidgets = new HashMap<Figure, FigureWidget>(); slotWidgets = new HashMap<Slot, SlotWidget>(); connectionWidgets = new HashMap<Connection, ConnectionWidget>(); WidgetAction selectAction = new ExtendedSelectAction(selectProvider); Diagram d = getModel().getDiagramToView(); if (getModel().getShowBlocks()) { Scheduler s = Lookup.getDefault().lookup(Scheduler.class); Collection<InputBlock> newBlocks = new ArrayList<InputBlock>(s.schedule(d.getGraph())); d.schedule(newBlocks); } for (Figure f : d.getFigures()) { FigureWidget w = new FigureWidget(f, this, mainLayer); w.getActions().addAction(selectAction); w.getActions().addAction(hoverAction); w.getActions().addAction(ActionFactory.createPopupMenuAction(w)); w.getActions().addAction(new DoubleClickAction(w)); w.setVisible(false); figureWidgets.put(f, w); for (InputSlot s : f.getInputSlots()) { SlotWidget sw = new InputSlotWidget(s, this, slotLayer, w); slotWidgets.put(s, sw); sw.getActions().addAction(selectAction); } for (OutputSlot s : f.getOutputSlots()) { SlotWidget sw = new OutputSlotWidget(s, this, slotLayer, w); slotWidgets.put(s, sw); sw.getActions().addAction(selectAction); } } if (getModel().getShowBlocks()) { for (InputBlock bn : d.getGraph().getBlocks()) { BlockWidget w = new BlockWidget(this, d, bn); w.setVisible(false); blockWidgets.put(bn, w); blockLayer.addChild(w); } } this.smallUpdate(true); } private void smallUpdate(boolean relayout) { this.updateHiddenNodes(model.getHiddenNodes(), relayout); boolean b = this.getUndoRedoEnabled(); this.setUndoRedoEnabled(false); this.setSelection(getModel().getSelectedNodes()); this.setUndoRedoEnabled(b); this.validate(); } private boolean isVisible(Connection c) { FigureWidget w1 = figureWidgets.get(c.getInputSlot().getFigure()); FigureWidget w2 = figureWidgets.get(c.getOutputSlot().getFigure()); if (w1.isVisible() && w2.isVisible()) { return true; } return false; } private void relayout(Set<Widget> oldVisibleWidgets) { Diagram diagram = getModel().getDiagramToView(); HashSet<Figure> figures = new HashSet<Figure>(); for (Figure f : diagram.getFigures()) { FigureWidget w = figureWidgets.get(f); if (w.isVisible()) { figures.add(f); } } HashSet<Connection> edges = new HashSet<Connection>(); for (Connection c : diagram.getConnections()) { if (isVisible(c)) { edges.add(c); } } if (getModel().getShowBlocks()) { HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(OldHierarchicalLayoutManager.Combine.SAME_OUTPUTS); HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); manager.setMaxLayerLength(9); manager.setMinLayerDifference(3); m.setManager(manager); m.setSubManager(new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS)); m.doLayout(new LayoutGraph(edges, figures)); } else { HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); manager.setMaxLayerLength(10); manager.doLayout(new LayoutGraph(edges, figures)); } int maxX = -BORDER_SIZE; int maxY = -BORDER_SIZE; for (Figure f : diagram.getFigures()) { FigureWidget w = figureWidgets.get(f); if (w.isVisible()) { Point p = f.getPosition(); Dimension d = f.getSize(); maxX = Math.max(maxX, p.x + d.width); maxY = Math.max(maxY, p.y + d.height); } } for (Connection c : diagram.getConnections()) { List<Point> points = c.getControlPoints(); FigureWidget w1 = figureWidgets.get((Figure) c.getTo().getVertex()); FigureWidget w2 = figureWidgets.get((Figure) c.getFrom().getVertex()); if (w1.isVisible() && w2.isVisible()) { for (Point p : points) { if (p != null) { maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y); } } } } if (getModel().getShowBlocks()) { for (Block b : diagram.getBlocks()) { BlockWidget w = blockWidgets.get(b.getInputBlock()); if (w != null && w.isVisible()) { Rectangle r = b.getBounds(); maxX = Math.max(maxX, r.x + r.width); maxY = Math.max(maxY, r.y + r.height); } } } bottomRight.setPreferredLocation(new Point(maxX + BORDER_SIZE, maxY + BORDER_SIZE)); int offx = 0; int offy = 0; int curWidth = maxX + 2 * BORDER_SIZE; int curHeight = maxY + 2 * BORDER_SIZE; Rectangle bounds = this.getScrollPane().getBounds(); if (curWidth < bounds.width) { offx = (bounds.width - curWidth) / 2; } if (curHeight < bounds.height) { offy = (bounds.height - curHeight) / 2; } final int offx2 = offx; final int offy2 = offy; SceneAnimator animator = this.getSceneAnimator(); connectionLayer.removeChildren(); int visibleFigureCount = 0; for (Figure f : diagram.getFigures()) { if (figureWidgets.get(f).isVisible()) { visibleFigureCount++; } } for (Figure f : diagram.getFigures()) { for (OutputSlot s : f.getOutputSlots()) { SceneAnimator anim = animator; if (visibleFigureCount > ANIMATION_LIMIT) { anim = null; } processOutputSlot(s, s.getConnections(), 0, null, null, offx2, offy2, anim); } } for (Figure f : diagram.getFigures()) { FigureWidget w = figureWidgets.get(f); if (w.isVisible()) { Point p = f.getPosition(); Point p2 = new Point(p.x + offx2, p.y + offy2); Rectangle r = new Rectangle(p.x + offx2, p.y + offy2, f.getSize().width, f.getSize().height); if (oldVisibleWidgets.contains(w)) { if (visibleFigureCount > ANIMATION_LIMIT) { w.setPreferredLocation(p2); } else { animator.animatePreferredLocation(w, p2); } } else { w.setPreferredLocation(p2); } } } if (getModel().getShowBlocks()) { for (Block b : diagram.getBlocks()) { BlockWidget w = blockWidgets.get(b.getInputBlock()); if (w != null && w.isVisible()) { Point location = new Point(b.getBounds().x + offx2, b.getBounds().y + offy2); Rectangle r = new Rectangle(location.x, location.y, b.getBounds().width, b.getBounds().height); if (oldVisibleWidgets.contains(w)) { if (visibleFigureCount > ANIMATION_LIMIT) { w.setPreferredBounds(r); } else { animator.animatePreferredBounds(w, r); } } else { w.setPreferredBounds(r); } } } } } private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); private void processOutputSlot(OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) { Map<Point, List<Connection>> pointMap = new HashMap<Point, List<Connection>>(); for (Connection c : connections) { if (!isVisible(c)) { continue; } List<Point> controlPoints = c.getControlPoints(); if (controlPointIndex >= controlPoints.size()) { continue; } Point cur = controlPoints.get(controlPointIndex); if (cur == null) { cur = specialNullPoint; } else if (controlPointIndex == 0 && !s.getShowName()) { cur = new Point(cur.x, cur.y - SLOT_OFFSET); } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().getShowName()) { cur = new Point(cur.x, cur.y + SLOT_OFFSET); } if (pointMap.containsKey(cur)) { pointMap.get(cur).add(c); } else { List<Connection> newList = new ArrayList<Connection>(2); newList.add(c); pointMap.put(cur, newList); } } for (Point p : pointMap.keySet()) { List<Connection> connectionList = pointMap.get(p); boolean isBold = false; boolean isDashed = true; for (Connection c : connectionList) { if (c.getStyle() == Connection.ConnectionStyle.BOLD) { isBold = true; } if (c.getStyle() != Connection.ConnectionStyle.DASHED) { isDashed = false; } } LineWidget newPredecessor = predecessor; if (p == specialNullPoint) { } else if (lastPoint == specialNullPoint) { } else if (lastPoint != null) { Point p1 = new Point(lastPoint.x + offx, lastPoint.y + offy); Point p2 = new Point(p.x + offx, p.y + offy); LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, animator, isBold, isDashed); newPredecessor = w; connectionLayer.addChild(w); w.getActions().addAction(hoverAction); } processOutputSlot(s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator); } } private void clearSelection() { if (selectedWidgets.size() == 0) { return; } for (FigureWidget w : selectedWidgets) { assert w.getState().isSelected(); w.setState(w.getState().deriveSelected(false)); content.remove(w.getNode()); } selectedWidgets.clear(); } public Lookup getLookup() { return lookup; } public void gotoFigures(final List<Figure> figures) { Rectangle overall = null; showFigures(figures); for (Figure f : figures) { FigureWidget fw = getFigureWidget(f); if (fw != null) { Rectangle r = fw.getBounds(); Point p = fw.getLocation(); Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height); if (overall == null) { overall = r2; } else { overall = overall.union(r2); } } } if (overall != null) { centerRectangle(overall); } } private Point calcCenter(Rectangle r) { Point center = new Point((int) r.getCenterX(), (int) r.getCenterY()); center.x -= getScrollPane().getViewport().getViewRect().width / 2; center.y -= getScrollPane().getViewport().getViewRect().height / 2; // Ensure to be within area center.x = Math.max(0, center.x); center.x = Math.min(getScrollPane().getViewport().getViewSize().width - getScrollPane().getViewport().getViewRect().width, center.x); center.y = Math.max(0, center.y); center.y = Math.min(getScrollPane().getViewport().getViewSize().height - getScrollPane().getViewport().getViewRect().height, center.y); return center; } private void centerRectangle(Rectangle r) { if (getScrollPane().getViewport().getViewRect().width == 0 || getScrollPane().getViewport().getViewRect().height == 0) { return; } Rectangle r2 = new Rectangle(r.x, r.y, r.width, r.height); r2 = convertSceneToView(r2); double factorX = (double) r2.width / (double) getScrollPane().getViewport().getViewRect().width; double factorY = (double) r2.height / (double) getScrollPane().getViewport().getViewRect().height; double factor = Math.max(factorX, factorY); if (factor >= 1.0) { Point p = getScrollPane().getViewport().getViewPosition(); setZoomFactor(getZoomFactor() / factor); r2.x /= factor; r2.y /= factor; r2.width /= factor; r2.height /= factor; getScrollPane().getViewport().setViewPosition(calcCenter(r2)); } else { getScrollPane().getViewport().setViewPosition(calcCenter(r2)); } } private void addToSelection(Figure f) { FigureWidget w = getFigureWidget(f); addToSelection(w); } private void addToSelection(FigureWidget w) { assert !selectedWidgets.contains(w); selectedWidgets.add(w); content.add(w.getNode()); w.setState(w.getState().deriveSelected(true)); } private void setSelection(Set<Integer> nodes) { clearSelection(); for (Figure f : getModel().getDiagramToView().getFigures()) { if (doesIntersect(f.getSource().getSourceNodesAsSet(), nodes)) { addToSelection(f); } } selectionUpdated(); this.validate(); } public void setSelection(Collection<Figure> list) { clearSelection(); for (Figure f : list) { addToSelection(f); } selectionUpdated(); this.validate(); } public Set<Figure> getSelectedFigures() { Set<Figure> result = new HashSet<Figure>(); for (Widget w : selectedWidgets) { if (w instanceof FigureWidget) { FigureWidget fw = (FigureWidget) w; if (fw.getState().isSelected()) { result.add(fw.getFigure()); } } } return result; } public Set<Integer> getSelectedNodes() { Set<Integer> result = new HashSet<Integer>(); for (Widget w : selectedWidgets) { if (w instanceof FigureWidget) { FigureWidget fw = (FigureWidget) w; if (fw.getState().isSelected()) { result.addAll(fw.getFigure().getSource().getSourceNodesAsSet()); } } } return result; } private UndoRedo.Manager getUndoRedoManager() { if (undoRedoManager == null) { undoRedoManager = new UndoRedo.Manager(); undoRedoManager.setLimit(UNDOREDO_LIMIT); } return undoRedoManager; } public UndoRedo getUndoRedo() { return getUndoRedoManager(); } private boolean isVisible(Figure f) { for (Integer n : f.getSource().getSourceNodesAsSet()) { if (getModel().getHiddenNodes().contains(n)) { return false; } } return true; } private boolean doesIntersect(Set s1, Set s2) { if (s1.size() > s2.size()) { Set tmp = s1; s1 = s2; s2 = tmp; } for (Object o : s1) { if (s2.contains(o)) { return true; } } return false; } public void showNot(final Set<Integer> nodes) { updateHiddenNodes(nodes, true); } public void showOnly(final Set<Integer> nodes) { HashSet<Integer> allNodes = new HashSet<Integer>(getModel().getGraphToView().getGroup().getAllNodes()); allNodes.removeAll(nodes); updateHiddenNodes(allNodes, true); } private void updateHiddenNodes(Set<Integer> newHiddenNodes, boolean doRelayout) { Set<InputBlock> visibleBlocks = new HashSet<InputBlock>(); Diagram diagram = getModel().getDiagramToView(); assert diagram != null; Set<Widget> oldVisibleWidgets = new HashSet<Widget>(); for (Figure f : diagram.getFigures()) { FigureWidget w = figureWidgets.get(f); if (w.isVisible()) { oldVisibleWidgets.add(w); } } if (getModel().getShowBlocks()) { for (InputBlock b : diagram.getGraph().getBlocks()) { BlockWidget w = blockWidgets.get(b); if (w.isVisible()) { oldVisibleWidgets.add(w); } } } for (Figure f : diagram.getFigures()) { boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes); FigureWidget w = this.figureWidgets.get(f); w.setBoundary(false); if (!hiddenAfter) { // Figure is shown w.setVisible(true); for (InputNode n : f.getSource().getSourceNodes()) { visibleBlocks.add(diagram.getGraph().getBlock(n)); } } else { // Figure is hidden w.setVisible(false); } } if (getModel().getShowNodeHull()) { List<FigureWidget> boundaries = new ArrayList<FigureWidget>(); for (Figure f : diagram.getFigures()) { FigureWidget w = this.figureWidgets.get(f); if (!w.isVisible()) { Set<Figure> set = new HashSet<Figure>(f.getPredecessorSet()); set.addAll(f.getSuccessorSet()); boolean b = false; for (Figure neighbor : set) { FigureWidget neighborWidget = figureWidgets.get(neighbor); if (neighborWidget.isVisible()) { b = true; break; } } if (b) { w.setBoundary(true); for (InputNode n : f.getSource().getSourceNodes()) { visibleBlocks.add(diagram.getGraph().getBlock(n)); } boundaries.add(w); } } } for (FigureWidget w : boundaries) { if (w.isBoundary()) { w.setVisible(true); } } } if (getModel().getShowBlocks()) { for (InputBlock b : diagram.getGraph().getBlocks()) { boolean visibleAfter = visibleBlocks.contains(b); BlockWidget w = blockWidgets.get(b); if (visibleAfter) { // Block must be shown w.setVisible(true); } else { // Block must be hidden w.setVisible(false); } } } getModel().setHiddenNodes(newHiddenNodes); if (doRelayout) { relayout(oldVisibleWidgets); } this.validate(); addUndo(); } private void showFigures(Collection<Figure> f) { HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes()); for (Figure fig : f) { newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet()); } updateHiddenNodes(newHiddenNodes, true); } private void showFigure(Figure f) { HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes()); newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet()); updateHiddenNodes(newHiddenNodes, true); } public void showAll(final Collection<Figure> f) { showFigures(f); } public void show(final Figure f) { showFigure(f); } public void gotoFigure(final Figure f) { if (!isVisible(f)) { showFigure(f); } FigureWidget fw = getFigureWidget(f); if (fw != null) { Rectangle r = fw.getBounds(); Point p = fw.getLocation(); centerRectangle(new Rectangle(p.x, p.y, r.width, r.height)); // Select figure clearSelection(); addToSelection(fw); selectionUpdated(); } } public JPopupMenu createPopupMenu() { JPopupMenu menu = new JPopupMenu(); for (Action a : actions) { if (a == null) { menu.addSeparator(); } else { menu.add(a); } } return menu; } private static class DiagramUndoRedo extends AbstractUndoableEdit implements ChangedListener<DiagramViewModel> { private DiagramViewModel oldModel; private DiagramViewModel newModel; private Point oldScrollPosition; private DiagramScene scene; public DiagramUndoRedo(DiagramScene scene, Point oldScrollPosition, DiagramViewModel oldModel, DiagramViewModel newModel) { assert oldModel != null; assert newModel != null; this.oldModel = oldModel; this.newModel = newModel; this.scene = scene; this.oldScrollPosition = oldScrollPosition; } @Override public void redo() throws CannotRedoException { super.redo(); boolean b = scene.getUndoRedoEnabled(); scene.setUndoRedoEnabled(false); scene.getModel().getViewChangedEvent().addListener(this); scene.getModel().setData(newModel); scene.getModel().getViewChangedEvent().removeListener(this); scene.setUndoRedoEnabled(b); } @Override public void undo() throws CannotUndoException { super.undo(); boolean b = scene.getUndoRedoEnabled(); scene.setUndoRedoEnabled(false); scene.getModel().getViewChangedEvent().addListener(this); scene.getModel().setData(oldModel); scene.getModel().getViewChangedEvent().removeListener(this); SwingUtilities.invokeLater(new Runnable() { public void run() { scene.setScrollPosition(oldScrollPosition); } }); scene.setUndoRedoEnabled(b); } public void changed(DiagramViewModel source) { scene.getModel().getViewChangedEvent().removeListener(this); if (oldModel.getSelectedNodes().equals(newModel.getHiddenNodes())) { scene.smallUpdate(false); } else { scene.smallUpdate(true); } } } private boolean undoRedoEnabled = true; public void setUndoRedoEnabled(boolean b) { this.undoRedoEnabled = b; } public boolean getUndoRedoEnabled() { return undoRedoEnabled; } public void changed(DiagramViewModel source) { assert source == model : "Receive only changed event from current model!"; assert source != null; update(); } private void addUndo() { DiagramViewModel newModelCopy = model.copy(); if (undoRedoEnabled) { this.getUndoRedoManager().undoableEditHappened(new UndoableEditEvent(this, new DiagramUndoRedo(this, this.getScrollPosition(), modelCopy, newModelCopy))); } this.modelCopy = newModelCopy; } }