Package org.enhydra.jawe.components.graph

Source Code of org.enhydra.jawe.components.graph.JaWEGraphUI$PEKeyHandler

package org.enhydra.jawe.components.graph;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.Map;

import javax.swing.Action;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import org.enhydra.jawe.JaWEManager;
import org.enhydra.jawe.base.controller.JaWEActions;
import org.enhydra.shark.xpdl.XMLElement;
import org.enhydra.shark.xpdl.XPDLConstants;
import org.enhydra.shark.xpdl.elements.Activity;
import org.jgraph.JGraph;
import org.jgraph.event.GraphLayoutCacheEvent;
import org.jgraph.event.GraphLayoutCacheListener;
import org.jgraph.event.GraphModelEvent;
import org.jgraph.event.GraphModelListener;
import org.jgraph.graph.CellHandle;
import org.jgraph.graph.CellView;
import org.jgraph.graph.DefaultGraphModel;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.GraphContext;
import org.jgraph.graph.GraphLayoutCache;
import org.jgraph.plaf.basic.BasicGraphUI;

/**
* This class and it's inner classes controls mouse actions and clipboard.
* It is addapted to get wanted editing cell behaviour, selection behaviour
* , to implement cell overlaping, to implement right participant adjustment
* after cell (or group of cells) is moved, and to implement proper copying
* and pasting/cloning of cells, as well as pasting at wanted location (along
* with right participant adjustment).
*/
public class JaWEGraphUI extends BasicGraphUI {

    public final static int SELECTION = 0;
    public final static int MULTIPLE_SELECTION = 1;
    public final static int INSERT_ELEMENT = 2;
    public final static int INSERT_PARTICIPANT = 3;
    public final static int INSERT_SPEC_ELEMENT = 4;
    public final static int INSERT_TRANSITION_START = 5;
    public final static int INSERT_TRANSITION_POINTS = 6;
    protected int status;
    protected boolean aborted = false;
    protected boolean selectOnRelease = false;
    protected GraphActivityInterface gai;

    /**
     * Returns graph.
     */
    public Graph getGraph() {
        return (Graph) graph;
    }

    public GraphController getGraphController() {
        return ((GraphMarqueeHandler) marquee).getGraphController();
    }

    /**
     * Paint the background of this graph. Calls paintGrid.
     */
    protected void paintBackground(Graphics g) {
        Rectangle pageBounds = new Rectangle(0, 0, graph.getWidth(), graph.getHeight());

        if (graph.isGridVisible()) {
            paintGrid(graph.getGridSize(), g, pageBounds);
        }
    }

    /**
     * This method is called by EditAction class, as well as by
     * pressing F2 or clicking a mouse on a cell.
     */
    protected boolean startEditing(Object cell, MouseEvent event) {
        if (cell instanceof WorkflowElement) {
            XMLElement el = ((WorkflowElement) cell).getPropertyObject();
            if (el instanceof Activity) {
                Activity act = (Activity) el;
                if (act.getActivityType() == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
                    //CUSTOM
                    JaWEManager.getInstance().getJaWEController().getJaWEActions().getAction(JaWEActions.EDIT_PROPERTIES_ACTION).actionPerformed(null);
                    //END CUSTOM
                    return true;
                } else if (act.getActivityType() == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
                    //CUSTOM
                    JaWEManager.getInstance().getJaWEController().getJaWEActions().getAction(JaWEActions.EDIT_PROPERTIES_ACTION).actionPerformed(null);
                    //END CUSTOM
                    return true;
                }
            } else if (el instanceof FreeTextExpressionParticipant || el instanceof CommonExpressionParticipant) {
                return true;
            }

            JaWEManager.getInstance().getJaWEController().getJaWEActions().getAction(JaWEActions.EDIT_PROPERTIES_ACTION).actionPerformed(null);
            return true;
        }
        return false;
    }

