| /* |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| package org.apache.batik.gvt.text; |
| |
| import java.awt.Shape; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.NoninvertibleTransformException; |
| import java.awt.geom.Point2D; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| |
| import org.apache.batik.gvt.GraphicsNode; |
| import org.apache.batik.gvt.RootGraphicsNode; |
| import org.apache.batik.gvt.Selectable; |
| import org.apache.batik.gvt.Selector; |
| import org.apache.batik.gvt.TextNode; |
| import org.apache.batik.gvt.event.GraphicsNodeChangeEvent; |
| import org.apache.batik.gvt.event.GraphicsNodeEvent; |
| import org.apache.batik.gvt.event.GraphicsNodeKeyEvent; |
| import org.apache.batik.gvt.event.GraphicsNodeMouseEvent; |
| import org.apache.batik.gvt.event.SelectionEvent; |
| import org.apache.batik.gvt.event.SelectionListener; |
| |
| /** |
| * A simple implementation of GraphicsNodeMouseListener for text selection. |
| * |
| * @author <a href="mailto:bill.haneman@ireland.sun.com">Bill Haneman</a> |
| * @version $Id$ |
| */ |
| |
| public class ConcreteTextSelector implements Selector { |
| |
| private ArrayList listeners; |
| private GraphicsNode selectionNode; |
| private RootGraphicsNode selectionNodeRoot; |
| |
| public ConcreteTextSelector() { |
| } |
| |
| public void mouseClicked(GraphicsNodeMouseEvent evt) { |
| checkSelectGesture(evt); |
| } |
| |
| public void mouseDragged(GraphicsNodeMouseEvent evt) { |
| checkSelectGesture(evt); |
| } |
| |
| public void mouseEntered(GraphicsNodeMouseEvent evt) { |
| checkSelectGesture(evt); |
| } |
| |
| public void mouseExited(GraphicsNodeMouseEvent evt) { |
| checkSelectGesture(evt); |
| } |
| |
| public void mouseMoved(GraphicsNodeMouseEvent evt) { |
| } |
| |
| public void mousePressed(GraphicsNodeMouseEvent evt) { |
| checkSelectGesture(evt); |
| } |
| |
| public void mouseReleased(GraphicsNodeMouseEvent evt) { |
| checkSelectGesture(evt); |
| } |
| |
| public void keyPressed(GraphicsNodeKeyEvent evt) { |
| report(evt, "keyPressed"); |
| } |
| |
| public void keyReleased(GraphicsNodeKeyEvent evt) { |
| report(evt, "keyReleased"); |
| } |
| |
| public void keyTyped(GraphicsNodeKeyEvent evt) { |
| report(evt, "keyTyped"); |
| } |
| |
| public void changeStarted (GraphicsNodeChangeEvent gnce) { |
| } |
| |
| public void changeCompleted (GraphicsNodeChangeEvent gnce) { |
| if (selectionNode == null) { |
| return; |
| } |
| Shape newShape = |
| ((Selectable)selectionNode).getHighlightShape(); |
| dispatchSelectionEvent |
| (new SelectionEvent(getSelection(), |
| SelectionEvent.SELECTION_CHANGED, |
| newShape)); |
| } |
| |
| public void setSelection(Mark begin, Mark end) { |
| TextNode node = begin.getTextNode(); |
| if (node != end.getTextNode()) { |
| throw new Error("Markers not from same TextNode"); |
| } |
| node.setSelection(begin, end); |
| selectionNode = node; |
| selectionNodeRoot = node.getRoot(); |
| Object selection = getSelection(); |
| Shape shape = node.getHighlightShape(); |
| dispatchSelectionEvent(new SelectionEvent |
| (selection, SelectionEvent.SELECTION_DONE, shape)); |
| } |
| |
| public void clearSelection() { |
| if (selectionNode == null) { |
| return; |
| } |
| dispatchSelectionEvent(new SelectionEvent |
| (null, SelectionEvent.SELECTION_CLEARED, null)); |
| selectionNode = null; |
| selectionNodeRoot = null; |
| } |
| |
| /* |
| * Checks the event to see if it is a selection gesture and processes it |
| * accordingly. |
| * @param evt the GraphicsNodeEvent, which may be a "select gesture" |
| * Param evt is a GraphicsNodeEvent rather than a GraphicsNodeMouseEvent |
| * for future extension, so we can use Shift-arrow, etc. |
| */ |
| protected void checkSelectGesture(GraphicsNodeEvent evt) { |
| |
| GraphicsNodeMouseEvent mevt = null; |
| if (evt instanceof GraphicsNodeMouseEvent) { |
| mevt = (GraphicsNodeMouseEvent) evt; |
| } |
| |
| GraphicsNode source = evt.getGraphicsNode(); |
| if (isDeselectGesture(evt)) { |
| if (selectionNode != null) { |
| selectionNodeRoot.removeTreeGraphicsNodeChangeListener(this); |
| } |
| clearSelection(); |
| } else if (mevt != null) { |
| |
| Point2D p = new Point2D.Double(mevt.getX(), mevt.getY()); |
| AffineTransform t = source.getGlobalTransform(); |
| if (t == null) { |
| t = new AffineTransform(); |
| } |
| else { |
| try { |
| t = t.createInverse(); |
| } catch (NoninvertibleTransformException ni) { |
| } |
| } |
| p = t.transform(p, null); |
| |
| if ((source instanceof Selectable) && |
| (isSelectStartGesture(evt))) { |
| if (selectionNode != source) { |
| if (selectionNode != null) { |
| selectionNodeRoot |
| .removeTreeGraphicsNodeChangeListener(this); |
| } |
| selectionNode = source; |
| if (source != null) { |
| selectionNodeRoot = source.getRoot(); |
| selectionNodeRoot |
| .addTreeGraphicsNodeChangeListener(this); |
| } |
| } |
| |
| ((Selectable) source).selectAt(p.getX(), p.getY()); |
| dispatchSelectionEvent( |
| new SelectionEvent(null, |
| SelectionEvent.SELECTION_STARTED, |
| null)); |
| |
| } else if (isSelectEndGesture(evt)) { |
| if (selectionNode == source) { |
| ((Selectable) source).selectTo(p.getX(), p.getY()); |
| } |
| Object oldSelection = getSelection(); |
| if (selectionNode != null) { |
| Shape newShape; |
| newShape = ((Selectable)selectionNode).getHighlightShape(); |
| dispatchSelectionEvent |
| (new SelectionEvent(oldSelection, |
| SelectionEvent.SELECTION_DONE, |
| newShape)); |
| } |
| } else if (isSelectContinueGesture(evt)) { |
| |
| if (selectionNode == source) { |
| boolean result = ((Selectable) source).selectTo(p.getX(), |
| p.getY()); |
| if (result) { |
| Shape newShape = |
| ((Selectable) selectionNode).getHighlightShape(); |
| |
| dispatchSelectionEvent( |
| new SelectionEvent(null, |
| SelectionEvent.SELECTION_CHANGED, |
| newShape)); |
| } |
| } |
| } else if ((source instanceof Selectable) && |
| (isSelectAllGesture(evt))) { |
| if (selectionNode != source) { |
| if (selectionNode != null) { |
| selectionNodeRoot |
| .removeTreeGraphicsNodeChangeListener(this); |
| } |
| selectionNode = source; |
| if (source != null) { |
| selectionNodeRoot = source.getRoot(); |
| selectionNodeRoot |
| .addTreeGraphicsNodeChangeListener(this); |
| } |
| } |
| ((Selectable) source).selectAll(p.getX(), p.getY()); |
| Object oldSelection = getSelection(); |
| Shape newShape = |
| ((Selectable) source).getHighlightShape(); |
| dispatchSelectionEvent( |
| new SelectionEvent(oldSelection, |
| SelectionEvent.SELECTION_DONE, |
| newShape)); |
| } |
| } |
| } |
| |
| private boolean isDeselectGesture(GraphicsNodeEvent evt) { |
| return ((evt.getID() == GraphicsNodeMouseEvent.MOUSE_CLICKED) |
| && (((GraphicsNodeMouseEvent) evt).getClickCount() == 1)); |
| } |
| |
| private boolean isSelectStartGesture(GraphicsNodeEvent evt) { |
| return (evt.getID() == GraphicsNodeMouseEvent.MOUSE_PRESSED); |
| } |
| |
| private boolean isSelectEndGesture(GraphicsNodeEvent evt) { |
| return ((evt.getID() == GraphicsNodeMouseEvent.MOUSE_RELEASED)); |
| } |
| |
| private boolean isSelectContinueGesture(GraphicsNodeEvent evt) { |
| return (evt.getID() == GraphicsNodeMouseEvent.MOUSE_DRAGGED); |
| } |
| |
| private boolean isSelectAllGesture(GraphicsNodeEvent evt) { |
| return ((evt.getID() == GraphicsNodeMouseEvent.MOUSE_CLICKED) |
| && (((GraphicsNodeMouseEvent) evt).getClickCount() == 2)); |
| } |
| |
| /* |
| * Get the contents of the current selection. |
| */ |
| public Object getSelection() { |
| Object value = null; |
| if (selectionNode instanceof Selectable) { |
| value = ((Selectable) selectionNode).getSelection(); |
| } |
| return value; |
| } |
| |
| /** |
| * Reports whether the current selection contains any objects. |
| */ |
| public boolean isEmpty() { |
| return (getSelection() == null); |
| } |
| |
| /** |
| * Reports whether the current selection contains any objects. |
| */ |
| public void dispatchSelectionEvent(SelectionEvent e) { |
| if (listeners != null) { |
| Iterator iter = listeners.iterator(); |
| switch(e.getID()) { |
| case SelectionEvent.SELECTION_DONE: |
| while (iter.hasNext()) { |
| ((SelectionListener)iter.next()).selectionDone(e); |
| } |
| break; |
| case SelectionEvent.SELECTION_CHANGED: |
| while (iter.hasNext()) { |
| ((SelectionListener)iter.next()).selectionChanged(e); |
| } |
| break; |
| case SelectionEvent.SELECTION_CLEARED: |
| while (iter.hasNext()) { |
| ((SelectionListener)iter.next()).selectionCleared(e); |
| } |
| break; |
| case SelectionEvent.SELECTION_STARTED: |
| while (iter.hasNext()) { |
| ((SelectionListener)iter.next()).selectionStarted(e); |
| } |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Add a SelectionListener to this Selector's notification list. |
| * @param l the SelectionListener to add. |
| */ |
| public void addSelectionListener(SelectionListener l) { |
| if (listeners == null) { |
| listeners = new ArrayList(); |
| } |
| listeners.add(l); |
| } |
| |
| /** |
| * Remove a SelectionListener from this Selector's notification list. |
| * @param l the SelectionListener to be removed. |
| */ |
| public void removeSelectionListener(SelectionListener l) { |
| if (listeners != null) { |
| listeners.remove(l); |
| } |
| } |
| |
| private void report(GraphicsNodeEvent evt, String message) { |
| GraphicsNode source = evt.getGraphicsNode(); |
| String label = "(non-text node)"; |
| if (source instanceof TextNode) { |
| char[] cbuff; |
| java.text.CharacterIterator iter = |
| ((TextNode) source).getAttributedCharacterIterator(); |
| cbuff = new char[iter.getEndIndex()]; |
| if (cbuff.length > 0) cbuff[0] = iter.first(); |
| for (int i=1; i<cbuff.length;++i) { |
| cbuff[i] = iter.next(); |
| } |
| label = new String(cbuff); |
| } |
| System.out.println("Mouse "+message+" in "+label); |
| } |
| } |
| |
| |