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