diff options
| author | Tomasz Zarna | 2012-02-17 14:24:37 +0000 |
|---|---|---|
| committer | Matthias Sohn | 2012-02-17 14:24:37 +0000 |
| commit | c5cd6e4b637cf9b904458177db2a08e0ddbe66ce (patch) | |
| tree | 63787961f81277232254a9b582d05538ecdeb3dd | |
| parent | c64ef88dca83f25fe2f677f6a618e09c5cab40dc (diff) | |
| download | egit-c5cd6e4b637cf9b904458177db2a08e0ddbe66ce.tar.gz egit-c5cd6e4b637cf9b904458177db2a08e0ddbe66ce.tar.xz egit-c5cd6e4b637cf9b904458177db2a08e0ddbe66ce.zip | |
Show whitespace chars in the Commit dialog
Bug: 371353
Change-Id: I5e9501bb6d9d568858a85649a660cba9722a57ab
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
3 files changed, 138 insertions, 26 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index 5f921e1a41..140c7fc397 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -1996,6 +1996,9 @@ public class UIText extends NLS { public static String SpellcheckableMessageArea_redo; /** */ + public static String SpellcheckableMessageArea_showWhitespace; + + /** */ public static String SpellcheckableMessageArea_undo; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/SpellcheckableMessageArea.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/SpellcheckableMessageArea.java index 92b949c1ba..e0e68e990c 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/SpellcheckableMessageArea.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/SpellcheckableMessageArea.java @@ -1,7 +1,7 @@ /******************************************************************************* * Copyright (C) 2010, Benjamin Muskalla <bmuskalla@eclipsesource.com> * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com> - * Copyright (C) 2011, IBM Corporation + * Copyright (C) 2011-2012, IBM Corporation * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -10,6 +10,7 @@ * * Contributors: * Benjamin Muskalla (EclipseSource) - initial implementation + * Tomasz Zarna (IBM) - show whitespace action, bug 371353 *******************************************************************************/ package org.eclipse.egit.ui.internal.dialogs; @@ -19,6 +20,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.egit.core.internal.Utils; import org.eclipse.egit.ui.Activator; @@ -33,15 +35,19 @@ import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.SubMenuManager; import org.eclipse.jface.commands.ActionHandler; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.Document; -import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPainter; +import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.MarginPainter; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.WhitespaceCharacterPainter; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistant; import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; @@ -54,6 +60,8 @@ import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.ISharedTextColors; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; @@ -77,6 +85,7 @@ import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.ui.handlers.IHandlerActivation; import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.texteditor.AbstractTextEditor; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; @@ -123,19 +132,78 @@ public class SpellcheckableMessageArea extends Composite { boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode)); setEnabled(isEnabled); - if (wasEnabled != isEnabled) { + if (wasEnabled != isEnabled) firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE); - } } /** * @see Action#run() */ public void run() { - if (fOperationCode != -1 && fOperationTarget != null) { + if (fOperationCode != -1 && fOperationTarget != null) fOperationTarget.doOperation(fOperationCode); + } + } + + private static abstract class TextEditorPropertyAction extends Action implements IPropertyChangeListener { + + private SourceViewer viewer; + private String preferenceKey; + private IPreferenceStore store; + + public TextEditorPropertyAction(String label, SourceViewer viewer, String preferenceKey) { + super(label, IAction.AS_CHECK_BOX); + this.viewer = viewer; + this.preferenceKey = preferenceKey; + this.store = EditorsUI.getPreferenceStore(); + if (store != null) + store.addPropertyChangeListener(this); + synchronizeWithPreference(); + } + + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(getPreferenceKey())) + synchronizeWithPreference(); + } + + protected void synchronizeWithPreference() { + boolean checked = false; + if (store != null) + checked = store.getBoolean(getPreferenceKey()); + if (checked != isChecked()) { + setChecked(checked); + toggleState(checked); + } else if (checked) { + toggleState(false); + toggleState(true); } } + + private String getPreferenceKey() { + return preferenceKey; + } + + @Override + public void run() { + toggleState(isChecked()); + if (store != null) + store.setValue(getPreferenceKey(), isChecked()); + } + + public void dispose() { + if (store != null) + store.removePropertyChangeListener(this); + } + + /** + * @param checked + * new state + */ + abstract protected void toggleState(boolean checked); + + protected ITextViewer getTextViewer() { + return viewer; + } } private final SourceViewer sourceViewer; @@ -255,28 +323,24 @@ public class SpellcheckableMessageArea extends Composite { private boolean active = true; public void modifyText(ModifyEvent e) { - if (!active) { + if (!active) return; - } String lineDelimiter = textWidget.getLineDelimiter(); List<WrapEdit> wrapEdits = calculateWrapEdits( textWidget.getText(), MAX_LINE_WIDTH, lineDelimiter); // Prevent infinite loop because replaceTextRange causes a ModifyEvent active = false; - for (WrapEdit wrapEdit : wrapEdits) { + for (WrapEdit wrapEdit : wrapEdits) textWidget.replaceTextRange(wrapEdit.getStart(), wrapEdit.getLength(), lineDelimiter); - } active = true; } }; textWidget.addModifyListener(hardWrapModifyListener); } - } else { - if (hardWrapModifyListener != null) { - getTextWidget().removeModifyListener(hardWrapModifyListener); - hardWrapModifyListener = null; - } + } else if (hardWrapModifyListener != null) { + getTextWidget().removeModifyListener(hardWrapModifyListener); + hardWrapModifyListener = null; } } @@ -307,6 +371,48 @@ public class SpellcheckableMessageArea extends Composite { redoAction.setText(UIText.SpellcheckableMessageArea_redo); redoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_REDO); + final TextEditorPropertyAction showWhitespaceAction = new TextEditorPropertyAction( + UIText.SpellcheckableMessageArea_showWhitespace, + sourceViewer, + AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS) { + + private IPainter whitespaceCharPainter; + + @Override + protected void toggleState(boolean checked) { + if (checked) + installPainter(); + else + uninstallPainter(); + } + + /** + * Installs the painter on the viewer. + */ + private void installPainter() { + Assert.isTrue(whitespaceCharPainter == null); + ITextViewer v = getTextViewer(); + if (v instanceof ITextViewerExtension2) { + whitespaceCharPainter = new WhitespaceCharacterPainter(v); + ((ITextViewerExtension2) v).addPainter(whitespaceCharPainter); + } + } + + /** + * Remove the painter from the viewer. + */ + private void uninstallPainter() { + if (whitespaceCharPainter == null) + return; + ITextViewer v = getTextViewer(); + if (v instanceof ITextViewerExtension2) + ((ITextViewerExtension2) v) + .removePainter(whitespaceCharPainter); + whitespaceCharPainter.deactivate(true); + whitespaceCharPainter = null; + } + }; + MenuManager contextMenu = new MenuManager(); contextMenu.add(cutAction); contextMenu.add(copyAction); @@ -315,6 +421,8 @@ public class SpellcheckableMessageArea extends Composite { contextMenu.add(undoAction); contextMenu.add(redoAction); contextMenu.add(new Separator()); + contextMenu.add(showWhitespaceAction); + contextMenu.add(new Separator()); if(isEditable(sourceViewer)) { final SubMenuManager quickFixMenu = new SubMenuManager(contextMenu); @@ -359,21 +467,17 @@ public class SpellcheckableMessageArea extends Composite { public void focusLost(FocusEvent e) { IHandlerService service = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); - if (cutHandlerActivation != null) { + if (cutHandlerActivation != null) service.deactivateHandler(cutHandlerActivation); - } - if (copyHandlerActivation != null) { + if (copyHandlerActivation != null) service.deactivateHandler(copyHandlerActivation); - } - if (pasteHandlerActivation != null) { + if (pasteHandlerActivation != null) service.deactivateHandler(pasteHandlerActivation); - } - if (selectAllHandlerActivation != null) { + if (selectAllHandlerActivation != null) service.deactivateHandler(selectAllHandlerActivation); - } if (undoHandlerActivation != null) service.deactivateHandler(undoHandlerActivation); @@ -400,6 +504,12 @@ public class SpellcheckableMessageArea extends Composite { redoAction.update(); } }); + + getTextWidget().addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent disposeEvent) { + showWhitespaceAction.dispose(); + } + }); } private void addProposals(final SubMenuManager quickFixMenu) { @@ -441,9 +551,8 @@ public class SpellcheckableMessageArea extends Composite { public ImageDescriptor getImageDescriptor() { Image image = proposal.getImage(); - if (image != null) { + if (image != null) return ImageDescriptor.createFromImage(image); - } return null; } }; @@ -685,9 +794,8 @@ public class SpellcheckableMessageArea extends Composite { lineLength += wordLength; } - if (chunkIndex != chunks.length - 1) { + if (chunkIndex != chunks.length - 1) offset += lineDelimiterLength; - } } return wrapEdits; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 10b4d28775..4dd9fae613 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -655,6 +655,7 @@ CommitDialog_Title=Commit Changes to Git Repository CommitDialog_WrongTypeOfCommitMessageProvider=The extension used as CommitMessageProvider has the wrong type (it must implement org.eclipse.egit.ui.ICommitMessageProvider) SpellcheckableMessageArea_redo=Redo +SpellcheckableMessageArea_showWhitespace=Show &Whitespace Characters SpellcheckableMessageArea_undo=Undo SpellCheckingMessageArea_copy=&Copy SpellCheckingMessageArea_cut=C&ut |