    // FIXED by xxp - there was a problem when zooming-out activity
    public void startEditingAtCell(JGraph pGraph, Object cell) {
        if (cell != null) {
            startEditing(cell, null);
        }
    }

    /**
     * Creates the listener responsible for updating the selection based on
     * mouse events.
     */
    protected MouseListener createMouseListener() {
        return new PEMouseHandler();
    }

    /**
     * Handles selection in a way that we expect.
     */
    public class PEMouseHandler extends MouseHandler {

        public void mousePressed(MouseEvent e) {
            if (!graph.hasFocus()) {
                graph.requestFocus();
            }
            aborted = false;
            selectOnRelease = false;
            if (status == SELECTION && graph.isSelectionEnabled()) {
                // find where was clicked...
                int s = graph.getTolerance();

                Rectangle2D r = graph.fromScreen(new Rectangle(e.getX() - s, e.getY() - s, 2 * s, 2 * s));
                focus = (focus != null && focus.intersects(graph, r)) ? focus : null;
                Point2D point = graph.fromScreen(new Point(e.getPoint()));

                // changed from original because of overlapping
                if (focus == null) {
                    cell = graph.getNextViewAt(focus, point.getX(), point.getY());
                    focus = cell;
                } else {
                    cell = focus;
                }

                // if it's right mouse button show popup menu, otherwise user whish to select something
                if (SwingUtilities.isRightMouseButton(e)) {
                    // POPUP
                    if (cell != null) {
                        if (!graph.isCellSelected(cell.getCell())) {
                            selectCellForEvent(cell.getCell(), e);
                        }
                    } else {
                        graph.clearSelection();
                    }

                    ((GraphMarqueeHandler) marquee).popupMenu(e.getPoint());
                } else {
                    // SIMPLE SELECTION
                    if (cell != null) {
                        if (e.getClickCount() == 2) {
                            startEditing(cell.getCell(), e);
                        } else {
                            if (graph.isCellSelected(cell.getCell()) && !e.isControlDown() && graph.getSelectionCells().length > 1) {
                                selectOnRelease = true;
                            } else {
                                if (!graph.isCellSelected(cell.getCell()) || e.isControlDown()) {
                                    selectCellForEvent(cell.getCell(), e);
                                }
                            }

                            if (handle != null) {
                                handle.mousePressed(e);
                            }
                        }
                    } else {
                        // MULTIPLE SELECTION
                        marquee.mousePressed(e);
                        status = MULTIPLE_SELECTION;
                    }
                }
            }

            if (SwingUtilities.isRightMouseButton(e)) {
                if (status == INSERT_TRANSITION_POINTS) {
                    status = INSERT_TRANSITION_START;
                    ((GraphMarqueeHandler) marquee).reset();
                } else {
                    ((GraphMarqueeHandler) marquee).setSelectionMode();
                    status = SELECTION;
                }
            } else {
                if (graph.isEditable()) {
                    if (status == INSERT_PARTICIPANT) {
                        // maybe latter we can add inserting participants where user choose, not at end...
                        ((GraphMarqueeHandler) marquee).insertParticipant();
                    } else if (status == INSERT_SPEC_ELEMENT) {
                        // this is reserved for special buttons... like block or process. Maybe we should move them somewhere.
                        ((GraphMarqueeHandler) marquee).insertSpecialElement();
                    } else if (status == INSERT_ELEMENT) {
                        ((GraphMarqueeHandler) marquee).insertElement((Point) getGraph().fromScreen(e.getPoint()));
                    } else if (status == INSERT_TRANSITION_START) {
                        GraphPortViewInterface gpvi = (GraphPortViewInterface) graph.getPortViewAt(e.getX(), e.getY());
                        if (gpvi != null) {
                            if (((GraphMarqueeHandler) marquee).insertTransitionFirstPort(gpvi)) {
                                status = INSERT_TRANSITION_POINTS;
                                gai = gpvi.getGraphActivity();
                            }
                        }
                    } else if (status == INSERT_TRANSITION_POINTS) {
                        GraphPortViewInterface gpvi = (GraphPortViewInterface) graph.getPortViewAt(e.getX(), e.getY());
                        if (gpvi == null) {
                            ((GraphMarqueeHandler) marquee).addPoint(e.getPoint());
                            ((GraphMarqueeHandler) marquee).drawTransition(e);
                        } else {
                            if (((GraphMarqueeHandler) marquee).insertTransitionSecondPort(gpvi)) {
                                status = INSERT_TRANSITION_START;
                                ((GraphMarqueeHandler) marquee).reset();
                            }
                        }
                    }
                } else {
                    // maybe display info... external package so can't be edited...
                }
            }

            e.consume();
        }

