mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-13 03:55:22 +02:00
Implement bug 140333 - [Editor] View non-printable characters
This commit is contained in:
parent
35c934dd1f
commit
e77a039088
5 changed files with 574 additions and 9 deletions
BIN
core/org.eclipse.cdt.ui/icons/etool16/show_invisible_chars.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/etool16/show_invisible_chars.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 123 B |
|
@ -133,8 +133,10 @@ todoTaskPrefName=Task Tags
|
||||||
Editors.DefaultTextEditor = Default Text Editor
|
Editors.DefaultTextEditor = Default Text Editor
|
||||||
AsmEditor.name = Assembly Editor
|
AsmEditor.name = Assembly Editor
|
||||||
|
|
||||||
CFolderActionSet.label=C Folder Actions
|
# Show Invisble Characters
|
||||||
CFolderActionSet.description=C Folder Action Set
|
ShowInvisibleCharactersAction.label=Show Invisible Characters
|
||||||
|
ShowInvisibleCharactersAction.tooltip=Show Invisible Characters
|
||||||
|
ShowInvisibleCharactersAction.description=Show invisible (whitespace) characters CR, LF, TAB and SPACE
|
||||||
|
|
||||||
# Task Action
|
# Task Action
|
||||||
DeleteTaskAction.label=Delete C/C++ Markers
|
DeleteTaskAction.label=Delete C/C++ Markers
|
||||||
|
@ -159,18 +161,13 @@ PathNameSorter.tooltip= Sort the view by Resource Path
|
||||||
# Action sets
|
# Action sets
|
||||||
CSearchActionSet.label= C/C++ Search
|
CSearchActionSet.label= C/C++ Search
|
||||||
CSearchActionSet.description= Action set containing search related C/C++ actions
|
CSearchActionSet.description= Action set containing search related C/C++ actions
|
||||||
RefactoringActionSet.label= Refactoring
|
CEditorPresentationActionSet.label=C/C++ Editor Presentation
|
||||||
RefactoringActionSet.description= Action set containing refactoring related actions
|
CEditorPresentationActionSet.description=Actions to customize the C/C++ editor presentation
|
||||||
|
|
||||||
# Menus
|
# Menus
|
||||||
searchMenu.label= Se&arch
|
searchMenu.label= Se&arch
|
||||||
refactoringMenu.label= Re&factor
|
refactoringMenu.label= Re&factor
|
||||||
|
|
||||||
# Refactoring
|
|
||||||
Refactoring.renameAction.label= Re&name
|
|
||||||
Refactoring.undoAction.label= &Undo
|
|
||||||
Refactoring.redoAction.label= &Redo
|
|
||||||
|
|
||||||
# Open Type
|
# Open Type
|
||||||
OpenTypeAction.label= Open &Type...
|
OpenTypeAction.label= Open &Type...
|
||||||
OpenTypeAction.tooltip= Open Type
|
OpenTypeAction.tooltip= Open Type
|
||||||
|
|
|
@ -218,6 +218,7 @@
|
||||||
</actionSet>
|
</actionSet>
|
||||||
<showInPart id="org.eclipse.cdt.ui.includeBrowser"/>
|
<showInPart id="org.eclipse.cdt.ui.includeBrowser"/>
|
||||||
<showInPart id="org.eclipse.cdt.ui.CView"/>
|
<showInPart id="org.eclipse.cdt.ui.CView"/>
|
||||||
|
<actionSet id="org.eclipse.cdt.ui.CEditorPresentationActionSet"/>
|
||||||
<!--perspectiveShortcut
|
<!--perspectiveShortcut
|
||||||
id="org.eclipse.cdt.ui.CBrowsingPerspective">
|
id="org.eclipse.cdt.ui.CBrowsingPerspective">
|
||||||
</perspectiveShortcut-->
|
</perspectiveShortcut-->
|
||||||
|
@ -801,6 +802,24 @@
|
||||||
tooltip="%NewProjectDropDownAction.tooltip">
|
tooltip="%NewProjectDropDownAction.tooltip">
|
||||||
</action>
|
</action>
|
||||||
</actionSet>
|
</actionSet>
|
||||||
|
<actionSet
|
||||||
|
description="%CEditorPresentationActionSet.description"
|
||||||
|
id="org.eclipse.cdt.ui.CEditorPresentationActionSet"
|
||||||
|
label="%CEditorPresentationActionSet.label">
|
||||||
|
<action
|
||||||
|
class="org.eclipse.cdt.internal.ui.actions.ShowInvisibleCharactersAction"
|
||||||
|
definitionId="org.eclipse.cdt.ui.edit.text.c.show.invisible.chars"
|
||||||
|
icon="icons/etool16/show_invisible_chars.gif"
|
||||||
|
id="org.eclipse.cdt.ui.ShowInvisibleCharactersAction"
|
||||||
|
label="%ShowInvisibleCharactersAction.label"
|
||||||
|
style="toggle"
|
||||||
|
toolbarPath="org.eclipse.ui.edit.text.actionSet.presentation/Presentation"
|
||||||
|
tooltip="%ShowInvisibleCharactersAction.tooltip">
|
||||||
|
<enablement>
|
||||||
|
<objectClass name="org.eclipse.jface.text.ITextSelection"/>
|
||||||
|
</enablement>
|
||||||
|
</action>
|
||||||
|
</actionSet>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.ui.ide.projectNatureImages">
|
point="org.eclipse.ui.ide.projectNatureImages">
|
||||||
|
@ -1052,6 +1071,12 @@
|
||||||
categoryId="org.eclipse.cdt.ui.category.source"
|
categoryId="org.eclipse.cdt.ui.category.source"
|
||||||
id="org.eclipse.cdt.ui.edit.text.c.show.tooltip">
|
id="org.eclipse.cdt.ui.edit.text.c.show.tooltip">
|
||||||
</command>
|
</command>
|
||||||
|
<command
|
||||||
|
name="%ShowInvisibleCharactersAction.label"
|
||||||
|
description="%ShowInvisibleCharactersAction.description"
|
||||||
|
categoryId="org.eclipse.cdt.ui.category.source"
|
||||||
|
id="org.eclipse.cdt.ui.edit.text.c.show.invisible.chars">
|
||||||
|
</command>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
id="pdomSearchPage"
|
id="pdomSearchPage"
|
||||||
|
|
|
@ -0,0 +1,280 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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 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.swt.custom.StyleRange;
|
||||||
|
import org.eclipse.swt.custom.StyledText;
|
||||||
|
import org.eclipse.swt.custom.StyledTextContent;
|
||||||
|
import org.eclipse.swt.events.PaintEvent;
|
||||||
|
import org.eclipse.swt.events.PaintListener;
|
||||||
|
import org.eclipse.swt.graphics.Color;
|
||||||
|
import org.eclipse.swt.graphics.GC;
|
||||||
|
import org.eclipse.swt.graphics.Point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A painter for drawing visible characters for (invisible) whitespace
|
||||||
|
* characters.
|
||||||
|
*
|
||||||
|
* @author anton.leherbauer@windriver.com
|
||||||
|
*/
|
||||||
|
public class InvisibleCharacterPainter implements IPainter, PaintListener {
|
||||||
|
|
||||||
|
private static final char PILCROW_SIGN= '\u00b6';
|
||||||
|
private static final char MIDDLE_DOT= '\u00b7';
|
||||||
|
private static final char RIGHT_POINTING_DOUBLE_ANGLE= '\u00bb';
|
||||||
|
private static final char LATIN_SMALL_LETTER_THORN= '\u00fe';
|
||||||
|
|
||||||
|
/** Indicates whether this painter is active */
|
||||||
|
private boolean fIsActive= false;
|
||||||
|
/** The source viewer this painter is attached to */
|
||||||
|
private ITextViewer fTextViewer;
|
||||||
|
/** The viewer's widget */
|
||||||
|
private StyledText fTextWidget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new painter for the given text viewer.
|
||||||
|
* @param textViewer the text viewer the painter should be attached to
|
||||||
|
*/
|
||||||
|
public InvisibleCharacterPainter(ITextViewer textViewer) {
|
||||||
|
super();
|
||||||
|
fTextViewer= textViewer;
|
||||||
|
fTextWidget= textViewer.getTextWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IPainter#dispose()
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
fTextViewer= null;
|
||||||
|
fTextWidget= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IPainter#paint(int)
|
||||||
|
*/
|
||||||
|
public void paint(int reason) {
|
||||||
|
IDocument document= fTextViewer.getDocument();
|
||||||
|
if (document == null) {
|
||||||
|
deactivate(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fIsActive) {
|
||||||
|
fIsActive= true;
|
||||||
|
fTextWidget.addPaintListener(this);
|
||||||
|
redrawAll(true);
|
||||||
|
} else if (reason == CONFIGURATION || reason == INTERNAL) {
|
||||||
|
redrawAll(false);
|
||||||
|
} else if (reason == TEXT_CHANGE) {
|
||||||
|
// redraw current line only
|
||||||
|
try {
|
||||||
|
IRegion lineRegion =
|
||||||
|
document.getLineInformationOfOffset(getDocumentOffset(fTextWidget.getCaretOffset()));
|
||||||
|
int widgetOffset= getWidgetOffset(lineRegion.getOffset());
|
||||||
|
int charCount= fTextWidget.getCharCount();
|
||||||
|
int redrawLength= Math.min(lineRegion.getLength(), charCount - widgetOffset);
|
||||||
|
if (widgetOffset >= 0 && redrawLength > 0) {
|
||||||
|
fTextWidget.redrawRange(widgetOffset, redrawLength, true);
|
||||||
|
}
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IPainter#deactivate(boolean)
|
||||||
|
*/
|
||||||
|
public void deactivate(boolean redraw) {
|
||||||
|
if (fIsActive) {
|
||||||
|
fIsActive= false;
|
||||||
|
fTextWidget.removePaintListener(this);
|
||||||
|
if (redraw) {
|
||||||
|
redrawAll(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IPainter#setPositionManager(org.eclipse.jface.text.IPaintPositionManager)
|
||||||
|
*/
|
||||||
|
public void setPositionManager(IPaintPositionManager manager) {
|
||||||
|
// no need for a position manager
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
|
||||||
|
*/
|
||||||
|
public void paintControl(PaintEvent event) {
|
||||||
|
if (fTextWidget != null) {
|
||||||
|
handleDrawRequest(event.gc, event.x, event.y, event.width, event.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw characters in view range.
|
||||||
|
* @param gc
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param w
|
||||||
|
* @param h
|
||||||
|
*/
|
||||||
|
private void handleDrawRequest(GC gc, int x, int y, int w, int h) {
|
||||||
|
int lineCount= fTextWidget.getLineCount();
|
||||||
|
int startLine= (y + fTextWidget.getTopPixel()) / fTextWidget.getLineHeight();
|
||||||
|
int endLine= (y + h - 1 + fTextWidget.getTopPixel()) / fTextWidget.getLineHeight();
|
||||||
|
if (startLine <= endLine && startLine < lineCount) {
|
||||||
|
int startOffset= fTextWidget.getOffsetAtLine(startLine);
|
||||||
|
int endOffset =
|
||||||
|
endLine < lineCount - 1 ? fTextWidget.getOffsetAtLine(endLine + 1) : fTextWidget.getCharCount();
|
||||||
|
handleDrawRequest(gc, startOffset, endOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw characters of content range.
|
||||||
|
* @param gc
|
||||||
|
* @param startOffset inclusive start index
|
||||||
|
* @param endOffset exclusive end index
|
||||||
|
*/
|
||||||
|
private void handleDrawRequest(GC gc, int startOffset, int endOffset) {
|
||||||
|
StyledTextContent content= fTextWidget.getContent();
|
||||||
|
int length= endOffset - startOffset;
|
||||||
|
String text= content.getTextRange(startOffset, length);
|
||||||
|
assert text.length() == length;
|
||||||
|
StyleRange styleRange= null;
|
||||||
|
Color fg= null;
|
||||||
|
Point selection= fTextWidget.getSelection();
|
||||||
|
StringBuffer visibleChar= new StringBuffer(20);
|
||||||
|
for (int textOffset= 0; textOffset <= length; ++textOffset) {
|
||||||
|
int delta= 0;
|
||||||
|
if (textOffset < length) {
|
||||||
|
delta= 1;
|
||||||
|
char c= text.charAt(textOffset);
|
||||||
|
switch (c) {
|
||||||
|
case ' ' :
|
||||||
|
visibleChar.append(MIDDLE_DOT);
|
||||||
|
continue;
|
||||||
|
case '\t' :
|
||||||
|
visibleChar.append(RIGHT_POINTING_DOUBLE_ANGLE);
|
||||||
|
break;
|
||||||
|
case '\r' :
|
||||||
|
visibleChar.append(LATIN_SMALL_LETTER_THORN);
|
||||||
|
if (textOffset >= length - 1 || text.charAt(textOffset + 1) != '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case '\n' :
|
||||||
|
visibleChar.append(PILCROW_SIGN);
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
delta= 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (visibleChar.length() > 0) {
|
||||||
|
int widgetOffset= startOffset + textOffset - visibleChar.length() + delta;
|
||||||
|
if (widgetOffset >= selection.x && widgetOffset < selection.y) {
|
||||||
|
fg= fTextWidget.getSelectionForeground();
|
||||||
|
} else if (styleRange == null || styleRange.start + styleRange.length <= widgetOffset) {
|
||||||
|
styleRange= fTextWidget.getStyleRangeAtOffset(widgetOffset);
|
||||||
|
if (styleRange == null || styleRange.foreground == null) {
|
||||||
|
fg= fTextWidget.getForeground();
|
||||||
|
} else {
|
||||||
|
fg= styleRange.foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw(gc, widgetOffset, visibleChar.toString(), fg);
|
||||||
|
visibleChar.delete(0, visibleChar.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redraw all of the text widgets visible content.
|
||||||
|
* @param redrawBackground If true, clean background before painting text.
|
||||||
|
*/
|
||||||
|
private void redrawAll(boolean redrawBackground) {
|
||||||
|
int startLine= fTextWidget.getTopPixel() / fTextWidget.getLineHeight();
|
||||||
|
int startOffset= fTextWidget.getOffsetAtLine(startLine);
|
||||||
|
int endLine= 1 + (fTextWidget.getTopPixel() + fTextWidget.getClientArea().height) / fTextWidget.getLineHeight();
|
||||||
|
int endOffset;
|
||||||
|
if (endLine >= fTextWidget.getLineCount()) {
|
||||||
|
endOffset= fTextWidget.getCharCount();
|
||||||
|
} else {
|
||||||
|
endOffset= fTextWidget.getOffsetAtLine(endLine);
|
||||||
|
}
|
||||||
|
if (startOffset < endOffset) {
|
||||||
|
// add 2 for line separator characters
|
||||||
|
endOffset= Math.min(endOffset + 2, fTextWidget.getCharCount());
|
||||||
|
int redrawOffset= startOffset;
|
||||||
|
int redrawLength= endOffset - redrawOffset;
|
||||||
|
fTextWidget.redrawRange(startOffset, redrawLength, redrawBackground);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw character c at widget offset.
|
||||||
|
* @param gc
|
||||||
|
* @param offset the widget offset
|
||||||
|
* @param c the character to be drawn
|
||||||
|
* @param fg the foreground color
|
||||||
|
*/
|
||||||
|
private void draw(GC gc, int offset, String c, Color fg) {
|
||||||
|
Point pos= fTextWidget.getLocationAtOffset(offset);
|
||||||
|
gc.setForeground(fg);
|
||||||
|
gc.drawString(c, pos.x, pos.y, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.actions;
|
||||||
|
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.text.IPainter;
|
||||||
|
import org.eclipse.jface.text.ITextOperationTarget;
|
||||||
|
import org.eclipse.jface.text.ITextViewer;
|
||||||
|
import org.eclipse.jface.text.ITextViewerExtension2;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.ui.IEditorActionDelegate;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IPartListener2;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
|
import org.eclipse.ui.IWorkbenchPartReference;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
|
||||||
|
import org.eclipse.ui.texteditor.ITextEditor;
|
||||||
|
import org.eclipse.ui.texteditor.IUpdate;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.InvisibleCharacterPainter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This action toggles the visibility of whitespace characters by
|
||||||
|
* attaching/detaching an {@link InvisibleCharacterPainter} to the
|
||||||
|
* active (text-)editor.
|
||||||
|
*
|
||||||
|
* @author anton.leherbauer@windriver.com
|
||||||
|
*/
|
||||||
|
public class ShowInvisibleCharactersAction implements IEditorActionDelegate, IWorkbenchWindowActionDelegate, IUpdate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PartListener to act on changes of the active editor.
|
||||||
|
*/
|
||||||
|
private class PartListener implements IPartListener2 {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partActivated(IWorkbenchPartReference partRef) {
|
||||||
|
if (partRef.getPart(false) instanceof IEditorPart) {
|
||||||
|
updateActiveEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partBroughtToTop(IWorkbenchPartReference partRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partClosed(IWorkbenchPartReference partRef) {
|
||||||
|
if (partRef.getPart(false) instanceof IEditorPart) {
|
||||||
|
updateActiveEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partDeactivated(IWorkbenchPartReference partRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partOpened(IWorkbenchPartReference partRef) {
|
||||||
|
if (partRef.getPart(false) instanceof IEditorPart) {
|
||||||
|
updateActiveEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partHidden(IWorkbenchPartReference partRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partVisible(IWorkbenchPartReference partRef) {
|
||||||
|
if (partRef.getPart(false) instanceof IEditorPart) {
|
||||||
|
updateActiveEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partInputChanged(IWorkbenchPartReference partRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPainter fInvisibleCharPainter;
|
||||||
|
private IWorkbenchWindow fWindow;
|
||||||
|
private IPartListener2 fPartListener;
|
||||||
|
private ITextEditor fTextEditor;
|
||||||
|
private boolean fIsChecked;
|
||||||
|
private IAction fAction;
|
||||||
|
|
||||||
|
public ShowInvisibleCharactersAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the painter to the current editor.
|
||||||
|
*/
|
||||||
|
private void addPainter() {
|
||||||
|
ITextEditor editor= getTextEditor();
|
||||||
|
ITextViewer viewer= getTextViewer(editor);
|
||||||
|
if (viewer instanceof ITextViewerExtension2) {
|
||||||
|
ITextViewerExtension2 viewerExt2= (ITextViewerExtension2)viewer;
|
||||||
|
if (fInvisibleCharPainter == null) {
|
||||||
|
fInvisibleCharPainter= new InvisibleCharacterPainter(viewer);
|
||||||
|
}
|
||||||
|
viewerExt2.addPainter(fInvisibleCharPainter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ITextViewer from an ITextEditor by adapting
|
||||||
|
* it to a ITextOperationTarget.
|
||||||
|
* @param editor the ITextEditor
|
||||||
|
* @return the text viewer or <code>null</code>
|
||||||
|
*/
|
||||||
|
private ITextViewer getTextViewer(ITextEditor editor) {
|
||||||
|
Object target= editor.getAdapter(ITextOperationTarget.class);
|
||||||
|
if (target instanceof ITextViewer) {
|
||||||
|
return (ITextViewer)target;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the painter from the current editor.
|
||||||
|
*/
|
||||||
|
private void removePainter() {
|
||||||
|
ITextEditor editor= getTextEditor();
|
||||||
|
ITextViewer viewer= getTextViewer(editor);
|
||||||
|
if (viewer instanceof ITextViewerExtension2) {
|
||||||
|
ITextViewerExtension2 viewerExt2= (ITextViewerExtension2)viewer;
|
||||||
|
viewerExt2.removePainter(fInvisibleCharPainter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setEditor(ITextEditor editor) {
|
||||||
|
if (editor != null && editor == getTextEditor()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fInvisibleCharPainter != null) {
|
||||||
|
removePainter();
|
||||||
|
fInvisibleCharPainter.deactivate(false);
|
||||||
|
fInvisibleCharPainter.dispose();
|
||||||
|
fInvisibleCharPainter= null;
|
||||||
|
}
|
||||||
|
fTextEditor= editor;
|
||||||
|
update();
|
||||||
|
if (fTextEditor != null && fIsChecked) {
|
||||||
|
addPainter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITextEditor getTextEditor() {
|
||||||
|
return fTextEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IEditorActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, org.eclipse.ui.IEditorPart)
|
||||||
|
*/
|
||||||
|
public void setActiveEditor(IAction action, IEditorPart targetEditor) {
|
||||||
|
fAction= action;
|
||||||
|
if (targetEditor instanceof ITextEditor) {
|
||||||
|
setEditor((ITextEditor)targetEditor);
|
||||||
|
} else {
|
||||||
|
setEditor(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
|
||||||
|
*/
|
||||||
|
public void init(IWorkbenchWindow window) {
|
||||||
|
fWindow= window;
|
||||||
|
fPartListener= new PartListener();
|
||||||
|
fWindow.getActivePage().addPartListener(fPartListener);
|
||||||
|
updateActiveEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
if (fWindow != null) {
|
||||||
|
IWorkbenchPage activePage= fWindow.getActivePage();
|
||||||
|
if (activePage != null) {
|
||||||
|
activePage.removePartListener(fPartListener);
|
||||||
|
}
|
||||||
|
fPartListener= null;
|
||||||
|
fWindow= null;
|
||||||
|
}
|
||||||
|
fAction= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
|
||||||
|
*/
|
||||||
|
public void run(IAction action) {
|
||||||
|
fAction= action;
|
||||||
|
fIsChecked= action.isChecked();
|
||||||
|
if (fIsChecked) {
|
||||||
|
addPainter();
|
||||||
|
} else if (fInvisibleCharPainter != null) {
|
||||||
|
removePainter();
|
||||||
|
fInvisibleCharPainter.deactivate(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
|
||||||
|
*/
|
||||||
|
public void selectionChanged(IAction action, ISelection selection) {
|
||||||
|
fAction= action;
|
||||||
|
fIsChecked= action.isChecked();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the active editor.
|
||||||
|
*/
|
||||||
|
protected void updateActiveEditor() {
|
||||||
|
IWorkbenchPage page= fWindow.getActivePage();
|
||||||
|
if (page != null) {
|
||||||
|
IEditorPart editorPart= page.getActiveEditor();
|
||||||
|
if (editorPart instanceof ITextEditor) {
|
||||||
|
setEditor((ITextEditor)editorPart);
|
||||||
|
} else {
|
||||||
|
setEditor(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.texteditor.IUpdate#update()
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
if (fAction != null) {
|
||||||
|
fAction.setEnabled(getTextEditor() != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue