001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.gvt.text;
020:
021: import java.awt.Shape;
022: import java.awt.geom.AffineTransform;
023: import java.awt.geom.NoninvertibleTransformException;
024: import java.awt.geom.Point2D;
025: import java.util.ArrayList;
026: import java.util.Iterator;
027:
028: import org.apache.batik.gvt.GraphicsNode;
029: import org.apache.batik.gvt.RootGraphicsNode;
030: import org.apache.batik.gvt.Selectable;
031: import org.apache.batik.gvt.Selector;
032: import org.apache.batik.gvt.TextNode;
033: import org.apache.batik.gvt.event.GraphicsNodeChangeEvent;
034: import org.apache.batik.gvt.event.GraphicsNodeEvent;
035: import org.apache.batik.gvt.event.GraphicsNodeKeyEvent;
036: import org.apache.batik.gvt.event.GraphicsNodeMouseEvent;
037: import org.apache.batik.gvt.event.SelectionEvent;
038: import org.apache.batik.gvt.event.SelectionListener;
039:
040: /**
041: * A simple implementation of GraphicsNodeMouseListener for text selection.
042: *
043: * @author <a href="mailto:bill.haneman@ireland.sun.com">Bill Haneman</a>
044: * @version $Id: ConcreteTextSelector.java 475477 2006-11-15 22:44:28Z cam $
045: */
046:
047: public class ConcreteTextSelector implements Selector {
048:
049: private ArrayList listeners;
050: private GraphicsNode selectionNode;
051: private RootGraphicsNode selectionNodeRoot;
052:
053: public ConcreteTextSelector() {
054: }
055:
056: public void mouseClicked(GraphicsNodeMouseEvent evt) {
057: checkSelectGesture(evt);
058: }
059:
060: public void mouseDragged(GraphicsNodeMouseEvent evt) {
061: checkSelectGesture(evt);
062: }
063:
064: public void mouseEntered(GraphicsNodeMouseEvent evt) {
065: checkSelectGesture(evt);
066: }
067:
068: public void mouseExited(GraphicsNodeMouseEvent evt) {
069: checkSelectGesture(evt);
070: }
071:
072: public void mouseMoved(GraphicsNodeMouseEvent evt) {
073: }
074:
075: public void mousePressed(GraphicsNodeMouseEvent evt) {
076: checkSelectGesture(evt);
077: }
078:
079: public void mouseReleased(GraphicsNodeMouseEvent evt) {
080: checkSelectGesture(evt);
081: }
082:
083: public void keyPressed(GraphicsNodeKeyEvent evt) {
084: report(evt, "keyPressed");
085: }
086:
087: public void keyReleased(GraphicsNodeKeyEvent evt) {
088: report(evt, "keyReleased");
089: }
090:
091: public void keyTyped(GraphicsNodeKeyEvent evt) {
092: report(evt, "keyTyped");
093: }
094:
095: public void changeStarted(GraphicsNodeChangeEvent gnce) {
096: }
097:
098: public void changeCompleted(GraphicsNodeChangeEvent gnce) {
099: if (selectionNode == null) {
100: return;
101: }
102: Shape newShape = ((Selectable) selectionNode)
103: .getHighlightShape();
104: dispatchSelectionEvent(new SelectionEvent(getSelection(),
105: SelectionEvent.SELECTION_CHANGED, newShape));
106: }
107:
108: public void setSelection(Mark begin, Mark end) {
109: TextNode node = begin.getTextNode();
110: if (node != end.getTextNode()) {
111: throw new Error("Markers not from same TextNode");
112: }
113: node.setSelection(begin, end);
114: selectionNode = node;
115: selectionNodeRoot = node.getRoot();
116: Object selection = getSelection();
117: Shape shape = node.getHighlightShape();
118: dispatchSelectionEvent(new SelectionEvent(selection,
119: SelectionEvent.SELECTION_DONE, shape));
120: }
121:
122: public void clearSelection() {
123: if (selectionNode == null) {
124: return;
125: }
126: dispatchSelectionEvent(new SelectionEvent(null,
127: SelectionEvent.SELECTION_CLEARED, null));
128: selectionNode = null;
129: selectionNodeRoot = null;
130: }
131:
132: /*
133: * Checks the event to see if it is a selection gesture and processes it
134: * accordingly.
135: * @param evt the GraphicsNodeEvent, which may be a "select gesture"
136: * Param evt is a GraphicsNodeEvent rather than a GraphicsNodeMouseEvent
137: * for future extension, so we can use Shift-arrow, etc.
138: */
139: protected void checkSelectGesture(GraphicsNodeEvent evt) {
140:
141: GraphicsNodeMouseEvent mevt = null;
142: if (evt instanceof GraphicsNodeMouseEvent) {
143: mevt = (GraphicsNodeMouseEvent) evt;
144: }
145:
146: GraphicsNode source = evt.getGraphicsNode();
147: if (isDeselectGesture(evt)) {
148: if (selectionNode != null) {
149: selectionNodeRoot
150: .removeTreeGraphicsNodeChangeListener(this );
151: }
152: clearSelection();
153: } else if (mevt != null) {
154:
155: Point2D p = new Point2D.Double(mevt.getX(), mevt.getY());
156: AffineTransform t = source.getGlobalTransform();
157: if (t == null) {
158: t = new AffineTransform();
159: } else {
160: try {
161: t = t.createInverse();
162: } catch (NoninvertibleTransformException ni) {
163: }
164: }
165: p = t.transform(p, null);
166:
167: if ((source instanceof Selectable)
168: && (isSelectStartGesture(evt))) {
169: if (selectionNode != source) {
170: if (selectionNode != null) {
171: selectionNodeRoot
172: .removeTreeGraphicsNodeChangeListener(this );
173: }
174: selectionNode = source;
175: if (source != null) {
176: selectionNodeRoot = source.getRoot();
177: selectionNodeRoot
178: .addTreeGraphicsNodeChangeListener(this );
179: }
180: }
181:
182: ((Selectable) source).selectAt(p.getX(), p.getY());
183: dispatchSelectionEvent(new SelectionEvent(null,
184: SelectionEvent.SELECTION_STARTED, null));
185:
186: } else if (isSelectEndGesture(evt)) {
187: if (selectionNode == source) {
188: ((Selectable) source).selectTo(p.getX(), p.getY());
189: }
190: Object oldSelection = getSelection();
191: if (selectionNode != null) {
192: Shape newShape;
193: newShape = ((Selectable) selectionNode)
194: .getHighlightShape();
195: dispatchSelectionEvent(new SelectionEvent(
196: oldSelection,
197: SelectionEvent.SELECTION_DONE, newShape));
198: }
199: } else if (isSelectContinueGesture(evt)) {
200:
201: if (selectionNode == source) {
202: boolean result = ((Selectable) source).selectTo(p
203: .getX(), p.getY());
204: if (result) {
205: Shape newShape = ((Selectable) selectionNode)
206: .getHighlightShape();
207:
208: dispatchSelectionEvent(new SelectionEvent(null,
209: SelectionEvent.SELECTION_CHANGED,
210: newShape));
211: }
212: }
213: } else if ((source instanceof Selectable)
214: && (isSelectAllGesture(evt))) {
215: if (selectionNode != source) {
216: if (selectionNode != null) {
217: selectionNodeRoot
218: .removeTreeGraphicsNodeChangeListener(this );
219: }
220: selectionNode = source;
221: if (source != null) {
222: selectionNodeRoot = source.getRoot();
223: selectionNodeRoot
224: .addTreeGraphicsNodeChangeListener(this );
225: }
226: }
227: ((Selectable) source).selectAll(p.getX(), p.getY());
228: Object oldSelection = getSelection();
229: Shape newShape = ((Selectable) source)
230: .getHighlightShape();
231: dispatchSelectionEvent(new SelectionEvent(oldSelection,
232: SelectionEvent.SELECTION_DONE, newShape));
233: }
234: }
235: }
236:
237: private boolean isDeselectGesture(GraphicsNodeEvent evt) {
238: return ((evt.getID() == GraphicsNodeMouseEvent.MOUSE_CLICKED) && (((GraphicsNodeMouseEvent) evt)
239: .getClickCount() == 1));
240: }
241:
242: private boolean isSelectStartGesture(GraphicsNodeEvent evt) {
243: return (evt.getID() == GraphicsNodeMouseEvent.MOUSE_PRESSED);
244: }
245:
246: private boolean isSelectEndGesture(GraphicsNodeEvent evt) {
247: return ((evt.getID() == GraphicsNodeMouseEvent.MOUSE_RELEASED));
248: }
249:
250: private boolean isSelectContinueGesture(GraphicsNodeEvent evt) {
251: return (evt.getID() == GraphicsNodeMouseEvent.MOUSE_DRAGGED);
252: }
253:
254: private boolean isSelectAllGesture(GraphicsNodeEvent evt) {
255: return ((evt.getID() == GraphicsNodeMouseEvent.MOUSE_CLICKED) && (((GraphicsNodeMouseEvent) evt)
256: .getClickCount() == 2));
257: }
258:
259: /*
260: * Get the contents of the current selection.
261: */
262: public Object getSelection() {
263: Object value = null;
264: if (selectionNode instanceof Selectable) {
265: value = ((Selectable) selectionNode).getSelection();
266: }
267: return value;
268: }
269:
270: /**
271: * Reports whether the current selection contains any objects.
272: */
273: public boolean isEmpty() {
274: return (getSelection() == null);
275: }
276:
277: /**
278: * Reports whether the current selection contains any objects.
279: */
280: public void dispatchSelectionEvent(SelectionEvent e) {
281: if (listeners != null) {
282: Iterator iter = listeners.iterator();
283: switch (e.getID()) {
284: case SelectionEvent.SELECTION_DONE:
285: while (iter.hasNext()) {
286: ((SelectionListener) iter.next()).selectionDone(e);
287: }
288: break;
289: case SelectionEvent.SELECTION_CHANGED:
290: while (iter.hasNext()) {
291: ((SelectionListener) iter.next())
292: .selectionChanged(e);
293: }
294: break;
295: case SelectionEvent.SELECTION_CLEARED:
296: while (iter.hasNext()) {
297: ((SelectionListener) iter.next())
298: .selectionCleared(e);
299: }
300: break;
301: case SelectionEvent.SELECTION_STARTED:
302: while (iter.hasNext()) {
303: ((SelectionListener) iter.next())
304: .selectionStarted(e);
305: }
306: break;
307: }
308: }
309: }
310:
311: /**
312: * Add a SelectionListener to this Selector's notification list.
313: * @param l the SelectionListener to add.
314: */
315: public void addSelectionListener(SelectionListener l) {
316: if (listeners == null) {
317: listeners = new ArrayList();
318: }
319: listeners.add(l);
320: }
321:
322: /**
323: * Remove a SelectionListener from this Selector's notification list.
324: * @param l the SelectionListener to be removed.
325: */
326: public void removeSelectionListener(SelectionListener l) {
327: if (listeners != null) {
328: listeners.remove(l);
329: }
330: }
331:
332: private void report(GraphicsNodeEvent evt, String message) {
333: GraphicsNode source = evt.getGraphicsNode();
334: String label = "(non-text node)";
335: if (source instanceof TextNode) {
336: char[] cbuff;
337: java.text.CharacterIterator iter = ((TextNode) source)
338: .getAttributedCharacterIterator();
339: cbuff = new char[iter.getEndIndex()];
340: if (cbuff.length > 0)
341: cbuff[0] = iter.first();
342: for (int i = 1; i < cbuff.length; ++i) {
343: cbuff[i] = iter.next();
344: }
345: label = new String(cbuff);
346: }
347: System.out.println("Mouse " + message + " in " + label);
348: }
349: }
|