        public void mouseMoved(MouseEvent e) {
            if (status == INSERT_TRANSITION_START || status == INSERT_TRANSITION_POINTS) {
                ((GraphMarqueeHandler) marquee).drawTransition(e);
            }

            e.consume();
        }

        public void mouseDragged(MouseEvent e) {
            if (status == SELECTION && !aborted) {
                // added - if one of selected cell is Participant there must be no dragging
                Object[] sc = graph.getSelectionCells();
                if (sc != null) {
                    for (int i = 0; i < sc.length; i++) {
                        if (sc[i] instanceof GraphParticipantInterface) {
                            e.consume();
                            return;
                        }
                    }
                }

                selectOnRelease = false;
                autoscroll(graph, e.getPoint());
                if (handle != null) {
                    handle.mouseDragged(e);
                }
            } else if (status == MULTIPLE_SELECTION && !aborted) {
                // drag rectangle for multiply selection
                marquee.mouseDragged(e);
            }

            // CUSTOM
            if (status == INSERT_TRANSITION_START) {
                insertTransitionStart(e.getX(), e.getY());
            } else if (status == INSERT_TRANSITION_POINTS) {
                ((GraphMarqueeHandler) marquee).drawTransition(e);
            }
            // END CUSTOM

            e.consume();
        }

        public void mouseReleased(MouseEvent e) {
            // CUSTOM
            if (status == INSERT_TRANSITION_POINTS) {
                GraphPortViewInterface gpvi = (GraphPortViewInterface) graph.getPortViewAt(e.getX(), e.getY());
                if (gpvi != null) {
                    if (!gai.equals(gpvi.getGraphActivity())) {
                        if (((GraphMarqueeHandler) marquee).insertTransitionSecondPort(gpvi)) {
                            status = INSERT_TRANSITION_START;
                            ((GraphMarqueeHandler) marquee).reset();
                        }
                    }
                }
            }
            // END CUSTOM

            if (status == SELECTION) {
                if (handle != null && !aborted) {
                    handle.mouseReleased(e);
                }

                if (selectOnRelease) {
                    selectCellForEvent(cell.getCell(), e);
                }
            } else if (status == MULTIPLE_SELECTION && graph.isSelectionEnabled() && !aborted) {
                marquee.mouseReleased(e);
                status = SELECTION;
            }

            e.consume();
        }
    }

    // CUSTOM: extracted out this method for reuse by GraphControllerPanel
    public void insertTransitionStart(int x, int y) {
        GraphPortViewInterface gpvi = (GraphPortViewInterface) graph.getPortViewAt(x, y);
        if (gpvi != null) {
            if (((GraphMarqueeHandler) marquee).insertTransitionFirstPort(gpvi)) {
                status = INSERT_TRANSITION_POINTS;
            }
        }
    }
    // END CUSTOM

    /**
     * Constructs the "root handle" for <code>context</code>.
     *
     * @param context
     *           reference to the context of the current selection.
     */
    public CellHandle createHandle(GraphContext context) {
        if (context != null && !context.isEmpty() && graph.isEnabled()) {
            return new PERootHandle(context);
        }
        return null;
    }

