From 90c639c9c1270210709dfa532f26b56ed2c28bd2 Mon Sep 17 00:00:00 2001 From: Lorenzo Dalla Vecchia Date: Mon, 13 Feb 2017 14:10:32 +0100 Subject: [PATCH 1/2] Preference page UI reconciliation hook The new method makes it easy to set inter-dependent control states (typically conditional enabling). --- .../ui/preferences/ATAConfigurationBlock.java | 11 ++-------- ...ypeScriptRepositoryConfigurationBlock.java | 10 ++------- .../FormatterConfigurationBlock.java | 10 ++------- .../preferences/NodejsConfigurationBlock.java | 10 ++------- .../TextMateConfigurationBlock.java | 10 ++------- .../OptionsConfigurationBlock.java | 21 +++++++++++++++++-- 6 files changed, 29 insertions(+), 43 deletions(-) diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/ATAConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/ATAConfigurationBlock.java index aa58208c..ebb30222 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/ATAConfigurationBlock.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/ATAConfigurationBlock.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added reconcileControls hook */ package ts.eclipse.ide.internal.ui.preferences; @@ -17,8 +18,6 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; @@ -69,13 +68,7 @@ public void enablePreferenceContent(boolean enable) { } @Override - protected Control createContents(Composite parent) { - Composite nodejsComposite = createUI(parent); - validateSettings(null, null, null); - return nodejsComposite; - } - - private Composite createUI(Composite parent) { + protected Composite createUI(Composite parent) { final ScrolledPageContent pageContent = new ScrolledPageContent(parent); Composite composite = pageContent.getBody(); GridLayout layout = new GridLayout(); diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/AbstractTypeScriptRepositoryConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/AbstractTypeScriptRepositoryConfigurationBlock.java index 0ba5cd6e..a161f754 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/AbstractTypeScriptRepositoryConfigurationBlock.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/AbstractTypeScriptRepositoryConfigurationBlock.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added reconcileControls hook */ package ts.eclipse.ide.internal.ui.preferences; @@ -23,7 +24,6 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; @@ -55,13 +55,7 @@ public AbstractTypeScriptRepositoryConfigurationBlock(IStatusChangeListener cont } @Override - protected Control createContents(Composite parent) { - Composite contents = createUI(parent); - validateSettings(null, null, null); - return contents; - } - - private Composite createUI(Composite parent) { + protected Composite createUI(Composite parent) { final ScrolledPageContent pageContent = new ScrolledPageContent(parent); Composite composite = pageContent.getBody(); GridLayout layout = new GridLayout(); diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/FormatterConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/FormatterConfigurationBlock.java index 8d1a9753..76c61ecb 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/FormatterConfigurationBlock.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/FormatterConfigurationBlock.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added reconcileControls hook */ package ts.eclipse.ide.internal.ui.preferences; @@ -16,7 +17,6 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; @@ -97,13 +97,7 @@ public void enablePreferenceContent(boolean enable) { } @Override - protected Control createContents(Composite parent) { - Composite nodejsComposite = createUI(parent); - validateSettings(null, null, null); - return nodejsComposite; - } - - private Composite createUI(Composite parent) { + protected Composite createUI(Composite parent) { final ScrolledPageContent pageContent = new ScrolledPageContent(parent); Composite composite = pageContent.getBody(); GridLayout layout = new GridLayout(); diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/NodejsConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/NodejsConfigurationBlock.java index 45d1e5fc..5c80db24 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/NodejsConfigurationBlock.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/NodejsConfigurationBlock.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added reconcileControls hook */ package ts.eclipse.ide.internal.ui.preferences; @@ -22,7 +23,6 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; @@ -91,13 +91,7 @@ public void enablePreferenceContent(boolean enable) { } @Override - protected Control createContents(Composite parent) { - Composite nodejsComposite = createUI(parent); - validateSettings(null, null, null); - return nodejsComposite; - } - - private Composite createUI(Composite parent) { + protected Composite createUI(Composite parent) { final ScrolledPageContent pageContent = new ScrolledPageContent(parent); Composite composite = pageContent.getBody(); GridLayout layout = new GridLayout(); diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TextMateConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TextMateConfigurationBlock.java index 5d907c43..04b23d97 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TextMateConfigurationBlock.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TextMateConfigurationBlock.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added reconcileControls hook */ package ts.eclipse.ide.internal.ui.preferences; @@ -16,7 +17,6 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; @@ -65,13 +65,7 @@ public void enablePreferenceContent(boolean enable) { } @Override - protected Control createContents(Composite parent) { - Composite nodejsComposite = createUI(parent); - validateSettings(null, null, null); - return nodejsComposite; - } - - private Composite createUI(Composite parent) { + protected Composite createUI(Composite parent) { final ScrolledPageContent pageContent = new ScrolledPageContent(parent); Composite composite = pageContent.getBody(); GridLayout layout = new GridLayout(); diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/OptionsConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/OptionsConfigurationBlock.java index a3ae7cc7..61ab9f7a 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/OptionsConfigurationBlock.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/OptionsConfigurationBlock.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Corporation - initial API and implementation + * IBM Corporation - initial API and implementation + * Lorenzo Dalla Vecchia - added reconcileControls hook *******************************************************************************/ package ts.eclipse.ide.ui.preferences; @@ -318,7 +319,14 @@ protected void setShell(Shell shell) { fShell = shell; } - protected abstract Control createContents(Composite parent); + public final Composite createContents(Composite parent) { + Composite contentsComposite = createUI(parent); + reconcileControls(); + validateSettings(null, null, null); + return contentsComposite; + } + + protected abstract Composite createUI(Composite parent); protected Button addCheckBox(Composite parent, String label, Key key, String[] values, int indent) { ControlData data = new ControlData(key, values); @@ -630,6 +638,7 @@ protected void controlChanged(Widget widget) { return; } String oldValue = setValue(data.getKey(), newValue); + reconcileControls(); validateSettings(data.getKey(), oldValue, newValue); } @@ -637,6 +646,7 @@ protected void textChanged(Text textControl) { Key key = (Key) textControl.getData(); String number = textControl.getText(); String oldValue = setValue(key, number); + reconcileControls(); validateSettings(key, oldValue, number); } @@ -644,6 +654,7 @@ protected void textChanged(Combo comboControl) { Key key = (Key) comboControl.getData(); String number = comboControl.getText(); String oldValue = setValue(key, number); + reconcileControls(); validateSettings(key, oldValue, number); } @@ -732,6 +743,7 @@ public void useProjectSpecificSettings(boolean enable) { } fDisabledProjectSettings = null; updateControls(); + reconcileControls(); validateSettings(null, null, null); } else { fDisabledProjectSettings = new IdentityHashMap(); @@ -825,6 +837,7 @@ public void performDefaults() { settingsUpdated(); updateControls(); + reconcileControls(); validateSettings(null, null, null); } @@ -840,12 +853,16 @@ public void performRevert() { settingsUpdated(); updateControls(); + reconcileControls(); validateSettings(null, null, null); } public void dispose() { } + protected void reconcileControls() { + } + protected void updateControls() { // update the UI for (int i = fCheckBoxes.size() - 1; i >= 0; i--) { From cceac341002cd5aa6ddadd3fd1f285ee2fcbd9d8 Mon Sep 17 00:00:00 2001 From: Lorenzo Dalla Vecchia Date: Mon, 13 Feb 2017 17:02:57 +0100 Subject: [PATCH 2/2] Added Format on Save feature --- .../ui/editor/TypeScriptDocumentProvider.java | 146 ++++++++++++++++- .../eclipse/ide/core/utils/DocumentUtils.java | 25 ++- eclipse/ts.eclipse.ide.ui/plugin.properties | 2 + eclipse/ts.eclipse.ide.ui/plugin.xml | 25 ++- .../ide/internal/ui/TypeScriptUIMessages.java | 5 + .../ui/TypeScriptUIMessages.properties | 5 + .../SaveActionsConfigurationBlock.java | 153 ++++++++++++++++++ .../SaveActionsPreferencePage.java | 107 ++++++++++++ .../TypeScriptUIPreferenceInitializer.java | 13 ++ .../TypeScriptUIPreferenceConstants.java | 16 ++ 10 files changed, 491 insertions(+), 6 deletions(-) create mode 100644 eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsConfigurationBlock.java create mode 100644 eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsPreferencePage.java diff --git a/eclipse/jsdt/ts.eclipse.ide.jsdt.ui/src/ts/eclipse/ide/jsdt/internal/ui/editor/TypeScriptDocumentProvider.java b/eclipse/jsdt/ts.eclipse.ide.jsdt.ui/src/ts/eclipse/ide/jsdt/internal/ui/editor/TypeScriptDocumentProvider.java index 3178ba5d..7a4a1ac8 100644 --- a/eclipse/jsdt/ts.eclipse.ide.jsdt.ui/src/ts/eclipse/ide/jsdt/internal/ui/editor/TypeScriptDocumentProvider.java +++ b/eclipse/jsdt/ts.eclipse.ide.jsdt.ui/src/ts/eclipse/ide/jsdt/internal/ui/editor/TypeScriptDocumentProvider.java @@ -7,17 +7,53 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added save actions */ package ts.eclipse.ide.jsdt.internal.ui.editor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.IUndoManager; +import org.eclipse.ltk.core.refactoring.PerformChangeOperation; +import org.eclipse.ltk.core.refactoring.RefactoringCore; +import org.eclipse.ltk.core.refactoring.TextFileChange; +import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.editors.text.ForwardingDocumentProvider; import org.eclipse.ui.editors.text.TextFileDocumentProvider; +import org.eclipse.ui.preferences.ScopedPreferenceStore; +import org.eclipse.ui.texteditor.ChainedPreferenceStore; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaDocumentSetupParticipant; import org.eclipse.wst.jsdt.ui.text.IJavaScriptPartitions; +import ts.client.CodeEdit; +import ts.eclipse.ide.core.TypeScriptCorePlugin; +import ts.eclipse.ide.core.resources.IIDETypeScriptFile; +import ts.eclipse.ide.core.resources.IIDETypeScriptProject; +import ts.eclipse.ide.core.utils.DocumentUtils; +import ts.eclipse.ide.core.utils.TypeScriptResourceUtil; +import ts.eclipse.ide.jsdt.internal.ui.JSDTTypeScriptUIPlugin; +import ts.eclipse.ide.ui.TypeScriptUIPlugin; +import ts.eclipse.ide.ui.preferences.TypeScriptUIPreferenceConstants; + public class TypeScriptDocumentProvider extends TextFileDocumentProvider { public TypeScriptDocumentProvider() { @@ -26,11 +62,115 @@ public TypeScriptDocumentProvider() { new JavaDocumentSetupParticipant(), provider); setParentDocumentProvider(provider); } - + @Override protected DocumentProviderOperation createSaveOperation(Object element, IDocument document, boolean overwrite) throws CoreException { - // TODO Auto-generated method stub - return super.createSaveOperation(element, document, overwrite); + final DocumentProviderOperation delegate = super.createSaveOperation(element, document, overwrite); + return new DocumentProviderOperation() { + @Override + protected void execute(IProgressMonitor monitor) throws CoreException { + SubMonitor progress = SubMonitor.convert(monitor, 10); + + // Retrieve the file that is being saved + IFile file = getFile(element); + if (file == null) { + return; + } + IPreferenceStore preferenceStore = createProjectSpecificPreferenceStore(file.getProject()); + boolean runSaveActions = preferenceStore + .getBoolean(TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS); + + try { + delegate.run(progress.newChild(8)); + if (runSaveActions) { + try { + performSaveActions(file, document, progress.newChild(2), preferenceStore); + } catch (Exception e) { + JSDTTypeScriptUIPlugin.log(e); + } + } else { + progress.setWorkRemaining(0); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (InvocationTargetException e) { + throw new CoreException( + new Status(IStatus.ERROR, TypeScriptCorePlugin.PLUGIN_ID, "Error while saving " + file, e)); + } + } + }; + } + + private void performSaveActions(IFile file, IDocument document, IProgressMonitor monitor, + IPreferenceStore preferenceStore) { + boolean runFormat = preferenceStore.getBoolean(TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS_FORMAT); + SubMonitor progress = SubMonitor.convert(monitor, (runFormat ? 10 : 0)); + if (!runFormat) { + return; + } + + IUndoManager manager = RefactoringCore.getUndoManager(); + + CompositeChange saveActionsChange = new CompositeChange("Save Actions"); + List undoChanges = new ArrayList<>(); + boolean success = false; + try { + manager.aboutToPerformChange(saveActionsChange); + + // Format the file contents + if (runFormat) { + TextFileChange change = new TextFileChange("Format", file); + try { + IIDETypeScriptProject tsProject = TypeScriptResourceUtil.getTypeScriptProject(file.getProject()); + final IIDETypeScriptFile tsFile = tsProject.openFile(file, document); + List codeEdits = tsFile.format(0, document.getLength()).get(); + change.setEdit(DocumentUtils.toTextEdit(codeEdits, document)); + change.initializeValidationData(new NullProgressMonitor()); + PerformChangeOperation performChangeOperation = new PerformChangeOperation(change); + ResourcesPlugin.getWorkspace().run(performChangeOperation, progress.newChild(10)); + Change undoChange = performChangeOperation.getUndoChange(); + if (undoChange != null) { + undoChanges.add(undoChange); + } + } catch (Exception e) { + JSDTTypeScriptUIPlugin.log(e); + } + } + + success = true; + } finally { + manager.changePerformed(saveActionsChange, success); + } + + // Add an undo change if possible + if (!undoChanges.isEmpty()) { + manager.addUndo(saveActionsChange.getName(), new CompositeChange(saveActionsChange.getName(), + undoChanges.toArray(new Change[undoChanges.size()]))); + } + } + + private static IPreferenceStore createProjectSpecificPreferenceStore(IProject project) { + List stores = new ArrayList(); + if (project != null) { + stores.add(new EclipsePreferencesAdapter(new ProjectScope(project), TypeScriptUIPlugin.PLUGIN_ID)); + stores.add(new EclipsePreferencesAdapter(new ProjectScope(project), TypeScriptCorePlugin.PLUGIN_ID)); + } + stores.add(new ScopedPreferenceStore(InstanceScope.INSTANCE, TypeScriptUIPlugin.PLUGIN_ID)); + stores.add(new ScopedPreferenceStore(InstanceScope.INSTANCE, TypeScriptCorePlugin.PLUGIN_ID)); + stores.add(new ScopedPreferenceStore(DefaultScope.INSTANCE, TypeScriptUIPlugin.PLUGIN_ID)); + stores.add(new ScopedPreferenceStore(DefaultScope.INSTANCE, TypeScriptCorePlugin.PLUGIN_ID)); + return new ChainedPreferenceStore(stores.toArray(new IPreferenceStore[stores.size()])); + } + + private IFile getFile(Object element) { + return getFile(getFileInfo(element)); + } + + private IFile getFile(FileInfo fileInfo) { + if (fileInfo != null && fileInfo.fElement instanceof IFileEditorInput) { + return ((IFileEditorInput) fileInfo.fElement).getFile(); + } + return null; } } diff --git a/eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/core/utils/DocumentUtils.java b/eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/core/utils/DocumentUtils.java index 4bf16c67..9235b80b 100644 --- a/eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/core/utils/DocumentUtils.java +++ b/eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/core/utils/DocumentUtils.java @@ -1,3 +1,14 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * 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: + * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - made toTextEdit public + */ package ts.eclipse.ide.core.utils; import java.util.List; @@ -67,7 +78,19 @@ public static void applyEdits(IDocument document, List codeEdits) } } - private static TextEdit toTextEdit(List codeEdits, IDocument document) throws TypeScriptException { + /** + * Transforms a list of documents edits into a standard {@link TextEdit} + * object that can be used for more complex operations, such as with the + * refactoring API. + * + * @param codeEdits + * list of TypeScript {@link CodeEdit}. + * @param document + * document to use as context for validating edit positions. + * @return a {@link TextEdit} object. + * @throws TypeScriptException + */ + public static TextEdit toTextEdit(List codeEdits, IDocument document) throws TypeScriptException { MultiTextEdit textEdit = new MultiTextEdit(); for (CodeEdit codeEdit : codeEdits) { toTextEdit(codeEdit, document, textEdit); diff --git a/eclipse/ts.eclipse.ide.ui/plugin.properties b/eclipse/ts.eclipse.ide.ui/plugin.properties index a2c6675a..91026ed4 100644 --- a/eclipse/ts.eclipse.ide.ui/plugin.properties +++ b/eclipse/ts.eclipse.ide.ui/plugin.properties @@ -7,6 +7,7 @@ # # Contributors: # Angelo Zerr - Initial API and implementation +# Lorenzo Dalla Vecchia - Added save actions ############################################################################### pluginName=TypeScript - Eclipse - UI IDE providerName=Angelo ZERR @@ -29,6 +30,7 @@ EditorPreferencePage.name=Editor FormatterPreferencePage.name=Formatter ValidationPreferencePage.name=Validation TextMatePreferencePage.name=TextMate +SaveActionsPreferencePage.name=Save Actions # Menu/Commands TypeScript.root.name=TypeScript diff --git a/eclipse/ts.eclipse.ide.ui/plugin.xml b/eclipse/ts.eclipse.ide.ui/plugin.xml index cb11714d..57623ce8 100644 --- a/eclipse/ts.eclipse.ide.ui/plugin.xml +++ b/eclipse/ts.eclipse.ide.ui/plugin.xml @@ -10,6 +10,7 @@ # # Contributors: # Angelo Zerr - Initial API and implementation +# Lorenzo Dalla Vecchia - Added save actions ############################################################################### --> @@ -238,7 +239,13 @@ class="ts.eclipse.ide.internal.ui.preferences.TextMatePreferencePage" id="ts.eclipse.ide.ui.preference.TextMatePreferencePage" category="ts.eclipse.ide.ui.preference.EditorPreferencePage"> - + + + @@ -330,7 +337,21 @@ - + + + + + + + + + diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.java index 90cb0ba2..3e9eaf75 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - Added save actions */ package ts.eclipse.ide.internal.ui; @@ -95,6 +96,10 @@ public class TypeScriptUIMessages extends NLS { public static String FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForFunctions; public static String FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForControlBlocks; + // Save actions + public static String SaveActionsPreferencePage_performTheSelectedActionsOnSave; + public static String SaveActionsPreferencePage_formatSourceCode; + public static String ValidationConfigurationBlock_tslintjson_group_label; public static String ValidationConfigurationBlock_tslintjson_strategy_DisableTslint; public static String ValidationConfigurationBlock_tslintjson_strategy_UseDefaultTslintJson; diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.properties b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.properties index 902f969c..c7d90f70 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.properties +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/TypeScriptUIMessages.properties @@ -7,6 +7,7 @@ # # Contributors: # Angelo Zerr - Initial API and implementation +# Lorenzo Dalla Vecchia - Added save actions ############################################################################### # Buttons @@ -79,6 +80,10 @@ FormatterConfigurationBlock_formatOptions_insertSpaceAfterOpeningAndBeforeClosin FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForFunctions=Defines whether an open brace is put onto a new line for functions or not. FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForControlBlocks=Defines whether an open brace is put onto a new line for control blocks or not. +# Save actions +SaveActionsPreferencePage_performTheSelectedActionsOnSave=Perform the selected actions on save +SaveActionsPreferencePage_formatSourceCode=Format source code + ValidationConfigurationBlock_tslintjson_group_label=Configuration for 'tslint.json' ValidationConfigurationBlock_tslintjson_strategy_DisableTslint=Disable tslint ValidationConfigurationBlock_tslintjson_strategy_UseDefaultTslintJson=Use the default 'tslint.json'. diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsConfigurationBlock.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsConfigurationBlock.java new file mode 100644 index 00000000..f9220ac1 --- /dev/null +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsConfigurationBlock.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * 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: + * Lorenzo Dalla Vecchia - initial API and implementation + */ +package ts.eclipse.ide.internal.ui.preferences; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.dialogs.ControlEnableState; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; + +import ts.eclipse.ide.internal.ui.TypeScriptUIMessages; +import ts.eclipse.ide.internal.ui.dialogs.IStatusChangeListener; +import ts.eclipse.ide.ui.preferences.OptionsConfigurationBlock; +import ts.eclipse.ide.ui.preferences.ScrolledPageContent; +import ts.eclipse.ide.ui.preferences.TypeScriptUIPreferenceConstants; + +/** + * Editor save actions configuration block. + * + */ +public class SaveActionsConfigurationBlock extends OptionsConfigurationBlock { + + // Editor Save Actions + private static final Key PREF_EDITOR_SAVE_ACTIONS = getTypeScriptUIKey( + TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS); + private static final Key PREF_EDITOR_SAVE_ACTIONS_FORMAT = getTypeScriptUIKey( + TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS_FORMAT); + + private Composite controlsComposite; + private ControlEnableState blockEnableState; + private Button saveActionsButton; + private Composite saveActionsContainer; + private ControlEnableState saveActionsContainerEnableState; + + public SaveActionsConfigurationBlock(IStatusChangeListener context, IProject project, + IWorkbenchPreferenceContainer container) { + super(context, project, getKeys(), container); + blockEnableState = null; + } + + private static Key[] getKeys() { + return new Key[] { PREF_EDITOR_SAVE_ACTIONS, PREF_EDITOR_SAVE_ACTIONS_FORMAT }; + } + + public void enablePreferenceContent(boolean enable) { + if (controlsComposite != null && !controlsComposite.isDisposed()) { + if (enable) { + if (blockEnableState != null) { + blockEnableState.restore(); + blockEnableState = null; + } + } else { + if (blockEnableState == null) { + blockEnableState = ControlEnableState.disable(controlsComposite); + } + } + } + } + + @Override + protected Composite createUI(Composite parent) { + final ScrolledPageContent pageContent = new ScrolledPageContent(parent); + Composite composite = pageContent.getBody(); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + composite.setLayout(layout); + + controlsComposite = new Composite(composite, SWT.NONE); + controlsComposite.setFont(composite.getFont()); + controlsComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false)); + + layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.numColumns = 1; + controlsComposite.setLayout(layout); + + // save actions + createSaveActions(controlsComposite); + return pageContent; + } + + /** + * Create save actions. + * + * @param parent + */ + private void createSaveActions(Composite parent) { + + // Perform the selected actions on save + saveActionsButton = addCheckBox(parent, + TypeScriptUIMessages.SaveActionsPreferencePage_performTheSelectedActionsOnSave, + PREF_EDITOR_SAVE_ACTIONS, new String[] { "true", "false" }, 0); + + saveActionsContainer = new Composite(parent, SWT.NONE); + { + GridData data = new GridData(SWT.FILL, SWT.TOP, true, false); + data.horizontalIndent = 10; + saveActionsContainer.setLayoutData(data); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.numColumns = 1; + saveActionsContainer.setLayout(layout); + } + + // Format source code + addCheckBox(saveActionsContainer, TypeScriptUIMessages.SaveActionsPreferencePage_formatSourceCode, + PREF_EDITOR_SAVE_ACTIONS_FORMAT, new String[] { "true", "false" }, 0); + } + + @Override + protected void reconcileControls() { + if (saveActionsButton.getSelection()) { + if (saveActionsContainerEnableState != null) { + saveActionsContainerEnableState.restore(); + saveActionsContainerEnableState = null; + } + } else { + if (saveActionsContainerEnableState == null) { + saveActionsContainerEnableState = ControlEnableState.disable(saveActionsContainer); + } + } + } + + @Override + protected void validateSettings(Key changedKey, String oldValue, String newValue) { + if (!areSettingsEnabled()) { + return; + } + if (changedKey != null) { + + } + } + + @Override + protected String[] getFullBuildDialogStrings(boolean workspaceSettings) { + return null; + } + +} diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsPreferencePage.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsPreferencePage.java new file mode 100644 index 00000000..87b1d39c --- /dev/null +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/SaveActionsPreferencePage.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * 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: + * Lorenzo Dalla Vecchia - initial API and implementation + */ +package ts.eclipse.ide.internal.ui.preferences; + +import org.eclipse.core.resources.IProject; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; + +import ts.eclipse.ide.ui.preferences.PropertyAndPreferencePage; + +/** + * Save actions formatter preferences page + * + */ +public class SaveActionsPreferencePage extends PropertyAndPreferencePage { + + public static final String PREF_ID = "ts.eclipse.ide.ui.preference.SaveActionsPreferencePage"; //$NON-NLS-1$ + public static final String PROP_ID = "ts.eclipse.ide.ui.property.SaveActionsPreferencePage"; //$NON-NLS-1$ + + private SaveActionsConfigurationBlock configurationBlock; + + public SaveActionsPreferencePage() { + } + + @Override + public void createControl(Composite parent) { + IWorkbenchPreferenceContainer container = (IWorkbenchPreferenceContainer) getContainer(); + configurationBlock = new SaveActionsConfigurationBlock(getNewStatusChangedListener(), getProject(), container); + super.createControl(parent); + } + + @Override + protected Control createPreferenceBodyContent(Composite composite) { + return configurationBlock.createContents(composite); + } + + @Override + protected boolean hasProjectSpecificOptions(IProject project) { + return configurationBlock.hasProjectSpecificOptions(project); + } + + @Override + protected String getPreferencePageID() { + return PREF_ID; + } + + @Override + protected String getPropertyPageID() { + return PROP_ID; + } + + @Override + protected void enablePreferenceContent(boolean enable) { + if (configurationBlock != null) { + configurationBlock.enablePreferenceContent(enable); + } + } + + @Override + protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) { + super.enableProjectSpecificSettings(useProjectSpecificSettings); + if (configurationBlock != null) { + configurationBlock.useProjectSpecificSettings(useProjectSpecificSettings); + } + } + + @Override + public void dispose() { + if (configurationBlock != null) { + configurationBlock.dispose(); + } + super.dispose(); + } + + @Override + protected void performDefaults() { + super.performDefaults(); + if (configurationBlock != null) { + configurationBlock.performDefaults(); + } + } + + @Override + public boolean performOk() { + if (configurationBlock != null && !configurationBlock.performOk()) { + return false; + } + return super.performOk(); + } + + @Override + public void performApply() { + if (configurationBlock != null) { + configurationBlock.performApply(); + } + } + +} diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TypeScriptUIPreferenceInitializer.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TypeScriptUIPreferenceInitializer.java index a45ea651..8bceebf0 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TypeScriptUIPreferenceInitializer.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/internal/ui/preferences/TypeScriptUIPreferenceInitializer.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added save actions */ package ts.eclipse.ide.internal.ui.preferences; @@ -31,6 +32,8 @@ public void initializeDefaultPreferences() { // initialize properties for TextMate using initializeTextMatePreferences(node); + // initialize properties for editor save actions + initializeEditorSaveActionsPreferences(node); } /** @@ -41,4 +44,14 @@ public void initializeDefaultPreferences() { private void initializeTextMatePreferences(IEclipsePreferences node) { node.putBoolean(TypeScriptUIPreferenceConstants.USE_TEXMATE_FOR_SYNTAX_COLORING, false); } + + /** + * initialize properties for editor save actions + * + * @param node + */ + private void initializeEditorSaveActionsPreferences(IEclipsePreferences node) { + node.putBoolean(TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS, false); + node.putBoolean(TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS_FORMAT, true); + } } \ No newline at end of file diff --git a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/TypeScriptUIPreferenceConstants.java b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/TypeScriptUIPreferenceConstants.java index 9ae746c8..bdcb3256 100644 --- a/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/TypeScriptUIPreferenceConstants.java +++ b/eclipse/ts.eclipse.ide.ui/src/ts/eclipse/ide/ui/preferences/TypeScriptUIPreferenceConstants.java @@ -7,6 +7,7 @@ * * Contributors: * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - added save actions */ package ts.eclipse.ide.ui.preferences; @@ -16,11 +17,26 @@ */ public class TypeScriptUIPreferenceConstants { + // TextMate + /** * True is TextMate must be used to colorize TypeScript, JSX files and false otherwise. */ public final static String USE_TEXMATE_FOR_SYNTAX_COLORING = "useTextMateForSyntaxColoring"; + // Editor Save Actions + + /** + * True if saving an editor should automatically perform some actions. + */ + public static final String EDITOR_SAVE_ACTIONS = "editorSaveActions"; // $NON-NLS-1$ + + /** + * True if the editor save actions should include formatting the source + * code. + */ + public static final String EDITOR_SAVE_ACTIONS_FORMAT = "editorSaveActions.format"; // $NON-NLS-1$ + private TypeScriptUIPreferenceConstants() { } }