diff options
author | Anton Leherbauer | 2006-07-14 13:21:47 +0000 |
---|---|---|
committer | Anton Leherbauer | 2006-07-14 13:21:47 +0000 |
commit | 77d0b48df32d06eac7dbd9d65f77ab5629c6f1ce (patch) | |
tree | 1d7d7a67d58ec69a1a1a1539862b64d46d7e7d2d | |
parent | 5343674d38e47704221c994567695de515a49eb5 (diff) | |
download | org.eclipse.cdt-77d0b48df32d06eac7dbd9d65f77ab5629c6f1ce.tar.gz org.eclipse.cdt-77d0b48df32d06eac7dbd9d65f77ab5629c6f1ce.tar.xz org.eclipse.cdt-77d0b48df32d06eac7dbd9d65f77ab5629c6f1ce.zip |
Implement Bugzilla 81511 - Unreachable #ifdef blocks should be marked in editor (part 1)
This is the highlighting part. Folding will follow.
7 files changed, 1234 insertions, 76 deletions
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java new file mode 100644 index 00000000000..5944c133c32 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/LineBackgroundPainter.java @@ -0,0 +1,464 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPaintPositionManager; +import org.eclipse.jface.text.IPainter; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension5; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.TypedPosition; +import org.eclipse.swt.custom.LineBackgroundEvent; +import org.eclipse.swt.custom.LineBackgroundListener; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; + +/** + * A painter for configurable background painting a range of text lines. + * Replicates also the functionality of the + * {@link org.eclipse.jface.text.CursorLinePainter} + * because only one {@link LineBackgroundListener} is allowed + * per {@link StyledText} widget. + * + * @author anton.leherbauer@windriver.com + * + * @since 4.0 + */ +public class LineBackgroundPainter implements IPainter, LineBackgroundListener { + + /** The default position type for untyped positions */ + private static final String DEFAULT_TYPE= "__default__"; //$NON-NLS-1$ + /** The position type for the cursor line position */ + private static final String CURSOR_LINE_TYPE= "__cursor_line__"; //$NON-NLS-1$ + + /** Manager for position changes */ + private IPaintPositionManager fPositionManager; + /** Indicates whether this painter is active */ + private boolean fIsActive= false; + /** The text viewer this painter is associated with */ + private ITextViewer fTextViewer; + /** The viewer's widget */ + private StyledText fTextWidget; + /** Text positions (cursor line position is always at index 0 */ + private List fPositions= new ArrayList(); + /** Cached text positions */ + private List fLastPositions= new ArrayList(); + /** Temporary changed positions */ + private List fChangedPositions= new ArrayList(); + /** Cursor line position */ + private Position fCursorLine= new TypedPosition(0, 0, CURSOR_LINE_TYPE); + /** Saved cursor line position */ + private Position fLastCursorLine= new Position(0, 0); + /** Enablement of the cursor line highlighting */ + private boolean fCursorLineEnabled; + /** Map of position type to color */ + private Map fColorMap= new HashMap(); + + /** + * Creates a new painter for the given text viewer. + * @param textViewer + */ + public LineBackgroundPainter(ITextViewer textViewer) { + super(); + fTextViewer= textViewer; + fTextWidget= textViewer.getTextWidget(); + fPositions.add(fCursorLine); + fLastPositions.add(fLastCursorLine); + } + + /** + * Sets the color in which to draw the background of the given position type. + * + * @param positionType the position type for which to specify the background color + * @param color the color in which to draw the background of the given position type + */ + public void setBackgroundColor(String positionType, Color color) { + fColorMap.put(positionType, color); + } + + /** + * Sets the color in which to draw the background of the cursor line. + * + * @param cursorLineColor the color in which to draw the background of the cursor line + */ + public void setCursorLineColor(Color cursorLineColor) { + fColorMap.put(CURSOR_LINE_TYPE, cursorLineColor); + } + + /** + * Sets the color in which to draw the background of untyped positions. + * + * @param color the color in which to draw the background of untyped positions + */ + public void setDefaultColor(Color color) { + fColorMap.put(DEFAULT_TYPE, color); + } + + /** + * Enable/disable cursor line highlighting. + * + * @param enable + */ + public void enableCursorLine(boolean enable) { + fCursorLineEnabled= enable; + if (fCursorLineEnabled) { + updateCursorLine(); + } + } + + /** + * Set highlight positions. It is assumed that all positions + * are up-to-date with respect to the text viewers document. + * + * @param positions a list of <code>Position</code>s + */ + public void setHighlightPositions(List positions) { + boolean isActive= fIsActive; + deactivate(isActive); + fPositions.clear(); + fPositions.add(fCursorLine); + fPositions.addAll(positions); + if (isActive) { + activate(true); + } + } + + /** + * Trigger redraw of managed positions. + */ + public void redraw() { + if(fIsActive) { + fTextWidget.redraw(); + } + } + + /** + * Manage all positions. + * @param positions + */ + private void managePositions(List positions) { + if (fPositionManager == null) { + return; + } + int sz= fPositions.size(); + for (int i= 0; i < sz; ++i) { + Position position= (Position)positions.get(i); + fPositionManager.managePosition(position); + } + } + + /** + * Unmanage all positions. + * @param positions + */ + private void unmanagePositions(List positions) { + if (fPositionManager == null) { + return; + } + int sz= fPositions.size(); + for (int i= 0; i < sz; ++i) { + Position position= (Position)positions.get(i); + fPositionManager.unmanagePosition(position); + } + } + + /* + * @see org.eclipse.jface.text.IPainter#dispose() + */ + public void dispose() { + // no deactivate! + fIsActive= false; + fTextViewer= null; + fTextWidget= null; + fCursorLine= null; + fLastCursorLine= null; + fPositions= null; + fLastPositions= null; + fChangedPositions= null; + fColorMap= null; + } + + /* + * @see org.eclipse.jface.text.IPainter#paint(int) + */ + public void paint(int reason) { + IDocument document= fTextViewer.getDocument(); + if (document == null) { + deactivate(false); + return; + } + activate(false); + if (fCursorLineEnabled) { + // redraw in case of text changes prior to update of current cursor line + if (!fLastCursorLine.equals(fCursorLine)) { + redrawPositions(Collections.singletonList(fLastCursorLine)); + fLastCursorLine.offset= fCursorLine.offset; + fLastCursorLine.length= fCursorLine.length; + } + updateCursorLine(); + } + List changedPositions= getChangedPositions(); + if (changedPositions != null) { + redrawPositions(changedPositions); + updatePositions(); + redrawPositions(changedPositions); + } + } + + /** + * Activate the painter. + * @param redraw + */ + private void activate(boolean redraw) { + if (!fIsActive) { + fIsActive= true; + fTextWidget.addLineBackgroundListener(this); + if (redraw) { + if (fCursorLineEnabled) { + updateCursorLine(); + } + updatePositions(); + redrawPositions(fPositions); + } + managePositions(fPositions); + } + } + + /** + * Copy positions from the current position list to the last position list. + */ + private void updatePositions() { + int sz= fPositions.size(); + for (int i= 0; i < sz; ++i) { + Position position= (Position)fPositions.get(i); + Position copy; + if (i == fLastPositions.size()) { + copy= new Position(position.offset, position.length); + copy.isDeleted= position.isDeleted; + fLastPositions.add(copy); + } else { + copy= (Position)fLastPositions.get(i); + copy.offset= position.offset; + copy.length= position.length; + copy.isDeleted= position.isDeleted; + } + position.isDeleted= false; + } + int diff= fLastPositions.size() - sz; + while (diff > 0) { + --diff; + fLastPositions.remove(sz + diff); + } + } + + /** + * Check which positions have changed since last redraw. + * @return a list of changed positions or <code>null</code> if none changed. + */ + private List getChangedPositions() { + if (fLastPositions.size() != fPositions.size()) { + return fLastPositions; + } + List changedPositions= null; + for (int i= 0, sz= fPositions.size(); i < sz; ++i) { + Position previous= (Position)fLastPositions.get(i); + Position current= (Position)fPositions.get(i); + if (!previous.equals(current)) { + if (changedPositions == null) { + changedPositions= fChangedPositions; + changedPositions.clear(); + } + changedPositions.add(previous); + } + } + return changedPositions; + } + + /** + * Trigger redraw of given text positions. + */ + private void redrawPositions(List positions) { + final int minOffset= fTextViewer.getTopIndexStartOffset(); + final int maxOffset= fTextViewer.getBottomIndexEndOffset()+3; + Rectangle clientArea= fTextWidget.getClientArea(); + int width= clientArea.width + fTextWidget.getHorizontalPixel(); + int lineHeight= fTextWidget.getLineHeight(); + for (int i= 0, sz= positions.size(); i < sz; ++i) { + Position position= (Position)positions.get(i); + // if the position that is about to be drawn was deleted then we can't + if (position.isDeleted()) { + continue; + } + // check if position overlaps with visible area + if (!position.overlapsWith(minOffset, maxOffset - minOffset + 1)) { + continue; + } + int widgetOffset= getWidgetOffset(position.offset); + if (widgetOffset < 0 || widgetOffset > fTextWidget.getCharCount()) { + continue; + } + // TLETODO [performance] SyledText.getLocationAtOffset() is very expensive + Point upperLeft= fTextWidget.getLocationAtOffset(widgetOffset); + int upperY= Math.max(Math.min(upperLeft.y, clientArea.height), 0); + int height; + if (position.length == 0) { + height= lineHeight; + } else { + int widgetEndOffset= Math.min(widgetOffset + position.length, fTextWidget.getCharCount()); + Point lowerRight= fTextWidget.getLocationAtOffset(widgetEndOffset); + int lowerY= Math.min(lowerRight.y + lineHeight, clientArea.height); + height= lowerY - upperY; + } + if (height > 0) { + fTextWidget.redraw(0, upperY, width, height, false); + } + } + } + + /* + * @see org.eclipse.jface.text.IPainter#deactivate(boolean) + */ + public void deactivate(boolean redraw) { + if (fIsActive) { + fIsActive= false; + fTextWidget.removeLineBackgroundListener(this); + if (redraw) { + redrawPositions(fLastPositions); + } + unmanagePositions(fPositions); + } + } + + /* + * @see org.eclipse.jface.text.IPainter#setPositionManager(org.eclipse.jface.text.IPaintPositionManager) + */ + public void setPositionManager(IPaintPositionManager manager) { + fPositionManager= manager; + } + + /** + * Convert a document offset to the corresponding widget offset. + * @param documentOffset + * @return widget offset + */ + private int getWidgetOffset(int documentOffset) { + if (fTextViewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension= (ITextViewerExtension5)fTextViewer; + return extension.modelOffset2WidgetOffset(documentOffset); + } else { + IRegion visible= fTextViewer.getVisibleRegion(); + int widgetOffset= documentOffset - visible.getOffset(); + if (widgetOffset > visible.getLength()) { + return -1; + } + return widgetOffset; + } + } + + /** + * Convert a widget offset to the corresponding document offset. + * @param widgetOffset + * @return document offset + */ + private int getDocumentOffset(int widgetOffset) { + if (fTextViewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension= (ITextViewerExtension5)fTextViewer; + return extension.widgetOffset2ModelOffset(widgetOffset); + } else { + IRegion visible= fTextViewer.getVisibleRegion(); + if (widgetOffset > visible.getLength()) { + return -1; + } + return widgetOffset + visible.getOffset(); + } + } + + /* + * @see org.eclipse.swt.custom.LineBackgroundListener#lineGetBackground(org.eclipse.swt.custom.LineBackgroundEvent) + */ + public void lineGetBackground(LineBackgroundEvent event) { + if (fTextWidget != null) { + Position match= findIncludingPosition(getDocumentOffset(event.lineOffset)); + if (match != null) { + Color color= getColorForPosition(match); + if (color != null) { + event.lineBackground= color; + } + } + } + } + + /** + * Get the color associated with given position. + * @param position + * @return the color associated with the position type + */ + private Color getColorForPosition(Position position) { + if (position == fCursorLine) { + if (fCursorLine.length == 0) { + return (Color)fColorMap.get(CURSOR_LINE_TYPE); + } + } else { + if (position instanceof TypedPosition) { + String type= ((TypedPosition)position).getType(); + return (Color)fColorMap.get(type); + } else { + return (Color)fColorMap.get(DEFAULT_TYPE); + } + } + return null; + } + + /** + * Find position which includes the (document-)offset. + * @param offset + * @return the first position including the offset or <code>null</code>. + */ + private Position findIncludingPosition(int offset) { + // TLETODO [performance] Use binary search? + for (int i= fCursorLineEnabled ? 0 : 1, sz= fPositions.size(); i < sz; ++i) { + Position position= (Position)fPositions.get(i); + if (position.offset == offset || position.includes(offset)) { + return position; + } + } + return null; + } + + /** + * Updates the position of the cursor line. + */ + private void updateCursorLine() { + try { + + IDocument document= fTextViewer.getDocument(); + int lineNumber= document.getLineOfOffset(getDocumentOffset(fTextWidget.getCaretOffset())); + + fCursorLine.isDeleted= false; + fCursorLine.offset= document.getLineOffset(lineNumber); + fCursorLine.length= 0; + + } catch (BadLocationException e) { + // gracefully ignored + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index e9d743b2d11..afc860e111f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -56,7 +56,6 @@ import org.eclipse.jface.text.source.IAnnotationHoverExtension; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.ICharacterPairMatcher; import org.eclipse.jface.text.source.ILineRange; -import org.eclipse.jface.text.source.ISharedTextColors; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.ISourceViewerExtension3; import org.eclipse.jface.text.source.IVerticalRuler; @@ -517,10 +516,12 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS public final static String MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1$ /** Preference key for matching brackets color */ public final static String MATCHING_BRACKETS_COLOR = "matchingBracketsColor"; //$NON-NLS-1$ + /** Preference key for inactive code painter enablement */ + public static final String INACTIVE_CODE_ENABLE = "inactiveCodeEnable"; //$NON-NLS-1$ + /** Preference key for inactive code painter color */ + public static final String INACTIVE_CODE_COLOR = "inactiveCodeColor"; //$NON-NLS-1$ /** Preference key for inserting spaces rather than tabs */ public final static String SPACES_FOR_TABS = "spacesForTabs"; //$NON-NLS-1$ - /** Preference key for linked position color */ - public final static String LINKED_POSITION_COLOR = "linkedPositionColor"; //$NON-NLS-1$ /** Preference key for compiler task tags */ private final static String TRANSLATION_TASK_TAGS= CCorePreferenceConstants.TRANSLATION_TASK_TAGS; @@ -575,6 +576,11 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS if (fCEditorErrorTickUpdater != null) { fCEditorErrorTickUpdater.updateEditorImage(getInputCElement()); } + + if (getSourceViewer() != null) { + CSourceViewerDecorationSupport decoSupport = (CSourceViewerDecorationSupport) getSourceViewerDecorationSupport(getSourceViewer()); + decoSupport.editorInputChanged(input); + } } /** @@ -1211,6 +1217,29 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS dragSource.addDragListener(dragSourceListener); } + /* + * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#getSourceViewerDecorationSupport(org.eclipse.jface.text.source.ISourceViewer) + */ + protected SourceViewerDecorationSupport getSourceViewerDecorationSupport( + ISourceViewer viewer) { + if (fSourceViewerDecorationSupport == null) { + fSourceViewerDecorationSupport= new CSourceViewerDecorationSupport(viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors()); + configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport); + } + return fSourceViewerDecorationSupport; + } + + /* + * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#configureSourceViewerDecorationSupport(org.eclipse.ui.texteditor.SourceViewerDecorationSupport) + */ + protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) { + super.configureSourceViewerDecorationSupport(support); + //Enhance the stock source viewer decorator with a bracket matcher + support.setCharacterPairMatcher(fBracketMatcher); + support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR); + ((CSourceViewerDecorationSupport)support).setInactiveCodePainterPreferenceKeys(INACTIVE_CODE_ENABLE, INACTIVE_CODE_COLOR); + } + /** * Jumps to the matching bracket. */ @@ -1448,29 +1477,19 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS } /* - * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int) + * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int) */ protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { - fAnnotationAccess = createAnnotationAccess(); - - ISharedTextColors sharedColors = CUIPlugin.getDefault().getSharedTextColors(); - fOverviewRuler = createOverviewRuler(sharedColors); - ISourceViewer sourceViewer = new CSourceViewer( this, parent, ruler, styles, - fOverviewRuler, + getOverviewRuler(), isOverviewRulerVisible()); - fSourceViewerDecorationSupport = - new SourceViewerDecorationSupport(sourceViewer, fOverviewRuler, fAnnotationAccess, sharedColors); - - configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport); - //Enhance the stock source viewer decorator with a bracket matcher - fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher); - fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR); + CSourceViewerDecorationSupport decoSupport = (CSourceViewerDecorationSupport) getSourceViewerDecorationSupport(sourceViewer); + decoSupport.editorInputChanged(getEditorInput()); CUIHelp.setHelp(this, sourceViewer.getTextWidget(), ICHelpContextIds.CEDITOR_VIEW); @@ -1620,6 +1639,10 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS // Do nothing the outliner is listener to the // CoreModel WorkingCopy changes instead. // It will allow more fined grained. + if (somethingHasChanged && getSourceViewer() != null) { + CSourceViewerDecorationSupport decoSupport = (CSourceViewerDecorationSupport) getSourceViewerDecorationSupport(getSourceViewer()); + decoSupport.editorInputChanged(getEditorInput()); + } } public CSourceViewer getCSourceViewer() { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java index 126901bc687..2afc3369a20 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java @@ -14,7 +14,10 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.text.DocumentCommand; import org.eclipse.jface.text.ITextViewerExtension; import org.eclipse.jface.text.contentassist.IContentAssistant; @@ -24,10 +27,16 @@ import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPathEditorInput; +import org.eclipse.ui.editors.text.ILocationProvider; +import org.eclipse.ui.ide.ResourceUtil; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.ui.editor.CEditor.ITextConverter; @@ -80,6 +89,35 @@ public class CSourceViewer extends ProjectionViewer implements ITextViewerExtens } catch (CoreException e) { CUIPlugin.getDefault().log(e); } + } else { + // compute the language from the plain editor input + IContentType contentType = null; + IEditorInput input = editor.getEditorInput(); + IFile file = ResourceUtil.getFile(input); + if (file != null) { + contentType = CCorePlugin.getContentType(file.getProject(), file.getName()); + try { + return LanguageManager.getInstance().getLanguage(contentType); + } catch (CoreException exc) { + CUIPlugin.getDefault().log(exc.getStatus()); + } + } else if (input instanceof IPathEditorInput) { + IPath path = ((IPathEditorInput)input).getPath(); + contentType = CCorePlugin.getContentType(path.lastSegment()); + } else { + ILocationProvider locationProvider = (ILocationProvider)input.getAdapter(ILocationProvider.class); + if (locationProvider != null) { + IPath path = locationProvider.getPath(input); + contentType = CCorePlugin.getContentType(path.lastSegment()); + } + } + if (contentType != null) { + try { + return LanguageManager.getInstance().getLanguage(contentType); + } catch (CoreException exc) { + CUIPlugin.getDefault().log(exc.getStatus()); + } + } } return null; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewerDecorationSupport.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewerDecorationSupport.java new file mode 100644 index 00000000000..b696516e8cf --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewerDecorationSupport.java @@ -0,0 +1,528 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.editor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewerExtension2; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.IAnnotationAccess; +import org.eclipse.jface.text.source.IOverviewRuler; +import org.eclipse.jface.text.source.ISharedTextColors; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IPositionConverter; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.LineBackgroundPainter; + +/** + * <code>SourceViewerDecorationSupport</code> with extension(s): + * <ul> + * <li>inactive code painter</li> + * </ul> + * + * @author anton.leherbauer@windriver.com + * + * @since 4.0 + */ +public class CSourceViewerDecorationSupport + extends SourceViewerDecorationSupport { + + /** + * This job takes the current translation unit and produces an + * AST in the background. Upon completion, {@link #inactiveCodePositionsChanged} + * is called in the display thread. + */ + private class UpdateJob extends Job { + + /** + * @param name + */ + public UpdateJob(String name) { + super(name); + setSystem(true); + setPriority(Job.DECORATE); + } + + /* + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + protected IStatus run(IProgressMonitor monitor) { + IStatus result = Status.OK_STATUS; + if (fASTTranslationUnit == null && fTranslationUnit != null) { + try { + fParseTimeStamp = System.currentTimeMillis(); + fASTTranslationUnit = fTranslationUnit.getLanguage().getASTTranslationUnit(fTranslationUnit, ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_SKIP_INDEXED_HEADERS); + } catch (CoreException exc) { + result = exc.getStatus(); + } + } + if (monitor.isCanceled() || fViewer == null) { + result = Status.CANCEL_STATUS; + } else { + final List inactiveCodePositions = collectInactiveCodePositions(fASTTranslationUnit); + Runnable updater = new Runnable() { + public void run() { + inactiveCodePositionsChanged(inactiveCodePositions); + } + }; + fViewer.getTextWidget().getDisplay().asyncExec(updater); + } + return result; + } + + } + + /** + * Implementation of <code>IRegion</code> that can be reused + * by setting the offset and the length. + */ + private static class ReusableRegion extends Position implements IRegion { + public ReusableRegion(int offset, int length) { + super(offset, length); + } + public ReusableRegion(IRegion region) { + super(region.getOffset(), region.getLength()); + } + } + + /** The preference key for the inactive code highlight color */ + private String fInactiveCodeColorKey; + /** The preference key for the inactive code highlight enablement */ + private String fInactiveCodeEnableKey; + /** The generic line background painter instance. */ + private LineBackgroundPainter fLineBackgroundPainter; + /** The shared colors instance (duplicate of private base class member) */ + private ISharedTextColors fSharedColors; + /** The preference store (duplicate of private base class member) */ + private IPreferenceStore fPrefStore; + /** The preference key for the cursor line highlight color (duplicate of private base class member) */ + private String fCLPColorKey; + /** The preference key for the cursor line highlight enablement (duplicate of private base class member) */ + private String fCLPEnableKey; + /** The source viewer (duplicate of private base class member) */ + protected ISourceViewer fViewer; + /** The current translation unit */ + private ITranslationUnit fTranslationUnit; + /** The corresponding AST translation unit */ + private IASTTranslationUnit fASTTranslationUnit; + /** The time stamp when the parsing was initiated */ + private long fParseTimeStamp; + /** The background job doing the AST parsing */ + private Job fUpdateJob; + + /** + * Inherited constructor. + * + * @param sourceViewer + * @param overviewRuler + * @param annotationAccess + * @param sharedTextColors + */ + CSourceViewerDecorationSupport( + ISourceViewer sourceViewer, + IOverviewRuler overviewRuler, + IAnnotationAccess annotationAccess, + ISharedTextColors sharedTextColors) { + super(sourceViewer, overviewRuler, annotationAccess, sharedTextColors); + // we have to save our own reference, because super class members are all private + fViewer = sourceViewer; + fSharedColors = sharedTextColors; + } + + /** + * Notify that the associated editor got a new input. + * This is currently also used to notify of a reconcilation + * to update the inactive code while editing. + * + * @param input the new editor input + */ + void editorInputChanged(IEditorInput input) { + if (fUpdateJob != null) { + fUpdateJob.cancel(); + } + fTranslationUnit = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(input); + fASTTranslationUnit = null; + if (isInactiveCodePositionsActive()) { + updateInactiveCodePositions(); + } + } + + /** + * Schedule update of the AST in the background. + */ + private void updateInactiveCodePositions() { + if (fUpdateJob == null) { + fUpdateJob = new UpdateJob("Update Inactive Code Positions"); //$NON-NLS-1$ + } + if (fUpdateJob.getState() == Job.NONE) { + fUpdateJob.schedule(); + } + } + + /* + * @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#dispose() + */ + public void dispose() { + super.dispose(); + fViewer = null; + if (fUpdateJob != null) { + fUpdateJob.cancel(); + } + } + + /* + * @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#handlePreferenceStoreChanged(org.eclipse.jface.util.PropertyChangeEvent) + */ + protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { + String p = event.getProperty(); + if (p.equals(fCLPEnableKey)) { + if (isCLPActive()) { + showCLP(); + } else { + hideCLP(); + } + } else if (p.equals(fCLPColorKey)) { + updateCLPColor(); + } else if (p.equals(fInactiveCodeEnableKey)) { + if (isInactiveCodePositionsActive()) { + showInactiveCodePositions(); + } else { + hideInactiveCodePositions(); + } + } else if (p.equals(fInactiveCodeColorKey)) { + updateInactiveCodeColor(); + } + super.handlePreferenceStoreChanged(event); + } + + /** + * Update the color for inactive code positions. + */ + private void updateInactiveCodeColor() { + if (fLineBackgroundPainter != null) { + fLineBackgroundPainter.setDefaultColor(getColor(fInactiveCodeColorKey)); + if (isInactiveCodePositionsActive()) { + fLineBackgroundPainter.redraw(); + } + } + } + + /** + * Update the color for the cursor line painter. + */ + private void updateCLPColor() { + if (fLineBackgroundPainter != null) { + fLineBackgroundPainter.setCursorLineColor(getColor(fCLPColorKey)); + if (isCLPActive()) { + fLineBackgroundPainter.redraw(); + } + } + } + + /** + * Hide cursor line painter. + */ + private void hideCLP() { + if (fLineBackgroundPainter != null) { + if (!isInactiveCodePositionsActive()) { + uninstallInactiveCodePainter(); + } else { + fLineBackgroundPainter.enableCursorLine(false); + fLineBackgroundPainter.redraw(); + } + } + } + + /** + * Show cursor line painter. + */ + private void showCLP() { + installInactiveCodePainter(); + if (fLineBackgroundPainter != null) { + fLineBackgroundPainter.enableCursorLine(true); + fLineBackgroundPainter.redraw(); + } + } + + /** + * @return true if cursor line painter is active. + */ + private boolean isCLPActive() { + if (fPrefStore != null) { + return fPrefStore.getBoolean(fCLPEnableKey); + } + return false; + } + + /** + * @return true if inactive code painter is active. + */ + private boolean isInactiveCodePositionsActive() { + if (fPrefStore != null) { + return fPrefStore.getBoolean(fInactiveCodeEnableKey); + } + return false; + } + + /** + * Returns the shared color for the given key. + * + * @param key the color key string + * @return the shared color for the given key + */ + private Color getColor(String key) { + if (fPrefStore != null) { + RGB rgb = PreferenceConverter.getColor(fPrefStore, key); + return getColor(rgb); + } + return null; + } + + /** + * Returns the shared color for the given RGB. + * + * @param rgb the rgb + * @return the shared color for the given rgb + */ + private Color getColor(RGB rgb) { + return fSharedColors.getColor(rgb); + } + + /* + * @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#install(org.eclipse.jface.preference.IPreferenceStore) + */ + public void install(IPreferenceStore store) { + super.install(store); + fPrefStore = store; + if (isCLPActive()) { + showCLP(); + } + if (isInactiveCodePositionsActive()) { + showInactiveCodePositions(); + } + } + + /* + * @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#uninstall() + */ + public void uninstall() { + uninstallInactiveCodePainter(); + super.uninstall(); + } + + /** + * Install inactive code/cursor line painter. + */ + private void installInactiveCodePainter() { + if (fLineBackgroundPainter == null) { + if (fViewer instanceof ITextViewerExtension2) { + fLineBackgroundPainter = new LineBackgroundPainter(fViewer); + fLineBackgroundPainter.setDefaultColor(getColor(fInactiveCodeColorKey)); + fLineBackgroundPainter.setCursorLineColor(getColor(fCLPColorKey)); + fLineBackgroundPainter.enableCursorLine(isCLPActive()); + ((ITextViewerExtension2)fViewer).addPainter(fLineBackgroundPainter); + } + } + } + + /** + * Uninstall inactive code/cursor line painter. + */ + private void uninstallInactiveCodePainter() { + if (fLineBackgroundPainter != null) { + ((ITextViewerExtension2)fViewer).removePainter(fLineBackgroundPainter); + fLineBackgroundPainter.deactivate(true); + fLineBackgroundPainter.dispose(); + fLineBackgroundPainter = null; + } + } + + /** + * Show inactive code positions. + */ + private void showInactiveCodePositions() { + installInactiveCodePainter(); + updateInactiveCodePositions(); + } + + /** + * Hide inactive code positions. + */ + private void hideInactiveCodePositions() { + if (fLineBackgroundPainter != null) { + if (!isCLPActive()) { + uninstallInactiveCodePainter(); + } else { + fLineBackgroundPainter.setHighlightPositions(Collections.EMPTY_LIST); + } + } + } + + private void inactiveCodePositionsChanged(List inactiveCodePositions) { + if (fLineBackgroundPainter != null) { + if (!inactiveCodePositions.isEmpty()) { + IPositionConverter pt = CCorePlugin.getPositionTrackerManager().findPositionConverter(fTranslationUnit.getPath(), fParseTimeStamp); + if (pt != null) { + List convertedPositions = new ArrayList(inactiveCodePositions.size()); + for (Iterator iter = inactiveCodePositions.iterator(); iter + .hasNext();) { + IRegion pos = (IRegion) iter.next(); + convertedPositions.add(new ReusableRegion(pt.historicToActual(pos))); + } + inactiveCodePositions = convertedPositions; + } + } + fLineBackgroundPainter.setHighlightPositions(inactiveCodePositions); + } + } + + /** + * Collect source positions of preprocessor-hidden branches + * in the given translation unit. + * + * @param translationUnit the {@link IASTTranslationUnit}, may be <code>null</code> + * @return a {@link List} of {@link IRegion}s + */ + private static List collectInactiveCodePositions(IASTTranslationUnit translationUnit) { + List positions = new ArrayList(); + if (translationUnit == null) { + return positions; + } + int inactiveCodeStart = -1; + boolean inInactiveCode = false; + IASTPreprocessorStatement[] preprocStmts = translationUnit.getAllPreprocessorStatements(); + for (int i = 0; i < preprocStmts.length; i++) { + IASTPreprocessorStatement statement = preprocStmts[i]; + if (statement instanceof IASTPreprocessorIfStatement) { + IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement; + if (!inInactiveCode && !ifStmt.taken()) { + IASTNodeLocation nodeLocation = ifStmt.getNodeLocations()[0]; + inactiveCodeStart = nodeLocation.getNodeOffset(); + inInactiveCode = true; + } else if (inInactiveCode && ifStmt.taken()) { + // should not happen! + assert false; + } + } else if (statement instanceof IASTPreprocessorIfdefStatement) { + IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement; + if (!inInactiveCode && !ifdefStmt.taken()) { + IASTNodeLocation nodeLocation = ifdefStmt.getNodeLocations()[0]; + inactiveCodeStart = nodeLocation.getNodeOffset(); + inInactiveCode = true; + } else if (inInactiveCode && ifdefStmt.taken()) { + // should not happen! + assert false; + } + } else if (statement instanceof IASTPreprocessorIfndefStatement) { + IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement; + if (!inInactiveCode && !ifndefStmt.taken()) { + IASTNodeLocation nodeLocation = ifndefStmt.getNodeLocations()[0]; + inactiveCodeStart = nodeLocation.getNodeOffset(); + inInactiveCode = true; + } else if (inInactiveCode && ifndefStmt.taken()) { + // should not happen! + assert false; + } + } else if (statement instanceof IASTPreprocessorElseStatement) { + IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement; + if (!inInactiveCode && !elseStmt.taken()) { + IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0]; + inactiveCodeStart = nodeLocation.getNodeOffset(); + inInactiveCode = true; + } else if (inInactiveCode && elseStmt.taken()) { + IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0]; + int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength(); + positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart)); + inInactiveCode = false; + } + } else if (statement instanceof IASTPreprocessorElifStatement) { + IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement)statement; + if (!inInactiveCode && !elifStmt.taken()) { + IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0]; + inactiveCodeStart = nodeLocation.getNodeOffset(); + inInactiveCode = true; + } else if (inInactiveCode && elifStmt.taken()) { + IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0]; + int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength(); + positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart)); + inInactiveCode = false; + } + } else if (statement instanceof IASTPreprocessorEndifStatement) { + IASTPreprocessorEndifStatement endifStmt = (IASTPreprocessorEndifStatement)statement; + if (inInactiveCode) { + IASTNodeLocation nodeLocation = endifStmt.getNodeLocations()[0]; + int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength(); + positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart)); + inInactiveCode = false; + } + } + } + if (inInactiveCode) { + IASTNodeLocation[] nodeLocations = translationUnit.getNodeLocations(); + IASTNodeLocation lastNode = nodeLocations[nodeLocations.length - 1]; + int inactiveCodeEnd = lastNode.getNodeOffset() + lastNode.getNodeLength(); + positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart)); + inInactiveCode = false; + } + return positions; + } + + /* + * @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#setCursorLinePainterPreferenceKeys(java.lang.String, java.lang.String) + */ + public void setCursorLinePainterPreferenceKeys(String enableKey, String colorKey) { + // this is a dirty hack to override the original cursor line painter + // and replace it with the generic BackgroundLinePainter + fCLPEnableKey = enableKey; + fCLPColorKey = colorKey; + super.setCursorLinePainterPreferenceKeys(enableKey + "-overridden", colorKey); //$NON-NLS-1$ + } + + /** + * Set the preference keys for the inactive code painter. + * @param enableKey + * @param colorKey + */ + public void setInactiveCodePainterPreferenceKeys(String enableKey, String colorKey) { + fInactiveCodeEnableKey = enableKey; + fInactiveCodeColorKey = colorKey; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java index 567c458fac6..cfea8e19093 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java @@ -16,20 +16,13 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; -import org.eclipse.cdt.internal.ui.ICHelpContextIds; -import org.eclipse.cdt.internal.ui.editor.CEditor; -import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; -import org.eclipse.cdt.internal.ui.text.CTextTools; -import org.eclipse.cdt.internal.ui.text.ICColorConstants; -import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.cdt.ui.PreferenceConstants; -import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.RGB; @@ -50,26 +43,36 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.texteditor.AbstractTextEditor; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; + +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.ICColorConstants; + /* * The page for setting the editor options. */ public class CEditorPreferencePage extends AbstractPreferencePage implements IWorkbenchPreferencePage { - protected final String[][] fListModel = new String[][] { { PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.MultiLine"), ICColorConstants.C_MULTI_LINE_COMMENT }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.singleLine"), ICColorConstants.C_SINGLE_LINE_COMMENT }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.keywords"), ICColorConstants.C_KEYWORD }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.builtInTypes"), ICColorConstants.C_TYPE }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.strings"), ICColorConstants.C_STRING }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.operators"), ICColorConstants.C_OPERATOR }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.braces"), ICColorConstants.C_BRACES }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.numbers"), ICColorConstants.C_NUMBER }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags.others"), ICColorConstants.C_DEFAULT }, { //$NON-NLS-1$ - PreferencesMessages.getString("CEditorPreferencePage.cCommentTaskTags"), PreferenceConstants.EDITOR_TASK_TAG_COLOR } //$NON-NLS-1$ + protected final String[][] fListModel = new String[][] { { PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.MultiLine"), ICColorConstants.C_MULTI_LINE_COMMENT }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.singleLine"), ICColorConstants.C_SINGLE_LINE_COMMENT }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.keywords"), ICColorConstants.C_KEYWORD }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.builtInTypes"), ICColorConstants.C_TYPE }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.strings"), ICColorConstants.C_STRING }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.operators"), ICColorConstants.C_OPERATOR }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.braces"), ICColorConstants.C_BRACES }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.numbers"), ICColorConstants.C_NUMBER }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.others"), ICColorConstants.C_DEFAULT }, { //$NON-NLS-1$ + PreferencesMessages.getString("CEditorPreferencePage.syntaxPage.cCommentTaskTags"), PreferenceConstants.EDITOR_TASK_TAG_COLOR } //$NON-NLS-1$ }; protected final String[][] fAppearanceColorListModel = new String[][] { {PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.matchingBracketColor"), CEditor.MATCHING_BRACKETS_COLOR, null }, //$NON-NLS-1$ - {PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.linkedPositionColor"), CEditor.LINKED_POSITION_COLOR, null }, //$NON-NLS-1$ + {PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.inactiveCodeColor"), CEditor.INACTIVE_CODE_COLOR, null }, //$NON-NLS-1$ }; private CTextTools fCTextTools; @@ -82,6 +85,12 @@ public class CEditorPreferencePage extends AbstractPreferencePage implements IWo private CEditorHoverConfigurationBlock fCEditorHoverConfigurationBlock; private FoldingConfigurationBlock fFoldingConfigurationBlock; + private List fAppearanceColorList; + + private ColorEditor fAppearanceColorEditor; + + private Button fAppearanceColorDefault; + public CEditorPreferencePage() { super(); @@ -111,9 +120,10 @@ public class CEditorPreferencePage extends AbstractPreferencePage implements IWo overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_OPERATOR + "_bold")); //$NON-NLS-1$ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.MATCHING_BRACKETS_COLOR)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.MATCHING_BRACKETS)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.INACTIVE_CODE_COLOR)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.INACTIVE_CODE_ENABLE)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.SPACES_FOR_TABS)); - overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.LINKED_POSITION_COLOR)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_TASK_TAG_COLOR)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_TASK_TAG_BOLD)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_TASK_INDICATION_COLOR)); @@ -140,6 +150,9 @@ public class CEditorPreferencePage extends AbstractPreferencePage implements IWo store.setDefault(CEditor.MATCHING_BRACKETS, true); PreferenceConverter.setDefault(store, CEditor.MATCHING_BRACKETS_COLOR, new RGB(170,170,170)); + store.setDefault(CEditor.INACTIVE_CODE_ENABLE, true); + PreferenceConverter.setDefault(store, CEditor.INACTIVE_CODE_COLOR, new RGB(224, 224, 224)); + store.setDefault(CEditor.SPACES_FOR_TABS, false); PreferenceConverter.setDefault(store, ICColorConstants.C_MULTI_LINE_COMMENT, new RGB(63, 127, 95)); @@ -169,8 +182,6 @@ public class CEditorPreferencePage extends AbstractPreferencePage implements IWo PreferenceConverter.setDefault(store, ICColorConstants.C_NUMBER, new RGB(0, 0, 0)); store.setDefault(ICColorConstants.C_DEFAULT + "_bold", false); //$NON-NLS-1$ - PreferenceConverter.setDefault(store, CEditor.LINKED_POSITION_COLOR, new RGB(0, 200, 100)); - } /* @@ -328,11 +339,117 @@ public class CEditorPreferencePage extends AbstractPreferencePage implements IWo String label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.matchingBrackets"); //$NON-NLS-1$ addCheckBox(behaviorComposite, label, CEditor.MATCHING_BRACKETS, 0); + label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.inactiveCode"); //$NON-NLS-1$ + addCheckBox(behaviorComposite, label, CEditor.INACTIVE_CODE_ENABLE, 0); + label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.tabSpace"); //$NON-NLS-1$ addCheckBox(behaviorComposite, label, CEditor.SPACES_FOR_TABS, 0); + + Label l = new Label(behaviorComposite, SWT.LEFT); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = 2; + gd.heightHint = convertHeightInCharsToPixels(1) / 2; + l.setLayoutData(gd); + + l = new Label(behaviorComposite, SWT.LEFT); + l.setText(PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.appearanceColorOptions")); //$NON-NLS-1$ + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = 2; + l.setLayoutData(gd); + + Composite editorComposite = new Composite(behaviorComposite, SWT.NONE); + layout = new GridLayout(); + layout.numColumns = 2; + layout.marginHeight = 0; + layout.marginWidth = 0; + editorComposite.setLayout(layout); + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL); + gd.horizontalSpan = 2; + editorComposite.setLayoutData(gd); + + fAppearanceColorList = new List(editorComposite, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER); + gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + gd.heightHint = convertHeightInCharsToPixels(8); + fAppearanceColorList.setLayoutData(gd); + + Composite stylesComposite = new Composite(editorComposite, SWT.NONE); + layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.numColumns = 2; + stylesComposite.setLayout(layout); + stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + l = new Label(stylesComposite, SWT.LEFT); + l.setText(PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.Color")); //$NON-NLS-1$ + gd = new GridData(); + gd.horizontalAlignment = GridData.BEGINNING; + l.setLayoutData(gd); + + fAppearanceColorEditor = new ColorEditor(stylesComposite); + Button foregroundColorButton = fAppearanceColorEditor.getButton(); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalAlignment = GridData.BEGINNING; + foregroundColorButton.setLayoutData(gd); + + SelectionListener colorDefaultSelectionListener= new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + boolean systemDefault= fAppearanceColorDefault.getSelection(); + fAppearanceColorEditor.getButton().setEnabled(!systemDefault); + + int i= fAppearanceColorList.getSelectionIndex(); + String key= fAppearanceColorListModel[i][2]; + if (key != null) + fOverlayStore.setValue(key, systemDefault); + } + }; + + fAppearanceColorDefault= new Button(stylesComposite, SWT.CHECK); + fAppearanceColorDefault.setText(PreferencesMessages.getString("CEditorPreferencePage.colorPage.systemDefault")); //$NON-NLS-1$ + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalAlignment= GridData.BEGINNING; + gd.horizontalSpan= 2; + fAppearanceColorDefault.setLayoutData(gd); + fAppearanceColorDefault.setVisible(false); + fAppearanceColorDefault.addSelectionListener(colorDefaultSelectionListener); + + fAppearanceColorList.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleAppearanceColorListSelection(); + } + }); + foregroundColorButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + int i = fAppearanceColorList.getSelectionIndex(); + String key = fAppearanceColorListModel[i][1]; + + PreferenceConverter.setValue(fOverlayStore, key, fAppearanceColorEditor.getColorValue()); + } + }); return behaviorComposite; } + private void handleAppearanceColorListSelection() { + int i = fAppearanceColorList.getSelectionIndex(); + String key = fAppearanceColorListModel[i][1]; + RGB rgb = PreferenceConverter.getColor(fOverlayStore, key); + fAppearanceColorEditor.setColorValue(rgb); + updateAppearanceColorWidgets(fAppearanceColorListModel[i][2]); + } + + private void updateAppearanceColorWidgets(String systemDefaultKey) { + if (systemDefaultKey == null) { + fAppearanceColorDefault.setSelection(false); + fAppearanceColorDefault.setVisible(false); + fAppearanceColorEditor.getButton().setEnabled(true); + } else { + boolean systemDefault= fOverlayStore.getBoolean(systemDefaultKey); + fAppearanceColorDefault.setSelection(systemDefault); + fAppearanceColorDefault.setVisible(true); + fAppearanceColorEditor.getButton().setEnabled(!systemDefault); + } + } + private Control createHeader(Composite parent) { String text = PreferencesMessages.getString("CEditorPreferencePage.link"); //$NON-NLS-1$ Link link = new Link(parent, SWT.NONE); @@ -392,6 +509,16 @@ public class CEditorPreferencePage extends AbstractPreferencePage implements IWo initializeFields(); + for (int i = 0; i < fAppearanceColorListModel.length; i++) { + fAppearanceColorList.add(fAppearanceColorListModel[i][0]); + } + fAppearanceColorList.getDisplay().asyncExec(new Runnable() { + public void run() { + fAppearanceColorList.select(0); + handleAppearanceColorListSelection(); + } + }); + for (int i = 0; i < fListModel.length; i++) { fList.add(fListModel[i][0]); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index 17c543b086a..ce3ebbd9692 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -59,8 +59,6 @@ TodoTaskInputDialog.error.comma=Name cannot contain a comma. TodoTaskInputDialog.error.entryExists=Entry with the same name already exists. TodoTaskInputDialog.error.noSpace=Name can not start or end with a whitespace. -CEditorPreferencePage.cCommentTaskTags=Task Tags - CEditorPreferencePage.link=Note that some preferences may be set on the <a href="org.eclipse.ui.preferencePages.GeneralTextEditor">Text Editors</a> preference page. CEditorPreferencePage.generalTabTitle=Appeara&nce CEditorPreferencePage.annotationTabTitle= &Annotations @@ -91,20 +89,16 @@ CEditorPreferencePage.ContentAssistPage.completionProposalForegroundColor=&Foreg CEditorPreferencePage.ContentAssistPage.parameterBackgroundColor=Bac&kground for method parameters: CEditorPreferencePage.ContentAssistPage.parameterForegroundColor=Fo®round for method parameters: CEditorPreferencePage.ContentAssistPage.autoActivationEnableDoubleColon=Enable "::" as trigger -CEditorPreferencePage.cCommentTaskTags.MultiLine=Multi-line comment -CEditorPreferencePage.cCommentTaskTags.singleLine=Single-line comment -CEditorPreferencePage.cCommentTaskTags.keywords=Keywords -CEditorPreferencePage.cCommentTaskTags.builtInTypes=Built-in types -CEditorPreferencePage.cCommentTaskTags.strings=Strings -CEditorPreferencePage.cCommentTaskTags.operators=Operators -CEditorPreferencePage.cCommentTaskTags.braces=Braces -CEditorPreferencePage.cCommentTaskTags.numbers=Numbers -CEditorPreferencePage.cCommentTaskTags.others=Others -CEditorPreferencePage.annotationsPage.presentationOptions=Annotation Presentation Options -CEditorPreferencePage.annotationsPage.showInText=Show In Text -CEditorPreferencePage.annotationsPage.showInOverview=Show In Overview Ruler -CEditorPreferencePage.annotationsPage.showInVertical=Show In Vertical Ruler -CEditorPreferencePage.annotationsPage.color=Annotations Color +CEditorPreferencePage.syntaxPage.MultiLine=Multi-line comment +CEditorPreferencePage.syntaxPage.singleLine=Single-line comment +CEditorPreferencePage.syntaxPage.keywords=Keywords +CEditorPreferencePage.syntaxPage.builtInTypes=Built-in types +CEditorPreferencePage.syntaxPage.strings=Strings +CEditorPreferencePage.syntaxPage.operators=Operators +CEditorPreferencePage.syntaxPage.braces=Braces +CEditorPreferencePage.syntaxPage.numbers=Numbers +CEditorPreferencePage.syntaxPage.others=Others +CEditorPreferencePage.syntaxPage.cCommentTaskTags=Task Tags CEditorPreferencePage.colorPage.backgroundColor=Bac&kground Color: CEditorPreferencePage.colorPage.systemDefault=S&ystem Default CEditorPreferencePage.colorPage.custom=C&ustom @@ -112,30 +106,14 @@ CEditorPreferencePage.colorPage.foreground=Fo®round: CEditorPreferencePage.colorPage.color=C&olor: CEditorPreferencePage.colorPage.bold=&Bold CEditorPreferencePage.colorPage.preview=Preview: -CEditorPreferencePage.behaviorPage.textFont=Text &font: -CEditorPreferencePage.behaviorPage.tabWidth=Displayed &tab width: -CEditorPreferencePage.behaviorPage.marginColumn=Print m&argin column: CEditorPreferencePage.behaviorPage.tabSpace=&Insert space for tabs CEditorPreferencePage.behaviorPage.matchingBrackets=Highlight &matching brackets -CEditorPreferencePage.behaviorPage.highlightLine=&Highlight current line -CEditorPreferencePage.behaviorPage.printMargin=Show &print margin -CEditorPreferencePage.behaviorPage.showLineNumbers=Show &line numbers -CEditorPreferencePage.behaviorPage.showOverviewRuler=Show &overview ruler -CEditorPreferencePage.behaviorPage.appearanceColorOptions=Appearance color options -CEditorPreferencePage.behaviorPage.lineNumberColor=Line number foreground -CEditorPreferencePage.behaviorPage.matchingBracketColor=Matching bracket highlight -CEditorPreferencePage.behaviorPage.currentLineHighlightColor=Current line highlight -CEditorPreferencePage.behaviorPage.printMarginColor=Print margin -CEditorPreferencePage.behaviorPage.linkedPositionColor=HyperLink -CEditorPreferencePage.behaviorPage.selectionForegroundColor=Selection foreground -CEditorPreferencePage.behaviorPage.selectionBackgroundColor=Selection background -CEditorPreferencePage.behaviorPage.systemDefault=System Default -CEditorPreferencePage.accessibility.disableCustomCarets= &Use custom caret -CEditorPreferencePage.accessibility.wideCaret= Enable thic&k caret +CEditorPreferencePage.behaviorPage.inactiveCode=Highlight &inactive code +CEditorPreferencePage.behaviorPage.appearanceColorOptions=Appearance color options: +CEditorPreferencePage.behaviorPage.matchingBracketColor=Matching brackets highlight +CEditorPreferencePage.behaviorPage.inactiveCodeColor=Inactive code highlight CEditorPreferencePage.behaviorPage.Color=Color: CEditorPreferencePage.textFont.changeButton=C&hange... -CEditorPreferencePage.Navigation=Navigation -CEditorPreferencePage.Enable_Hyperlink_Navigation=Enable Hyperlink Navigation TemplatePreferencePage.Viewer.preview=Preview: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java index e5f9caee450..e6c9806bff4 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -168,7 +168,7 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { scanner = fTextTools.getCppCodeScanner(); } else if (language instanceof GCCLanguage) { scanner = fTextTools.getCCodeScanner(); - } else { + } else if (language != null) { ILanguageUI languageUI = (ILanguageUI)language.getAdapter(ILanguageUI.class); if (languageUI != null) scanner = languageUI.getCodeScanner(); |