    /**
     * Manages selection movement. It is adapted to suport proper
     * undo in coordination with WorkflowManager class.
     */
    public class PERootHandle extends RootHandle {

        /**
         * Creates a root handle which contains handles for the given
         * cells. The root handle and all its childs point to the
         * specified JGraph instance. The root handle is responsible
         * for dragging the selection.
         */
        public PERootHandle(GraphContext ctx) {
            super(ctx);
        }

        protected Point2D getInitialLocation(Object[] cells) {
            try {
                return super.getInitialLocation(cells);
            } catch (Throwable thr) {
                return null;
            }
        }

        public void mouseReleased(MouseEvent event) {
            if (event != null && !event.isConsumed()) {
                if (activeHandle != null) {
                    activeHandle.mouseReleased(event);
                    activeHandle = null;
                } else if (isMoving && !event.getPoint().equals(start)) {
                    if (cachedBounds != null) {
                        int dx = event.getX() - (int) start.getX();//HM, JGraph3.4.1
                        int dy = event.getY() - (int) start.getY();//HM, JGraph3.4.1
                        Point2D tmp = graph.fromScreen(new Point(dx, dy));//HM, JGraph3.4.1
                        GraphLayoutCache.translateViews(views, tmp.getX(), tmp.getY());//HM, JGraph3.4.1
                    }


                    // Harald Meister: snap activities to grid if grid is enabled
                    if (GraphUtilities.getGraphController().getGraphSettings().shouldShowGrid() &&
                            views[0] instanceof GraphActivityViewInterface) {
                        GraphActivityViewInterface view = (GraphActivityViewInterface) views[0];
                        Rectangle2D rect = view.getBounds();//HM, JGraph3.4.1
                        int dx = 0;
                        int dy = 0;

                        int gridsize = GraphUtilities.getGraphController().getGraphSettings().getGridSize();
                        int deltax = (int) rect.getX() % gridsize;
                        int deltay = (int) rect.getY() % gridsize;
                        int halfgrid = gridsize / 2;
                        if (deltax > halfgrid) {
                            dx += (gridsize - deltax);
                        } else {
                            dx -= deltax;
                        }
                        if (deltay > halfgrid) {
                            dy += (gridsize - deltay);
                        } else {
                            dy -= deltay;
                        }
                        Point2D tmp = graph.fromScreen(new Point(dx, dy));//HM, JGraph3.4.1
                        GraphLayoutCache.translateViews(views, tmp.getX(), tmp.getY());//HM, JGraph3.4.1
                    }
                    // Harald Meister


                    CellView[] all = graphLayoutCache.getAllDescendants(views);

                    if (graph.isMoveable()) { // Move Cells
                        Map propertyMap = GraphConstants.createAttributes(all, null);
                        GraphManager gm = getGraph().getGraphManager();
                        gm.moveCellsAndArrangeParticipants(propertyMap);
                    }
                    event.consume();
                }
            }
            start = null;
        }
    }

    /**
     * Returns a listener that can update the graph when the view changes.
     */
    protected GraphLayoutCacheListener createGraphLayoutCacheListener() {
        return new PEGraphLayoutCacheHandler();
    }

    /**
     * This class observes view changes and is adapted to disallow
     * deselection of cells after dragging.
     */
    public class PEGraphLayoutCacheHandler extends GraphLayoutCacheHandler {
        /*
         * (non-Javadoc)
         *
         * @see org.jgraph.event.GraphLayoutCacheListener#graphLayoutCacheChanged(org.jgraph.event.GraphLayoutCacheEvent)
         */

