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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.ui.infoviews;
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.custom.StyledText;
15 import org.eclipse.swt.graphics.Color;
16 import org.eclipse.swt.graphics.Font;
17 import org.eclipse.swt.graphics.Point;
18 import org.eclipse.swt.widgets.Composite;
19 import org.eclipse.swt.widgets.Control;
21 import org.eclipse.core.runtime.Assert;
23 import org.eclipse.jface.action.Action;
24 import org.eclipse.jface.action.IAction;
25 import org.eclipse.jface.action.IMenuManager;
26 import org.eclipse.jface.preference.IPreferenceStore;
27 import org.eclipse.jface.resource.JFaceResources;
28 import org.eclipse.jface.util.IPropertyChangeListener;
29 import org.eclipse.jface.util.PropertyChangeEvent;
30 import org.eclipse.jface.viewers.ISelection;
31 import org.eclipse.jface.viewers.IStructuredSelection;
32 import org.eclipse.jface.viewers.StructuredSelection;
34 import org.eclipse.jface.text.BadLocationException;
35 import org.eclipse.jface.text.Document;
36 import org.eclipse.jface.text.IDocument;
37 import org.eclipse.jface.text.IRegion;
38 import org.eclipse.jface.text.ITextOperationTarget;
39 import org.eclipse.jface.text.ITextSelection;
40 import org.eclipse.jface.text.TextViewer;
41 import org.eclipse.jface.text.source.SourceViewer;
43 import org.eclipse.ui.IActionBars;
44 import org.eclipse.ui.PlatformUI;
46 import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
48 import org.eclipse.jdt.core.ICodeAssist;
49 import org.eclipse.jdt.core.IJavaElement;
50 import org.eclipse.jdt.core.IJavaProject;
51 import org.eclipse.jdt.core.ISourceRange;
52 import org.eclipse.jdt.core.ISourceReference;
53 import org.eclipse.jdt.core.JavaModelException;
55 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
56 import org.eclipse.jdt.internal.corext.util.Strings;
58 import org.eclipse.jdt.ui.IContextMenuConstants;
59 import org.eclipse.jdt.ui.actions.OpenAction;
60 import org.eclipse.jdt.ui.text.IJavaPartitions;
61 import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
63 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
64 import org.eclipse.jdt.internal.ui.JavaPlugin;
65 import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer;
66 import org.eclipse.jdt.internal.ui.text.JavaCodeReader;
67 import org.eclipse.jdt.internal.ui.text.SimpleJavaSourceViewerConfiguration;
70 * View which shows source for a given Java element.
74 public class SourceView extends AbstractInfoView {
76 /** Symbolic Java editor font name. */
77 private static final String SYMBOLIC_FONT_NAME= "org.eclipse.jdt.ui.editors.textfont"; //$NON-NLS-1$
80 * Internal property change listener for handling changes in the editor's preferences.
84 class PropertyChangeListener implements IPropertyChangeListener {
86 * @see IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
88 public void propertyChange(PropertyChangeEvent event) {
92 if (fViewerConfiguration.affectsTextPresentation(event)) {
93 fViewerConfiguration.handlePropertyChangeEvent(event);
94 fViewer.invalidateTextPresentation();
100 * Internal property change listener for handling workbench font changes.
102 class FontPropertyChangeListener implements IPropertyChangeListener {
104 * @see IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
106 public void propertyChange(PropertyChangeEvent event) {
110 String property= event.getProperty();
112 if (SYMBOLIC_FONT_NAME.equals(property))
118 * The Javadoc view's select all action.
120 private static class SelectAllAction extends Action {
122 private TextViewer fTextViewer;
125 * Creates the action.
127 * @param textViewer the text viewer
129 public SelectAllAction(TextViewer textViewer) {
130 super("selectAll"); //$NON-NLS-1$
132 Assert.isNotNull(textViewer);
133 fTextViewer= textViewer;
135 setText(InfoViewMessages.SelectAllAction_label);
136 setToolTipText(InfoViewMessages.SelectAllAction_tooltip);
137 setDescription(InfoViewMessages.SelectAllAction_description);
139 PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IAbstractTextEditorHelpContextIds.SELECT_ALL_ACTION);
143 * Selects all in the viewer.
147 fTextViewer.doOperation(ITextOperationTarget.SELECT_ALL);
151 /** This view's source viewer */
152 private SourceViewer fViewer;
153 /** The viewers configuration */
154 private JavaSourceViewerConfiguration fViewerConfiguration;
155 /** The viewer's font properties change listener. */
156 private IPropertyChangeListener fFontPropertyChangeListener= new FontPropertyChangeListener();
158 * The editor's property change listener.
161 private IPropertyChangeListener fPropertyChangeListener= new PropertyChangeListener();
162 /** The open action */
163 public OpenAction fOpen;
164 /** The number of removed leading comment lines. */
165 private int fCommentLineCount;
166 /** The select all action. */
167 private SelectAllAction fSelectAllAction;
168 /** Element opened by the open action. */
169 private IJavaElement fLastOpenedElement;
173 * @see AbstractInfoView#internalCreatePartControl(Composite)
176 protected void internalCreatePartControl(Composite parent) {
177 IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore();
178 fViewer= new JavaSourceViewer(parent, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL, store);
179 fViewerConfiguration= new SimpleJavaSourceViewerConfiguration(JavaPlugin.getDefault().getJavaTextTools().getColorManager(), store, null, IJavaPartitions.JAVA_PARTITIONING, false);
180 fViewer.configure(fViewerConfiguration);
181 fViewer.setEditable(false);
184 JFaceResources.getFontRegistry().addListener(fFontPropertyChangeListener);
186 store.addPropertyChangeListener(fPropertyChangeListener);
188 getViewSite().setSelectionProvider(fViewer);
192 * @see AbstractInfoView#internalCreatePartControl(Composite)
195 protected void createActions() {
196 super.createActions();
197 fSelectAllAction= new SelectAllAction(fViewer);
200 fOpen= new OpenAction(getViewSite()) {
203 * @see org.eclipse.jdt.ui.actions.SelectionDispatchAction#getSelection()
206 public ISelection getSelection() {
207 return convertToJavaElementSelection(fViewer.getSelection());
211 * @see org.eclipse.jdt.ui.actions.OpenAction#run(IStructuredSelection)
214 public void run(IStructuredSelection selection) {
215 if (selection.isEmpty()) {
216 getShell().getDisplay().beep();
219 super.run(selection);
223 * @see org.eclipse.jdt.ui.actions.OpenAction#getElementToOpen(Object)
226 public Object getElementToOpen(Object object) throws JavaModelException {
227 if (object instanceof IJavaElement)
228 fLastOpenedElement= (IJavaElement)object;
230 fLastOpenedElement= null;
231 return super.getElementToOpen(object);
235 * @see org.eclipse.jdt.ui.actions.OpenAction#run(Object[])
238 public void run(Object[] elements) {
239 stopListeningForSelectionChanges();
241 startListeningForSelectionChanges();
248 * @see org.eclipse.jdt.internal.ui.infoviews.AbstractInfoView#getSelectAllAction()
252 protected IAction getSelectAllAction() {
253 return fSelectAllAction;
257 * @see AbstractInfoView#fillActionBars(IActionBars)
260 protected void fillActionBars(IActionBars actionBars) {
261 super.fillActionBars(actionBars);
262 fOpen.generated_5795278149633683358(actionBars);
266 * @see AbstractInfoView#getControl()
269 protected Control getControl() {
270 return fViewer.getControl();
274 * @see AbstractInfoView#menuAboutToShow(IMenuManager)
277 public void menuAboutToShow(IMenuManager menu) {
278 super.menuAboutToShow(menu);
279 menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, fOpen);
283 * @see AbstractInfoView#setForeground(Color)
286 protected void setForeground(Color color) {
287 fViewer.getTextWidget().setForeground(color);
291 * @see AbstractInfoView#setBackground(Color)
294 protected void setBackground(Color color) {
295 fViewer.getTextWidget().setBackground(color);
299 * @see org.eclipse.jdt.internal.ui.infoviews.AbstractInfoView#getBackgroundColorKey()
303 protected String getBackgroundColorKey() {
304 return "org.eclipse.jdt.ui.DeclarationView.backgroundColor"; //$NON-NLS-1$
308 * Converts the given selection to a structured selection
309 * containing Java elements.
311 * @param selection the selection
312 * @return a structured selection with Java elements
314 private IStructuredSelection convertToJavaElementSelection(ISelection selection) {
316 if (!(selection instanceof ITextSelection && fCurrentViewInput instanceof ISourceReference))
317 return StructuredSelection.EMPTY;
319 ITextSelection textSelection= (ITextSelection)selection;
321 Object codeAssist= fCurrentViewInput.getAncestor(IJavaElement.COMPILATION_UNIT);
322 if (codeAssist == null)
323 codeAssist= fCurrentViewInput.getAncestor(IJavaElement.CLASS_FILE);
325 if (codeAssist instanceof ICodeAssist) {
326 IJavaElement[] elements= null;
328 ISourceRange range= ((ISourceReference)fCurrentViewInput).getSourceRange();
329 elements= ((ICodeAssist)codeAssist).codeSelect(range.getOffset() + getOffsetInUnclippedDocument(textSelection), textSelection.getLength());
330 } catch (JavaModelException e) {
331 return StructuredSelection.EMPTY;
333 if (elements != null && elements.length > 0) {
334 return new StructuredSelection(elements[0]);
336 return StructuredSelection.EMPTY;
339 return StructuredSelection.EMPTY;
343 * Computes and returns the offset in the unclipped document based on the given text selection
344 * from the clipped document.
346 * @param textSelection the text selection
347 * @return the offset in the unclipped document or <code>-1</code> if the offset cannot be
350 private int getOffsetInUnclippedDocument(ITextSelection textSelection) {
351 IDocument unclippedDocument= null;
353 unclippedDocument= new Document(((ISourceReference)fCurrentViewInput).getSource());
354 } catch (JavaModelException e) {
357 IDocument clippedDoc= (IDocument)fViewer.getInput();
359 IRegion unclippedLineInfo= unclippedDocument.getLineInformation(fCommentLineCount + textSelection.getStartLine());
360 IRegion clippedLineInfo= clippedDoc.getLineInformation(textSelection.getStartLine());
361 int removedIndentation= unclippedLineInfo.getLength() - clippedLineInfo.getLength();
362 int relativeLineOffset= textSelection.getOffset() - clippedLineInfo.getOffset();
363 return unclippedLineInfo.getOffset() + removedIndentation + relativeLineOffset ;
364 } catch (BadLocationException ex) {
370 * @see AbstractInfoView#internalDispose()
373 protected void internalDispose() {
375 fViewerConfiguration= null;
376 JFaceResources.getFontRegistry().removeListener(fFontPropertyChangeListener);
377 JavaPlugin.getDefault().getCombinedPreferenceStore().removePropertyChangeListener(fPropertyChangeListener);
381 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
384 public void setFocus() {
385 fViewer.getTextWidget().setFocus();
389 * @see AbstractInfoView#computeInput(Object)
392 protected Object computeInput(Object input) {
394 if (fViewer == null || !(input instanceof ISourceReference))
397 ISourceReference sourceRef= (ISourceReference)input;
399 if (fLastOpenedElement != null && input instanceof IJavaElement && ((IJavaElement)input).getHandleIdentifier().equals(fLastOpenedElement.getHandleIdentifier())) {
400 fLastOpenedElement= null;
403 fLastOpenedElement= null;
408 source= sourceRef.getSource();
409 } catch (JavaModelException ex) {
410 return ""; //$NON-NLS-1$
414 return ""; //$NON-NLS-1$
416 source= removeLeadingComments(source);
417 String delim= StubUtility.getLineDelimiterUsed((IJavaElement) input);
419 String[] sourceLines= Strings.convertIntoLines(source);
420 if (sourceLines == null || sourceLines.length == 0)
421 return ""; //$NON-NLS-1$
423 String firstLine= sourceLines[0];
424 boolean firstCharNotWhitespace= firstLine != null && firstLine.length() > 0 && !Character.isWhitespace(firstLine.charAt(0));
425 if (firstCharNotWhitespace)
426 sourceLines[0]= ""; //$NON-NLS-1$
427 IJavaProject project;
428 if (input instanceof IJavaElement)
429 project= ((IJavaElement) input).getJavaProject();
432 Strings.trimIndentation(sourceLines, project);
434 if (firstCharNotWhitespace)
435 sourceLines[0]= firstLine;
437 return Strings.concatenate(sourceLines, delim);
441 * @see AbstractInfoView#doSetInput(Object)
444 protected void doSetInput(Object input) {
445 if (input instanceof IDocument)
446 fViewer.setInput(input);
447 else if (input == null)
448 fViewer.setInput(new Document("")); //$NON-NLS-1$
450 IDocument document= new Document(input.toString());
451 JavaPlugin.getDefault().getJavaTextTools().setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING);
452 fViewer.setInput(document);
457 * Removes the leading comments from the given source.
459 * @param source the string with the source
460 * @return the source without leading comments
462 private String removeLeadingComments(String source) {
463 JavaCodeReader reader= new JavaCodeReader();
464 IDocument document= new Document(source);
466 i= reader.generated_2147504054850208463(document);
469 fCommentLineCount= document.getLineOfOffset(i);
470 } catch (BadLocationException e) {
471 fCommentLineCount= 0;
477 return source.substring(i);
481 * Sets the font for this viewer sustaining selection and scroll position.
483 private void setViewerFont() {
484 Font font= JFaceResources.getFont(SYMBOLIC_FONT_NAME);
486 if (fViewer.getDocument() != null) {
488 Point selection= fViewer.getSelectedRange();
489 int topIndex= fViewer.getTopIndex();
491 StyledText styledText= fViewer.getTextWidget();
492 Control parent= fViewer.getControl();
494 parent.setRedraw(false);
496 styledText.setFont(font);
498 fViewer.setSelectedRange(selection.x , selection.y);
499 fViewer.setTopIndex(topIndex);
501 if (parent instanceof Composite) {
502 Composite composite= (Composite) parent;
503 composite.layout(true);
506 parent.setRedraw(true);
510 StyledText styledText= fViewer.getTextWidget();
511 styledText.setFont(font);
516 * @see org.eclipse.jdt.internal.ui.infoviews.AbstractInfoView#getHelpContextId()
520 protected String getHelpContextId() {
521 return IJavaHelpContextIds.SOURCE_VIEW;