Bonjour à tous,

Je pensais utiliser SWT pour gagner du temps sur une interface simple, pensant que, comme la plateforme est attractive et existe depuis un certain temps, la plupart des contrôles graphiques les plus répandus doivent déjà exister.

Or, je m'aperçois qu'il est pourtant très difficile de trouver du code pré-existant et des contrôles personnalisés en dehors des "snippets" de base.

J'ai donc entrepris de développer moi-même mon "Treeview"
qui, pour faire court, possède des fonctionnalités identiques à celles de (par exemple) l'arbre qui affiche les fichiers de projet dans Eclipse, ou encore l'arbre des répertoires dans Windows :



- Renommage: un clic sur un élément le transforme en zone de texte éditable, et permet de le renommer.
- Glisser-déposer: On peut glisser et déposer les feuilles de l'arbre, qui représentent des fichiers. On peut aussi glisser-déposer les dossiers. Ceci permet de changer l'ordre d'affichage mais aussi de déplacer rapidement un élément dans un sous-dossier (du classique!).
- Sous-dossiers: L'arbre contient des noeuds de deux types : 1) Les dossiers ou sous-dossiers (un dossier peut contenir des sous-dossiers mais aussi des fichiers normaux). 2) Les fichiers. Remarque: Ceux-ci sont un peu particuliers. Ils n'existent pas seulement en tant que feuilles de l'arbre, mais peuvent eux aussi "contenir" d'autres fichiers -- Pour mieux comprendre, imaginez les packages: ils peuvent être contenus non seulement dans un dossier, mais aussi dans un autre package.


Pour l'instant j'ai essayé de fusionner deux snippets existants dans les tutoriaux SWT: Celui permettant le renommage et celui permettant le glisser-déposer.

Evidemment, ce serait trop simple : Quand on renomme un dossier puis qu'on déplace ses enfants, le programme plante en se plaignant qu'un des composites a déjà été "disposed". Je n'arrive pas à localiser dans le code l'endroit où le renommage casse les références et dispose la feuille concernée.

Est-ce que quelqu'un voit le problème?

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
 
 
import org.eclipse.swt.*;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
 
