KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > custom > StyledTextDropTargetEffect


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.custom;
12
13 import org.eclipse.swt.*;
14 import org.eclipse.swt.dnd.*;
15 import org.eclipse.swt.graphics.*;
16 import org.eclipse.swt.widgets.*;
17
18 /**
19  * This adapter class provides a default drag under effect (eg. select and scroll)
20  * when a drag occurs over a <code>Table</code>.
21  *
22  * <p>Classes that wish to provide their own drag under effect for a <code>StyledText</code>
23  * can extend this class, override the <code>StyledTextDropTargetEffect.dragOver</code>
24  * method and override any other applicable methods in <code>StyledTextDropTargetEffect</code> to
25  * display their own drag under effect.</p>
26  *
27  * Subclasses that override any methods of this class should call the corresponding
28  * <code>super</code> method to get the default drag under effect implementation.
29  *
30  * <p>The feedback value is either one of the FEEDBACK constants defined in
31  * class <code>DND</code> which is applicable to instances of this class,
32  * or it must be built by <em>bitwise OR</em>'ing together
33  * (that is, using the <code>int</code> "|" operator) two or more
34  * of those <code>DND</code> effect constants.
35  * </p>
36  * <p>
37  * <dl>
38  * <dt><b>Feedback:</b></dt>
39  * <dd>FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
40  * </dl>
41  * </p>
42  *
43  * @see DropTargetAdapter
44  * @see DropTargetEvent
45  *
46  * @since 3.3
47  */

