1
|
/*******************************************************************************
|
2
|
* Copyright (c) 2003, 2006 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.ui.internal.navigator;
|
12
|
|
13
|
import org.eclipse.jface.viewers.ILabelProvider;
|
14
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
15
|
import org.eclipse.swt.SWT;
|
16
|
import org.eclipse.swt.custom.TreeEditor;
|
17
|
import org.eclipse.swt.events.FocusAdapter;
|
18
|
import org.eclipse.swt.events.FocusEvent;
|
19
|
import org.eclipse.swt.graphics.Point;
|
20
|
import org.eclipse.swt.widgets.Composite;
|
21
|
import org.eclipse.swt.widgets.Event;
|
22
|
import org.eclipse.swt.widgets.Listener;
|
23
|
import org.eclipse.swt.widgets.Text;
|
24
|
import org.eclipse.swt.widgets.Tree;
|
25
|
import org.eclipse.swt.widgets.TreeItem;
|
26
|
import org.eclipse.ui.internal.navigator.extensions.INavigatorSiteEditor;
|
27
|
import org.eclipse.ui.navigator.CommonViewer;
|
28
|
|
29
|
|
30
|
/**
|
31
|
* A NavigatorSiteEditor is used to edit (i.e., rename) elements in a Navigator view. It displays a
|
32
|
* text editor box overlay on the Navigator tree widget.
|
33
|
*
|
34
|
* @since 3.2
|
35
|
*/
|
36
|
public class NavigatorSiteEditor implements INavigatorSiteEditor {
|
37
|
|
38
|
private Tree navigatorTree;
|
39
|
private TreeEditor treeEditor;
|
40
|
private Text textEditor;
|
41
|
private Composite textEditorParent;
|
42
|
private TextActionHandler textActionHandler;
|
43
|
private String text; // the text being edited
|
44
|
private CommonViewer commonViewer;
|
45
|
|
46
|
|
47
|
/**
|
48
|
* Creates an instance of a NavigatorSiteEditor.
|
49
|
*
|
50
|
* @param aCommonViewer
|
51
|
* the viewer this editor applies to
|
52
|
* @param navigatorTree
|
53
|
* the tree that is being edited
|
54
|
*/
|
55
|
public NavigatorSiteEditor(CommonViewer aCommonViewer, Tree navigatorTree) {
|
56
|
commonViewer = aCommonViewer;
|
57
|
this.navigatorTree = navigatorTree;
|
58
|
treeEditor = new TreeEditor(navigatorTree);
|
59
|
}
|
60
|
|
61
|
/**
|
62
|
* Creates the parent composite for the editor overlay.
|
63
|
*
|
64
|
* @return the parent composite for the editor overlay
|
65
|
*/
|
66
|
Composite createParent() {
|
67
|
Composite result = new Composite(navigatorTree, SWT.NONE);
|
68
|
TreeItem[] selectedItems = navigatorTree.getSelection();
|
69
|
treeEditor.horizontalAlignment = SWT.LEFT;
|
70
|
treeEditor.grabHorizontal = true;
|
71
|
treeEditor.setEditor(result, selectedItems[0]);
|
72
|
return result;
|
73
|
}
|
74
|
|
75
|
/**
|
76
|
* Creates the text editor widget.
|
77
|
*
|
78
|
* @param runnable
|
79
|
* the Runnable to execute when editing ends by the user pressing enter or clicking
|
80
|
* outside the text editor box.
|
81
|
*/
|
82
|
void createTextEditor(final Runnable runnable) {
|
83
|
// Create text editor parent. This draws a nice bounding rect.
|
84
|
textEditorParent = createParent();
|
85
|
textEditorParent.setVisible(false);
|
86
|
// RAP [bmichalik]: unsupported event type handler removed
|
87
|
// textEditorParent.addListener(SWT.Paint, new Listener() {
|
88
|
// public void handleEvent(Event e) {
|
89
|
// Point textSize = textEditor.getSize();
|
90
|
// Point parentSize = textEditorParent.getSize();
|
91
|
// e.gc.drawRectangle(0, 0, Math.min(textSize.x + 4, parentSize.x - 1), parentSize.y - 1);
|
92
|
// }
|
93
|
// });
|
94
|
|
95
|
// Create inner text editor.
|
96
|
textEditor = new Text(textEditorParent, SWT.NONE);
|
97
|
textEditorParent.setBackground(textEditor.getBackground());
|
98
|
textEditor.addListener(SWT.Modify, new Listener() {
|
99
|
public void handleEvent(Event e) {
|
100
|
Point textSize = textEditor.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
101
|
textSize.x += textSize.y; // Add extra space for new characters.
|
102
|
Point parentSize = textEditorParent.getSize();
|
103
|
textEditor.setBounds(2, 1, Math.min(textSize.x, parentSize.x - 4), parentSize.y - 2);
|
104
|
textEditorParent.redraw();
|
105
|
}
|
106
|
});
|
107
|
textEditor.addListener(SWT.Traverse, new Listener() {
|
108
|
public void handleEvent(Event event) {
|
109
|
//Workaround for Bug 20214 due to extra
|
110
|
//traverse events
|
111
|
switch (event.detail) {
|
112
|
case SWT.TRAVERSE_ESCAPE :
|
113
|
//Do nothing in this case
|
114
|
disposeTextWidget();
|
115
|
event.doit = true;
|
116
|
event.detail = SWT.TRAVERSE_NONE;
|
117
|
break;
|
118
|
case SWT.TRAVERSE_RETURN :
|
119
|
saveChangesAndDispose(runnable);
|
120
|
event.doit = true;
|
121
|
event.detail = SWT.TRAVERSE_NONE;
|
122
|
break;
|
123
|
}
|
124
|
}
|
125
|
});
|
126
|
textEditor.addFocusListener(new FocusAdapter() {
|
127
|
public void focusLost(FocusEvent fe) {
|
128
|
saveChangesAndDispose(runnable);
|
129
|
}
|
130
|
});
|
131
|
|
132
|
if (textActionHandler != null) {
|
133
|
textActionHandler.addText(textEditor);
|
134
|
}
|
135
|
}
|
136
|
|
137
|
/**
|
138
|
* Closes the text editor widget.
|
139
|
*/
|
140
|
void disposeTextWidget() {
|
141
|
if (textActionHandler != null) {
|
142
|
textActionHandler.removeText(textEditor);
|
143
|
}
|
144
|
if (textEditorParent != null) {
|
145
|
textEditorParent.dispose();
|
146
|
textEditorParent = null;
|
147
|
textEditor = null;
|
148
|
treeEditor.setEditor(null, null);
|
149
|
}
|
150
|
}
|
151
|
|
152
|
/**
|
153
|
* Displays a text editor overlay on the tree widget.
|
154
|
*
|
155
|
* @param runnable
|
156
|
* Runnable to execute when editing ends either by the user pressing enter or
|
157
|
* clicking outside the editor box.
|
158
|
*/
|
159
|
public void edit(Runnable runnable) {
|
160
|
IStructuredSelection selection = (IStructuredSelection) commonViewer.getSelection();
|
161
|
|
162
|
if (selection.size() != 1) {
|
163
|
return;
|
164
|
}
|
165
|
text = getLabel(selection.getFirstElement());
|
166
|
if (text == null) {
|
167
|
return;
|
168
|
}
|
169
|
// Make sure text editor is created only once. Simply reset text
|
170
|
// editor when action is executed more than once. Fixes bug 22269.
|
171
|
if (textEditorParent == null) {
|
172
|
createTextEditor(runnable);
|
173
|
}
|
174
|
textEditor.setText(text);
|
175
|
// Open text editor with initial size.
|
176
|
textEditorParent.setVisible(true);
|
177
|
Point textSize = textEditor.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
178
|
textSize.x += textSize.y; // Add extra space for new characters.
|
179
|
Point parentSize = textEditorParent.getSize();
|
180
|
textEditor.setBounds(2, 1, Math.min(textSize.x, parentSize.x - 4), parentSize.y - 2);
|
181
|
textEditorParent.redraw();
|
182
|
textEditor.selectAll();
|
183
|
textEditor.setFocus();
|
184
|
}
|
185
|
|
186
|
/**
|
187
|
* Returns the displayed label of the given element.
|
188
|
*
|
189
|
* @param element
|
190
|
* the element that is displayed in the navigator
|
191
|
* @return the displayed label of the given element.
|
192
|
*/
|
193
|
String getLabel(Object element) {
|
194
|
return ((ILabelProvider) commonViewer.getLabelProvider()).getText(element);
|
195
|
}
|
196
|
|
197
|
|
198
|
public String getText() {
|
199
|
return text;
|
200
|
}
|
201
|
|
202
|
/**
|
203
|
* Saves the changes and disposes of the text widget.
|
204
|
*
|
205
|
* @param runnable
|
206
|
* Runnable to execute
|
207
|
*/
|
208
|
void saveChangesAndDispose(final Runnable runnable) {
|
209
|
final String newText = textEditor.getText();
|
210
|
// Run this in an async to make sure that the operation that triggered
|
211
|
// this action is completed. Otherwise this leads to problems when the
|
212
|
// icon of the item being renamed is clicked (i.e., which causes the rename
|
213
|
// text widget to lose focus and trigger this method).
|
214
|
Runnable editRunnable = new Runnable() {
|
215
|
public void run() {
|
216
|
disposeTextWidget();
|
217
|
if (newText.length() > 0 && newText.equals(text) == false) {
|
218
|
text = newText;
|
219
|
runnable.run();
|
220
|
}
|
221
|
text = null;
|
222
|
}
|
223
|
};
|
224
|
navigatorTree.getShell().getDisplay().asyncExec(editRunnable);
|
225
|
}
|
226
|
|
227
|
|
228
|
public void setTextActionHandler(TextActionHandler actionHandler) {
|
229
|
textActionHandler = actionHandler;
|
230
|
}
|
231
|
|
232
|
}
|