package org.visualdataweb.vowl.rendering; /** * this class is a click listener, to react if an element of a GraphDataModifier is clicked */ import org.visualdataweb.vowl.controlView.RunLayoutControl; import org.visualdataweb.vowl.infoPanel.InfoPanelDataExtractor; import org.visualdataweb.vowl.infoPanel.InfoPanelManager; import prefuse.Display; import prefuse.controls.Control; import prefuse.controls.ControlAdapter; import prefuse.data.Edge; import prefuse.data.Graph; import prefuse.data.Node; import prefuse.visual.EdgeItem; import prefuse.visual.NodeItem; import prefuse.visual.VisualItem; import prefuse.visual.tuple.TableDecoratorItem; import org.visualdataweb.vowl.storage.DisplayStorage; import org.visualdataweb.vowl.types.ColumnNames; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; public class ControlListener extends ControlAdapter implements Control { private static final int MAX_ZOOM_STEP = 3; /* The viewManagerID is an String extracted from the ViewManager of the current OWLWorkspace. * It is used to identify the data which belongs to the current Protégé window. * Within Protégé the user can open different ontologies, which can be shown within the same window or * within different windows. If the are shown within different windows, they are the same protege instance. * So an identifier is needed which is different for each protege instance but ontology independent. */ private String viewManagerID; private int yLast; private Point2D down = new Point2D.Float(); /** * Constructor * * @param id - viewManagerID */ public ControlListener(String id) { viewManagerID = id; } /** * mouse-click event on a visual item (node item or edge item) */ @Override public void itemClicked(VisualItem item, MouseEvent e) { if (item instanceof NodeItem) { NodeItem node = (NodeItem) item; Object isClickedTestObject = item.get(ColumnNames.IS_CLICKED); removeAttributeIsClickedFromAllGraphElements(node.getGraph()); if (isClickedTestObject != null) { boolean isClicked = (Boolean) isClickedTestObject; item.set(ColumnNames.IS_CLICKED, !isClicked); if (isClicked) { InfoPanelManager ipm = new InfoPanelManager(viewManagerID); ipm.clearTable(viewManagerID); ipm.refreshTable(viewManagerID); } else { @SuppressWarnings("unused") InfoPanelDataExtractor ipde = new InfoPanelDataExtractor(node, viewManagerID); } } else { item.set(ColumnNames.IS_CLICKED, true); @SuppressWarnings("unused") InfoPanelDataExtractor ipde = new InfoPanelDataExtractor(node, viewManagerID); } } if (item instanceof EdgeItem) { EdgeItem edge = (EdgeItem) item; Object isClickedTestObject = item.get(ColumnNames.IS_CLICKED); removeAttributeIsClickedFromAllGraphElements(edge.getGraph()); if (isClickedTestObject != null) { boolean isClicked = (Boolean) isClickedTestObject; item.set(ColumnNames.IS_CLICKED, !isClicked); if (isClicked) { InfoPanelManager ipm = new InfoPanelManager(viewManagerID); ipm.clearTable(viewManagerID); ipm.refreshTable(viewManagerID); } else { @SuppressWarnings("unused") InfoPanelDataExtractor ipde = new InfoPanelDataExtractor(edge, viewManagerID); } } else { item.set(ColumnNames.IS_CLICKED, true); @SuppressWarnings("unused") InfoPanelDataExtractor ipde = new InfoPanelDataExtractor(edge, viewManagerID); } } if (item instanceof TableDecoratorItem) { TableDecoratorItem tdi = (TableDecoratorItem) item; Graph graph = (Graph) ((Display) e.getSource()).getVisualization().getGroup("GraphDataModifier"); // find the corresponding object (EdgeItem or NodeItem) to which this TableDecoratorItem belongs to Object parentObject = null; for (int i = 0; i < graph.getEdgeCount(); i++) { Edge edge = graph.getEdge(i); Integer tdiID = (Integer) tdi.get(ColumnNames.ID); Integer edgeID = (Integer) edge.get(ColumnNames.ID); if (tdiID == edgeID) { parentObject = edge; break; } } if (parentObject == null) { for (int i = 0; i < graph.getNodeCount(); i++) { Node node = graph.getNode(i); Integer tdiID = (Integer) tdi.get(ColumnNames.ID); Integer nodeID = (Integer) node.get(ColumnNames.ID); if (tdiID == nodeID) { parentObject = node; break; } } } // if the corresponding object (EdgeItem or NodeItem) has been found call this method again // but with the corresponding object instead of the original TableDecoratorItem if (parentObject != null) { if (parentObject instanceof VisualItem) { itemClicked((VisualItem) parentObject, e); } } } } /** * mouse-over event on a visual item (node item or edge item) */ @Override public void itemEntered(VisualItem item, MouseEvent e) { // if ctrl is pressed, user zooms -> ignore itemEntered if (e.getModifiers() == InputEvent.CTRL_MASK) { ctrlZoom(e); return; } // only mark items as highlighted if the layout process is active RunLayoutControl rlc = new RunLayoutControl(viewManagerID); if (rlc.isLayouting()) { if (item instanceof NodeItem) { /* set highlight attribute to true, NodeRenderer will change the color */ item.set(ColumnNames.IS_HIGHLIGHTED, true); } if (item instanceof EdgeItem) { /* set highlight attribute to true, EdgeRenderer will change the color */ item.set(ColumnNames.IS_HIGHLIGHTED, true); } if (item instanceof TableDecoratorItem) { /* set highlight attribute to true, EdgeRenderer will change the color */ item.set(ColumnNames.IS_HIGHLIGHTED, true); } } } /** * mouse moves away from a visual item (node item or edge item) */ @Override public void itemExited(VisualItem item, java.awt.event.MouseEvent e) { // if ctrl is pressed, user zooms -> ignore itemExited // disable highlight possible but it should be same as zoom by mouse wheel or zoom by prefuse's right click zoom if (e.getModifiers() == InputEvent.CTRL_MASK) { ctrlZoom(e); return; } if (item instanceof NodeItem) { /* set highlight attribute to false, NodeRenderer will change the color */ item.set(ColumnNames.IS_HIGHLIGHTED, false); } if (item instanceof EdgeItem) { /* set highlight attribute to false, EdgeRenderer will change the color */ item.set(ColumnNames.IS_HIGHLIGHTED, false); } if (item instanceof TableDecoratorItem) { /* set highlight attribute to false, EdgeRenderer will change the color */ item.set(ColumnNames.IS_HIGHLIGHTED, false); } } /** * remove the attribute "is clicked" from all nodes and edges */ private void removeAttributeIsClickedFromAllGraphElements(Graph graph) { for (int i = 0; i < graph.getNodeCount(); i++) { Node node = graph.getNode(i); node.set(ColumnNames.IS_CLICKED, false); } for (int i = 0; i < graph.getEdgeCount(); i++) { Edge edge = graph.getEdge(i); edge.set(ColumnNames.IS_CLICKED, false); } } /** * item is moved (user action) */ public void itemMoved(VisualItem item, MouseEvent e) { if (e.getModifiers() == InputEvent.CTRL_MASK) { ctrlZoom(e); } else { if (DisplayStorage.getPrefuseDisplay(viewManagerID).getCursor() .equals(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR))) { DisplayStorage.getPrefuseDisplay(viewManagerID).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } } /** * mouse move listener, check if user pressed CTRL as zooming alternative * * @param e - MouseEvent */ public void mouseMoved(MouseEvent e) { ctrlZoom(e); } /** * move the mouse and press CTRL as zooming alternative * * @param e - MouseEvent */ private void ctrlZoom(MouseEvent e) { if (e.getModifiers() == InputEvent.CTRL_MASK) { if (DisplayStorage.getPrefuseDisplay(viewManagerID).isTranformInProgress() || yLast == -1 || down == null) { yLast = -1; return; } int y = e.getY(); int dy = y - yLast; double zoom = 1 + ((double) dy) / 100; // 'invert' the zooming, mouse up to get closer if (1 + (1 - zoom) > 0) { zoom = 1 + (1 - zoom); } // "filter" zoom levels which are too high or below zero if (zoom > MAX_ZOOM_STEP || zoom < 0) { zoom = 1; } PrefuseZoomControl zm = new PrefuseZoomControl(); int status = zm.zoom(DisplayStorage.getPrefuseDisplay(viewManagerID), down, zoom, false); int cursor = Cursor.N_RESIZE_CURSOR; if (status == PrefuseZoomControl.PUBLIC_NO_ZOOM) { cursor = Cursor.WAIT_CURSOR; } DisplayStorage.getPrefuseDisplay(viewManagerID).setCursor(Cursor.getPredefinedCursor(cursor)); yLast = y; } else { /* always zoom to the center of the view, alternative the mouse position could be taken with: = e.getPoint(); */ int x = (int) DisplayStorage.getPrefuseDisplay(viewManagerID).getBounds().getCenterX(); int y = (int) DisplayStorage.getPrefuseDisplay(viewManagerID).getBounds().getCenterY(); down = new Point(x, y); yLast = 0; DisplayStorage.getPrefuseDisplay(viewManagerID).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } } class PrefuseZoomControl extends prefuse.controls.ZoomControl { public static final int PUBLIC_NO_ZOOM = NO_ZOOM; /** * Zoom the given display at the given point by the zoom factor, * in either absolute (item-space) or screen co-ordinates. * * @param display the Display to zoom * @param p the point to center the zoom upon * @param zoom the scale factor by which to zoom * @param abs if true, the point p should be assumed to be in absolute * coordinates, otherwise it will be treated as scree (pixel) coordinates * @return a return code indicating the status of the zoom operation. * One of {@link #ZOOM}, {@link #NO_ZOOM}, {@link #MIN_ZOOM}, {@link #MAX_ZOOM}. */ @Override public int zoom(Display display, Point2D p, double zoom, boolean abs) { return super.zoom(display, p, zoom, abs); } }