public class AdvancedTreeView {
 
 
	private void buildTree(Tree tree) {
		for (int i = 0; i < 3; i++) {
			TreeItem item = new TreeItem(tree, SWT.NONE);
			item.setText("item "+i);
			for (int j = 0; j < 3; j++) {
				TreeItem subItem = new TreeItem(item, SWT.NONE);
				subItem.setText("item "+i+" "+j);
				for (int k = 0; k < 3; k++) {
					TreeItem subsubItem = new TreeItem(subItem, SWT.NONE);
					subsubItem.setText("item "+i+" "+j+" "+k);
				}
			}
		}
 
	}
	public AdvancedTreeView(final Composite parent) {
		//final Display display = new Display ();
 
		final Tree tree = new Tree(parent, SWT.BORDER);
 
		buildTree(tree); ///DEBUG !
 
		/////////////////
		//
		//		MANAGE DRAG AND DROP
		//
		//////////////////
		Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
		int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
 
		final DragSource source = new DragSource (tree, operations);
		source.setTransfer(types);
		final TreeItem[] dragSourceItem = new TreeItem[1];
		source.addDragListener (new DragSourceListener () {
			public void dragStart(DragSourceEvent event) {
				TreeItem[] selection = tree.getSelection();
				if (selection.length > 0 && selection[0].getItemCount() == 0) {
					event.doit = true;
					dragSourceItem[0] = selection[0];
				} else {
					event.doit = false;
				}
			};
			public void dragSetData (DragSourceEvent event) {
				event.data = dragSourceItem[0].getText();
			}
			public void dragFinished(DragSourceEvent event) {
				if (event.detail == DND.DROP_MOVE)
					dragSourceItem[0].dispose();
					dragSourceItem[0] = null;
			}
		});
 
		DropTarget target = new DropTarget(tree, operations);
		target.setTransfer(types);
		target.addDropListener (new DropTargetAdapter() {
			public void dragOver(DropTargetEvent event) {
				event.feedback = DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL;
				if (event.item != null) {
					TreeItem item = (TreeItem)event.item;
 
					Point pt = parent.getDisplay().map(null, tree, event.x, event.y);
					Rectangle bounds = item.getBounds();
					if (pt.y < bounds.y + bounds.height/3) {
						event.feedback |= DND.FEEDBACK_INSERT_BEFORE;
					} else if (pt.y > bounds.y + 2*bounds.height/3) {
						event.feedback |= DND.FEEDBACK_INSERT_AFTER;
					} else {
						event.feedback |= DND.FEEDBACK_SELECT;
					}
				}
			}
			public void drop(DropTargetEvent event) {
				if (event.data == null) {
					event.detail = DND.DROP_NONE;
					return;
				}
				String text = (String)event.data;
				if (event.item == null) {
					TreeItem item = new TreeItem(tree, SWT.NONE);
					item.setText(text);
				} else {
					TreeItem item = (TreeItem)event.item;
					Point pt = parent.getDisplay().map(null, tree, event.x, event.y);
					Rectangle bounds = item.getBounds();
					TreeItem parent = item.getParentItem();
					if (parent != null) {
						TreeItem[] items = parent.getItems();
						int index = 0;
						for (int i = 0; i < items.length; i++) {
							if (items[i] == item) {
								index = i;
								break;
							}
						}
						if (pt.y < bounds.y + bounds.height/3) {
							TreeItem newItem = new TreeItem(parent, SWT.NONE, index);
							newItem.setText(text);
						} else if (pt.y > bounds.y + 2*bounds.height/3) {
							TreeItem newItem = new TreeItem(parent, SWT.NONE, index+1);
							newItem.setText(text);
						} else {
							TreeItem newItem = new TreeItem(item, SWT.NONE);
							newItem.setText(text);
						}
 
					} else {
						TreeItem[] items = tree.getItems();
						int index = 0;
						for (int i = 0; i < items.length; i++) {
							if (items[i] == item) {
								index = i;
								break;
							}
						}
						if (pt.y < bounds.y + bounds.height/3) {
							TreeItem newItem = new TreeItem(tree, SWT.NONE, index);
							newItem.setText(text);
						} else if (pt.y > bounds.y + 2*bounds.height/3) {
							TreeItem newItem = new TreeItem(tree, SWT.NONE, index+1);
							newItem.setText(text);
						} else {
							TreeItem newItem = new TreeItem(item, SWT.NONE);
							newItem.setText(text);
						}
					}
 
 
				}
			}
		});
 
		/////////////////
		//
		//		MANAGE RENAMING
		//
		//////////////////		
		final TreeItem [] lastItem = new TreeItem [1];
		final TreeEditor editor = new TreeEditor (tree);
		final Color black = parent.getDisplay().getSystemColor (SWT.COLOR_BLACK);
		tree.addListener (SWT.Selection, new Listener () {
			public void handleEvent (Event event) {
				final TreeItem item = (TreeItem) event.item;
				if (item != null && item == lastItem [0]) {
					boolean showBorder = true;
					final Composite composite = new Composite (tree, SWT.NONE);
					if (showBorder) composite.setBackground (black);
					final Text text = new Text (composite, SWT.NONE);
					final int inset = showBorder ? 1 : 0;
					composite.addListener (SWT.Resize, new Listener () {
						public void handleEvent (Event e) {
							Rectangle rect = composite.getClientArea ();
							text.setBounds (rect.x + inset, rect.y + inset, rect.width - inset * 2, rect.height - inset * 2);
						}
					});
					Listener textListener = new Listener () {
						public void handleEvent (final Event e) {
							switch (e.type) {
								case SWT.FocusOut:
									item.setText (text.getText ());
									composite.dispose ();
									break;
								case SWT.Verify:
									String newText = text.getText ();
									String leftText = newText.substring (0, e.start);
									String rightText = newText.substring (e.end, newText.length ());
									GC gc = new GC (text);
									Point size = gc.textExtent (leftText + e.text + rightText);
									gc.dispose ();
									size = text.computeSize (size.x, SWT.DEFAULT);
									editor.horizontalAlignment = SWT.LEFT;
									Rectangle itemRect = item.getBounds (), rect = tree.getClientArea ();
									editor.minimumWidth = Math.max (size.x, itemRect.width) + inset * 2;
									int left = itemRect.x, right = rect.x + rect.width;
									editor.minimumWidth = Math.min (editor.minimumWidth, right - left);
									editor.minimumHeight = size.y + inset * 2;
									editor.layout ();
									break;
								case SWT.Traverse:
									switch (e.detail) {
										case SWT.TRAVERSE_RETURN:
											item.setText (text.getText ());
											//FALL THROUGH
										case SWT.TRAVERSE_ESCAPE:
											composite.dispose ();
											e.doit = false;
									}
									break;
							}
						}
					};
					text.addListener (SWT.FocusOut, textListener);
					text.addListener (SWT.Traverse, textListener);
					text.addListener (SWT.Verify, textListener);
					editor.setEditor (composite, item);
					text.setText (item.getText ());
					text.selectAll ();
					text.setFocus ();
				}
				lastItem [0] = item;
			}
		});
 
	}
 
	public static void main (String [] args) {
 
		final Display display = new Display ();
		final Shell shell = new Shell (display);
		shell.setLayout(new FillLayout());
 
		AdvancedTreeView tree = new AdvancedTreeView(shell);
 
		shell.setSize (400, 400);
		shell.open ();
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		display.dispose ();
	}
}