48 public class StyledTextDropTargetEffect extends DropTargetEffect {
49     static final int CARET_WIDTH = 2;
50     static final int SCROLL_HYSTERESIS = 100; // milli seconds
51
static final int SCROLL_TOLERANCE = 20; // pixels
52

53     int currentOffset = -1;
54     long scrollBeginTime;
55     int scrollX = -1, scrollY = -1;
56     Listener paintListener;
57     
58     /**
59      * Creates a new <code>StyledTextDropTargetEffect</code> to handle the drag under effect on the specified
60      * <code>StyledText</code>.
61      *
62      * @param styledText the <code>StyledText</code> over which the user positions the cursor to drop the data
63      */

64     public StyledTextDropTargetEffect(StyledText styledText) {
65         super(styledText);
66         paintListener = new Listener () {
67             public void handleEvent (Event event) {
68                 if (currentOffset != -1) {
69                     StyledText text = (StyledText) getControl();
70                     Point position = text.getLocationAtOffset(currentOffset);
71                     int height = text.getLineHeight(currentOffset);
72                     event.gc.setBackground(event.display.getSystemColor (SWT.COLOR_BLACK));
73                     event.gc.fillRectangle(position.x, position.y, CARET_WIDTH, height);
74                 }
75             }
76         };
77     }
78     
79     /**
80      * This implementation of <code>dragEnter</code> provides a default drag under effect
81      * for the feedback specified in <code>event.feedback</code>.
82      *
83      * For additional information see <code>DropTargetAdapter.dragEnter</code>.
84      *
85      * Subclasses that override this method should call <code>super.dragEnter(event)</code>
86      * to get the default drag under effect implementation.
87      *
88      * @param event the information associated with the drag start event
89      *
90      * @see DropTargetAdapter
91      * @see DropTargetEvent
92      */

93     public void dragEnter(DropTargetEvent event) {
94         currentOffset = -1;
95         scrollBeginTime = 0;
96         scrollX = -1;
97         scrollY = -1;
98         getControl().removeListener(SWT.Paint, paintListener);
99         getControl().addListener (SWT.Paint, paintListener);
100     }
101     
102     /**
103      * This implementation of <code>dragLeave</code> provides a default drag under effect
104      * for the feedback specified in <code>event.feedback</code>.
105      *
106      * For additional information see <code>DropTargetAdapter.dragLeave</code>.
107      *
108      * Subclasses that override this method should call <code>super.dragLeave(event)</code>
109      * to get the default drag under effect implementation.
110      *
111      * @param event the information associated with the drag leave event
112      *
113      * @see DropTargetAdapter
114      * @see DropTargetEvent
115      */

116     public void dragLeave(DropTargetEvent event) {
117         StyledText text = (StyledText) getControl();
118         if (currentOffset != -1) {
119             refreshCaret(text, currentOffset, -1);
120         }
121         text.removeListener(SWT.Paint, paintListener);
122         scrollBeginTime = 0;
123         scrollX = -1;
124         scrollY = -1;
125     }
126
127     /**
128      * This implementation of <code>dragOver</code> provides a default drag under effect
129      * for the feedback specified in <code>event.feedback</code>.
130      *
131      * For additional information see <code>DropTargetAdapter.dragOver</code>.
132      *
133      * Subclasses that override this method should call <code>super.dragOver(event)</code>
134      * to get the default drag under effect implementation.
135      *
136      * @param event the information associated with the drag over event
137      *
138      * @see DropTargetAdapter
139      * @see DropTargetEvent
140      * @see DND#FEEDBACK_SELECT
141      * @see DND#FEEDBACK_SCROLL
142      */

143     public void dragOver(DropTargetEvent event) {
144         int effect = event.feedback;
145         StyledText text = (StyledText) getControl();
146         
147         Point pt = text.getDisplay().map(null, text, event.x, event.y);
148         if ((effect & DND.FEEDBACK_SCROLL) == 0) {
149             scrollBeginTime = 0;
150             scrollX = scrollY = -1;
151         } else {
152             if (text.getCharCount() == 0) {
153                 scrollBeginTime = 0;
154                 scrollX = scrollY = -1;
155             } else {
156                 if (scrollX != -1 && scrollY != -1 && scrollBeginTime != 0 &&
157                     (pt.x >= scrollX && pt.x <= (scrollX + SCROLL_TOLERANCE) ||
158                      pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) {
159                     if (System.currentTimeMillis() >= scrollBeginTime) {
160                         Rectangle area = text.getClientArea();
161                         Rectangle bounds = text.getTextBounds(0, 0);
162                         int charWidth = bounds.width;
163                         int scrollAmount = 10*charWidth;
164                         if (pt.x < area.x + 3*charWidth) {
165                             int leftPixel = text.getHorizontalPixel();
166                             text.setHorizontalPixel(leftPixel - scrollAmount);
167                             if (text.getHorizontalPixel() != leftPixel) {
168                                 text.redraw();
169                             }
170                         }
171                         if (pt.x > area.width - 3*charWidth) {
172                             int leftPixel = text.getHorizontalPixel();
173                             text.setHorizontalPixel(leftPixel + scrollAmount);
174                             if (text.getHorizontalPixel() != leftPixel) {
175                                 text.redraw();
176                             }
177                         }
178                         int lineHeight = bounds.height;
179                         if (pt.y < area.y + lineHeight) {
180                             int topPixel = text.getTopPixel();
181                             text.setTopPixel(topPixel - lineHeight);
182                             if (text.getTopPixel() != topPixel) {
183                                 text.redraw();
184                             }
185                         }
186                         if (pt.y > area.height - lineHeight) {
187                             int topPixel = text.getTopPixel();
188                             text.setTopPixel(topPixel + lineHeight);
189                             if (text.getTopPixel() != topPixel) {
190                                 text.redraw();
191                             }
192                         }
193                         scrollBeginTime = 0;
194                         scrollX = scrollY = -1;
195                     }
196                 } else {
197                     scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
198                     scrollX = pt.x;
199                     scrollY = pt.y;
200                 }
201             }
202         }
203             
204         if ((effect & DND.FEEDBACK_SELECT) != 0) {
205             StyledTextContent content = text.getContent();
206             int newOffset = -1;
207             try {
208                 newOffset = text.getOffsetAtLocation(pt);
209             } catch (IllegalArgumentException JavaDoc ex1) {
210                 int maxOffset = content.getCharCount();
211                 Point maxLocation = text.getLocationAtOffset(maxOffset);
212                 if (pt.y >= maxLocation.y) {
213                     try {
214                         newOffset = text.getOffsetAtLocation(new Point(pt.x, maxLocation.y));
215                     } catch (IllegalArgumentException JavaDoc ex2) {
216                         newOffset = maxOffset;
217                     }
218                 } else {
219                     try {
220                         int startOffset = text.getOffsetAtLocation(new Point(0, pt.y));
221                         int endOffset = maxOffset;
222                         int line = content.getLineAtOffset(startOffset);
223                         int lineCount = content.getLineCount();
224                         if (line + 1 < lineCount) {
225                             endOffset = content.getOffsetAtLine(line + 1) - 1;
226                         }
227                         int lineHeight = text.getLineHeight(startOffset);
228                         for (int i = endOffset; i >= startOffset; i--) {
229                             Point p = text.getLocationAtOffset(i);
230                             if (p.x < pt.x && p.y < pt.y && p.y + lineHeight > pt.y) {
231                                 newOffset = i;
232                                 break;
233                             }
234                         }
235                     } catch (IllegalArgumentException JavaDoc ex2) {
236                         newOffset = -1;
237                     }
238                 }
239             }
240             if (newOffset != -1 && newOffset != currentOffset) {
241                 // check if offset is line delimiter
242
// see StyledText.isLineDelimiter()
243
int line = content.getLineAtOffset(newOffset);
244                 int lineOffset = content.getOffsetAtLine(line);
245                 int offsetInLine = newOffset - lineOffset;
246                 // offsetInLine will be greater than line length if the line
247
// delimiter is longer than one character and the offset is set
248
// in between parts of the line delimiter.
249
if (offsetInLine > content.getLine(line).length()) {
250                     newOffset = Math.max(0, newOffset - 1);
251                 }
252                 refreshCaret(text, currentOffset, newOffset);
253                 currentOffset = newOffset;
254             }
255         }
256     }
257
258     void refreshCaret(StyledText text, int oldOffset, int newOffset) {
259         if (oldOffset != newOffset) {
260             if (oldOffset != -1) {
261                 Point oldPos = text.getLocationAtOffset(oldOffset);
262                 int oldHeight = text.getLineHeight(oldOffset);
263                 text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false);
264             }
265             if (newOffset != -1) {
266                 Point newPos = text.getLocationAtOffset(newOffset);
267                 int newHeight = text.getLineHeight(newOffset);
268                 text.redraw (newPos.x, newPos.y, CARET_WIDTH, newHeight, false);
269             }
270         }
271     }
272
273     /**
274      * This implementation of <code>dropAccept</code> provides a default drag under effect
275      * for the feedback specified in <code>event.feedback</code>.
276      *
277      * For additional information see <code>DropTargetAdapter.dropAccept</code>.
278      *
279      * Subclasses that override this method should call <code>super.dropAccept(event)</code>
280      * to get the default drag under effect implementation.
281      *
282      * @param event the information associated with the drop accept event
283      *
284      * @see DropTargetAdapter
285      * @see DropTargetEvent
286      */

287     public void dropAccept(DropTargetEvent event) {
288         if (currentOffset != -1) {
289             StyledText text = (StyledText) getControl();
290             text.setSelection(currentOffset);
291             currentOffset = -1;
292         }
293     }
294 }
295
Popular Tags