22bf42f8da40aa77f8afa292608a26d38b1ebdce
[idea/community.git] / platform / lang-impl / src / com / intellij / application / options / editor / EditorOptionsPanel.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.intellij.application.options.editor;
18
19 import com.intellij.application.options.OptionId;
20 import com.intellij.application.options.OptionsApplicabilityFilter;
21 import com.intellij.codeInsight.CodeInsightSettings;
22 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
23 import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass;
24 import com.intellij.codeInsight.documentation.QuickDocOnMouseOverManager;
25 import com.intellij.ide.ui.UISettings;
26 import com.intellij.openapi.application.ApplicationBundle;
27 import com.intellij.openapi.components.ServiceManager;
28 import com.intellij.openapi.editor.Document;
29 import com.intellij.openapi.editor.Editor;
30 import com.intellij.openapi.editor.EditorFactory;
31 import com.intellij.openapi.editor.colors.EditorColorsManager;
32 import com.intellij.openapi.editor.colors.EditorColorsScheme;
33 import com.intellij.openapi.editor.ex.EditorEx;
34 import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
35 import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
36 import com.intellij.openapi.editor.richcopy.settings.RichCopySettings;
37 import com.intellij.openapi.fileEditor.FileEditor;
38 import com.intellij.openapi.fileEditor.FileEditorManager;
39 import com.intellij.openapi.fileEditor.TextEditor;
40 import com.intellij.openapi.options.ConfigurationException;
41 import com.intellij.openapi.options.SearchableConfigurable;
42 import com.intellij.openapi.project.Project;
43 import com.intellij.openapi.project.ProjectManager;
44 import com.intellij.openapi.util.Comparing;
45 import com.intellij.openapi.util.SystemInfo;
46 import com.intellij.openapi.util.text.StringUtil;
47 import com.intellij.openapi.vcs.VcsApplicationSettings;
48 import com.intellij.openapi.vcs.impl.LineStatusTrackerManager;
49 import com.intellij.ui.ListCellRendererWrapper;
50 import com.intellij.ui.components.JBCheckBox;
51 import com.intellij.ui.components.JBLabel;
52 import com.intellij.xml.util.XmlStringUtil;
53 import org.jetbrains.annotations.NotNull;
54 import org.jetbrains.annotations.Nullable;
55
56 import javax.swing.*;
57 import java.awt.*;
58 import java.awt.event.ActionEvent;
59 import java.awt.event.ActionListener;
60 import java.awt.event.ItemEvent;
61 import java.awt.event.ItemListener;
62
63 public class EditorOptionsPanel {
64   private JPanel    myBehaviourPanel;
65   private JCheckBox myCbHighlightBraces;
66   private static final String STRIP_CHANGED = ApplicationBundle.message("combobox.strip.modified.lines");
67
68   private static final String STRIP_ALL  = ApplicationBundle.message("combobox.strip.all");
69   private static final String STRIP_NONE = ApplicationBundle.message("combobox.strip.none");
70   private JComboBox myStripTrailingSpacesCombo;
71
72   private JCheckBox myCbVirtualSpace;
73   private JCheckBox myCbCaretInsideTabs;
74
75   private JTextField myRecentFilesLimitField;
76   private JTextField myCommandsHistoryLimitField;
77
78   private JCheckBox myCbHighlightScope;
79
80   private JTextField myClipboardContentLimitTextField;
81   private JCheckBox  myCbSmoothScrolling;
82   private JCheckBox  myCbVirtualPageAtBottom;
83   private JCheckBox  myCbEnableDnD;
84   private JCheckBox  myCbEnableWheelFontChange;
85   private JCheckBox  myCbHonorCamelHumpsWhenSelectingByClicking;
86
87   private JPanel       myHighlightSettingsPanel;
88   private JRadioButton myRbPreferScrolling;
89   private JRadioButton myRbPreferMovingCaret;
90   private JCheckBox    myCbRenameLocalVariablesInplace;
91   private JCheckBox    myCbHighlightIdentifierUnderCaret;
92   private JCheckBox    myCbEnsureBlankLineBeforeCheckBox;
93   private JCheckBox    myShowNotificationAfterReformatCodeCheckBox;
94   private JCheckBox    myShowNotificationAfterOptimizeImportsCheckBox;
95   private JCheckBox    myCbUseSoftWrapsAtEditor;
96   private JCheckBox    myCbUseSoftWrapsAtConsole;
97   private JCheckBox    myCbUseCustomSoftWrapIndent;
98   private JTextField   myCustomSoftWrapIndent;
99   private JLabel       myCustomSoftWrapIndentLabel;
100   private JCheckBox    myCbShowSoftWrapsOnlyOnCaretLine;
101   private JCheckBox    myPreselectCheckBox;
102   private JBCheckBox   myCbShowQuickDocOnMouseMove;
103   private JBLabel      myQuickDocDelayLabel;
104   private JTextField   myQuickDocDelayTextField;
105   private JComboBox    myRichCopyColorSchemeComboBox;
106   private JCheckBox    myShowInlineDialogForCheckBox;
107   private JBLabel      myStripTrailingSpacesExplanationLabel;
108   private JCheckBox    myCbEnableRichCopyByDefault;
109   private JCheckBox    myShowWhitespacesModificationsInLSTGutterCheckBox;
110
111   private static final String ACTIVE_COLOR_SCHEME = ApplicationBundle.message("combobox.richcopy.color.scheme.active");
112
113   private final ErrorHighlightingPanel myErrorHighlightingPanel = new ErrorHighlightingPanel();
114   private final MyConfigurable myConfigurable;
115
116
117   public EditorOptionsPanel() {
118     if (SystemInfo.isMac) {
119       myCbEnableWheelFontChange.setText(ApplicationBundle.message("checkbox.enable.ctrl.mousewheel.changes.font.size.macos"));
120     }
121
122
123     myStripTrailingSpacesCombo.addItem(STRIP_CHANGED);
124     myStripTrailingSpacesCombo.addItem(STRIP_ALL);
125     myStripTrailingSpacesCombo.addItem(STRIP_NONE);
126     ActionListener explainer = new ActionListener() {
127       @Override
128       public void actionPerformed(ActionEvent e) {
129         explainTrailingSpaces(getStripTrailingSpacesValue());
130       }
131     };
132     myStripTrailingSpacesCombo.addActionListener(explainer);
133     myCbVirtualSpace.addActionListener(explainer);
134
135
136
137     myHighlightSettingsPanel.setLayout(new BorderLayout());
138     myHighlightSettingsPanel.add(myErrorHighlightingPanel.getPanel(), BorderLayout.CENTER);
139
140
141     myCbRenameLocalVariablesInplace.setVisible(OptionsApplicabilityFilter.isApplicable(OptionId.RENAME_IN_PLACE));
142
143     myRichCopyColorSchemeComboBox.setRenderer(new ListCellRendererWrapper<String>() {
144       @Override
145       public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
146         final String textToUse;
147         if (RichCopySettings.ACTIVE_GLOBAL_SCHEME_MARKER.equals(value)) {
148           textToUse = ACTIVE_COLOR_SCHEME;
149         }
150         else {
151           textToUse = value;
152         }
153         setText(textToUse);
154       }
155     });
156
157     myConfigurable = new MyConfigurable();
158     initQuickDocProcessing();
159     initSoftWrapsSettingsProcessing();
160   }
161
162
163   public void reset() {
164     EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance();
165     CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
166     UISettings uiSettings = UISettings.getInstance();
167     VcsApplicationSettings vcsSettings = VcsApplicationSettings.getInstance();
168
169     // Display
170
171
172     myCbSmoothScrolling.setSelected(editorSettings.isSmoothScrolling());
173
174     // Brace highlighting
175
176     myCbHighlightBraces.setSelected(codeInsightSettings.HIGHLIGHT_BRACES);
177     myCbHighlightScope.setSelected(codeInsightSettings.HIGHLIGHT_SCOPE);
178     myCbHighlightIdentifierUnderCaret.setSelected(codeInsightSettings.HIGHLIGHT_IDENTIFIER_UNDER_CARET);
179
180     // Virtual space
181
182     myCbUseSoftWrapsAtEditor.setSelected(editorSettings.isUseSoftWraps(SoftWrapAppliancePlaces.MAIN_EDITOR));
183     myCbUseSoftWrapsAtConsole.setSelected(editorSettings.isUseSoftWraps(SoftWrapAppliancePlaces.CONSOLE));
184     myCbUseCustomSoftWrapIndent.setSelected(editorSettings.isUseCustomSoftWrapIndent());
185     myCustomSoftWrapIndent.setText(Integer.toString(editorSettings.getCustomSoftWrapIndent()));
186     myCbShowSoftWrapsOnlyOnCaretLine.setSelected(!editorSettings.isAllSoftWrapsShown());
187     updateSoftWrapSettingsRepresentation();
188
189     myCbVirtualSpace.setSelected(editorSettings.isVirtualSpace());
190     myCbCaretInsideTabs.setSelected(editorSettings.isCaretInsideTabs());
191     myCbVirtualPageAtBottom.setSelected(editorSettings.isAdditionalPageAtBottom());
192
193     // Limits
194     myClipboardContentLimitTextField.setText(Integer.toString(uiSettings.MAX_CLIPBOARD_CONTENTS));
195
196     // Strip trailing spaces on save
197
198     String stripTrailingSpaces = editorSettings.getStripTrailingSpaces();
199     if(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE.equals(stripTrailingSpaces)) {
200       myStripTrailingSpacesCombo.setSelectedItem(STRIP_NONE);
201     }
202     else if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED.equals(stripTrailingSpaces)) {
203       myStripTrailingSpacesCombo.setSelectedItem(STRIP_CHANGED);
204     }
205     else if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE.equals(stripTrailingSpaces)) {
206       myStripTrailingSpacesCombo.setSelectedItem(STRIP_ALL);
207     }
208     explainTrailingSpaces(stripTrailingSpaces);
209
210     myCbEnsureBlankLineBeforeCheckBox.setSelected(editorSettings.isEnsureNewLineAtEOF());
211     myCbShowQuickDocOnMouseMove.setSelected(editorSettings.isShowQuickDocOnMouseOverElement());
212     myQuickDocDelayTextField.setText(Long.toString(editorSettings.getQuickDocOnMouseOverElementDelayMillis()));
213     myQuickDocDelayTextField.setEnabled(editorSettings.isShowQuickDocOnMouseOverElement());
214     myQuickDocDelayLabel.setEnabled(editorSettings.isShowQuickDocOnMouseOverElement());
215
216     // Advanced mouse
217     myCbEnableDnD.setSelected(editorSettings.isDndEnabled());
218     myCbEnableWheelFontChange.setSelected(editorSettings.isWheelFontChangeEnabled());
219     myCbHonorCamelHumpsWhenSelectingByClicking.setSelected(editorSettings.isMouseClickSelectionHonorsCamelWords());
220
221     myRbPreferMovingCaret.setSelected(editorSettings.isRefrainFromScrolling());
222     myRbPreferScrolling.setSelected(!editorSettings.isRefrainFromScrolling());
223
224
225     myRecentFilesLimitField.setText(Integer.toString(uiSettings.RECENT_FILES_LIMIT));
226     myCommandsHistoryLimitField.setText(Integer.toString(uiSettings.CONSOLE_COMMAND_HISTORY_LIMIT));
227
228     myCbRenameLocalVariablesInplace.setSelected(editorSettings.isVariableInplaceRenameEnabled());
229     myPreselectCheckBox.setSelected(editorSettings.isPreselectRename());
230     myShowInlineDialogForCheckBox.setSelected(editorSettings.isShowInlineLocalDialog());
231
232     myShowNotificationAfterReformatCodeCheckBox.setSelected(editorSettings.getOptions().SHOW_NOTIFICATION_AFTER_REFORMAT_CODE_ACTION);
233     myShowNotificationAfterOptimizeImportsCheckBox.setSelected(editorSettings.getOptions().SHOW_NOTIFICATION_AFTER_OPTIMIZE_IMPORTS_ACTION);
234
235     myShowWhitespacesModificationsInLSTGutterCheckBox.setSelected(vcsSettings.SHOW_WHITESPACES_IN_LST);
236
237     myErrorHighlightingPanel.reset();
238
239     RichCopySettings settings = RichCopySettings.getInstance();
240     myCbEnableRichCopyByDefault.setSelected(settings.isEnabled());
241     myRichCopyColorSchemeComboBox.removeAllItems();
242     EditorColorsScheme[] schemes = EditorColorsManager.getInstance().getAllSchemes();
243     myRichCopyColorSchemeComboBox.addItem(RichCopySettings.ACTIVE_GLOBAL_SCHEME_MARKER);
244     for (EditorColorsScheme scheme : schemes) {
245       myRichCopyColorSchemeComboBox.addItem(scheme.getName());
246     }
247     String toSelect = settings.getSchemeName();
248     if (!StringUtil.isEmpty(toSelect)) {
249       myRichCopyColorSchemeComboBox.setSelectedItem(toSelect);
250     }
251   }
252
253   private void explainTrailingSpaces(@NotNull @EditorSettingsExternalizable.StripTrailingSpaces String stripTrailingSpaces) {
254     if(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE.equals(stripTrailingSpaces)) {
255       myStripTrailingSpacesExplanationLabel.setVisible(false);
256       return;
257     }
258     myStripTrailingSpacesExplanationLabel.setVisible(true);
259     boolean isVirtualSpace = myCbVirtualSpace.isSelected();
260     String text;
261     String virtSpaceText = myCbVirtualSpace.getText();
262     if (isVirtualSpace) {
263       text = "Trailing spaces will be trimmed even in the line under caret.<br>To disable trimming in that line uncheck the '<b>"+virtSpaceText+"</b>' above.";
264     }
265     else {
266       text = "Trailing spaces will <b><font color=red>NOT</font></b> be trimmed in the line under caret.<br>To enable trimming in that line too check the '<b>"+virtSpaceText+"</b>' above.";
267     }
268     myStripTrailingSpacesExplanationLabel.setText(XmlStringUtil.wrapInHtml(text));
269   }
270
271   public void apply() throws ConfigurationException {
272     EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance();
273     CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
274     UISettings uiSettings=UISettings.getInstance();
275     VcsApplicationSettings vcsSettings = VcsApplicationSettings.getInstance();
276
277     // Display
278
279     editorSettings.setSmoothScrolling(myCbSmoothScrolling.isSelected());
280
281
282     // Brace Highlighting
283
284     codeInsightSettings.HIGHLIGHT_BRACES = myCbHighlightBraces.isSelected();
285     codeInsightSettings.HIGHLIGHT_SCOPE = myCbHighlightScope.isSelected();
286     codeInsightSettings.HIGHLIGHT_IDENTIFIER_UNDER_CARET = myCbHighlightIdentifierUnderCaret.isSelected();
287     clearAllIdentifierHighlighters();
288
289     // Virtual space
290
291     editorSettings.setUseSoftWraps(myCbUseSoftWrapsAtEditor.isSelected(), SoftWrapAppliancePlaces.MAIN_EDITOR);
292     editorSettings.setUseSoftWraps(myCbUseSoftWrapsAtConsole.isSelected(), SoftWrapAppliancePlaces.CONSOLE);
293     editorSettings.setUseCustomSoftWrapIndent(myCbUseCustomSoftWrapIndent.isSelected());
294     editorSettings.setCustomSoftWrapIndent(getCustomSoftWrapIndent());
295     editorSettings.setAllSoftwrapsShown(!myCbShowSoftWrapsOnlyOnCaretLine.isSelected());
296     editorSettings.setVirtualSpace(myCbVirtualSpace.isSelected());
297     editorSettings.setCaretInsideTabs(myCbCaretInsideTabs.isSelected());
298     editorSettings.setAdditionalPageAtBottom(myCbVirtualPageAtBottom.isSelected());
299
300     // Limits
301
302
303
304     boolean uiSettingsChanged = false;
305     int maxClipboardContents = getMaxClipboardContents();
306     if (uiSettings.MAX_CLIPBOARD_CONTENTS != maxClipboardContents) {
307       uiSettings.MAX_CLIPBOARD_CONTENTS = maxClipboardContents;
308       uiSettingsChanged = true;
309     }
310
311     if(uiSettingsChanged){
312       uiSettings.fireUISettingsChanged();
313     }
314
315     // Strip trailing spaces on save
316
317     if(STRIP_NONE.equals(myStripTrailingSpacesCombo.getSelectedItem())) {
318       editorSettings.setStripTrailingSpaces(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE);
319     }
320     else if(STRIP_CHANGED.equals(myStripTrailingSpacesCombo.getSelectedItem())){
321       editorSettings.setStripTrailingSpaces(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED);
322     }
323     else {
324       editorSettings.setStripTrailingSpaces(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
325     }
326
327     editorSettings.setEnsureNewLineAtEOF(myCbEnsureBlankLineBeforeCheckBox.isSelected());
328
329     if (myCbShowQuickDocOnMouseMove.isSelected() ^ editorSettings.isShowQuickDocOnMouseOverElement()) {
330       boolean enabled = myCbShowQuickDocOnMouseMove.isSelected();
331       editorSettings.setShowQuickDocOnMouseOverElement(enabled);
332       ServiceManager.getService(QuickDocOnMouseOverManager.class).setEnabled(enabled);
333     }
334
335     Long quickDocDelay = getQuickDocDelayFromGui();
336     if (quickDocDelay != null) {
337       editorSettings.setQuickDocOnMouseOverElementDelayMillis(quickDocDelay);
338     }
339
340     editorSettings.setDndEnabled(myCbEnableDnD.isSelected());
341
342     editorSettings.setWheelFontChangeEnabled(myCbEnableWheelFontChange.isSelected());
343     editorSettings.setMouseClickSelectionHonorsCamelWords(myCbHonorCamelHumpsWhenSelectingByClicking.isSelected());
344     editorSettings.setRefrainFromScrolling(myRbPreferMovingCaret.isSelected());
345
346     editorSettings.setVariableInplaceRenameEnabled(myCbRenameLocalVariablesInplace.isSelected());
347     editorSettings.setPreselectRename(myPreselectCheckBox.isSelected());
348     editorSettings.setShowInlineLocalDialog(myShowInlineDialogForCheckBox.isSelected());
349
350     editorSettings.getOptions().SHOW_NOTIFICATION_AFTER_REFORMAT_CODE_ACTION = myShowNotificationAfterReformatCodeCheckBox.isSelected();
351     editorSettings.getOptions().SHOW_NOTIFICATION_AFTER_OPTIMIZE_IMPORTS_ACTION = myShowNotificationAfterOptimizeImportsCheckBox.isSelected();
352
353     if (vcsSettings.SHOW_WHITESPACES_IN_LST != myShowWhitespacesModificationsInLSTGutterCheckBox.isSelected()) {
354       vcsSettings.SHOW_WHITESPACES_IN_LST = myShowWhitespacesModificationsInLSTGutterCheckBox.isSelected();
355       Project[] projects = ProjectManager.getInstance().getOpenProjects();
356       for (Project project : projects) {
357         LineStatusTrackerManager.getInstance(project).updateSettings();
358       }
359     }
360
361     reinitAllEditors();
362
363     String temp=myRecentFilesLimitField.getText();
364     if(temp.trim().length() > 0){
365       try {
366         int newRecentFilesLimit= Integer.parseInt(temp);
367         if(newRecentFilesLimit>0&&uiSettings.RECENT_FILES_LIMIT!=newRecentFilesLimit){
368           uiSettings.RECENT_FILES_LIMIT=newRecentFilesLimit;
369           uiSettingsChanged = true;
370         }
371       }catch (NumberFormatException ignored){}
372     }
373     if(uiSettingsChanged){
374       uiSettings.fireUISettingsChanged();
375     }
376     uiSettings.CONSOLE_COMMAND_HISTORY_LIMIT = StringUtil.parseInt(myCommandsHistoryLimitField.getText(), uiSettings.CONSOLE_COMMAND_HISTORY_LIMIT);
377
378     myErrorHighlightingPanel.apply();
379
380     RichCopySettings settings = RichCopySettings.getInstance();
381     settings.setEnabled(myCbEnableRichCopyByDefault.isSelected());
382     Object item = myRichCopyColorSchemeComboBox.getSelectedItem();
383     if (item instanceof String) {
384       settings.setSchemeName(item.toString());
385     }
386
387     restartDaemons();
388   }
389
390   @Nullable
391   private Long getQuickDocDelayFromGui() {
392     String quickDocDelayAsText = myQuickDocDelayTextField.getText();
393     if (StringUtil.isEmptyOrSpaces(quickDocDelayAsText)) {
394       return null;
395     }
396
397     try {
398       long delay = Long.parseLong(quickDocDelayAsText);
399       return delay > 0 ? delay : null;
400     }
401     catch (NumberFormatException e) {
402       // Ignore incorrect value.
403       return null;
404     }
405   }
406
407   public static void restartDaemons() {
408     Project[] projects = ProjectManager.getInstance().getOpenProjects();
409     for (Project project : projects) {
410       DaemonCodeAnalyzer.getInstance(project).settingsChanged();
411     }
412   }
413
414   private static void clearAllIdentifierHighlighters() {
415     for (Project project : ProjectManager.getInstance().getOpenProjects()) {
416       for (FileEditor fileEditor : FileEditorManager.getInstance(project).getAllEditors()) {
417         if (fileEditor instanceof TextEditor) {
418           Document document = ((TextEditor)fileEditor).getEditor().getDocument();
419           IdentifierHighlighterPass.clearMyHighlights(document, project);
420         }
421       }
422     }
423   }
424
425   public static void reinitAllEditors() {
426     Editor[] editors = EditorFactory.getInstance().getAllEditors();
427     for (Editor editor : editors) {
428       ((EditorEx)editor).reinitSettings();
429     }
430   }
431
432   public void disposeUIResources() {
433     myErrorHighlightingPanel.disposeUIResources();
434   }
435
436   private int getMaxClipboardContents(){
437     int maxClipboardContents = -1;
438     try {
439       maxClipboardContents = Integer.parseInt(myClipboardContentLimitTextField.getText());
440     } catch (NumberFormatException ignored) {}
441     if (maxClipboardContents <= 0) {
442       maxClipboardContents = 1;
443     }
444     return maxClipboardContents;
445   }
446
447   public boolean isModified() {
448     EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance();
449     CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
450     UISettings uiSettings=UISettings.getInstance();
451     VcsApplicationSettings vcsSettings = VcsApplicationSettings.getInstance();
452
453     // Display
454     boolean isModified = isModified(myCbSmoothScrolling, editorSettings.isSmoothScrolling());
455
456     // Brace highlighting
457     isModified |= isModified(myCbHighlightBraces, codeInsightSettings.HIGHLIGHT_BRACES);
458     isModified |= isModified(myCbHighlightScope, codeInsightSettings.HIGHLIGHT_SCOPE);
459     isModified |= isModified(myCbHighlightIdentifierUnderCaret, codeInsightSettings.HIGHLIGHT_IDENTIFIER_UNDER_CARET);
460
461     // Virtual space
462     isModified |= isModified(myCbUseSoftWrapsAtEditor, editorSettings.isUseSoftWraps(SoftWrapAppliancePlaces.MAIN_EDITOR));
463     isModified |= isModified(myCbUseSoftWrapsAtConsole, editorSettings.isUseSoftWraps(SoftWrapAppliancePlaces.CONSOLE));
464     isModified |= isModified(myCbUseCustomSoftWrapIndent, editorSettings.isUseCustomSoftWrapIndent());
465     isModified |= editorSettings.getCustomSoftWrapIndent() != getCustomSoftWrapIndent();
466     isModified |= isModified(myCbShowSoftWrapsOnlyOnCaretLine, !editorSettings.isAllSoftWrapsShown());
467     isModified |= isModified(myCbVirtualSpace, editorSettings.isVirtualSpace());
468     isModified |= isModified(myCbCaretInsideTabs, editorSettings.isCaretInsideTabs());
469     isModified |= isModified(myCbVirtualPageAtBottom, editorSettings.isAdditionalPageAtBottom());
470
471     // Limits
472
473
474     isModified |= getMaxClipboardContents() != uiSettings.MAX_CLIPBOARD_CONTENTS;
475
476     // Paste
477
478     // Strip trailing spaces, ensure EOL on EOF on save
479     isModified |= !getStripTrailingSpacesValue().equals(editorSettings.getStripTrailingSpaces());
480     isModified |= isModified(myCbEnsureBlankLineBeforeCheckBox, editorSettings.isEnsureNewLineAtEOF());
481
482     isModified |= isModified(myCbShowQuickDocOnMouseMove, editorSettings.isShowQuickDocOnMouseOverElement());
483     Long quickDocDelay = getQuickDocDelayFromGui();
484     if (quickDocDelay != null && !quickDocDelay.equals(Long.valueOf(editorSettings.getQuickDocOnMouseOverElementDelayMillis()))) {
485       return true;
486     }
487
488     // advanced mouse
489     isModified |= isModified(myCbEnableDnD, editorSettings.isDndEnabled());
490     isModified |= isModified(myCbEnableWheelFontChange, editorSettings.isWheelFontChangeEnabled());
491     isModified |= isModified(myCbHonorCamelHumpsWhenSelectingByClicking, editorSettings.isMouseClickSelectionHonorsCamelWords());
492
493     isModified |= myRbPreferMovingCaret.isSelected() != editorSettings.isRefrainFromScrolling();
494
495
496     isModified |= isModified(myRecentFilesLimitField, UISettings.getInstance().RECENT_FILES_LIMIT);
497     isModified |= isModified(myCommandsHistoryLimitField, UISettings.getInstance().CONSOLE_COMMAND_HISTORY_LIMIT);
498     isModified |= isModified(myCbRenameLocalVariablesInplace, editorSettings.isVariableInplaceRenameEnabled());
499     isModified |= isModified(myPreselectCheckBox, editorSettings.isPreselectRename());
500     isModified |= isModified(myShowInlineDialogForCheckBox, editorSettings.isShowInlineLocalDialog());
501
502     isModified |= isModified(myShowNotificationAfterReformatCodeCheckBox, editorSettings.getOptions().SHOW_NOTIFICATION_AFTER_REFORMAT_CODE_ACTION);
503     isModified |= isModified(myShowNotificationAfterOptimizeImportsCheckBox, editorSettings.getOptions().SHOW_NOTIFICATION_AFTER_OPTIMIZE_IMPORTS_ACTION);
504
505     isModified |= isModified(myShowWhitespacesModificationsInLSTGutterCheckBox, vcsSettings.SHOW_WHITESPACES_IN_LST);
506
507     isModified |= myErrorHighlightingPanel.isModified();
508
509     RichCopySettings settings = RichCopySettings.getInstance();
510     isModified |= isModified(myCbEnableRichCopyByDefault, settings.isEnabled());
511     isModified |= !Comparing.equal(settings.getSchemeName(), myRichCopyColorSchemeComboBox.getSelectedItem());
512
513     return isModified;
514   }
515
516   private static boolean isModified(JToggleButton checkBox, boolean value) {
517     return checkBox.isSelected() != value;
518   }
519
520   private static boolean isModified(JTextField textField, int value) {
521     try {
522       int fieldValue = Integer.parseInt(textField.getText().trim());
523       return fieldValue != value;
524     }
525     catch(NumberFormatException e) {
526       return false;
527     }
528   }
529
530   @NotNull
531   @EditorSettingsExternalizable.StripTrailingSpaces
532   private String getStripTrailingSpacesValue() {
533     Object selectedItem = myStripTrailingSpacesCombo.getSelectedItem();
534     if(STRIP_NONE.equals(selectedItem)) {
535       return EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE;
536     }
537     if(STRIP_CHANGED.equals(selectedItem)){
538       return EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED;
539     }
540     return EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE;
541   }
542
543   private int getCustomSoftWrapIndent() {
544     String indentAsString = myCustomSoftWrapIndent.getText();
545     int defaultIndent = 0;
546     if (indentAsString == null) {
547       return defaultIndent;
548     }
549     try {
550       int indent = Integer.parseInt(indentAsString.trim());
551       return indent >= 0 ? indent : defaultIndent;
552     } catch (IllegalArgumentException e) {
553       // Ignore
554     }
555     return defaultIndent;
556   }
557
558   private void initQuickDocProcessing() {
559     myCbShowQuickDocOnMouseMove.addItemListener(new ItemListener() {
560       @Override
561       public void itemStateChanged(ItemEvent e) {
562         myQuickDocDelayTextField.setEnabled(myCbShowQuickDocOnMouseMove.isSelected());
563         myQuickDocDelayLabel.setEnabled(myCbShowQuickDocOnMouseMove.isSelected());
564       }
565     });
566   }
567
568   private void initSoftWrapsSettingsProcessing() {
569     ItemListener listener = new ItemListener() {
570       @Override
571       public void itemStateChanged(ItemEvent e) {
572         updateSoftWrapSettingsRepresentation();
573       }
574     };
575     myCbUseSoftWrapsAtEditor.addItemListener(listener);
576     myCbUseSoftWrapsAtConsole.addItemListener(listener);
577     myCbUseCustomSoftWrapIndent.addItemListener(listener);
578   }
579
580   private void updateSoftWrapSettingsRepresentation() {
581     boolean softWrapsEnabled = myCbUseSoftWrapsAtEditor.isSelected() || myCbUseSoftWrapsAtConsole.isSelected();
582     myCbUseCustomSoftWrapIndent.setEnabled(softWrapsEnabled);
583     myCustomSoftWrapIndent.setEnabled(myCbUseCustomSoftWrapIndent.isEnabled() && myCbUseCustomSoftWrapIndent.isSelected());
584     myCustomSoftWrapIndentLabel.setEnabled(myCustomSoftWrapIndent.isEnabled());
585     myCbShowSoftWrapsOnlyOnCaretLine.setEnabled(softWrapsEnabled);
586   }
587
588   public JComponent getComponent() {
589     return myBehaviourPanel;
590   }
591
592   public class MyConfigurable implements SearchableConfigurable {
593     @Override
594     @NotNull
595     public String getId() {
596       return "Editor.Behavior";
597     }
598
599     @Override
600     public Runnable enableSearch(final String option) {
601       return null;
602     }
603
604     @Override
605     public String getDisplayName() {
606       return ApplicationBundle.message("tab.editor.settings.behavior");
607     }
608
609     @Override
610     public String getHelpTopic() {
611       return null;
612     }
613
614     @Override
615     public JComponent createComponent() {
616       return myBehaviourPanel;
617     }
618
619     @Override
620     public boolean isModified() {
621       return EditorOptionsPanel.this.isModified();
622     }
623
624     @Override
625     public void apply() throws ConfigurationException {
626       EditorOptionsPanel.this.apply();
627     }
628
629     @Override
630     public void reset() {
631       EditorOptionsPanel.this.reset();
632     }
633
634     @Override
635     public void disposeUIResources() {
636       EditorOptionsPanel.this.disposeUIResources();
637     }
638   }
639
640 }