]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 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.jdt.internal.ui.refactoring.reorg; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.HashMap; | |
15 | import java.util.HashSet; | |
16 | import java.util.Iterator; | |
17 | import java.util.List; | |
18 | import java.util.Map; | |
19 | import java.util.Set; | |
20 | ||
21 | import org.eclipse.swt.SWT; | |
22 | import org.eclipse.swt.custom.CLabel; | |
23 | import org.eclipse.swt.custom.SashForm; | |
24 | import org.eclipse.swt.custom.ViewForm; | |
25 | import org.eclipse.swt.events.SelectionAdapter; | |
26 | import org.eclipse.swt.events.SelectionEvent; | |
27 | import org.eclipse.swt.graphics.Image; | |
28 | import org.eclipse.swt.layout.GridData; | |
29 | import org.eclipse.swt.layout.GridLayout; | |
30 | import org.eclipse.swt.widgets.Button; | |
31 | import org.eclipse.swt.widgets.Composite; | |
32 | import org.eclipse.swt.widgets.Control; | |
33 | import org.eclipse.swt.widgets.Label; | |
34 | import org.eclipse.swt.widgets.Shell; | |
35 | import org.eclipse.swt.widgets.Text; | |
36 | import org.eclipse.swt.widgets.Tree; | |
37 | import org.eclipse.swt.widgets.TreeItem; | |
38 | ||
39 | import org.eclipse.core.runtime.Assert; | |
40 | import org.eclipse.core.runtime.IStatus; | |
41 | ||
42 | import org.eclipse.jface.dialogs.Dialog; | |
43 | import org.eclipse.jface.dialogs.IDialogConstants; | |
44 | import org.eclipse.jface.dialogs.StatusDialog; | |
45 | import org.eclipse.jface.preference.IPreferenceStore; | |
46 | import org.eclipse.jface.resource.ImageDescriptor; | |
47 | import org.eclipse.jface.resource.JFaceResources; | |
48 | import org.eclipse.jface.viewers.DoubleClickEvent; | |
49 | import org.eclipse.jface.viewers.IDoubleClickListener; | |
50 | import org.eclipse.jface.viewers.ISelection; | |
51 | import org.eclipse.jface.viewers.ISelectionChangedListener; | |
52 | import org.eclipse.jface.viewers.IStructuredSelection; | |
53 | import org.eclipse.jface.viewers.ITreeContentProvider; | |
54 | import org.eclipse.jface.viewers.SelectionChangedEvent; | |
55 | import org.eclipse.jface.viewers.StructuredSelection; | |
56 | import org.eclipse.jface.viewers.Viewer; | |
57 | import org.eclipse.jface.window.Window; | |
58 | import org.eclipse.jface.wizard.IWizardPage; | |
59 | ||
60 | import org.eclipse.jface.text.Document; | |
61 | import org.eclipse.jface.text.source.SourceViewer; | |
62 | ||
63 | import org.eclipse.ui.PlatformUI; | |
64 | import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; | |
65 | ||
66 | import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; | |
67 | import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; | |
68 | import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; | |
69 | ||
70 | import org.eclipse.jdt.core.ICompilationUnit; | |
71 | import org.eclipse.jdt.core.IField; | |
72 | import org.eclipse.jdt.core.IJavaElement; | |
73 | import org.eclipse.jdt.core.ILocalVariable; | |
74 | import org.eclipse.jdt.core.IMember; | |
75 | import org.eclipse.jdt.core.IMethod; | |
76 | import org.eclipse.jdt.core.ISourceRange; | |
77 | import org.eclipse.jdt.core.IType; | |
78 | import org.eclipse.jdt.core.JavaModelException; | |
79 | ||
80 | import org.eclipse.jdt.internal.corext.refactoring.Checks; | |
81 | import org.eclipse.jdt.internal.corext.refactoring.rename.RenameCompilationUnitProcessor; | |
82 | import org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor; | |
83 | import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil; | |
84 | import org.eclipse.jdt.internal.corext.util.Messages; | |
85 | ||
86 | import org.eclipse.jdt.ui.JavaElementComparator; | |
87 | import org.eclipse.jdt.ui.JavaElementLabelProvider; | |
88 | import org.eclipse.jdt.ui.JavaElementLabels; | |
89 | import org.eclipse.jdt.ui.PreferenceConstants; | |
90 | import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration; | |
91 | import org.eclipse.jdt.ui.text.JavaTextTools; | |
92 | ||
93 | import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; | |
94 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
95 | import org.eclipse.jdt.internal.ui.JavaPluginImages; | |
96 | import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; | |
97 | import org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler; | |
98 | import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer; | |
99 | import org.eclipse.jdt.internal.ui.refactoring.RefactoringMessages; | |
100 | import org.eclipse.jdt.internal.ui.util.ExceptionHandler; | |
101 | import org.eclipse.jdt.internal.ui.util.SWTUtil; | |
102 | import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider; | |
103 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; | |
104 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener; | |
105 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil; | |
106 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField; | |
107 | ||
108 | /** | |
109 | * | |
110 | * Wizard page for displaying a tree of similarly named elements renamed along with a | |
111 | * type. | |
112 | * | |
113 | * @since 3.2 | |
114 | * | |
115 | */ | |
116 | class RenameTypeWizardSimilarElementsPage extends UserInputWizardPage { | |
117 | ||
118 | public static class EditElementDialog extends StatusDialog implements IDialogFieldListener { | |
119 | ||
120 | private StringDialogField fNameField; | |
121 | private IJavaElement fElementToEdit; | |
122 | ||
123 | public EditElementDialog(Shell parent, IJavaElement elementToEdit, String newName) { | |
124 | super(parent); | |
125 | setTitle(RefactoringMessages.RenameTypeWizardSimilarElementsPage_change_element_name); | |
126 | fElementToEdit= elementToEdit; | |
127 | ||
128 | fNameField= new StringDialogField(); | |
129 | fNameField.setDialogFieldListener(this); | |
130 | fNameField.setLabelText(RefactoringMessages.RenameTypeWizardSimilarElementsPage_enter_new_name); | |
131 | ||
132 | fNameField.setText(newName); | |
133 | } | |
134 | ||
135 | /* | |
136 | * @see org.eclipse.jface.dialogs.Dialog#isResizable() | |
137 | * @since 3.4 | |
138 | */ | |
139 | @Override | |
140 | protected boolean isResizable() { | |
141 | return true; | |
142 | } | |
143 | ||
144 | /* | |
145 | * (non-Javadoc) | |
146 | * | |
147 | * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) | |
148 | */ | |
149 | @Override | |
150 | protected Control createDialogArea(Composite parent) { | |
151 | final Composite composite= (Composite) super.createDialogArea(parent); | |
152 | LayoutUtil.doDefaultLayout(composite, new DialogField[] { fNameField }, true, SWT.DEFAULT, SWT.DEFAULT); | |
153 | fNameField.postSetFocusOnDialogField(parent.getDisplay()); | |
154 | ||
155 | LayoutUtil.setWidthHint(fNameField.getLabelControl(null), convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH)); | |
156 | Text text= fNameField.getTextControl(null); | |
157 | LayoutUtil.setHorizontalGrabbing(text); | |
158 | TextFieldNavigationHandler.install(text); | |
159 | ||
160 | Dialog.applyDialogFont(composite); | |
161 | return composite; | |
162 | } | |
163 | ||
164 | /* | |
165 | * (non-Javadoc) | |
166 | * | |
167 | * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener#dialogFieldChanged(org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField) | |
168 | */ | |
169 | public void dialogFieldChanged(DialogField field) { | |
170 | if (field == fNameField) | |
171 | updateStatus(validateSettings()); | |
172 | } | |
173 | ||
174 | private IStatus validateSettings() { | |
175 | final String name= fNameField.getText(); | |
176 | if (name.length() == 0) { | |
177 | return new StatusInfo(IStatus.ERROR, RefactoringMessages.RenameTypeWizardSimilarElementsPage_name_empty); | |
178 | } | |
179 | IStatus status= JavaConventionsUtil.validateIdentifier(name, fElementToEdit); | |
180 | if (status.matches(IStatus.ERROR)) | |
181 | return status; | |
182 | if (!Checks.startsWithLowerCase(name)) | |
183 | return new StatusInfo(IStatus.WARNING, RefactoringMessages.RenameTypeWizardSimilarElementsPage_name_should_start_lowercase); | |
184 | ||
185 | if (fElementToEdit instanceof IMember && ((IMember) fElementToEdit).getDeclaringType() != null) { | |
186 | IType type= ((IMember) fElementToEdit).getDeclaringType(); | |
187 | if (fElementToEdit instanceof IField) { | |
188 | final IField f= type.getField(name); | |
189 | if (f.exists()) | |
190 | return new StatusInfo(IStatus.ERROR, RefactoringMessages.RenameTypeWizardSimilarElementsPage_field_exists); | |
191 | } | |
192 | if (fElementToEdit instanceof IMethod) { | |
193 | final IMethod m= type.getMethod(name, ((IMethod) fElementToEdit).getParameterTypes()); | |
194 | if (m.exists()) | |
195 | return new StatusInfo(IStatus.ERROR, RefactoringMessages.RenameTypeWizardSimilarElementsPage_method_exists); | |
196 | } | |
197 | } | |
198 | ||
199 | // cannot check local variables; no .getLocalVariable(String) in IMember | |
200 | ||
201 | return StatusInfo.OK_STATUS; | |
202 | } | |
203 | ||
204 | public String getNewName() { | |
205 | return fNameField.getText(); | |
206 | } | |
207 | } | |
208 | ||
209 | private static class SimilarElementTreeContentProvider implements ITreeContentProvider { | |
210 | ||
211 | private Map<IJavaElement, Set<IJavaElement>> fTreeElementMap; | |
212 | private Set<ICompilationUnit> fTopLevelElements; | |
213 | ||
214 | /* | |
215 | * @see ITreeContentProvider#getChildren(Object) | |
216 | */ | |
217 | public Object[] getChildren(Object parentElement) { | |
218 | final Set<IJavaElement> children= fTreeElementMap.get(parentElement); | |
219 | if (children != null) | |
220 | return children.toArray(); | |
221 | else | |
222 | return new Object[0]; | |
223 | } | |
224 | ||
225 | /* | |
226 | * @see ITreeContentProvider#getParent(Object) | |
227 | */ | |
228 | public Object getParent(Object element) { | |
229 | if (element instanceof IMember || element instanceof ILocalVariable) { | |
230 | return ((IJavaElement) element).getParent(); | |
231 | } | |
232 | if (element instanceof ICompilationUnit) | |
233 | return null; | |
234 | Assert.isTrue(false, "Should not get here"); //$NON-NLS-1$ | |
235 | return null; | |
236 | } | |
237 | ||
238 | /* | |
239 | * @see ITreeContentProvider#hasChildren(Object) | |
240 | */ | |
241 | public boolean hasChildren(Object element) { | |
242 | return fTreeElementMap.containsKey(element); | |
243 | } | |
244 | ||
245 | /* | |
246 | * @see IStructuredContentProvider#getElements(Object) | |
247 | */ | |
248 | public Object[] getElements(Object inputElement) { | |
249 | Assert.isTrue(inputElement == null || inputElement instanceof Map); | |
250 | return fTopLevelElements.toArray(); | |
251 | } | |
252 | ||
253 | /* | |
254 | * @see IContentProvider#dispose() | |
255 | */ | |
256 | public void dispose() { | |
257 | fTreeElementMap.clear(); | |
258 | fTreeElementMap= null; | |
259 | fTopLevelElements= null; | |
260 | } | |
261 | ||
262 | /* | |
263 | * @see IContentProvider#inputChanged(Viewer, Object, Object) | |
264 | */ | |
265 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { | |
266 | Assert.isTrue(newInput == null || newInput instanceof Map); | |
267 | if (newInput == null) | |
268 | return; | |
269 | @SuppressWarnings("unchecked") | |
270 | final Map<IJavaElement, String> similarElementsMap= (Map<IJavaElement, String>) newInput; | |
271 | final IJavaElement[] similarElements= similarElementsMap.keySet().toArray(new IJavaElement[0]); | |
272 | fTreeElementMap= new HashMap<IJavaElement, Set<IJavaElement>>(); | |
273 | fTopLevelElements= new HashSet<ICompilationUnit>(); | |
274 | for (int i= 0; i < similarElements.length; i++) { | |
275 | final IType declaring= (IType) similarElements[i].getAncestor(IJavaElement.TYPE); | |
276 | if (similarElements[i] instanceof IMember) { | |
277 | // methods, fields, initializers, inner types | |
278 | addToMap(declaring, similarElements[i]); | |
279 | } else { | |
280 | // local variables | |
281 | final IJavaElement parent= similarElements[i].getParent(); | |
282 | if (parent instanceof IMember) { | |
283 | // parent is a method or an initializer | |
284 | addToMap(parent, similarElements[i]); | |
285 | addToMap(declaring, parent); | |
286 | } | |
287 | } | |
288 | handleDeclaring(declaring); | |
289 | } | |
290 | } | |
291 | ||
292 | private void handleDeclaring(final IJavaElement someType) { | |
293 | ||
294 | final IJavaElement enclosing= someType.getParent(); | |
295 | if (enclosing instanceof ICompilationUnit) { | |
296 | fTopLevelElements.add((ICompilationUnit) enclosing); | |
297 | addToMap(someType.getParent(), someType); | |
298 | } else { | |
299 | addToMap(enclosing, someType); | |
300 | handleDeclaring(enclosing); | |
301 | } | |
302 | } | |
303 | ||
304 | private void addToMap(final IJavaElement key, final IJavaElement element) { | |
305 | Set<IJavaElement> elements= fTreeElementMap.get(key); | |
306 | if (elements == null) { | |
307 | elements= new HashSet<IJavaElement>(); | |
308 | fTreeElementMap.put(key, elements); | |
309 | } | |
310 | elements.add(element); | |
311 | } | |
312 | ||
313 | } | |
314 | ||
315 | private static class SimilarLabelProvider extends JavaElementLabelProvider { | |
316 | ||
317 | private Map<ImageDescriptor, Image> fDescriptorImageMap= new HashMap<ImageDescriptor, Image>(); | |
318 | private Map<IJavaElement, String> fElementToNewName; | |
319 | ||
320 | public SimilarLabelProvider() { | |
321 | super(JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_SMALL_ICONS); | |
322 | } | |
323 | ||
324 | public void initialize(Map<IJavaElement, String> elementToNewName) { | |
325 | this.fElementToNewName= elementToNewName; | |
326 | } | |
327 | ||
328 | @Override | |
329 | public void dispose() { | |
330 | for (Iterator<Image> iter= fDescriptorImageMap.values().iterator(); iter.hasNext();) { | |
331 | Image image= iter.next(); | |
332 | image.dispose(); | |
333 | } | |
334 | super.dispose(); | |
335 | } | |
336 | ||
337 | private Image manageImageDescriptor(ImageDescriptor descriptor) { | |
338 | Image image= fDescriptorImageMap.get(descriptor); | |
339 | if (image == null) { | |
340 | image= descriptor.createImage(); | |
341 | fDescriptorImageMap.put(descriptor, image); | |
342 | } | |
343 | return image; | |
344 | } | |
345 | ||
346 | @Override | |
347 | public Image getImage(Object element) { | |
348 | if (isSimilarElement(element)) | |
349 | return manageImageDescriptor(JavaPluginImages.DESC_OBJS_DEFAULT_CHANGE); | |
350 | return super.getImage(element); | |
351 | } | |
352 | ||
353 | public Image getJavaImage(Object element) { | |
354 | return super.getImage(element); | |
355 | } | |
356 | ||
357 | @Override | |
358 | public String getText(Object element) { | |
359 | if (isSimilarElement(element)) { | |
360 | return Messages.format(RefactoringMessages.RenameTypeWizardSimilarElementsPage_rename_to, new String[] { super.getText(element), fElementToNewName.get(element) } ); | |
361 | } | |
362 | return super.getText(element); | |
363 | } | |
364 | ||
365 | private boolean isSimilarElement(Object element) { | |
366 | return fElementToNewName.containsKey(element); | |
367 | } | |
368 | ||
369 | } | |
370 | ||
371 | private static class SimilarElementComparator extends JavaElementComparator { | |
372 | ||
373 | /* | |
374 | * (non-Javadoc) | |
375 | * @see org.eclipse.jdt.ui.JavaElementSorter#category(java.lang.Object) | |
376 | */ | |
377 | @Override | |
378 | public int category(Object element) { | |
379 | ||
380 | /* | |
381 | * We'd like to present the elements in the same order as they | |
382 | * appear in the source. This can be achieved by assigning a | |
383 | * distinct category to every element; the category being derived | |
384 | * from the source position of the element. | |
385 | */ | |
386 | ||
387 | ISourceRange sourceRange= null; | |
388 | if (element instanceof IMember) { | |
389 | IMember member= (IMember) element; | |
390 | try { | |
391 | sourceRange= member.getNameRange(); | |
392 | } catch (JavaModelException e) { | |
393 | // fall through | |
394 | } | |
395 | } | |
396 | if (element instanceof ILocalVariable) { | |
397 | ILocalVariable var= (ILocalVariable) element; | |
398 | sourceRange= var.getNameRange(); | |
399 | } | |
400 | ||
401 | if (sourceRange != null) | |
402 | return 100 + sourceRange.getOffset(); // +100: safe distance from all other categories. | |
403 | ||
404 | return super.category(element); | |
405 | } | |
406 | } | |
407 | ||
408 | public static final String PAGE_NAME= "SimilarElementSelectionPage"; //$NON-NLS-1$ | |
409 | ||
410 | private final long LABEL_FLAGS= JavaElementLabels.DEFAULT_QUALIFIED | JavaElementLabels.ROOT_POST_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH | JavaElementLabels.M_PARAMETER_TYPES | |
411 | | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_APP_RETURNTYPE | JavaElementLabels.M_EXCEPTIONS | JavaElementLabels.F_APP_TYPE_SIGNATURE | JavaElementLabels.T_TYPE_PARAMETERS; | |
412 | ||
413 | private Label fSimilarElementsLabel; | |
414 | private SourceViewer fSourceViewer; | |
415 | private ContainerCheckedTreeViewer fTreeViewer; | |
416 | private SimilarLabelProvider fTreeViewerLabelProvider; | |
417 | private Map<IJavaElement, String> fSimilarElementsToNewName; | |
418 | private Button fEditElementButton; | |
419 | private boolean fWasInitialized; | |
420 | private CLabel fCurrentElementLabel; | |
421 | ||
422 | public RenameTypeWizardSimilarElementsPage() { | |
423 | super(PAGE_NAME); | |
424 | } | |
425 | ||
426 | // --- UI creation | |
427 | ||
428 | public void createControl(Composite parent) { | |
429 | ||
430 | ViewForm viewForm= new ViewForm(parent, SWT.BORDER | SWT.FLAT); | |
431 | ||
432 | Composite inner= new Composite(viewForm, SWT.NULL); | |
433 | GridLayout layout= new GridLayout(); | |
434 | inner.setLayout(layout); | |
435 | ||
436 | createTreeAndSourceViewer(inner); | |
437 | createButtonComposite(inner); | |
438 | viewForm.setContent(inner); | |
439 | ||
440 | setControl(viewForm); | |
441 | ||
442 | Dialog.applyDialogFont(viewForm); | |
443 | PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.RENAME_TYPE_WIZARD_PAGE); | |
444 | } | |
445 | ||
446 | private void createTreeAndSourceViewer(Composite superComposite) { | |
447 | SashForm composite= new SashForm(superComposite, SWT.HORIZONTAL); | |
448 | initializeDialogUnits(superComposite); | |
449 | GridData gd= new GridData(GridData.FILL_BOTH); | |
450 | gd.heightHint= convertHeightInCharsToPixels(20); | |
451 | gd.widthHint= convertWidthInCharsToPixels(10); | |
452 | composite.setLayoutData(gd); | |
453 | GridLayout layout= new GridLayout(); | |
454 | layout.numColumns= 2; | |
455 | layout.marginWidth= 0; | |
456 | layout.marginHeight= 0; | |
457 | composite.setLayout(layout); | |
458 | ||
459 | createSimilarElementTreeComposite(composite); | |
460 | createSourceViewerComposite(composite); | |
461 | composite.setWeights(new int[] { 50, 50 }); | |
462 | } | |
463 | ||
464 | private void createSimilarElementTreeComposite(Composite parent) { | |
465 | Composite composite= new Composite(parent, SWT.NONE); | |
466 | composite.setLayoutData(new GridData(GridData.FILL_BOTH)); | |
467 | GridLayout layout= new GridLayout(); | |
468 | layout.marginWidth= 0; | |
469 | layout.marginHeight= 0; | |
470 | composite.setLayout(layout); | |
471 | ||
472 | createTypeHierarchyLabel(composite); | |
473 | createTreeViewer(composite); | |
474 | } | |
475 | ||
476 | private void createTypeHierarchyLabel(Composite composite) { | |
477 | fSimilarElementsLabel= new Label(composite, SWT.WRAP); | |
478 | GridData gd= new GridData(GridData.FILL_HORIZONTAL); | |
479 | gd.heightHint= JavaElementImageProvider.SMALL_SIZE.x; | |
480 | fSimilarElementsLabel.setLayoutData(gd); | |
481 | fSimilarElementsLabel.setText(RefactoringMessages.RenameTypeWizardSimilarElementsPage_review_similar_elements); | |
482 | } | |
483 | ||
484 | private void createTreeViewer(Composite composite) { | |
485 | Tree tree= new Tree(composite, SWT.CHECK | SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL); | |
486 | tree.setLayoutData(new GridData(GridData.FILL_BOTH)); | |
487 | fTreeViewer= new ContainerCheckedTreeViewer(tree); | |
488 | fTreeViewer.setUseHashlookup(true); | |
489 | fTreeViewer.setComparator(new SimilarElementComparator()); | |
490 | fTreeViewer.setContentProvider(new SimilarElementTreeContentProvider()); | |
491 | fTreeViewerLabelProvider= new SimilarLabelProvider(); | |
492 | fTreeViewer.setLabelProvider(fTreeViewerLabelProvider); | |
493 | fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { | |
494 | ||
495 | public void selectionChanged(SelectionChangedEvent event) { | |
496 | RenameTypeWizardSimilarElementsPage.this.treeViewerSelectionChanged(event); | |
497 | } | |
498 | }); | |
499 | fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { | |
500 | ||
501 | public void doubleClick(DoubleClickEvent event) { | |
502 | RenameTypeWizardSimilarElementsPage.this.editCurrentElement(); | |
503 | } | |
504 | }); | |
505 | } | |
506 | ||
507 | private void createSourceViewerComposite(Composite parent) { | |
508 | Composite c= new Composite(parent, SWT.NONE); | |
509 | c.setLayoutData(new GridData(GridData.FILL_BOTH)); | |
510 | GridLayout layout= new GridLayout(); | |
511 | layout.marginWidth= 0; | |
512 | layout.marginHeight= 0; | |
513 | c.setLayout(layout); | |
514 | ||
515 | createSourceViewerLabel(c); | |
516 | createSourceViewer(c); | |
517 | } | |
518 | ||
519 | private void createSourceViewerLabel(Composite c) { | |
520 | fCurrentElementLabel= new CLabel(c, SWT.NONE); | |
521 | GridData gd= new GridData(GridData.FILL_HORIZONTAL); | |
522 | gd.heightHint= JavaElementImageProvider.SMALL_SIZE.x; | |
523 | fCurrentElementLabel.setText(RefactoringMessages.RenameTypeWizardSimilarElementsPage_select_element_to_view_source); | |
524 | fCurrentElementLabel.setLayoutData(gd); | |
525 | } | |
526 | ||
527 | private void createSourceViewer(Composite c) { | |
528 | IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore(); | |
529 | fSourceViewer= new JavaSourceViewer(c, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION, store); | |
530 | fSourceViewer.configure(new JavaSourceViewerConfiguration(getJavaTextTools().getColorManager(), store, null, null)); | |
531 | fSourceViewer.setEditable(false); | |
532 | fSourceViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); | |
533 | fSourceViewer.getControl().setFont(JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT)); | |
534 | Document document= new Document(); | |
535 | getJavaTextTools().setupJavaDocumentPartitioner(document); | |
536 | fSourceViewer.setDocument(document); | |
537 | } | |
538 | ||
539 | private static JavaTextTools getJavaTextTools() { | |
540 | return JavaPlugin.getDefault().getJavaTextTools(); | |
541 | } | |
542 | ||
543 | private void createButtonComposite(Composite superComposite) { | |
544 | Composite buttonComposite= new Composite(superComposite, SWT.NONE); | |
545 | buttonComposite.setLayoutData(new GridData()); | |
546 | GridLayout layout= new GridLayout(2, false); | |
547 | layout.marginWidth= 0; | |
548 | buttonComposite.setLayout(layout); | |
549 | ||
550 | Button returnToDefaults= new Button(buttonComposite, SWT.PUSH); | |
551 | returnToDefaults.setText(RefactoringMessages.RenameTypeWizardSimilarElementsPage_restore_defaults); | |
552 | returnToDefaults.setLayoutData(new GridData()); | |
553 | SWTUtil.setButtonDimensionHint(returnToDefaults); | |
554 | returnToDefaults.addSelectionListener(new SelectionAdapter() { | |
555 | ||
556 | @Override | |
557 | public void widgetSelected(SelectionEvent e) { | |
558 | RenameTypeWizardSimilarElementsPage.this.resetDataInRefAndUI(); | |
559 | } | |
560 | }); | |
561 | fEditElementButton= new Button(buttonComposite, SWT.PUSH); | |
562 | fEditElementButton.setText(RefactoringMessages.RenameTypeWizardSimilarElementsPage_change_name); | |
563 | fEditElementButton.setLayoutData(new GridData()); | |
564 | fEditElementButton.setEnabled(false); | |
565 | SWTUtil.setButtonDimensionHint(fEditElementButton); | |
566 | fEditElementButton.addSelectionListener(new SelectionAdapter() { | |
567 | ||
568 | @Override | |
569 | public void widgetSelected(SelectionEvent e) { | |
570 | RenameTypeWizardSimilarElementsPage.this.editCurrentElement(); | |
571 | } | |
572 | }); | |
573 | } | |
574 | ||
575 | ||
576 | // ---------------------- Acting | |
577 | ||
578 | @Override | |
579 | public void setVisible(boolean visible) { | |
580 | if (visible) { | |
581 | initializeUIFromRef(); | |
582 | } | |
583 | super.setVisible(visible); | |
584 | selectFirstElement(); | |
585 | } | |
586 | ||
587 | private void selectFirstElement() { | |
588 | if (fTreeViewer.getTree().getItemCount() > 0) { | |
589 | TreeItem item= fTreeViewer.getTree().getItem(0); | |
590 | if (item.getData() != null) { | |
591 | fTreeViewer.reveal(item.getData()); | |
592 | Object data= getFirstSimilarElement(item); | |
593 | if (data != null) { | |
594 | fTreeViewer.setSelection(new StructuredSelection(data)); | |
595 | } | |
596 | } | |
597 | } | |
598 | fTreeViewer.getTree().setFocus(); | |
599 | } | |
600 | ||
601 | private Object getFirstSimilarElement(TreeItem item) { | |
602 | Object data= item.getData(); | |
603 | if (isSimilarElement(data)) { | |
604 | return data; | |
605 | } else { | |
606 | TreeItem[] children= item.getItems(); | |
607 | for (int i= 0; i < children.length; i++) { | |
608 | Object childData= getFirstSimilarElement(children[i]); | |
609 | if (childData != null) | |
610 | return childData; | |
611 | } | |
612 | } | |
613 | return null; | |
614 | } | |
615 | ||
616 | private void initializeUIFromRef() { | |
617 | // Get data from the refactoring | |
618 | final Map<IJavaElement, String> elementsToNewNames= getRenameTypeProcessor().getSimilarElementsToNewNames(); | |
619 | try { | |
620 | // To prevent flickering, stop redrawing | |
621 | getShell().setRedraw(false); | |
622 | if (fSimilarElementsToNewName == null || elementsToNewNames != fSimilarElementsToNewName) { | |
623 | fSimilarElementsToNewName= elementsToNewNames; | |
624 | fTreeViewerLabelProvider.initialize(fSimilarElementsToNewName); | |
625 | fTreeViewer.setInput(fSimilarElementsToNewName); | |
626 | } | |
627 | fTreeViewer.expandAll(); | |
628 | restoreSelectionAndNames(getRenameTypeProcessor().getSimilarElementsToSelection()); | |
629 | } finally { | |
630 | getShell().setRedraw(true); | |
631 | } | |
632 | fWasInitialized= true; | |
633 | } | |
634 | ||
635 | private void initializeRefFromUI() { | |
636 | IJavaElement[] selected= getCheckedSimilarElements(); | |
637 | Map<IJavaElement, Boolean> selection= getRenameTypeProcessor().getSimilarElementsToSelection(); | |
638 | for (Iterator<IJavaElement> iter= selection.keySet().iterator(); iter.hasNext();) { | |
639 | IJavaElement element= iter.next(); | |
640 | selection.put(element, Boolean.FALSE); | |
641 | } | |
642 | for (int i= 0; i < selected.length; i++) | |
643 | selection.put(selected[i], Boolean.TRUE); | |
644 | ||
645 | } | |
646 | ||
647 | private void resetDataInRefAndUI() { | |
648 | getRenameTypeProcessor().resetSelectedSimilarElements(); | |
649 | restoreSelectionAndNames(getRenameTypeProcessor().getSimilarElementsToSelection()); | |
650 | } | |
651 | ||
652 | protected void editCurrentElement() { | |
653 | IStructuredSelection selection= (IStructuredSelection) fTreeViewer.getSelection(); | |
654 | if ( (selection != null) && isSimilarElement(selection.getFirstElement())) { | |
655 | IJavaElement element= (IJavaElement) selection.getFirstElement(); | |
656 | String newName= fSimilarElementsToNewName.get(element); | |
657 | if (newName == null) | |
658 | return; | |
659 | EditElementDialog dialog= new EditElementDialog(getShell(), element, newName); | |
660 | if (dialog.open() == Window.OK) { | |
661 | String changedName= dialog.getNewName(); | |
662 | if (!changedName.equals(newName)) { | |
663 | fSimilarElementsToNewName.put(element, changedName); | |
664 | fTreeViewer.update(element, null); | |
665 | } | |
666 | } | |
667 | } | |
668 | } | |
669 | ||
670 | private void restoreSelectionAndNames(final Map<IJavaElement, Boolean> selection) { | |
671 | final Map<IJavaElement, Boolean> selectedElements= selection; | |
672 | for (Iterator<IJavaElement> iter= selectedElements.keySet().iterator(); iter.hasNext();) { | |
673 | IJavaElement element= iter.next(); | |
674 | boolean isSelected= selectedElements.get(element).booleanValue(); | |
675 | fTreeViewer.setChecked(element, isSelected); | |
676 | fTreeViewer.update(element, null); | |
677 | } | |
678 | } | |
679 | ||
680 | // ------------ Navigation | |
681 | ||
682 | /* | |
683 | * @see IWizardPage#getNextPage() | |
684 | */ | |
685 | @Override | |
686 | public IWizardPage getNextPage() { | |
687 | if (fWasInitialized) | |
688 | initializeRefFromUI(); | |
689 | // computes the input successor page | |
690 | // (=create changes) | |
691 | IWizardPage nextPage= super.getNextPage(); | |
692 | if (nextPage != this) // if user pressed cancel, then the next page is the current page | |
693 | nextPage.setPreviousPage(this); | |
694 | return nextPage; | |
695 | } | |
696 | ||
697 | ||
698 | /* | |
699 | * @see IWizardPage#getPreviousPage() | |
700 | */ | |
701 | @Override | |
702 | public IWizardPage getPreviousPage() { | |
703 | if (fWasInitialized) | |
704 | initializeRefFromUI(); | |
705 | return super.getPreviousPage(); | |
706 | } | |
707 | ||
708 | /* | |
709 | * @see RefactoringWizardPage#performFinish() | |
710 | */ | |
711 | @Override | |
712 | protected boolean performFinish() { | |
713 | initializeRefFromUI(); | |
714 | return super.performFinish(); | |
715 | } | |
716 | ||
717 | // ------------ Helper | |
718 | ||
719 | private boolean isSimilarElement(Object element) { | |
720 | if (!fWasInitialized) | |
721 | return false; | |
722 | ||
723 | return fSimilarElementsToNewName.containsKey(element); | |
724 | } | |
725 | ||
726 | private void treeViewerSelectionChanged(SelectionChangedEvent event) { | |
727 | try { | |
728 | final IJavaElement selection= getFirstSelectedSourceReference(event); | |
729 | setSourceViewerContents(selection); | |
730 | fEditElementButton.setEnabled(selection != null && (isSimilarElement(selection))); | |
731 | fCurrentElementLabel.setText(selection != null ? JavaElementLabels.getElementLabel(selection, LABEL_FLAGS) : RefactoringMessages.RenameTypeWizardSimilarElementsPage_select_element_to_view_source); | |
732 | fCurrentElementLabel.setImage(selection != null ? fTreeViewerLabelProvider.getJavaImage(selection) : null); | |
733 | } catch (JavaModelException e) { | |
734 | ExceptionHandler.handle(e, RefactoringMessages.RenameTypeWizard_defaultPageTitle, RefactoringMessages.RenameTypeWizard_unexpected_exception); | |
735 | } | |
736 | } | |
737 | ||
738 | private IJavaElement getFirstSelectedSourceReference(SelectionChangedEvent event) { | |
739 | ISelection s= event.getSelection(); | |
740 | if (! (s instanceof IStructuredSelection)) | |
741 | return null; | |
742 | IStructuredSelection strSel= (IStructuredSelection) s; | |
743 | if (strSel.size() != 1) | |
744 | return null; | |
745 | Object first= strSel.getFirstElement(); | |
746 | if (! (first instanceof IJavaElement)) | |
747 | return null; | |
748 | return (IJavaElement) first; | |
749 | } | |
750 | ||
751 | private void setSourceViewerContents(IJavaElement el) throws JavaModelException { | |
752 | String EMPTY= ""; //$NON-NLS-1$ | |
753 | if (el == null) { | |
754 | fSourceViewer.getDocument().set(EMPTY); | |
755 | return; | |
756 | } | |
757 | ICompilationUnit element= (ICompilationUnit) el.getAncestor(IJavaElement.COMPILATION_UNIT); | |
758 | if (element == null) { | |
759 | fSourceViewer.getDocument().set(EMPTY); | |
760 | return; | |
761 | } | |
762 | ||
763 | String contents= element.getSource(); | |
764 | try { | |
765 | fSourceViewer.setRedraw(false); | |
766 | fSourceViewer.getDocument().set(contents == null ? EMPTY : contents); | |
767 | ISourceRange sr= getNameRange(el); | |
768 | if (sr != null) { | |
769 | fSourceViewer.setSelectedRange(sr.getOffset(), sr.getLength()); | |
770 | } | |
771 | } finally { | |
772 | fSourceViewer.setRedraw(true); | |
773 | } | |
774 | } | |
775 | ||
776 | private ISourceRange getNameRange(IJavaElement element) throws JavaModelException { | |
777 | if (element instanceof IMember) | |
778 | return ((IMember) element).getNameRange(); | |
779 | else if (element instanceof ILocalVariable) | |
780 | return ((ILocalVariable) element).getNameRange(); | |
781 | else | |
782 | return null; | |
783 | } | |
784 | ||
785 | private IJavaElement[] getCheckedSimilarElements() { | |
786 | Object[] checked= fTreeViewer.getCheckedElements(); | |
787 | List<IJavaElement> elements= new ArrayList<IJavaElement>(checked.length); | |
788 | for (int i= 0; i < checked.length; i++) { | |
789 | if (isSimilarElement(checked[i])) | |
790 | elements.add((IJavaElement) checked[i]); | |
791 | } | |
792 | return elements.toArray(new IJavaElement[elements.size()]); | |
793 | } | |
794 | ||
795 | public RenameTypeProcessor getRenameTypeProcessor() { | |
796 | RefactoringProcessor proc= ((RenameRefactoring) getRefactoring()).getProcessor(); | |
797 | if (proc instanceof RenameTypeProcessor) | |
798 | return (RenameTypeProcessor) proc; | |
799 | else if (proc instanceof RenameCompilationUnitProcessor) { | |
800 | RenameCompilationUnitProcessor rcu= (RenameCompilationUnitProcessor) proc; | |
801 | return rcu.getRenameTypeProcessor(); | |
802 | } | |
803 | Assert.isTrue(false); // Should never get here | |
804 | return null; | |
805 | } | |
806 | } |