Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf2019-05-22 17:09:49 -0400
committerMichael Keppler2019-05-25 03:57:36 -0400
commit744a12abb1bd3c6922fe7758ce426b273551445c (patch)
tree7c3eac9647e06fb2b6b02cdbb6f2d6d84ec66094
parent325fbb6ba11e793409a0834d6e4b98b772c9e307 (diff)
downloadegit-744a12abb1bd3c6922fe7758ce426b273551445c.tar.gz
egit-744a12abb1bd3c6922fe7758ce426b273551445c.tar.xz
egit-744a12abb1bd3c6922fe7758ce426b273551445c.zip
Factor out some actions from SpellcheckableMessageArea
This enables re-using these actions in other viewers, too, and prepares for enabling showing white space in the diff viewer in the history view. Change-Id: Ic0990aea9df3f310a1a75823f5c3814ae66da4d1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/ActionUtils.java109
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/ShowWhitespaceAction.java139
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/SpellcheckableMessageArea.java329
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/TextEditorPropertyAction.java147
4 files changed, 417 insertions, 307 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/ActionUtils.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/ActionUtils.java
index f4616f5ab..2add80da5 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/ActionUtils.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/ActionUtils.java
@@ -17,7 +17,10 @@ import java.util.function.BooleanSupplier;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
import org.eclipse.jface.commands.ActionHandler;
+import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.widgets.Control;
@@ -109,6 +112,95 @@ public final class ActionUtils {
}
/**
+ * Creates a new text action using a given {@link ActionFactory} to use as a
+ * template to set the label, image, and action definition id.
+ *
+ * @param target
+ * for the action
+ * @param factory
+ * to configure the action
+ * @param operationCode
+ * for the action
+ * @return the configured {@link UpdateableAction}
+ */
+ public static UpdateableAction createTextAction(
+ ITextOperationTarget target, ActionFactory factory,
+ int operationCode) {
+ if (operationCode == ITextOperationTarget.REDO) {
+ // XXX: workaround for
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=206111
+ return createGlobalAction(factory,
+ () -> target.doOperation(operationCode), () -> true);
+ }
+ return createGlobalAction(factory,
+ () -> target.doOperation(operationCode),
+ () -> target.canDoOperation(operationCode));
+ }
+
+ private static UpdateableAction[] createStandardTextActions(
+ ITextOperationTarget target, boolean editable) {
+ UpdateableAction[] actions = new UpdateableAction[ITextOperationTarget.SELECT_ALL
+ + 1];
+ if (editable) {
+ actions[ITextOperationTarget.UNDO] = createTextAction(target,
+ ActionFactory.UNDO, ITextOperationTarget.UNDO);
+ actions[ITextOperationTarget.REDO] = createTextAction(target,
+ ActionFactory.REDO, ITextOperationTarget.REDO);
+ actions[ITextOperationTarget.CUT] = createTextAction(target,
+ ActionFactory.CUT, ITextOperationTarget.CUT);
+ actions[ITextOperationTarget.PASTE] = createTextAction(
+ target, ActionFactory.PASTE, ITextOperationTarget.PASTE);
+ actions[ITextOperationTarget.DELETE] = createTextAction(
+ target, ActionFactory.DELETE, ITextOperationTarget.DELETE);
+ }
+ actions[ITextOperationTarget.COPY] = createTextAction(target,
+ ActionFactory.COPY, ITextOperationTarget.COPY);
+ actions[ITextOperationTarget.SELECT_ALL] = createTextAction(
+ target, ActionFactory.SELECT_ALL,
+ ITextOperationTarget.SELECT_ALL);
+ return actions;
+ }
+
+ /**
+ * Create the standard text actions, fill them into a {@MenuManager} and
+ * return them as an array indexed by the {@link ITextOperationTarget}
+ * operation codes. For an editable target, creates undo, redo | cut, copy,
+ * paste | delete, select all; otherwise just copy, select all.
+ *
+ * @param target
+ * for the actions to operate on
+ * @param editable
+ * whether the target is editable
+ * @param manager
+ * to fill in; may be {@code null} if the actions shall not be
+ * added to a {@link MenuManager}
+ * @return the actions; may contain {@code null} values (index 0 will always
+ * be {@code null})
+ */
+ public static UpdateableAction[] fillStandardTextActions(
+ ITextOperationTarget target, boolean editable,
+ MenuManager manager) {
+ UpdateableAction[] actions = createStandardTextActions(target,
+ editable);
+ if (manager != null) {
+ if (editable) {
+ manager.add(actions[ITextOperationTarget.UNDO]);
+ manager.add(actions[ITextOperationTarget.REDO]);
+ manager.add(new Separator());
+ manager.add(actions[ITextOperationTarget.CUT]);
+ }
+ manager.add(actions[ITextOperationTarget.COPY]);
+ if (editable) {
+ manager.add(actions[ITextOperationTarget.PASTE]);
+ manager.add(new Separator());
+ manager.add(actions[ITextOperationTarget.DELETE]);
+ }
+ manager.add(actions[ITextOperationTarget.SELECT_ALL]);
+ }
+ return actions;
+ }
+
+ /**
* Hooks up the {@link Control} such that the given {@link IAction}s are
* registered with the given {@link IHandlerService} while the control has
* the focus. Ensures that actions are properly de-registered when the
@@ -117,7 +209,8 @@ public final class ActionUtils {
* @param control
* to hook up
* @param actions
- * to be registered while the control has the focus
+ * to be registered while the control has the focus; {@code null}
+ * items are skipped.
* @param service
* to register the actions with
*/
@@ -148,12 +241,14 @@ public final class ActionUtils {
// Looks like sometimes we get two focusGained events.
return;
}
- for (final IAction action : actions) {
- handlerActivations.add(service.activateHandler(
- action.getActionDefinitionId(),
- new ActionHandler(action), expression, false));
- if (action instanceof IUpdate) {
- ((IUpdate) action).update();
+ for (IAction action : actions) {
+ if (action != null) {
+ handlerActivations.add(service.activateHandler(
+ action.getActionDefinitionId(),
+ new ActionHandler(action), expression, false));
+ if (action instanceof IUpdate) {
+ ((IUpdate) action).update();
+ }
}
}
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/ShowWhitespaceAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/ShowWhitespaceAction.java
new file mode 100644
index 000000000..dbdd042af
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/ShowWhitespaceAction.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2019 Tomasz Zarna (IBM), Robin Stocker, and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Thomas Wolf <thomas.wolf@paranor.ch> - Factored out of SpellcheckableMessageArea.
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.dialogs;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IPainter;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.WhitespaceCharacterPainter;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+/**
+ * An action to toggle showing whitespace in a an {@link ITextViewer}.
+ */
+public class ShowWhitespaceAction extends TextEditorPropertyAction {
+
+ /**
+ * Creates a new {@link ShowWhitespaceAction}.
+ *
+ * @param viewer
+ * to operate on
+ * @param initiallyOff
+ * whether to show whitespace initially
+ */
+ public ShowWhitespaceAction(ITextViewer viewer, boolean initiallyOff) {
+ super(UIText.SpellcheckableMessageArea_showWhitespace, viewer,
+ AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS,
+ initiallyOff);
+ }
+
+ private IPainter whitespaceCharPainter;
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property == null) {
+ return;
+ }
+ switch (property) {
+ case AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS:
+ case AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES:
+ case AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES:
+ case AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES:
+ case AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES:
+ case AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES:
+ case AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES:
+ case AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS:
+ case AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS:
+ case AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS:
+ case AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN:
+ case AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED:
+ case AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE:
+ synchronizeWithPreference();
+ break;
+ default:
+ break;
+ }
+ }
+
+ @Override
+ protected final String getPreferenceKey() {
+ return AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS;
+ }
+
+ @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) {
+ IPreferenceStore store = getStore();
+ whitespaceCharPainter = new WhitespaceCharacterPainter(v,
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN),
+ store.getBoolean(
+ AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED),
+ store.getInt(
+ AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE));
+ ((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;
+ }
+}
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 35719cd54..d490c4cbc 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
@@ -24,15 +24,14 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
-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;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.ActionUtils;
+import org.eclipse.egit.ui.internal.ActionUtils.UpdateableAction;
import org.eclipse.egit.ui.internal.CommonUtils;
-import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
@@ -40,20 +39,13 @@ import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.SubMenuManager;
-import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
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.presentation.IPresentationReconciler;
@@ -71,8 +63,6 @@ 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.jgit.util.IntList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BidiSegmentEvent;
@@ -90,16 +80,12 @@ import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
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;
-import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.eclipse.ui.themes.IThemeManager;
@@ -116,119 +102,6 @@ public class SpellcheckableMessageArea extends Composite {
private static final Pattern TRAILING_NEWLINES = Pattern.compile("\\v+$"); //$NON-NLS-1$
- private static class TextViewerAction extends Action implements IUpdate {
-
- private int fOperationCode= -1;
- private ITextOperationTarget fOperationTarget;
-
- /**
- * Creates a new action.
- *
- * @param target
- * to operate on
- * @param operationCode
- * the opcode
- */
- public TextViewerAction(ITextOperationTarget target,
- int operationCode) {
- fOperationCode= operationCode;
- fOperationTarget = target;
- update();
- }
-
- /**
- * Updates the enabled state of the action.
- */
- @Override
- public void update() {
- // XXX: workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=206111
- if (fOperationCode == ITextOperationTarget.REDO) {
- return;
- }
- setEnabled(fOperationTarget != null
- && fOperationTarget.canDoOperation(fOperationCode));
- }
-
- /**
- * @see Action#run()
- */
- @Override
- public void run() {
- 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();
- }
-
- @Override
- public void propertyChange(PropertyChangeEvent event) {
- if (event.getProperty().equals(getPreferenceKey()))
- synchronizeWithPreference();
- }
-
- protected void synchronizeWithPreference() {
- // start read-only components without visible whitespace
- if (!viewer.getTextWidget().getEditable()) {
- return;
- }
- boolean checked = false;
- if (store != null)
- checked = store.getBoolean(getPreferenceKey());
- if (checked != isChecked()) {
- setChecked(checked);
- toggleState(checked);
- } else if (checked) {
- toggleState(false);
- toggleState(true);
- }
- }
-
- protected 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;
- }
-
- protected IPreferenceStore getStore() {
- return store;
- }
- }
-
private final HyperlinkSourceViewer sourceViewer;
private TextSourceViewerConfiguration configuration;
@@ -497,153 +370,18 @@ public class SpellcheckableMessageArea extends Composite {
}
}
- private TextViewerAction createFromActionFactory(ActionFactory factory,
- int operationCode) {
- IWorkbenchAction template = factory
- .create(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
- TextViewerAction action = new TextViewerAction(sourceViewer,
- operationCode);
- action.setText(template.getText());
- action.setImageDescriptor(template.getImageDescriptor());
- action.setDisabledImageDescriptor(
- template.getDisabledImageDescriptor());
- action.setActionDefinitionId(template.getActionDefinitionId());
- template.dispose();
- return action;
- }
-
private void configureContextMenu() {
final boolean editable = isEditable(sourceViewer);
- TextViewerAction cutAction;
- TextViewerAction undoAction;
- TextViewerAction redoAction;
- TextViewerAction pasteAction;
- IAction quickFixAction;
+ IAction quickFixAction = null;
if (editable) {
- cutAction = createFromActionFactory(ActionFactory.CUT,
- ITextOperationTarget.CUT);
- undoAction = createFromActionFactory(ActionFactory.UNDO,
- ITextOperationTarget.UNDO);
- redoAction = createFromActionFactory(ActionFactory.REDO,
- ITextOperationTarget.REDO);
- pasteAction = createFromActionFactory(ActionFactory.PASTE,
- ITextOperationTarget.PASTE);
quickFixAction = new QuickfixAction(sourceViewer);
- } else {
- cutAction = null;
- undoAction = null;
- redoAction = null;
- pasteAction = null;
- quickFixAction = null;
}
- TextViewerAction copyAction = createFromActionFactory(
- ActionFactory.COPY, ITextOperationTarget.COPY);
- TextViewerAction selectAllAction = createFromActionFactory(
- ActionFactory.SELECT_ALL, ITextOperationTarget.SELECT_ALL);
-
- final TextEditorPropertyAction showWhitespaceAction = new TextEditorPropertyAction(
- UIText.SpellcheckableMessageArea_showWhitespace,
- sourceViewer,
- AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS) {
-
- private IPainter whitespaceCharPainter;
-
- @Override
- public void propertyChange(PropertyChangeEvent event) {
- String property = event.getProperty();
- if (property.equals(getPreferenceKey())
- || AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN
- .equals(property)
- || AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED
- .equals(property)
- || AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE
- .equals(property)) {
- synchronizeWithPreference();
- }
- }
-
- @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) {
- IPreferenceStore store = getStore();
- whitespaceCharPainter = new WhitespaceCharacterPainter(
- v,
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN),
- store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED),
- store.getInt(AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE));
- ((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;
- }
- };
+ final ShowWhitespaceAction showWhitespaceAction = new ShowWhitespaceAction(
+ sourceViewer, !editable);
MenuManager contextMenu = new MenuManager();
- if (cutAction != null) {
- contextMenu.add(cutAction);
- }
- contextMenu.add(copyAction);
- if (pasteAction != null) {
- contextMenu.add(pasteAction);
- }
- contextMenu.add(selectAllAction);
- if (undoAction != null) {
- contextMenu.add(undoAction);
- }
- if (redoAction != null) {
- contextMenu.add(redoAction);
- }
+ UpdateableAction[] standardActions = ActionUtils
+ .fillStandardTextActions(sourceViewer, editable, contextMenu);
contextMenu.add(new Separator());
contextMenu.add(showWhitespaceAction);
contextMenu.add(new Separator());
@@ -662,15 +400,10 @@ public class SpellcheckableMessageArea extends Composite {
final StyledText textWidget = getTextWidget();
List<IAction> globalActions = new ArrayList<>();
- if (editable) {
- globalActions.add(cutAction);
- globalActions.add(pasteAction);
- globalActions.add(undoAction);
- globalActions.add(redoAction);
+ globalActions.addAll(Arrays.asList(standardActions));
+ if (quickFixAction != null) {
globalActions.add(quickFixAction);
}
- globalActions.add(copyAction);
- globalActions.add(selectAllAction);
if (contentAssistAction != null) {
globalActions.add(contentAssistAction);
}
@@ -679,35 +412,25 @@ public class SpellcheckableMessageArea extends Composite {
textWidget.setMenu(contextMenu.createContextMenu(textWidget));
- sourceViewer.addSelectionChangedListener(new ISelectionChangedListener() {
-
- @Override
- public void selectionChanged(SelectionChangedEvent event) {
- if (cutAction != null)
- cutAction.update();
- copyAction.update();
- }
-
- });
+ sourceViewer.addSelectionChangedListener(event -> {
+ if (standardActions[ITextOperationTarget.CUT] != null) {
+ standardActions[ITextOperationTarget.CUT].update();
+ }
+ standardActions[ITextOperationTarget.COPY].update();
+ });
if (editable) {
- sourceViewer.addTextListener(new ITextListener() {
- @Override
- public void textChanged(TextEvent event) {
- if (undoAction != null)
- undoAction.update();
- if (redoAction != null)
- redoAction.update();
+ sourceViewer.addTextListener(event -> {
+ if (standardActions[ITextOperationTarget.UNDO] != null) {
+ standardActions[ITextOperationTarget.UNDO].update();
+ }
+ if (standardActions[ITextOperationTarget.REDO] != null) {
+ standardActions[ITextOperationTarget.REDO].update();
}
});
}
- textWidget.addDisposeListener(new DisposeListener() {
- @Override
- public void widgetDisposed(DisposeEvent disposeEvent) {
- showWhitespaceAction.dispose();
- }
- });
+ textWidget.addDisposeListener(e -> showWhitespaceAction.dispose());
}
private void addProposals(final SubMenuManager quickFixMenu) {
@@ -848,8 +571,14 @@ public class SpellcheckableMessageArea extends Composite {
private IAction createContentAssistAction(
final SourceViewer viewer) {
- Action proposalAction = new TextViewerAction(viewer,
- ISourceViewer.CONTENTASSIST_PROPOSALS);
+ Action proposalAction = new Action() {
+
+ @Override
+ public void run() {
+ viewer.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
+ }
+
+ };
proposalAction
.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
return proposalAction;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/TextEditorPropertyAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/TextEditorPropertyAction.java
new file mode 100644
index 000000000..9df5386a1
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/TextEditorPropertyAction.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2019 Tomasz Zarna (IBM) and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Thomas Wolf <thomas.wolf@paranor.ch> - Factored out of SpellcheckableMessageArea.
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.dialogs;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.editors.text.EditorsUI;
+
+/**
+ * An {@link Action} that operates on an {@link ITextViewer} that represents a
+ * boolean preference in the text editor preferences. When toggled, it toggles
+ * the persisted state and invokes {@link #toggleState(boolean)}, which is to be
+ * implemented by sub-classes to update the text viewer in response to the
+ * preference change.
+ */
+public abstract class TextEditorPropertyAction extends Action
+ implements IPropertyChangeListener, IWorkbenchAction {
+
+ // Possibly originally copied from
+ // org.eclipse.compare.internal.TextEditorPropertyAction and adapted?
+
+ private ITextViewer viewer;
+
+ private String preferenceKey;
+
+ private IPreferenceStore store;
+
+ /**
+ * Creates a new {@link TextEditorPropertyAction}.
+ *
+ * @param label
+ * for the action
+ * @param viewer
+ * to operate on
+ * @param preferenceKey
+ * in the {@link EditorsUI#getPreferenceStore()} for this action
+ * @param initiallyOff
+ * if {@code true}, the action initially is not checked and does
+ * not reflect the preference state
+ */
+ public TextEditorPropertyAction(String label, ITextViewer viewer,
+ String preferenceKey, boolean initiallyOff) {
+ super(label, IAction.AS_CHECK_BOX);
+ this.viewer = viewer;
+ this.preferenceKey = preferenceKey;
+ this.store = EditorsUI.getPreferenceStore();
+ if (store != null) {
+ store.addPropertyChangeListener(this);
+ }
+ if (!initiallyOff) {
+ synchronizeWithPreference();
+ }
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getProperty().equals(getPreferenceKey())) {
+ synchronizeWithPreference();
+ }
+ }
+
+ /**
+ * Reads the preference and calls {@link #toggleState(boolean)} as
+ * appropriate.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Retrieves the preference key of this action.
+ *
+ * @return the preference key.
+ */
+ protected String getPreferenceKey() {
+ return preferenceKey;
+ }
+
+ @Override
+ public void run() {
+ toggleState(isChecked());
+ if (store != null) {
+ store.setValue(getPreferenceKey(), isChecked());
+ }
+ }
+
+ @Override
+ public void dispose() {
+ if (store != null) {
+ store.removePropertyChangeListener(this);
+ }
+ }
+
+ /**
+ * Updates the {@link ITextViewer} of this action as appropriate.
+ *
+ * @param checked
+ * new state
+ */
+ abstract protected void toggleState(boolean checked);
+
+ /**
+ * Retrieves the {@link ITextViewer} this action operates on.
+ *
+ * @return the {@link ITextViewer}
+ */
+ protected ITextViewer getTextViewer() {
+ return viewer;
+ }
+
+ /**
+ * Retrieves the {@link IPreferenceStore} this action operates on.
+ *
+ * @return the {@link IPreferenceStore}, or {@code null} if there is no
+ * preference store for text editors
+ */
+ protected IPreferenceStore getStore() {
+ return store;
+ }
+}
+

Back to the top