/** * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ /* * Created on May 29, 2006 */ package org.python.pydev.editor.preferences; import org.eclipse.jface.bindings.keys.KeySequence; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.python.pydev.plugin.PydevPlugin; import org.python.pydev.shared_core.string.StringUtils; import org.python.pydev.shared_core.string.WrapAndCaseUtils; import org.python.pydev.shared_ui.bindings.KeyBindingHelper; import org.python.pydev.shared_ui.field_editors.BooleanFieldEditorCustom; import org.python.pydev.shared_ui.field_editors.LabelFieldEditor; import org.python.pydev.shared_ui.field_editors.ScopedFieldEditorPreferencePage; import org.python.pydev.shared_ui.field_editors.ScopedPreferencesFieldEditor; /** * This class is the class that resulted of the separation of the PydevPrefs because * it was too big. * * @author Fabio */ public class PydevTypingPrefs extends ScopedFieldEditorPreferencePage implements IWorkbenchPreferencePage { public static final String AUTO_PAR = "AUTO_PAR"; public static final boolean DEFAULT_AUTO_PAR = true; public static final String AUTO_LINK = "AUTO_LINK"; public static final boolean DEFAULT_AUTO_LINK = false; public static final String AUTO_INDENT_TO_PAR_LEVEL = "AUTO_INDENT_TO_PAR_LEVEL"; public static final boolean DEFAULT_AUTO_INDENT_TO_PAR_LEVEL = true; public static final String AUTO_INDENT_AFTER_PAR_WIDTH = "AUTO_INDENT_AFTER_PAR_WIDTH"; public static final int DEFAULT_AUTO_INDENT_AFTER_PAR_WIDTH = 1; public static final String AUTO_DEDENT_ELSE = "AUTO_DEDENT_ELSE"; public static final boolean DEFAULT_AUTO_DEDENT_ELSE = true; public static final String SMART_INDENT_PAR = "SMART_INDENT_PAR"; public static final boolean DEFAULT_SMART_INDENT_PAR = true; public static final String INDENT_AFTER_PAR_AS_PEP8 = "INDENT_AFTER_PAR_AS_PEP8"; public static final boolean DEFAULT_INDENT_AFTER_PAR_AS_PEP8 = true; public static final String SMART_LINE_MOVE = "SMART_LINE_MOVE"; //Disabled by default (doesn't seem as useful as I though because Python does not have the end //braces and Java does (so, there are a number of cases where the indentation has to be hand-fixed //anyways) public static final boolean DEFAULT_SMART_LINE_MOVE = false; /** * fields for automatically replacing a colon * @see */ public static final String AUTO_COLON = "AUTO_COLON"; public static final boolean DEFAULT_AUTO_COLON = true; /** * fields for automatically skipping braces * @see org.python.pydev.editor.autoedit.PyAutoIndentStrategy */ public static final String AUTO_BRACES = "AUTO_BRACES"; public static final boolean DEFAULT_AUTO_BRACES = true; /** * Used if the 'import' should be written automatically in an from xxx import yyy */ public static final String AUTO_WRITE_IMPORT_STR = "AUTO_WRITE_IMPORT_STR"; public static final boolean DEFAULT_AUTO_WRITE_IMPORT_STR = true; public static final String AUTO_LITERALS = "AUTO_LITERALS"; public static final boolean DEFAULT_AUTO_LITERALS = true; public static final String AUTO_ADD_SELF = "AUTO_ADD_SELF"; public static final boolean DEFAULT_AUTO_ADD_SELF = true; public static final int TOOLTIP_WIDTH = 80; public PydevTypingPrefs() { super(GRID); setDescription("Editor"); setPreferenceStore(PydevPlugin.getDefault().getPreferenceStore()); } @Override protected void createFieldEditors() { final Composite initialParent = getFieldEditorParent(); final Composite p = initialParent; String preference = AUTO_LINK; String text = "Enable link on automatic parenthesis or literals closing?"; String tooltip = "Enabling this option will enable the linking mode after a parenthesis or literal is auto-closed."; addBooleanField(p, preference, text, tooltip); //auto par addBooleanField( p, AUTO_PAR, "Automatic parentheses insertion", "Enabling this option will enable automatic insertion of parentheses. " + "Specifically, whenever you hit a brace such as '(', '{', or '[', its related peer will be inserted " + "and your cursor will be placed between the two braces."); //smart indent? final BooleanFieldEditorCustom useSmartIndent = addBooleanField(p, SMART_INDENT_PAR, "Use smart-indent?", ""); //pep-8 indent? final BooleanFieldEditorCustom usePep8Indent = addBooleanField(p, INDENT_AFTER_PAR_AS_PEP8, " After {, [, ( indent as pep-8.\n", ""); final LabelFieldEditor labelPep8_1 = new LabelFieldEditor("__UNUSED__00", " I.e.: add indentation plus additional level right after", p); addField(labelPep8_1); final LabelFieldEditor labelPep8_2 = new LabelFieldEditor("__UNUSED__01", "", p); addField(labelPep8_2); // fill second column final LabelFieldEditor labelPep8_3 = new LabelFieldEditor("__UNUSED__02", " braces or indent to braces after another token.", p); addField(labelPep8_3); // indent final BooleanFieldEditorCustom autoIndentToParLevel = addBooleanField(p, AUTO_INDENT_TO_PAR_LEVEL, " After {, [, ( indent to its level (indents by tabs if unchecked)", ""); final IntegerFieldEditor indentationLevelsToAddField = new IntegerFieldEditor(AUTO_INDENT_AFTER_PAR_WIDTH, " Number of indentation levels to add:", p, 1); addField(indentationLevelsToAddField); final Runnable fixEnablement = new Runnable() { @Override public void run() { boolean useSmartIndentBool = useSmartIndent.getBooleanValue(); boolean usePep8IndentBool = usePep8Indent.getBooleanValue(); boolean useAutoIndentToParLevelBool = autoIndentToParLevel.getBooleanValue(); fixParensIndentEnablement(p, usePep8Indent, autoIndentToParLevel, indentationLevelsToAddField, labelPep8_1, labelPep8_2, labelPep8_3, useSmartIndentBool, usePep8IndentBool, useAutoIndentToParLevelBool); } }; autoIndentToParLevel.getCheckBox(p).addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fixEnablement.run(); } }); usePep8Indent.getCheckBox(p).addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fixEnablement.run(); } }); useSmartIndent.getCheckBox(p).addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fixEnablement.run(); } }); fixParensIndentEnablement(p, usePep8Indent, autoIndentToParLevel, indentationLevelsToAddField, labelPep8_1, labelPep8_2, labelPep8_3, getPreferenceStore().getBoolean(SMART_INDENT_PAR), getPreferenceStore().getBoolean(INDENT_AFTER_PAR_AS_PEP8), getPreferenceStore().getBoolean(AUTO_INDENT_TO_PAR_LEVEL)); //auto dedent 'else:' addBooleanField(p, AUTO_DEDENT_ELSE, "Automatic dedent of 'else:' and 'elif:'", ""); //auto braces addBooleanField( p, AUTO_BRACES, "Automatically skip matching braces when typing", "Enabling this option will enable automatically skipping matching braces " + "if you try to insert them. For example, if you have the following code:\n\n" + "def function(self):\n\n" + "...with your cursor before the end parenthesis (after the 'f' in \"self\"), typing a ')' will " + "simply move the cursor to the position after the ')' without inserting a new one."); //auto colon addBooleanField( p, AUTO_COLON, "Automatic colon detection", "Enabling this feature will enable the editor to detect if you are trying " + "to enter a colon which is already there. Instead of inserting another colon, the editor will " + "simply move your cursor to the next position after the colon."); //auto literals addBooleanField(p, AUTO_LITERALS, "Automatic literal closing", "Automatically close literals " + "(when ' or \" is added, another one is added to close it)."); //auto import str addBooleanField(p, AUTO_WRITE_IMPORT_STR, "Automatic insertion of the 'import' string on 'from xxx' ", "Enabling this will allow the editor to automatically write the" + "'import' string when you write a space after you've written 'from xxx '."); addBooleanField(p, AUTO_ADD_SELF, "Add 'self' automatically when declaring methods?", ""); KeySequence down = KeyBindingHelper.getCommandKeyBinding(ITextEditorActionDefinitionIds.MOVE_LINES_DOWN); KeySequence up = KeyBindingHelper.getCommandKeyBinding(ITextEditorActionDefinitionIds.MOVE_LINES_UP); String downKey = down != null ? down.format() : "Alt+Down"; //set the default if not there String upKey = up != null ? up.format() : "Alt+Up"; //set the default if not there addBooleanField(p, SMART_LINE_MOVE, StringUtils.format("Smart move for line up (%s) and line down (%s)?.", upKey, downKey), ""); addField(new LabelFieldEditor("__UNUSED__", "Note: smart move line up/down change applied on editor restart.", p)); addField(new ScopedPreferencesFieldEditor(p, PydevPlugin.DEFAULT_PYDEV_SCOPE, this)); } private BooleanFieldEditorCustom addBooleanField(Composite p, String preference, String text, String tooltip) { BooleanFieldEditorCustom field = new BooleanFieldEditorCustom(preference, text, BooleanFieldEditor.DEFAULT, p); addField(field); field.setTooltip(p, WrapAndCaseUtils.wrap(tooltip, TOOLTIP_WIDTH)); return field; } @Override public void init(IWorkbench workbench) { } private void fixParensIndentEnablement(final Composite p, final BooleanFieldEditorCustom usePep8Indent, final BooleanFieldEditorCustom autoIndentToParLevel, final IntegerFieldEditor indentationLevelsToAddField, LabelFieldEditor labelPep8_1, LabelFieldEditor labelPep8_2, LabelFieldEditor labelPep8_3, boolean useSmartIndentBool, boolean usePep8IndentBool, boolean useAutoIndentToParLevelBool) { if (!useSmartIndentBool) { // Disable all usePep8Indent.setEnabled(false, p); labelPep8_1.setEnabled(false, p); labelPep8_2.setEnabled(false, p); labelPep8_3.setEnabled(false, p); autoIndentToParLevel.setEnabled(false, p); indentationLevelsToAddField.setEnabled(false, p); } else { usePep8Indent.setEnabled(true, p); labelPep8_1.setEnabled(true, p); labelPep8_2.setEnabled(true, p); labelPep8_3.setEnabled(true, p); // Smart indent enabled, let's see if pep-8 is enabled if (usePep8IndentBool) { autoIndentToParLevel.setEnabled(false, p); indentationLevelsToAddField.setEnabled(false, p); } else { autoIndentToParLevel.setEnabled(true, p); indentationLevelsToAddField.setEnabled(!useAutoIndentToParLevelBool, p); } } } }