Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDropTargetEffect.d @ 0:6dd524f61e62
add dwt win and basic java stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 02 Mar 2009 14:44:16 +0100 |
parents | |
children | d46287db17ed |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6dd524f61e62 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2007, 2008 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 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.eclipse.swt.dnd.TreeDropTargetEffect; | |
14 | |
15 import org.eclipse.swt.SWT; | |
16 import org.eclipse.swt.graphics.Point; | |
17 import org.eclipse.swt.internal.win32.OS; | |
18 import org.eclipse.swt.widgets.Event; | |
19 import org.eclipse.swt.widgets.Tree; | |
20 import org.eclipse.swt.widgets.TreeItem; | |
21 | |
22 import org.eclipse.swt.dnd.DropTargetEffect; | |
23 import org.eclipse.swt.dnd.DropTargetEvent; | |
24 import org.eclipse.swt.dnd.DND; | |
25 | |
26 import java.lang.all; | |
27 | |
28 /** | |
29 * This class provides a default drag under effect (eg. select, insert, scroll and expand) | |
30 * when a drag occurs over a <code>Tree</code>. | |
31 * | |
32 * <p>Classes that wish to provide their own drag under effect for a <code>Tree</code> | |
33 * can extend the <code>TreeDropTargetEffect</code> class and override any applicable methods | |
34 * in <code>TreeDropTargetEffect</code> to display their own drag under effect.</p> | |
35 * | |
36 * Subclasses that override any methods of this class must call the corresponding | |
37 * <code>super</code> method to get the default drag under effect implementation. | |
38 * | |
39 * <p>The feedback value is either one of the FEEDBACK constants defined in | |
40 * class <code>DND</code> which is applicable to instances of this class, | |
41 * or it must be built by <em>bitwise OR</em>'ing together | |
42 * (that is, using the <code>int</code> "|" operator) two or more | |
43 * of those <code>DND</code> effect constants. | |
44 * </p> | |
45 * <p> | |
46 * <dl> | |
47 * <dt><b>Feedback:</b></dt> | |
48 * <dd>FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE, FEEDBACK_INSERT_AFTER, FEEDBACK_EXPAND, FEEDBACK_SCROLL</dd> | |
49 * </dl> | |
50 * </p><p> | |
51 * Note: Only one of the styles FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE or | |
52 * FEEDBACK_INSERT_AFTER may be specified. | |
53 * </p> | |
54 * | |
55 * @see DropTargetAdapter | |
56 * @see DropTargetEvent | |
57 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
58 * | |
59 * @since 3.3 | |
60 */ | |
61 public class TreeDropTargetEffect : DropTargetEffect { | |
62 static final int SCROLL_HYSTERESIS = 200; // milli seconds | |
63 static final int EXPAND_HYSTERESIS = 1000; // milli seconds | |
64 | |
65 int /*long*/ dropIndex; | |
66 int scrollIndex; | |
67 long scrollBeginTime; | |
68 int /*long*/ expandIndex; | |
69 long expandBeginTime; | |
70 TreeItem insertItem; | |
71 bool insertBefore; | |
72 | |
73 /** | |
74 * Creates a new <code>TreeDropTargetEffect</code> to handle the drag under effect on the specified | |
75 * <code>Tree</code>. | |
76 * | |
77 * @param tree the <code>Tree</code> over which the user positions the cursor to drop the data | |
78 */ | |
79 public this(Tree tree) { | |
80 super(tree); | |
81 } | |
82 | |
83 int checkEffect(int effect) { | |
84 // Some effects are mutually exclusive. Make sure that only one of the mutually exclusive effects has been specified. | |
85 if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE; | |
86 if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER; | |
87 return effect; | |
88 } | |
89 | |
90 /** | |
91 * This implementation of <code>dragEnter</code> provides a default drag under effect | |
92 * for the feedback specified in <code>event.feedback</code>. | |
93 * | |
94 * For additional information see <code>DropTargetAdapter.dragEnter</code>. | |
95 * | |
96 * Subclasses that override this method should call <code>super.dragEnter(event)</code> | |
97 * to get the default drag under effect implementation. | |
98 * | |
99 * @param event the information associated with the drag enter event | |
100 * | |
101 * @see DropTargetAdapter | |
102 * @see DropTargetEvent | |
103 */ | |
104 public void dragEnter(DropTargetEvent event) { | |
105 dropIndex = -1; | |
106 insertItem = null; | |
107 expandBeginTime = 0; | |
108 expandIndex = -1; | |
109 scrollBeginTime = 0; | |
110 scrollIndex = -1; | |
111 } | |
112 | |
113 /** | |
114 * This implementation of <code>dragLeave</code> provides a default drag under effect | |
115 * for the feedback specified in <code>event.feedback</code>. | |
116 * | |
117 * For additional information see <code>DropTargetAdapter.dragLeave</code>. | |
118 * | |
119 * Subclasses that override this method should call <code>super.dragLeave(event)</code> | |
120 * to get the default drag under effect implementation. | |
121 * | |
122 * @param event the information associated with the drag leave event | |
123 * | |
124 * @see DropTargetAdapter | |
125 * @see DropTargetEvent | |
126 */ | |
127 public void dragLeave(DropTargetEvent event) { | |
128 Tree tree = cast(Tree) control; | |
129 auto handle = tree.handle; | |
130 if (dropIndex !is -1) { | |
131 TVITEM tvItem; | |
132 tvItem.hItem = cast(HTREEITEM) dropIndex; | |
133 tvItem.mask = OS.TVIF_STATE; | |
134 tvItem.stateMask = OS.TVIS_DROPHILITED; | |
135 tvItem.state = 0; | |
136 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); | |
137 dropIndex = -1; | |
138 } | |
139 if (insertItem !is null) { | |
140 tree.setInsertMark(null, false); | |
141 insertItem = null; | |
142 } | |
143 expandBeginTime = 0; | |
144 expandIndex = -1; | |
145 scrollBeginTime = 0; | |
146 scrollIndex = -1; | |
147 } | |
148 | |
149 /** | |
150 * This implementation of <code>dragOver</code> provides a default drag under effect | |
151 * for the feedback specified in <code>event.feedback</code>. | |
152 * | |
153 * For additional information see <code>DropTargetAdapter.dragOver</code>. | |
154 * | |
155 * Subclasses that override this method should call <code>super.dragOver(event)</code> | |
156 * to get the default drag under effect implementation. | |
157 * | |
158 * @param event the information associated with the drag over event | |
159 * | |
160 * @see DropTargetAdapter | |
161 * @see DropTargetEvent | |
162 * @see DND#FEEDBACK_SELECT | |
163 * @see DND#FEEDBACK_INSERT_BEFORE | |
164 * @see DND#FEEDBACK_INSERT_AFTER | |
165 * @see DND#FEEDBACK_SCROLL | |
166 */ | |
167 public void dragOver(DropTargetEvent event) { | |
168 Tree tree = cast(Tree) getControl(); | |
169 int effect = checkEffect(event.feedback); | |
170 auto handle = tree.handle; | |
171 Point coordinates = new Point(event.x, event.y); | |
172 coordinates = tree.toControl(coordinates); | |
173 TVHITTESTINFO lpht; | |
174 lpht.pt.x = coordinates.x; | |
175 lpht.pt.y = coordinates.y; | |
176 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); | |
177 auto hItem = lpht.hItem; | |
178 if ((effect & DND.FEEDBACK_SCROLL) is 0) { | |
179 scrollBeginTime = 0; | |
180 scrollIndex = -1; | |
181 } else { | |
182 if (hItem !is cast(HTREEITEM)-1 && cast(HTREEITEM)scrollIndex is hItem && scrollBeginTime !is 0) { | |
183 if (System.currentTimeMillis() >= scrollBeginTime) { | |
184 auto topItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); | |
185 auto nextItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem); | |
186 bool scroll = true; | |
187 if (hItem is topItem) { | |
188 scroll = nextItem !is null; | |
189 } else { | |
190 RECT itemRect; | |
191 if (OS.TreeView_GetItemRect (handle, nextItem, &itemRect, true)) { | |
192 RECT rect; | |
193 OS.GetClientRect (handle, &rect); | |
194 POINT pt; | |
195 pt.x = itemRect.left; | |
196 pt.y = itemRect.top; | |
197 if (OS.PtInRect (&rect, pt)) { | |
198 pt.y = itemRect.bottom; | |
199 if (OS.PtInRect (&rect, pt)) scroll = false; | |
200 } | |
201 } | |
202 } | |
203 if (scroll) { | |
204 OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, nextItem); | |
205 tree.redraw(); | |
206 } | |
207 scrollBeginTime = 0; | |
208 scrollIndex = -1; | |
209 } | |
210 } else { | |
211 scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS; | |
212 scrollIndex = cast(int)hItem; | |
213 } | |
214 } | |
215 if ((effect & DND.FEEDBACK_EXPAND) is 0) { | |
216 expandBeginTime = 0; | |
217 expandIndex = -1; | |
218 } else { | |
219 if (cast(int)hItem !is -1 && expandIndex is cast(int)hItem && expandBeginTime !is 0) { | |
220 if (System.currentTimeMillis() >= expandBeginTime) { | |
221 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem) !is 0) { | |
222 TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem); | |
223 if (item !is null && !item.getExpanded()) { | |
224 item.setExpanded(true); | |
225 tree.redraw(); | |
226 Event expandEvent = new Event (); | |
227 expandEvent.item = item; | |
228 tree.notifyListeners(SWT.Expand, expandEvent); | |
229 } | |
230 } | |
231 expandBeginTime = 0; | |
232 expandIndex = -1; | |
233 } | |
234 } else { | |
235 expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS; | |
236 expandIndex = cast(int)hItem; | |
237 } | |
238 } | |
239 if (dropIndex !is -1 && (dropIndex !is cast(int)hItem || (effect & DND.FEEDBACK_SELECT) is 0)) { | |
240 TVITEM tvItem; | |
241 tvItem.hItem = cast(HTREEITEM) dropIndex; | |
242 tvItem.mask = OS.TVIF_STATE; | |
243 tvItem.stateMask = OS.TVIS_DROPHILITED; | |
244 tvItem.state = 0; | |
245 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); | |
246 dropIndex = -1; | |
247 } | |
248 if (cast(int)hItem !is -1 && cast(int)hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) { | |
249 TVITEM tvItem; | |
250 tvItem.hItem = cast(HTREEITEM) hItem; | |
251 tvItem.mask = OS.TVIF_STATE; | |
252 tvItem.stateMask = OS.TVIS_DROPHILITED; | |
253 tvItem.state = OS.TVIS_DROPHILITED; | |
254 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); | |
255 dropIndex = cast(int)hItem; | |
256 } | |
257 if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0 || (effect & DND.FEEDBACK_INSERT_AFTER) !is 0) { | |
258 bool before = (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0; | |
259 /* | |
260 * Bug in Windows. When TVM_SETINSERTMARK is used to set | |
261 * an insert mark for a tree and an item is expanded or | |
262 * collapsed near the insert mark, the tree does not redraw | |
263 * the insert mark properly. The fix is to hide and show | |
264 * the insert mark whenever an item is expanded or collapsed. | |
265 * Since the insert mark can not be queried from the tree, | |
266 * use the Tree API rather than calling the OS directly. | |
267 */ | |
268 TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem); | |
269 if (item !is null) { | |
270 if (item !is insertItem || before !is insertBefore) { | |
271 tree.setInsertMark(item, before); | |
272 } | |
273 insertItem = item; | |
274 insertBefore = before; | |
275 } else { | |
276 if (insertItem !is null) { | |
277 tree.setInsertMark(null, false); | |
278 } | |
279 insertItem = null; | |
280 } | |
281 } else { | |
282 if (insertItem !is null) { | |
283 tree.setInsertMark(null, false); | |
284 } | |
285 insertItem = null; | |
286 } | |
287 } | |
288 } |