        public void graphLayoutCacheChanged(GraphLayoutCacheEvent e) {
            Object[] changed = e.getChange().getChanged();
            if (changed != null && changed.length > 0) {
                for (int i = 0; i < changed.length; i++) {
                    graph.updateAutoSize(graphLayoutCache.getMapping(changed[i], false));
                }
            }
            Object[] inserted = e.getChange().getInserted();
            if (inserted != null && inserted.length > 0 && graphLayoutCache.isSelectsLocalInsertedCells() && !(graphLayoutCache.isSelectsAllInsertedCells() && !graphLayoutCache.isPartial()) && graph.isEnabled()) {
                Object[] roots = DefaultGraphModel.getRoots(graphModel, inserted);
                if (roots != null && roots.length > 0) {
                    focus = graphLayoutCache.getMapping(roots[0], false);
                    graph.setSelectionCells(roots);
                }
            }
            updateSize();
        }
    }

    /**
     * Listens for changes in the graph model and updates the view accordingly.
     */
    public class PEGraphModelHandler implements GraphModelListener, Serializable {

        public void graphChanged(GraphModelEvent e) {
            Object[] removed = e.getChange().getRemoved();
            // Remove from selection & focus
            if (removed != null && removed.length > 0) {
                // Update Focus If Necessary
                for (int i = 0; i < removed.length && focus != null; i++) {
                    if (removed[i] == focus.getCell()) {
                        focus = null;
                        break;
                    }
                }
                // Remove from selection
                graph.getSelectionModel().removeSelectionCells(removed);
            }
            if (graphLayoutCache != null) {
                graphLayoutCache.graphChanged(e.getChange());
            }
            // Get arrays
            Object[] inserted = e.getChange().getInserted();
            Object[] changed = e.getChange().getChanged();
            // Insert
            if (inserted != null && inserted.length > 0) {
                // Update focus to first inserted cell
                focus = graphLayoutCache.getMapping(inserted[0], false);
                for (int i = 0; i < inserted.length; i++) {
                    graph.updateAutoSize(graphLayoutCache.getMapping(inserted[i], false));
                }
            }
            // Change (update size)
            if (changed != null && changed.length > 0) {
                for (int i = 0; i < changed.length; i++) {
                    graph.updateAutoSize(graphLayoutCache.getMapping(changed[i], false));
                }
            }
            // Select if not partial
            if (!graphLayoutCache.isPartial() && graphLayoutCache.isSelectsAllInsertedCells() && graph.isEnabled()) {
                graph.setSelectionCells(inserted);
            }
            updateSize();
        }
    } // End of BasicGraphUI.GraphModelHandler

    public void reset() {
        status = ((GraphMarqueeHandler) marquee).getStatus();
    }

    /**
     * Creates the listener reponsible for getting key events from the graph.
     */
    protected KeyListener createKeyListener() {
        return new PEKeyHandler();
    }

    /**
     * This is used to get multiple key down events to appropriately generate
     * events.
     */
    public class PEKeyHandler extends KeyAdapter implements Serializable {

        /** Key code that is being generated for. */
        protected Action repeatKeyAction;
        /** Set to true while keyPressed is active. */
        protected boolean isKeyDown;

        public void keyPressed(KeyEvent e) {
            KeyStroke keyStroke = KeyStroke.getKeyStroke(e.getKeyCode(), e.getModifiers());
            if (keyStroke.getKeyCode() == KeyEvent.VK_ESCAPE) {
                if (marquee != null) {
                    marquee.mouseReleased(null);
                }
                ((GraphMarqueeHandler) marquee).setSelectionMode();
                aborted = true;
            }
        }

        public void keyReleased(KeyEvent e) {
        }
    }

    /**
     * Paints the renderer of <code>view</code> to <code>g</code> at
     * <code>bounds</code>. Recursive implementation that paints the children
     * first.
     * <p>
     * The reciever should NOT modify <code>clipBounds</code>, or
     * <code>insets</code>. The <code>preview</code> flag is passed to the
     * renderer, and is not used here.
     */
    public void paintCell(Graphics g, CellView view, Rectangle2D bounds,
            boolean preview) {
        super.paintCell(g, view, bounds, preview);
    }
}
TOP

Related Classes of org.enhydra.jawe.components.graph.JaWEGraphUI$PEKeyHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.