]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/javaeditor/ClassFileEditor.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / javaeditor / ClassFileEditor.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2012 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 *******************************************************************************/
11package org.eclipse.jdt.internal.ui.javaeditor;
12
13import java.lang.reflect.InvocationTargetException;
14import java.util.ArrayList;
15import java.util.Iterator;
16import java.util.List;
17
18import org.eclipse.swt.SWT;
19import org.eclipse.swt.custom.StackLayout;
20import org.eclipse.swt.custom.StyledText;
21import org.eclipse.swt.events.DisposeEvent;
22import org.eclipse.swt.events.DisposeListener;
23import org.eclipse.swt.events.SelectionEvent;
24import org.eclipse.swt.events.SelectionListener;
25import org.eclipse.swt.graphics.Color;
26import org.eclipse.swt.graphics.Font;
27import org.eclipse.swt.layout.FillLayout;
28import org.eclipse.swt.layout.GridData;
29import org.eclipse.swt.layout.GridLayout;
30import org.eclipse.swt.widgets.Button;
31import org.eclipse.swt.widgets.Composite;
32import org.eclipse.swt.widgets.Control;
33import org.eclipse.swt.widgets.Display;
34import org.eclipse.swt.widgets.Label;
35import org.eclipse.swt.widgets.Shell;
36
37import org.eclipse.core.runtime.Assert;
38import org.eclipse.core.runtime.CoreException;
39import org.eclipse.core.runtime.IPath;
40import org.eclipse.core.runtime.IProgressMonitor;
41import org.eclipse.core.runtime.IStatus;
42import org.eclipse.core.runtime.Status;
43import org.eclipse.core.runtime.jobs.Job;
44
45import org.eclipse.core.resources.IFile;
46
47import org.eclipse.jface.action.Action;
48import org.eclipse.jface.action.IAction;
49import org.eclipse.jface.action.IMenuManager;
50import org.eclipse.jface.operation.IRunnableWithProgress;
51import org.eclipse.jface.preference.IPreferenceStore;
52import org.eclipse.jface.resource.JFaceResources;
53import org.eclipse.jface.util.IPropertyChangeListener;
54import org.eclipse.jface.util.PropertyChangeEvent;
55
56import org.eclipse.jface.text.IWidgetTokenKeeper;
57import org.eclipse.jface.text.source.ISourceViewer;
58import org.eclipse.jface.text.source.IVerticalRuler;
59
60import org.eclipse.ui.IActionBars;
61import org.eclipse.ui.IEditorInput;
62import org.eclipse.ui.IFileEditorInput;
63import org.eclipse.ui.IWorkbenchCommandConstants;
64import org.eclipse.ui.PlatformUI;
65import org.eclipse.ui.actions.ActionContext;
66import org.eclipse.ui.actions.ActionGroup;
67
68import org.eclipse.ui.texteditor.IDocumentProvider;
69import org.eclipse.ui.texteditor.ITextEditorActionConstants;
70
71import org.eclipse.jdt.core.ClasspathContainerInitializer;
72import org.eclipse.jdt.core.IClassFile;
73import org.eclipse.jdt.core.IClasspathAttribute;
74import org.eclipse.jdt.core.IClasspathContainer;
75import org.eclipse.jdt.core.IClasspathEntry;
76import org.eclipse.jdt.core.IJavaElement;
77import org.eclipse.jdt.core.IJavaModelStatusConstants;
78import org.eclipse.jdt.core.IJavaProject;
79import org.eclipse.jdt.core.IPackageFragmentRoot;
80import org.eclipse.jdt.core.JavaCore;
81import org.eclipse.jdt.core.JavaModelException;
82import org.eclipse.jdt.core.ToolFactory;
83import org.eclipse.jdt.core.dom.CompilationUnit;
84import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
85import org.eclipse.jdt.core.util.ClassFormatException;
86
87import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
88import org.eclipse.jdt.internal.corext.util.Messages;
89
90import org.eclipse.jdt.ui.JavaElementLabels;
91import org.eclipse.jdt.ui.SharedASTProvider;
92import org.eclipse.jdt.ui.actions.RefactorActionGroup;
93import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess;
94
95import org.eclipse.jdt.internal.ui.JavaPlugin;
96import org.eclipse.jdt.internal.ui.JavaUIStatus;
97import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
98import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
99import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
100import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceAttachmentBlock;
101
102
103/**
104 * Java specific text editor.
105 */
106public class ClassFileEditor extends JavaEditor implements ClassFileDocumentProvider.InputChangeListener {
107
108
109 /**
110 * A form to attach source to a class file.
111 */
112 private class SourceAttachmentForm implements IPropertyChangeListener {
113
114 private final IClassFile fFile;
115 private Composite fComposite;
116 private Color fBackgroundColor;
117 private Color fForegroundColor;
118 private Color fSeparatorColor;
119 private List<Label> fBannerLabels= new ArrayList<Label>();
120 private List<Label> fHeaderLabels= new ArrayList<Label>();
121 private Font fFont;
122
123 /**
124 * Creates a source attachment form for a class file.
125 *
126 * @param file the class file
127 */
128 public SourceAttachmentForm(IClassFile file) {
129 fFile= file;
130 }
131
132 /**
133 * Returns the package fragment root of this file.
134 *
135 * @param file the class file
136 * @return the package fragment root of the given class file
137 */
138 private IPackageFragmentRoot getPackageFragmentRoot(IClassFile file) {
139
140 IJavaElement element= file.getParent();
141 while (element != null && element.getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT)
142 element= element.getParent();
143
144 return (IPackageFragmentRoot) element;
145 }
146
147 /**
148 * Creates the control of the source attachment form.
149 *
150 * @param parent the parent composite
151 * @return the creates source attachment form
152 */
153 public Control createControl(Composite parent) {
154
155 Display display= parent.getDisplay();
156 fBackgroundColor= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
157 fForegroundColor= display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
158 fSeparatorColor= new Color(display, 152, 170, 203);
159
160 JFaceResources.getFontRegistry().addListener(this);
161
162 fComposite= createComposite(parent);
163 fComposite.setLayout(new GridLayout());
164 fComposite.addDisposeListener(new DisposeListener() {
165 public void widgetDisposed(DisposeEvent e) {
166 JFaceResources.getFontRegistry().removeListener(SourceAttachmentForm.this);
167 fComposite= null;
168 fSeparatorColor.dispose();
169 fSeparatorColor= null;
170 fBannerLabels.clear();
171 fHeaderLabels.clear();
172 if (fFont != null) {
173 fFont.dispose();
174 fFont= null;
175 }
176 }
177 });
178
179 createTitleLabel(fComposite, JavaEditorMessages.SourceAttachmentForm_title);
180 createLabel(fComposite, null);
181 createLabel(fComposite, null);
182
183 createHeadingLabel(fComposite, JavaEditorMessages.SourceAttachmentForm_heading);
184
185 Composite separator= createCompositeSeparator(fComposite);
186 GridData data= new GridData(GridData.FILL_HORIZONTAL);
187 data.heightHint= 2;
188 separator.setLayoutData(data);
189
190 try {
191 IPackageFragmentRoot root= getPackageFragmentRoot(fFile);
192 if (root != null) {
193 createSourceAttachmentControls(fComposite, root);
194 }
195 } catch (JavaModelException e) {
196 String title= JavaEditorMessages.SourceAttachmentForm_error_title;
197 String message= JavaEditorMessages.SourceAttachmentForm_error_message;
198 ExceptionHandler.handle(e, fComposite.getShell(), title, message);
199 }
200
201 separator= createCompositeSeparator(fComposite);
202 data= new GridData(GridData.FILL_HORIZONTAL);
203 data.heightHint= 2;
204 separator.setLayoutData(data);
205
206 fNoSourceTextWidget= createCodeView(fComposite);
207 data= new GridData(GridData.FILL_BOTH);
208 fNoSourceTextWidget.setLayoutData(data);
209
210 updateCodeView(fNoSourceTextWidget, fFile);
211
212 return fComposite;
213 }
214
215 private void createSourceAttachmentControls(Composite composite, IPackageFragmentRoot root) throws JavaModelException {
216 IClasspathEntry entry;
217 try {
218 entry= JavaModelUtil.getClasspathEntry(root);
219 } catch (JavaModelException ex) {
220 if (ex.isDoesNotExist())
221 entry= null;
222 else
223 throw ex;
224 }
225 IPath containerPath= null;
226
227 if (entry == null || root.getKind() != IPackageFragmentRoot.K_BINARY) {
228 createLabel(composite, Messages.format(JavaEditorMessages.SourceAttachmentForm_message_noSource, BasicElementLabels.getFileName( fFile)));
229 return;
230 }
231
232 IJavaProject jproject= root.getJavaProject();
233 boolean canEditEncoding= true;
234 if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
235 containerPath= entry.getPath();
236 ClasspathContainerInitializer initializer= JavaCore.getClasspathContainerInitializer(containerPath.segment(0));
237 IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject);
238 if (initializer == null || container == null) {
239 createLabel(composite, Messages.format(JavaEditorMessages.ClassFileEditor_SourceAttachmentForm_cannotconfigure, BasicElementLabels.getPathLabel(containerPath, false)));
240 return;
241 }
242 String containerName= container.getDescription();
243 IStatus status= initializer.getSourceAttachmentStatus(containerPath, jproject);
244 if (status.getCode() == ClasspathContainerInitializer.ATTRIBUTE_NOT_SUPPORTED) {
245 createLabel(composite, Messages.format(JavaEditorMessages.ClassFileEditor_SourceAttachmentForm_notsupported, containerName));
246 return;
247 }
248 if (status.getCode() == ClasspathContainerInitializer.ATTRIBUTE_READ_ONLY) {
249 createLabel(composite, Messages.format(JavaEditorMessages.ClassFileEditor_SourceAttachmentForm_readonly, containerName));
250 return;
251 }
252 IStatus attributeStatus= initializer.getAttributeStatus(containerPath, jproject, IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING);
253 canEditEncoding= !(attributeStatus.getCode() == ClasspathContainerInitializer.ATTRIBUTE_NOT_SUPPORTED || attributeStatus.getCode() == ClasspathContainerInitializer.ATTRIBUTE_READ_ONLY);
254 entry= JavaModelUtil.findEntryInContainer(container, root.getPath());
255 Assert.isNotNull(entry);
256 }
257
258
259 Button button;
260
261 IPath path= entry.getSourceAttachmentPath();
262 if (path == null || path.isEmpty()) {
263 String rootLabel= JavaElementLabels.getElementLabel(root, JavaElementLabels.ALL_DEFAULT);
264 createLabel(composite, Messages.format(JavaEditorMessages.SourceAttachmentForm_message_noSourceAttachment, rootLabel));
265 createLabel(composite, JavaEditorMessages.SourceAttachmentForm_message_pressButtonToAttach);
266 createLabel(composite, null);
267
268 button= createButton(composite, JavaEditorMessages.SourceAttachmentForm_button_attachSource);
269
270 } else {
271 createLabel(composite, Messages.format(JavaEditorMessages.SourceAttachmentForm_message_noSourceInAttachment, BasicElementLabels.getFileName(fFile)));
272 createLabel(composite, JavaEditorMessages.SourceAttachmentForm_message_pressButtonToChange);
273 createLabel(composite, null);
274
275 button= createButton(composite, JavaEditorMessages.SourceAttachmentForm_button_changeAttachedSource);
276 }
277
278 button.addSelectionListener(getButtonListener(entry, containerPath, jproject, canEditEncoding));
279 }
280
281 private SelectionListener getButtonListener(final IClasspathEntry entry, final IPath containerPath, final IJavaProject jproject, final boolean canEditEncoding) {
282 return new SelectionListener() {
283 public void widgetSelected(SelectionEvent event) {
284 Shell shell= getSite().getShell();
285 try {
286 IClasspathEntry result= BuildPathDialogAccess.configureSourceAttachment(shell, entry, canEditEncoding);
287 if (result != null) {
288 applySourceAttachment(shell, result, jproject, containerPath, entry.getReferencingEntry() != null);
289 verifyInput(getEditorInput());
290 }
291 } catch (CoreException e) {
292 String title= JavaEditorMessages.SourceAttachmentForm_error_title;
293 String message= JavaEditorMessages.SourceAttachmentForm_error_message;
294 ExceptionHandler.handle(e, shell, title, message);
295 }
296 }
297
298 public void widgetDefaultSelected(SelectionEvent e) {}
299 };
300 }
301
302 protected void applySourceAttachment(Shell shell, IClasspathEntry newEntry, IJavaProject project, IPath containerPath, boolean isReferencedEntry) {
303 try {
304 IRunnableWithProgress runnable= SourceAttachmentBlock.getRunnable(shell, newEntry, project, containerPath, isReferencedEntry);
305 PlatformUI.getWorkbench().getProgressService().run(true, true, runnable);
306
307 } catch (InvocationTargetException e) {
308 String title= JavaEditorMessages.SourceAttachmentForm_attach_error_title;
309 String message= JavaEditorMessages.SourceAttachmentForm_attach_error_message;
310 ExceptionHandler.handle(e, shell, title, message);
311
312 } catch (InterruptedException e) {
313 // cancelled
314 }
315 }
316
317 /*
318 * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
319 */
320 public void propertyChange(PropertyChangeEvent event) {
321
322 for (Iterator<Label> iterator = fBannerLabels.iterator(); iterator.hasNext();) {
323 Label label = iterator.next();
324 label.setFont(JFaceResources.getBannerFont());
325 }
326
327 for (Iterator<Label> iterator = fHeaderLabels.iterator(); iterator.hasNext();) {
328 Label label = iterator.next();
329 label.setFont(JFaceResources.getHeaderFont());
330 }
331
332 fComposite.layout(true);
333 fComposite.redraw();
334 }
335
336 // --- copied from org.eclipse.update.ui.forms.internal.FormWidgetFactory
337
338 private Composite createComposite(Composite parent) {
339 Composite composite = new Composite(parent, SWT.NONE);
340 composite.setBackground(fBackgroundColor);
341 // composite.addMouseListener(new MouseAdapter() {
342 // public void mousePressed(MouseEvent e) {
343 // ((Control) e.widget).setFocus();
344 // }
345 // });
346 return composite;
347 }
348
349 private Composite createCompositeSeparator(Composite parent) {
350 Composite composite = new Composite(parent, SWT.NONE);
351 composite.setBackground(fSeparatorColor);
352 return composite;
353 }
354
355 private StyledText createCodeView(Composite parent) {
356 int styles= SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION;
357 StyledText styledText= new StyledText(parent, styles);
358 styledText.setBackground(fBackgroundColor);
359 styledText.setForeground(fForegroundColor);
360 styledText.setEditable(false);
361 return styledText;
362 }
363
364 private Label createLabel(Composite parent, String text) {
365 Label label= new Label(parent, SWT.WRAP);
366 if (text != null)
367 label.setText(text);
368 label.setBackground(fBackgroundColor);
369 label.setForeground(fForegroundColor);
370 GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
371 label.setLayoutData(gd);
372 return label;
373 }
374
375 private Label createTitleLabel(Composite parent, String text) {
376 Label label = new Label(parent, SWT.NONE);
377 if (text != null)
378 label.setText(text);
379 label.setBackground(fBackgroundColor);
380 label.setForeground(fForegroundColor);
381 label.setFont(JFaceResources.getHeaderFont());
382 fHeaderLabels.add(label);
383 return label;
384 }
385
386 private Label createHeadingLabel(Composite parent, String text) {
387 Label label = new Label(parent, SWT.NONE);
388 if (text != null)
389 label.setText(text);
390 label.setBackground(fBackgroundColor);
391 label.setForeground(fForegroundColor);
392 label.setFont(JFaceResources.getBannerFont());
393 fBannerLabels.add(label);
394 return label;
395 }
396
397 private Button createButton(Composite parent, String text) {
398 Button button = new Button(parent, SWT.FLAT);
399 button.setBackground(fBackgroundColor);
400 button.setForeground(fForegroundColor);
401 if (text != null)
402 button.setText(text);
403 return button;
404 }
405
406 private void updateCodeView(StyledText styledText, IClassFile classFile) {
407 String content= null;
408 ClassFileBytesDisassembler disassembler= ToolFactory.createDefaultClassFileBytesDisassembler();
409 try {
410 content= disassembler.disassemble(classFile.getBytes(), "\n", ClassFileBytesDisassembler.DETAILED); //$NON-NLS-1$
411 } catch (JavaModelException ex) {
412 JavaPlugin.log(ex.getStatus());
413 } catch (ClassFormatException ex) {
414 JavaPlugin.log(ex);
415 }
416 styledText.setText(content == null ? "" : content); //$NON-NLS-1$
417 }
418 }
419
420 /**
421 * Updater that takes care of minimizing changes of the editor input.
422 */
423 private class InputUpdater implements Runnable {
424
425 /** Has the runnable already been posted? */
426 private boolean fPosted= false;
427 /** Editor input */
428 private IClassFileEditorInput fClassFileEditorInput;
429
430
431 public InputUpdater() {
432 }
433
434 /*
435 * @see Runnable#run()
436 */
437 public void run() {
438
439 IClassFileEditorInput input;
440 synchronized (this) {
441 input= fClassFileEditorInput;
442 }
443
444 try {
445
446 if (getSourceViewer() != null)
447 setInput(input);
448
449 } finally {
450 synchronized (this) {
451 fPosted= false;
452 }
453 }
454 }
455
456 /**
457 * Posts this runnable into the event queue if not already there.
458 *
459 * @param input the input to be set when executed
460 */
461 public void post(IClassFileEditorInput input) {
462
463 synchronized(this) {
464 if (fPosted) {
465 if (isEqualInput(input, fClassFileEditorInput))
466 fClassFileEditorInput= input;
467 return;
468 }
469 }
470
471 if (isEqualInput(input, getEditorInput())) {
472 ISourceViewer viewer= getSourceViewer();
473 if (viewer != null) {
474 StyledText textWidget= viewer.getTextWidget();
475 if (textWidget != null && !textWidget.isDisposed()) {
476 synchronized (this) {
477 fPosted= true;
478 fClassFileEditorInput= input;
479 }
480 textWidget.getDisplay().asyncExec(this);
481 }
482 }
483 }
484 }
485
486 private boolean isEqualInput(IEditorInput input1, IEditorInput input2) {
487 return input1 != null && input1.equals(input2);
488 }
489 }
490
491
492 private StackLayout fStackLayout;
493 private Composite fParent;
494
495 private Composite fViewerComposite;
496 private Control fSourceAttachmentForm;
497
498 private CompositeActionGroup fContextMenuGroup;
499
500 private InputUpdater fInputUpdater= new InputUpdater();
501
502 /**
503 * The copy action used when there's attached source.
504 * @since 3.3
505 */
506 private IAction fSourceCopyAction;
507 /**
508 * The Select All action used when there's attached source.
509 * @since 3.3
510 */
511 private IAction fSelectAllAction;
512
513 /**
514 * StyledText widget used to show the disassembled code.
515 * if there's no source.
516 *
517 * @since 3.3
518 */
519 private StyledText fNoSourceTextWidget;
520
521
522 /**
523 * Default constructor.
524 */
525 public ClassFileEditor() {
526 setDocumentProvider(JavaPlugin.getDefault().getClassFileDocumentProvider());
527 setEditorContextMenuId("#ClassFileEditorContext"); //$NON-NLS-1$
528 setRulerContextMenuId("#ClassFileRulerContext"); //$NON-NLS-1$
529 setOutlinerContextMenuId("#ClassFileOutlinerContext"); //$NON-NLS-1$
530 // don't set help contextId, we install our own help context
531 }
532
533 /*
534 * @see AbstractTextEditor#createActions()
535 */
536 @Override
537 protected void createActions() {
538 super.createActions();
539
540 setAction(ITextEditorActionConstants.SAVE, null);
541 setAction(ITextEditorActionConstants.REVERT_TO_SAVED, null);
542
543 fSourceCopyAction= getAction(ITextEditorActionConstants.COPY);
544 fSelectAllAction= getAction(ITextEditorActionConstants.SELECT_ALL);
545
546 final ActionGroup group= new RefactorActionGroup(this, ITextEditorActionConstants.GROUP_EDIT, true);
547 fActionGroups.addGroup(group);
548 fContextMenuGroup= new CompositeActionGroup(new ActionGroup[] {group});
549
550 /*
551 * 1GF82PL: ITPJUI:ALL - Need to be able to add bookmark to class file
552 *
553 * // replace default action with class file specific ones
554 *
555 * setAction(ITextEditorActionConstants.BOOKMARK, new AddClassFileMarkerAction("AddBookmark.", this, IMarker.BOOKMARK, true)); //$NON-NLS-1$
556 * setAction(ITextEditorActionConstants.ADD_TASK, new AddClassFileMarkerAction("AddTask.", this, IMarker.TASK, false)); //$NON-NLS-1$
557 * setAction(ITextEditorActionConstants.RULER_MANAGE_BOOKMARKS, new ClassFileMarkerRulerAction("ManageBookmarks.", getVerticalRuler(), this, IMarker.BOOKMARK, true)); //$NON-NLS-1$
558 * setAction(ITextEditorActionConstants.RULER_MANAGE_TASKS, new ClassFileMarkerRulerAction("ManageTasks.", getVerticalRuler(), this, IMarker.TASK, true)); //$NON-NLS-1$
559 */
560 }
561
562 /*
563 * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager)
564 */
565 @Override
566 public void editorContextMenuAboutToShow(IMenuManager menu) {
567 super.editorContextMenuAboutToShow(menu);
568
569 ActionContext context= new ActionContext(getSelectionProvider().getSelection());
570 fContextMenuGroup.setContext(context);
571 fContextMenuGroup.fillContextMenu(menu);
572 fContextMenuGroup.setContext(null);
573 }
574
575 /*
576 * @see JavaEditor#getElementAt(int)
577 */
578 @Override
579 protected IJavaElement getElementAt(int offset) {
580 if (getEditorInput() instanceof IClassFileEditorInput) {
581 try {
582 IClassFileEditorInput input= (IClassFileEditorInput) getEditorInput();
583 return input.getClassFile().getElementAt(offset);
584 } catch (JavaModelException x) {
585 }
586 }
587 return null;
588 }
589
590 /*
591 * @see JavaEditor#getCorrespondingElement(IJavaElement)
592 */
593 @Override
594 protected IJavaElement getCorrespondingElement(IJavaElement element) {
595 if (getEditorInput() instanceof IClassFileEditorInput) {
596 IClassFileEditorInput input= (IClassFileEditorInput) getEditorInput();
597 IJavaElement parent= element.getAncestor(IJavaElement.CLASS_FILE);
598 if (input.getClassFile().equals(parent))
599 return element;
600 }
601 return null;
602 }
603
604 /*
605 * 1GEPKT5: ITPJUI:Linux - Source in editor for external classes is editable
606 * Removed methods isSaveOnClosedNeeded and isDirty.
607 * Added method isEditable.
608 */
609 /*
610 * @see org.eclipse.ui.texteditor.AbstractTextEditor#isEditable()
611 */
612 @Override
613 public boolean isEditable() {
614 return false;
615 }
616
617 /*
618 * @see org.eclipse.ui.texteditor.AbstractTextEditor#isEditorInputReadOnly()
619 * @since 3.2
620 */
621 @Override
622 public boolean isEditorInputReadOnly() {
623 return true;
624 }
625
626 /**
627 * Translates the given editor input into an <code>ExternalClassFileEditorInput</code>
628 * if it is a file editor input representing an external class file.
629 *
630 * @param input the editor input to be transformed if necessary
631 * @return the transformed editor input
632 */
633 protected IEditorInput transformEditorInput(IEditorInput input) {
634
635 if (input instanceof IFileEditorInput) {
636 IFile file= ((IFileEditorInput) input).getFile();
637 IClassFileEditorInput classFileInput= new ExternalClassFileEditorInput(file);
638 if (classFileInput.getClassFile() != null)
639 input= classFileInput;
640 }
641
642 return input;
643 }
644
645 /*
646 * @see AbstractTextEditor#doSetInput(IEditorInput)
647 */
648 @Override
649 protected void doSetInput(IEditorInput input) throws CoreException {
650 uninstallOccurrencesFinder();
651
652 input= transformEditorInput(input);
653 if (!(input instanceof IClassFileEditorInput)) {
654 String inputClassName= input != null ? input.getClass().getName() : "null"; //$NON-NLS-1$
655 String message= Messages.format(JavaEditorMessages.ClassFileEditor_error_invalid_input_message, inputClassName);
656 throw new CoreException(JavaUIStatus.createError(
657 IJavaModelStatusConstants.INVALID_RESOURCE_TYPE,
658 message,
659 null));
660 }
661
662 JavaModelException e= probeInputForSource(input);
663 if (e != null) {
664 IClassFileEditorInput classFileEditorInput= (IClassFileEditorInput) input;
665 IClassFile file= classFileEditorInput.getClassFile();
666 IJavaProject javaProject= file.getJavaProject();
667 if (!javaProject.exists() || !javaProject.isOnClasspath(file)) {
668 throw new CoreException(JavaUIStatus.createError(
669 IJavaModelStatusConstants.INVALID_RESOURCE,
670 JavaEditorMessages.ClassFileEditor_error_classfile_not_on_classpath,
671 null));
672 } else {
673 throw e;
674 }
675 }
676
677 IDocumentProvider documentProvider= getDocumentProvider();
678 if (documentProvider instanceof ClassFileDocumentProvider)
679 ((ClassFileDocumentProvider) documentProvider).removeInputChangeListener(this);
680
681 super.doSetInput(input);
682
683 documentProvider= getDocumentProvider();
684 if (documentProvider instanceof ClassFileDocumentProvider)
685 ((ClassFileDocumentProvider) documentProvider).addInputChangeListener(this);
686
687 verifyInput(getEditorInput());
688
689 JavaPlugin.getDefault().getASTProvider().activeJavaEditorChanged(this);
690
691 if (fSemanticManager != null)
692 installSemanticHighlighting();
693
694 }
695
696 /*
697 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#installSemanticHighlighting()
698 * @since 3.7
699 */
700 @Override
701 protected void installSemanticHighlighting() {
702 super.installSemanticHighlighting();
703 Job job= new Job(JavaEditorMessages.OverrideIndicatorManager_intallJob) {
704 /*
705 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
706 * @since 3.0
707 */
708 @Override
709 protected IStatus run(IProgressMonitor monitor) {
710 CompilationUnit ast= SharedASTProvider.getAST(getInputJavaElement(), SharedASTProvider.WAIT_YES, null);
711 if (fOverrideIndicatorManager != null)
712 fOverrideIndicatorManager.reconciled(ast, true, monitor);
713 if (fSemanticManager != null) {
714 SemanticHighlightingReconciler reconciler= fSemanticManager.getReconciler();
715 if (reconciler != null)
716 reconciler.reconciled(ast, false, monitor);
717 }
718 if (isMarkingOccurrences())
719 installOccurrencesFinder(false);
720 return Status.OK_STATUS;
721 }
722 };
723 job.setPriority(Job.DECORATE);
724 job.setSystem(true);
725 job.schedule();
726 }
727
728 /*
729 * @see IWorkbenchPart#createPartControl(Composite)
730 */
731 @Override
732 public void createPartControl(Composite parent) {
733
734 fParent= new Composite(parent, SWT.NONE);
735 fStackLayout= new StackLayout();
736 fParent.setLayout(fStackLayout);
737
738 fViewerComposite= new Composite(fParent, SWT.NONE);
739 fViewerComposite.setLayout(new FillLayout());
740
741 super.createPartControl(fViewerComposite);
742
743 fStackLayout.topControl= fViewerComposite;
744 fParent.layout();
745
746 try {
747 verifyInput(getEditorInput());
748 } catch (CoreException e) {
749 String title= JavaEditorMessages.ClassFileEditor_error_title;
750 String message= JavaEditorMessages.ClassFileEditor_error_message;
751 ExceptionHandler.handle(e, fParent.getShell(), title, message);
752 }
753 }
754
755 private JavaModelException probeInputForSource(IEditorInput input) {
756 if (input == null)
757 return null;
758
759 IClassFileEditorInput classFileEditorInput= (IClassFileEditorInput) input;
760 IClassFile file= classFileEditorInput.getClassFile();
761
762 try {
763 file.getSourceRange();
764 } catch (JavaModelException e) {
765 return e;
766 }
767
768 return null;
769 }
770
771 /**
772 * Checks if the class file input has no source attached. If so, a source attachment form is shown.
773 *
774 * @param input the editor input
775 * @throws JavaModelException if an exception occurs while accessing its corresponding resource
776 */
777 private void verifyInput(IEditorInput input) throws JavaModelException {
778
779 if (fParent == null || input == null)
780 return;
781
782 IClassFileEditorInput classFileEditorInput= (IClassFileEditorInput) input;
783 IClassFile file= classFileEditorInput.getClassFile();
784
785 IAction copyQualifiedName= getAction(IJavaEditorActionConstants.COPY_QUALIFIED_NAME);
786
787 boolean wasUsingSourceCopyAction= fSourceCopyAction == getAction(ITextEditorActionConstants.COPY);
788
789 // show source attachment form if no source found
790 if (file.getSourceRange() == null) {
791
792 // dispose old source attachment form
793 if (fSourceAttachmentForm != null)
794 fSourceAttachmentForm.dispose();
795
796 SourceAttachmentForm form= new SourceAttachmentForm(file);
797 fSourceAttachmentForm= form.createControl(fParent);
798
799 fStackLayout.topControl= fSourceAttachmentForm;
800 fParent.layout();
801
802 if (fNoSourceTextWidget != null) {
803 // Copy action for the no attached source case
804 final IAction copyAction= new Action() {
805 @Override
806 public void run() {
807 fNoSourceTextWidget.copy();
808 }
809 };
810 copyAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);
811 setAction(ITextEditorActionConstants.COPY, copyAction);
812 copyAction.setEnabled(fNoSourceTextWidget.getSelectionText().length() > 0);
813 fNoSourceTextWidget.addSelectionListener(new SelectionListener() {
814 public void widgetSelected(SelectionEvent e) {
815 copyAction.setEnabled(fNoSourceTextWidget.getSelectionText().length() > 0);
816 }
817 public void widgetDefaultSelected(SelectionEvent e) {
818 }
819 });
820
821 // Select All action for the no attached source case
822 final IAction selectAllAction= new Action() {
823 @Override
824 public void run() {
825 fNoSourceTextWidget.selectAll();
826 copyAction.setEnabled(true);
827 }
828 };
829 selectAllAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_SELECT_ALL);
830 setAction(ITextEditorActionConstants.SELECT_ALL, selectAllAction);
831 copyAction.setEnabled(fNoSourceTextWidget.getSelectionText().length() > 0);
832 copyQualifiedName.setEnabled(false);
833
834
835 }
836
837 } else { // show source viewer
838
839 if (fSourceAttachmentForm != null) {
840 fSourceAttachmentForm.dispose();
841 fSourceAttachmentForm= null;
842
843 fStackLayout.topControl= fViewerComposite;
844 fParent.layout();
845 }
846
847 setAction(ITextEditorActionConstants.COPY, fSourceCopyAction);
848 setAction(ITextEditorActionConstants.SELECT_ALL, fSelectAllAction);
849 copyQualifiedName.setEnabled(true);
850
851 }
852
853 IAction currentCopyAction= getAction(ITextEditorActionConstants.COPY);
854 boolean isUsingSourceCopyAction= fSourceCopyAction == currentCopyAction;
855 if (wasUsingSourceCopyAction != isUsingSourceCopyAction) {
856 IActionBars actionBars= getEditorSite().getActionBars();
857
858 if (isUsingSourceCopyAction) {
859 createNavigationActions();
860 } else {
861 for (int i= 0; i < ACTION_MAP.length; i++) {
862 IdMapEntry entry= ACTION_MAP[i];
863 actionBars.setGlobalActionHandler(entry.getActionId(), null);
864 setAction(entry.getActionId(), null);
865 }
866 }
867
868 actionBars.setGlobalActionHandler(ITextEditorActionConstants.COPY, currentCopyAction);
869 actionBars.setGlobalActionHandler(ITextEditorActionConstants.SELECT_ALL, getAction(ITextEditorActionConstants.SELECT_ALL));
870 actionBars.updateActionBars();
871 }
872
873 }
874
875 /*
876 * @see ClassFileDocumentProvider.InputChangeListener#inputChanged(IClassFileEditorInput)
877 */
878 public void inputChanged(IClassFileEditorInput input) {
879 fInputUpdater.post(input);
880 }
881
882 /*
883 * @see JavaEditor#createJavaSourceViewer(Composite, IVerticalRuler, int)
884 */
885 protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler ruler, int styles, IPreferenceStore store) {
886 return new JavaSourceViewer(parent, ruler, null, false, styles, store) {
887
888 @Override
889 public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
890 if (PlatformUI.getWorkbench().getHelpSystem().isContextHelpDisplayed())
891 return false;
892 return super.requestWidgetToken(requester);
893 }
894
895 @Override
896 public boolean requestWidgetToken(IWidgetTokenKeeper requester, int priority) {
897 if (PlatformUI.getWorkbench().getHelpSystem().isContextHelpDisplayed())
898 return false;
899 return super.requestWidgetToken(requester, priority);
900 }
901 };
902 }
903
904 /*
905 * @see org.eclipse.ui.IWorkbenchPart#dispose()
906 */
907 @Override
908 public void dispose() {
909 // http://bugs.eclipse.org/bugs/show_bug.cgi?id=18510
910 IDocumentProvider documentProvider= getDocumentProvider();
911 if (documentProvider instanceof ClassFileDocumentProvider)
912 ((ClassFileDocumentProvider) documentProvider).removeInputChangeListener(this);
913 super.dispose();
914 }
915
916 /*
917 * @see org.eclipse.ui.IWorkbenchPart#setFocus()
918 */
919 @Override
920 public void setFocus() {
921 super.setFocus();
922
923 if (fSourceAttachmentForm != null && !fSourceAttachmentForm.isDisposed())
924 fSourceAttachmentForm.setFocus();
925 }
926
927}