001: /*
002: * (C) Copyright IBM Corp. 1998-2004. All Rights Reserved.
003: *
004: * The program is provided "as is" without any warranty express or
005: * implied, including the warranty of non-infringement and the implied
006: * warranties of merchantibility and fitness for a particular purpose.
007: * IBM will not be liable for any damages suffered by you as a result
008: * of using the Program. In no event will IBM be liable for any
009: * special, indirect or consequential damages or lost profits even if
010: * IBM has been advised of the possibility of their occurrence. IBM
011: * will not be liable for any third party claims against you.
012: */
013: package com.ibm.richtext.textpanel;
014:
015: import java.awt.event.FocusEvent;
016: import java.awt.event.KeyEvent;
017: import java.awt.event.MouseEvent;
018:
019: import com.ibm.richtext.textformat.TextOffset;
020:
021: final class SelectionDragInteractor extends Behavior implements
022: Runnable {
023:
024: static final String COPYRIGHT = "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
025: private TextComponent fTextComponent;
026: private TextSelection fSelection;
027: private RunStrategy fRunStrategy;
028:
029: private TextOffset fAnchorStart; // aliases text offsets - client beware
030: private TextOffset fAnchorEnd;
031: private TextOffset fCurrent;
032:
033: private final boolean fWasZeroLength;
034:
035: private int fCurrentX;
036: private int fCurrentY;
037: private boolean fMouseOutside;
038:
039: private Thread fAutoscrollThread = null;
040: private boolean fThreadRun = true;
041:
042: private static final int kScrollSleep = 300;
043:
044: public SelectionDragInteractor(TextSelection selection,
045: TextComponent textComponent, RunStrategy runStrategy,
046: TextOffset anchorStart, TextOffset anchorEnd,
047: TextOffset current, int initialX, int initialY,
048: boolean wasZeroLength) {
049:
050: fTextComponent = textComponent;
051: fSelection = selection;
052: fRunStrategy = runStrategy;
053: fAnchorStart = anchorStart;
054: fAnchorEnd = anchorEnd;
055: fCurrent = current;
056:
057: fCurrentX = initialX;
058: fCurrentY = initialY;
059: fMouseOutside = false;
060:
061: fWasZeroLength = wasZeroLength;
062:
063: setSelection();
064: }
065:
066: public boolean textControlEventOccurred(Behavior.EventType event,
067: Object what) {
068:
069: return true;
070: }
071:
072: public boolean focusGained(FocusEvent event) {
073:
074: return true;
075: }
076:
077: public boolean focusLost(FocusEvent event) {
078:
079: return true;
080: }
081:
082: public boolean keyPressed(KeyEvent event) {
083:
084: return true;
085: }
086:
087: public boolean keyTyped(KeyEvent event) {
088:
089: return true;
090: }
091:
092: public boolean keyReleased(KeyEvent event) {
093:
094: return true;
095: }
096:
097: public synchronized boolean mouseDragged(MouseEvent e) {
098:
099: int x = e.getX(), y = e.getY();
100: if (fCurrentX != x || fCurrentY != y) {
101: fCurrentX = x;
102: fCurrentY = y;
103: processMouseLocation();
104: }
105: return true;
106: }
107:
108: public synchronized boolean mouseEnter(MouseEvent e) {
109:
110: fMouseOutside = false;
111: return true;
112: }
113:
114: public synchronized boolean mouseExited(MouseEvent e) {
115:
116: if (fAutoscrollThread == null) {
117: fAutoscrollThread = new Thread(this );
118: fAutoscrollThread.start();
119: }
120: fMouseOutside = true;
121: notify();
122:
123: return true;
124: }
125:
126: public synchronized boolean mouseReleased(MouseEvent e) {
127:
128: fMouseOutside = false;
129: fThreadRun = false;
130: if (fAutoscrollThread != null) {
131: fAutoscrollThread.interrupt();
132: }
133:
134: removeFromOwner();
135: boolean isZeroLength = TextSelection.rangeIsZeroLength(
136: fAnchorStart, fAnchorEnd, fCurrent);
137: fSelection.mouseReleased(isZeroLength != fWasZeroLength);
138:
139: return true;
140: }
141:
142: private void processMouseLocation() {
143:
144: fTextComponent.scrollToShow(fCurrentX, fCurrentY);
145: fTextComponent.pointToTextOffset(fCurrent, fCurrentX,
146: fCurrentY, null, true);
147: setSelection();
148: }
149:
150: private void setSelection() {
151:
152: if (fCurrent.greaterThan(fAnchorEnd)) {
153: fSelection.advanceToNextBoundary(fCurrent);
154: fSelection.setSelRangeAndDraw(fAnchorStart, fCurrent,
155: fAnchorStart);
156: } else if (fCurrent.lessThan(fAnchorStart)) {
157: fSelection.advanceToPreviousBoundary(fCurrent);
158: fSelection.setSelRangeAndDraw(fCurrent, fAnchorEnd,
159: fAnchorStart);
160: } else {
161: fCurrent.assign(fAnchorEnd);
162: fSelection.setSelRangeAndDraw(fAnchorStart, fAnchorEnd,
163: fAnchorStart);
164: }
165: }
166:
167: public void run() {
168:
169: Runnable doMouseLoc = new Runnable() {
170: public void run() {
171: processMouseLocation();
172: }
173: };
174:
175: while (fThreadRun) {
176:
177: try {
178: Thread.sleep(kScrollSleep);
179: } catch (InterruptedException e) {
180: return; // just quit scrolling
181: }
182:
183: synchronized (this ) {
184:
185: while (!fMouseOutside) {
186: try {
187: wait();
188: } catch (InterruptedException e) {
189: return; // just quit scrolling
190: }
191: }
192:
193: fRunStrategy.doIt(doMouseLoc);
194: }
195: }
196: }
197: }
|