API for custom color schemes was extracted. Two ruby dark schemes schemes were bundled.
[fedora-idea.git] / lang-impl / src / com / intellij / application / options / colors / ColorAndFontOptions.java
blob0b438f9d64211edfae5fd54ad838f65e7def69ec
1 package com.intellij.application.options.colors;
3 import com.intellij.application.options.OptionsContainingConfigurable;
4 import com.intellij.application.options.editor.EditorOptionsProvider;
5 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
6 import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
7 import com.intellij.ide.DataManager;
8 import com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable;
9 import com.intellij.openapi.actionSystem.PlatformDataKeys;
10 import com.intellij.openapi.application.ApplicationBundle;
11 import com.intellij.openapi.diff.impl.settings.DiffOptionsPanel;
12 import com.intellij.openapi.diff.impl.settings.DiffPreviewPanel;
13 import com.intellij.openapi.editor.EditorFactory;
14 import com.intellij.openapi.editor.colors.ColorKey;
15 import com.intellij.openapi.editor.colors.EditorColorsManager;
16 import com.intellij.openapi.editor.colors.EditorColorsScheme;
17 import com.intellij.openapi.editor.colors.TextAttributesKey;
18 import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager;
19 import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme;
20 import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl;
21 import com.intellij.openapi.editor.colors.impl.ReadOnlyColorsScheme;
22 import com.intellij.openapi.editor.markup.EffectType;
23 import com.intellij.openapi.editor.markup.TextAttributes;
24 import com.intellij.openapi.options.Configurable;
25 import com.intellij.openapi.options.ConfigurationException;
26 import com.intellij.openapi.options.ExternalizableScheme;
27 import com.intellij.openapi.options.SearchableConfigurable;
28 import com.intellij.openapi.options.colors.AttributesDescriptor;
29 import com.intellij.openapi.options.colors.ColorDescriptor;
30 import com.intellij.openapi.options.colors.ColorSettingsPage;
31 import com.intellij.openapi.options.colors.ColorSettingsPages;
32 import com.intellij.openapi.options.newEditor.OptionsEditor;
33 import com.intellij.openapi.project.Project;
34 import com.intellij.openapi.project.ProjectManager;
35 import com.intellij.openapi.util.Comparing;
36 import com.intellij.openapi.util.IconLoader;
37 import com.intellij.openapi.util.Pair;
38 import com.intellij.openapi.vcs.FileStatus;
39 import com.intellij.openapi.vcs.FileStatusFactory;
40 import com.intellij.openapi.vcs.FileStatusManager;
41 import com.intellij.psi.search.scope.packageSet.NamedScope;
42 import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
43 import com.intellij.psi.search.scope.packageSet.PackageSet;
44 import com.intellij.util.containers.HashMap;
45 import gnu.trove.THashSet;
46 import gnu.trove.TObjectHashingStrategy;
47 import org.jetbrains.annotations.Nls;
48 import org.jetbrains.annotations.NotNull;
49 import org.jetbrains.annotations.Nullable;
51 import javax.swing.*;
52 import java.awt.*;
53 import java.awt.event.ActionEvent;
54 import java.awt.event.ActionListener;
55 import java.util.*;
56 import java.util.List;
58 public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract implements EditorOptionsProvider {
59 private HashMap<String,MyColorScheme> mySchemes;
60 private MyColorScheme mySelectedScheme;
61 public static final String DIFF_GROUP = ApplicationBundle.message("title.diff");
62 public static final String FILE_STATUS_GROUP = ApplicationBundle.message("title.file.status");
63 public static final String SCOPES_GROUP = ApplicationBundle.message("title.scope.based");
65 private boolean mySomeSchemesDeleted = false;
66 private Map<NewColorAndFontPanel, SearchableConfigurable> mySubPanels;
68 private SchemesPanel myRootSchemesPanel;
70 private boolean myInitResetCompleted = false;
71 private boolean myInitResetInvoked = false;
73 private boolean myRevertChangesCompleted = false;
75 private boolean myApplyCompleted = false;
76 private boolean myDisposeCompleted = false;
78 public boolean isModified() {
79 boolean listModified = isSchemeListModified();
80 boolean schemeModified = isSomeSchemeModified();
82 if (listModified || schemeModified) {
83 myApplyCompleted = false;
86 return listModified;
89 private boolean isSchemeListModified(){
90 if (mySomeSchemesDeleted) return true;
92 if (!mySelectedScheme.getName().equals(EditorColorsManager.getInstance().getGlobalScheme().getName())) return true;
94 for (MyColorScheme scheme : mySchemes.values()) {
95 if (scheme.isNew()) return true;
98 return false;
101 private boolean isSomeSchemeModified() {
102 for (MyColorScheme scheme : mySchemes.values()) {
103 if (scheme.isModified()) return true;
105 return false;
108 public EditorColorsScheme selectScheme(@NotNull String name) {
109 mySelectedScheme = getScheme(name);
110 return mySelectedScheme;
113 private MyColorScheme getScheme(String name) {
114 return mySchemes.get(name);
117 public EditorColorsScheme getSelectedScheme() {
118 return mySelectedScheme;
121 public EditorColorsScheme getOriginalSelectedScheme() {
122 return mySelectedScheme == null ? null : mySelectedScheme.getOriginalScheme();
125 public EditorSchemeAttributeDescriptor[] getCurrentDescriptions() {
126 return mySelectedScheme.getDescriptors();
129 public static boolean isReadOnly(final EditorColorsScheme scheme) {
130 return ((MyColorScheme)scheme).isReadOnly();
133 public String[] getSchemeNames() {
134 ArrayList<MyColorScheme> schemes = new ArrayList<MyColorScheme>(mySchemes.values());
135 Collections.sort(schemes, new Comparator<MyColorScheme>() {
136 public int compare(MyColorScheme o1, MyColorScheme o2) {
137 if (isReadOnly(o1) && !isReadOnly(o2)) return -1;
138 if (!isReadOnly(o1) && isReadOnly(o2)) return 1;
140 return o1.getName().compareToIgnoreCase(o2.getName());
144 ArrayList<String> names = new ArrayList<String>(schemes.size());
145 for (MyColorScheme scheme : schemes) {
146 names.add(scheme.getName());
149 return names.toArray(new String[names.size()]);
152 public Collection<EditorColorsScheme> getSchemes() {
153 return new ArrayList<EditorColorsScheme>(mySchemes.values());
156 public void saveSchemeAs(String name) {
157 MyColorScheme scheme = mySelectedScheme;
158 if (scheme == null) return;
160 EditorColorsScheme clone = (EditorColorsScheme)scheme.getOriginalScheme().clone();
162 scheme.apply(clone);
164 clone.setName(name);
165 MyColorScheme newScheme = new MyColorScheme(clone);
166 initScheme(newScheme);
168 newScheme.setIsNew();
170 mySchemes.put(name, newScheme);
171 selectScheme(newScheme.getName());
172 resetSchemesCombo(null);
175 public void addImportedScheme(final EditorColorsScheme imported) {
176 MyColorScheme newScheme = new MyColorScheme(imported);
177 initScheme(newScheme);
179 mySchemes.put(imported.getName(), newScheme);
180 selectScheme(newScheme.getName());
181 resetSchemesCombo(null);
184 public void removeScheme(String name) {
185 if (mySelectedScheme.getName().equals(name)) {
186 //noinspection HardCodedStringLiteral
187 selectScheme("Default");
190 boolean deletedNewlyCreated = false;
192 MyColorScheme toDelete = mySchemes.get(name);
194 if (toDelete != null) {
195 deletedNewlyCreated = toDelete.isNew();
198 mySchemes.remove(name);
199 resetSchemesCombo(null);
200 mySomeSchemesDeleted = mySomeSchemesDeleted || !deletedNewlyCreated;
203 public void apply() throws ConfigurationException {
204 if (!myApplyCompleted) {
205 try {
206 EditorColorsManager myColorsManager = EditorColorsManager.getInstance();
208 myColorsManager.removeAllSchemes();
209 for (MyColorScheme scheme : mySchemes.values()) {
210 if (!scheme.isDefault()) {
211 scheme.apply();
212 myColorsManager.addColorsScheme(scheme.getOriginalScheme());
216 EditorColorsScheme originalScheme = mySelectedScheme.getOriginalScheme();
217 myColorsManager.setGlobalScheme(originalScheme);
219 applyChangesToEditors();
221 reset();
223 finally {
224 myApplyCompleted = true;
233 // initAll();
234 // resetSchemesCombo();
239 private void applyChangesToEditors() {
240 EditorFactory.getInstance().refreshAllEditors();
242 Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
243 for (Project openProject : openProjects) {
244 FileStatusManager.getInstance(openProject).fileStatusesChanged();
245 DaemonCodeAnalyzer.getInstance(openProject).restart();
249 private boolean myIsReset = false;
251 private void resetSchemesCombo(Object source) {
252 myIsReset = true;
253 try {
254 myRootSchemesPanel.resetSchemesCombo(source);
255 if (mySubPanels != null) {
256 for (NewColorAndFontPanel subPartialConfigurable : getPanels()) {
257 subPartialConfigurable.reset(source);
261 finally {
262 myIsReset = false;
266 @Override
267 public JComponent createComponent() {
268 if (myRootSchemesPanel == null) {
269 ensureSchemesPanel();
271 return myRootSchemesPanel;
274 @Override
275 public boolean hasOwnContent() {
276 return true;
279 protected Configurable[] buildConfigurables() {
280 myDisposeCompleted = false;
281 initAll();
283 ArrayList<NewColorAndFontPanel> panels = createSubPanels();
285 for (NewColorAndFontPanel partialConfigurable : panels) {
286 partialConfigurable.addSchemesListener(new ColorAndFontSettingsListener.Abstract(){
287 public void schemeChanged(final Object source) {
288 if (!myIsReset) {
289 resetSchemesCombo(source);
294 partialConfigurable.addDescriptionListener(new ColorAndFontSettingsListener.Abstract(){
295 @Override
296 public void fontChanged() {
297 for (NewColorAndFontPanel panel : getPanels()) {
298 panel.updatePreview();
305 List<Configurable> result = new ArrayList<Configurable>();
306 mySubPanels = new LinkedHashMap<NewColorAndFontPanel, SearchableConfigurable>(panels.size());
308 for (final NewColorAndFontPanel subPanel : panels) {
309 mySubPanels.put(subPanel, new InnerSearchableConfigurable(subPanel));
312 result.addAll(new ArrayList<SearchableConfigurable>(mySubPanels.values()));
314 return result.toArray(new Configurable[result.size()]);
317 private Set<NewColorAndFontPanel> getPanels() {
318 return mySubPanels.keySet();
321 private ArrayList<NewColorAndFontPanel> createSubPanels() {
323 ArrayList<NewColorAndFontPanel> result = new ArrayList<NewColorAndFontPanel>();
325 result.add(createFontConfigurable());
327 ColorSettingsPage[] pages = ColorSettingsPages.getInstance().getRegisteredPages();
328 for (ColorSettingsPage page : pages) {
329 final SimpleEditorPreview preview = new SimpleEditorPreview(this, page);
330 NewColorAndFontPanel panel = NewColorAndFontPanel.create(preview,
331 page.getDisplayName(),
332 this, null);
335 result.add(panel);
338 result.add(createDiffPanel());
340 result.add(NewColorAndFontPanel.create(new PreviewPanel.Empty(), ColorAndFontOptions.FILE_STATUS_GROUP, this, collectFileTypes()));
342 final JPanel scopePanel = createChooseScopePanel();
343 result.add(NewColorAndFontPanel.create(new PreviewPanel.Empty(){
344 public Component getPanel() {
346 return scopePanel;
349 }, ColorAndFontOptions.SCOPES_GROUP, this, null));
352 return result;
355 private Collection<String> collectFileTypes() {
356 ArrayList<String> result = new ArrayList<String>();
357 FileStatus[] statuses = FileStatusFactory.SERVICE.getInstance().getAllFileStatuses();
359 for (FileStatus status : statuses) {
360 result.add(status.getText());
362 return result;
365 private NewColorAndFontPanel createFontConfigurable() {
366 return new NewColorAndFontPanel(new SchemesPanel(this), new FontOptions(this), new FontEditorPreview(this), "Font", null){
367 @Override
368 public boolean containsFontOptions() {
369 return true;
374 private NewColorAndFontPanel createDiffPanel() {
375 final DiffPreviewPanel diffPreviewPanel = new DiffPreviewPanel();
376 diffPreviewPanel.setMergeRequest(null);
377 final DiffOptionsPanel optionsPanel = new DiffOptionsPanel(this);
379 optionsPanel.addListener(new ColorAndFontSettingsListener.Abstract(){
380 public void actionPerformed(final ActionEvent e) {
381 optionsPanel.applyChangesToScheme();
382 diffPreviewPanel.updateView();
387 SchemesPanel schemesPanel = new SchemesPanel(this);
389 schemesPanel.addListener(new ColorAndFontSettingsListener.Abstract(){
390 public void schemeChanged(final Object source) {
391 diffPreviewPanel.setColorScheme(getSelectedScheme());
392 optionsPanel.updateOptionsList();
393 diffPreviewPanel.updateView();
395 } );
397 return new NewColorAndFontPanel(schemesPanel, optionsPanel, diffPreviewPanel,ColorAndFontOptions.DIFF_GROUP, null);
401 private JPanel createChooseScopePanel() {
402 Project[] projects = ProjectManager.getInstance().getOpenProjects();
403 JPanel panel = new JPanel(new GridBagLayout());
404 //panel.setBorder(new LineBorder(Color.red));
405 if (projects.length == 0) return panel;
406 GridBagConstraints gc = new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
407 new Insets(0, 0, 0, 0), 0, 0);
408 final Project contextProject = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
409 final Project project = contextProject != null ? contextProject : projects[0];
411 JButton button = new JButton(ApplicationBundle.message("button.edit.scopes"));
412 button.setPreferredSize(new Dimension(230, button.getPreferredSize().height));
413 panel.add(button, gc);
414 gc.gridx = GridBagConstraints.REMAINDER;
415 gc.weightx = 1;
416 panel.add(new JPanel(), gc);
418 gc.gridy++;
419 gc.gridx=0;
420 gc.weighty = 1;
421 panel.add(new JPanel(), gc);
422 button.addActionListener(new ActionListener() {
423 public void actionPerformed(ActionEvent e) {
424 final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(DataManager.getInstance().getDataContext());
425 if (optionsEditor != null) {
426 optionsEditor.select(ScopeChooserConfigurable.getInstance(project));
430 return panel;
434 private void initAll() {
435 EditorColorsManager colorsManager = EditorColorsManager.getInstance();
436 EditorColorsScheme[] allSchemes = colorsManager.getAllSchemes();
438 mySchemes = new HashMap<String, MyColorScheme>();
439 for (EditorColorsScheme allScheme : allSchemes) {
440 MyColorScheme schemeDelegate = new MyColorScheme(allScheme);
441 initScheme(schemeDelegate);
442 mySchemes.put(schemeDelegate.getName(), schemeDelegate);
445 mySelectedScheme = mySchemes.get(EditorColorsManager.getInstance().getGlobalScheme().getName());
446 assert mySelectedScheme != null : EditorColorsManager.getInstance().getGlobalScheme().getName() + "; myschemes=" + mySchemes;
449 private static void initScheme(MyColorScheme scheme) {
450 ArrayList<EditorSchemeAttributeDescriptor> descriptions = new ArrayList<EditorSchemeAttributeDescriptor>();
451 initPluggedDescriptions(descriptions, scheme);
452 initDiffDescriptors(descriptions, scheme);
453 initFileStatusDescriptors(descriptions, scheme);
454 initScopesDescriptors(descriptions, scheme);
456 scheme.setDescriptors(descriptions.toArray(new EditorSchemeAttributeDescriptor[descriptions.size()]));
459 private static void initPluggedDescriptions(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
460 ColorSettingsPage[] pages = ColorSettingsPages.getInstance().getRegisteredPages();
461 for (ColorSettingsPage page : pages) {
462 initDescriptions(page, descriptions, scheme);
466 private static void initDescriptions(ColorSettingsPage page,
467 ArrayList<EditorSchemeAttributeDescriptor> descriptions,
468 MyColorScheme scheme) {
469 String group = page.getDisplayName();
470 AttributesDescriptor[] attributeDescriptors = page.getAttributeDescriptors();
471 for (AttributesDescriptor descriptor : attributeDescriptors) {
472 addSchemedDescription(descriptions, descriptor.getDisplayName(), group, descriptor.getKey(), scheme, null, null);
475 ColorDescriptor[] colorDescriptors = page.getColorDescriptors();
476 for (ColorDescriptor descriptor : colorDescriptors) {
477 ColorKey back = descriptor.getKind() == ColorDescriptor.Kind.BACKGROUND ? descriptor.getKey() : null;
478 ColorKey fore = descriptor.getKind() == ColorDescriptor.Kind.FOREGROUND ? descriptor.getKey() : null;
479 addEditorSettingDescription(descriptions, descriptor.getDisplayName(), group, back, fore, scheme);
483 private static void initDiffDescriptors(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
484 DiffOptionsPanel.addSchemeDescriptions(descriptions, scheme);
487 private static void initFileStatusDescriptors(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
489 FileStatus[] statuses = FileStatusFactory.SERVICE.getInstance().getAllFileStatuses();
491 for (FileStatus fileStatus : statuses) {
492 addEditorSettingDescription(descriptions,
493 fileStatus.getText(),
494 FILE_STATUS_GROUP,
495 null,
496 fileStatus.getColorKey(),
497 scheme);
501 private static void initScopesDescriptors(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
502 Set<Pair<NamedScope,NamedScopesHolder>> namedScopes = new THashSet<Pair<NamedScope,NamedScopesHolder>>(new TObjectHashingStrategy<Pair<NamedScope,NamedScopesHolder>>() {
503 public int computeHashCode(final Pair<NamedScope, NamedScopesHolder> object) {
504 return object.getFirst().getName().hashCode();
507 public boolean equals(final Pair<NamedScope, NamedScopesHolder> o1, final Pair<NamedScope, NamedScopesHolder> o2) {
508 return o1.getFirst().getName().equals(o2.getFirst().getName());
511 Project[] projects = ProjectManager.getInstance().getOpenProjects();
512 for (Project project : projects) {
513 DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
514 List<Pair<NamedScope,NamedScopesHolder>> cachedScopes = codeAnalyzer.getScopeBasedHighlightingCachedScopes();
515 namedScopes.addAll(cachedScopes);
518 List<Pair<NamedScope, NamedScopesHolder>> list = new ArrayList<Pair<NamedScope, NamedScopesHolder>>(namedScopes);
520 Collections.sort(list, new Comparator<Pair<NamedScope,NamedScopesHolder>>() {
521 public int compare(final Pair<NamedScope,NamedScopesHolder> o1, final Pair<NamedScope,NamedScopesHolder> o2) {
522 return o1.getFirst().getName().compareToIgnoreCase(o2.getFirst().getName());
525 for (Pair<NamedScope,NamedScopesHolder> pair : list) {
526 NamedScope namedScope = pair.getFirst();
527 String name = namedScope.getName();
528 TextAttributesKey textAttributesKey = getScopeTextAttributeKey(name);
529 if (scheme.getAttributes(textAttributesKey) == null) {
530 scheme.setAttributes(textAttributesKey, new TextAttributes());
532 NamedScopesHolder holder = pair.getSecond();
534 PackageSet value = namedScope.getValue();
535 String toolTip = holder.getDisplayName() + (value==null ? "" : ": "+ value.getText());
536 addSchemedDescription(descriptions,
537 name,
538 SCOPES_GROUP,
539 textAttributesKey,
540 scheme, holder.getIcon(), toolTip);
544 public static TextAttributesKey getScopeTextAttributeKey(final String scope) {
545 return TextAttributesKey.find("SCOPE_KEY_" + scope);
548 private static void addEditorSettingDescription(ArrayList<EditorSchemeAttributeDescriptor> array,
549 String name,
550 String group,
551 ColorKey backgroundKey,
552 ColorKey foregroundKey,
553 EditorColorsScheme scheme) {
554 String type = null;
555 if (foregroundKey != null) {
556 type = foregroundKey.getExternalName();
558 else {
559 if (backgroundKey != null) {
560 type = backgroundKey.getExternalName();
563 ColorAndFontDescription descr = new EditorSettingColorDescription(name, group, backgroundKey, foregroundKey, type, scheme);
564 array.add(descr);
567 private static void addSchemedDescription(ArrayList<EditorSchemeAttributeDescriptor> array, String name, String group, TextAttributesKey key,
568 EditorColorsScheme scheme,
569 Icon icon,
570 String toolTip) {
571 ColorAndFontDescription descr = new SchemeTextAttributesDescription(name, group, key, scheme, icon, toolTip);
572 array.add(descr);
575 public String getDisplayName() {
576 return ApplicationBundle.message("title.colors.and.fonts");
579 public Icon getIcon() {
580 return IconLoader.getIcon("/general/configurableColorsAndFonts.png");
583 private void revertChanges(){
584 if (isSchemeListModified() || isSomeSchemeModified()) {
585 myRevertChangesCompleted = false;
588 if (!myRevertChangesCompleted) {
589 ensureSchemesPanel();
592 try {
593 resetImpl();
595 finally {
596 myRevertChangesCompleted = true;
602 private void resetImpl() {
603 mySomeSchemesDeleted = false;
604 initAll();
605 resetSchemesCombo(null);
608 public void reset() {
609 if (!myInitResetInvoked) {
610 super.reset();
611 if (!myInitResetCompleted) {
612 ensureSchemesPanel();
614 try {
615 resetImpl();
617 finally {
618 myInitResetCompleted = true;
622 myInitResetInvoked = true;
624 else {
625 revertChanges();
630 public void resetFromChild() {
631 if (!myInitResetCompleted) {
632 ensureSchemesPanel();
635 try {
636 resetImpl();
638 finally {
639 myInitResetCompleted = true;
645 private void ensureSchemesPanel() {
646 if (myRootSchemesPanel == null) {
647 myRootSchemesPanel = new SchemesPanel(this);
649 myRootSchemesPanel.addListener(new ColorAndFontSettingsListener.Abstract(){
650 @Override
651 public void schemeChanged(final Object source) {
652 if (!myIsReset) {
653 resetSchemesCombo(source);
661 public void disposeUIResources() {
662 if (!myDisposeCompleted) {
663 try {
664 super.disposeUIResources();
665 if (mySubPanels != null) {
666 for (NewColorAndFontPanel subPanel : getPanels()) {
667 subPanel.disposeUIResources();
670 if (myRootSchemesPanel != null) {
671 myRootSchemesPanel.disposeUIResources();
674 finally {
675 myDisposeCompleted = true;
678 mySubPanels = null;
680 myInitResetCompleted = false;
681 myInitResetInvoked = false;
682 myRevertChangesCompleted = false;
684 myApplyCompleted = false;
685 myRootSchemesPanel = null;
688 public boolean currentSchemeIsReadOnly() {
689 return isReadOnly(mySelectedScheme);
692 public boolean currentSchemeIsShared() {
693 return ColorSettingsUtil.isSharedScheme(mySelectedScheme);
697 private static class SchemeTextAttributesDescription extends TextAttributesDescription {
698 private TextAttributes myAttributesToApply;
699 private TextAttributesKey key;
701 public SchemeTextAttributesDescription(String name, String group, TextAttributesKey key, EditorColorsScheme scheme, Icon icon,
702 String toolTip) {
703 super(name, group,
704 scheme.getAttributes(key) == null
705 ? new TextAttributes()
706 : scheme.getAttributes(key).clone(),
707 key, scheme, icon, toolTip);
708 this.key = key;
709 myAttributesToApply = scheme.getAttributes(key);
710 initCheckedStatus();
713 public void apply(EditorColorsScheme scheme) {
714 if (scheme == null) scheme = getScheme();
715 if (myAttributesToApply != null) {
716 scheme.setAttributes(key, getTextAttributes());
720 public boolean isModified() {
721 return !Comparing.equal(myAttributesToApply, getTextAttributes());
724 public boolean isErrorStripeEnabled() {
725 return true;
729 private static class GetSetColor {
730 private final ColorKey myKey;
731 private EditorColorsScheme myScheme;
732 private boolean isModified = false;
733 private Color myColor;
735 public GetSetColor(ColorKey key, EditorColorsScheme scheme) {
736 myKey = key;
737 myScheme = scheme;
738 myColor = myScheme.getColor(myKey);
741 public Color getColor() {
742 return myColor;
745 public void setColor(Color col) {
746 if (getColor() == null || !getColor().equals(col)) {
747 isModified = true;
748 myColor = col;
752 public void apply(EditorColorsScheme scheme) {
753 if (scheme == null) scheme = myScheme;
754 scheme.setColor(myKey, myColor);
757 public boolean isModified() {
758 return isModified;
762 private static class EditorSettingColorDescription extends ColorAndFontDescription {
763 private GetSetColor myGetSetForeground;
764 private GetSetColor myGetSetBackground;
766 public EditorSettingColorDescription(String name,
767 String group,
768 ColorKey backgroundKey,
769 ColorKey foregroundKey,
770 String type,
771 EditorColorsScheme scheme) {
772 super(name, group, type, scheme, null, null);
773 if (backgroundKey != null) {
774 myGetSetBackground = new GetSetColor(backgroundKey, scheme);
776 if (foregroundKey != null) {
777 myGetSetForeground = new GetSetColor(foregroundKey, scheme);
779 initCheckedStatus();
782 public int getFontType() {
783 return 0;
786 public void setFontType(int type) {
789 public Color getExternalEffectColor() {
790 return null;
793 public void setExternalEffectColor(Color color) {
796 public void setExternalEffectType(EffectType type) {
799 public EffectType getExternalEffectType() {
800 return EffectType.LINE_UNDERSCORE;
803 public Color getExternalForeground() {
804 if (myGetSetForeground == null) {
805 return null;
807 return myGetSetForeground.getColor();
810 public void setExternalForeground(Color col) {
811 if (myGetSetForeground == null) {
812 return;
814 myGetSetForeground.setColor(col);
817 public Color getExternalBackground() {
818 if (myGetSetBackground == null) {
819 return null;
821 return myGetSetBackground.getColor();
824 public void setExternalBackground(Color col) {
825 if (myGetSetBackground == null) {
826 return;
828 myGetSetBackground.setColor(col);
831 public Color getExternalErrorStripe() {
832 return null;
835 public void setExternalErrorStripe(Color col) {
838 public boolean isFontEnabled() {
839 return false;
842 public boolean isForegroundEnabled() {
843 return myGetSetForeground != null;
846 public boolean isBackgroundEnabled() {
847 return myGetSetBackground != null;
850 public boolean isEffectsColorEnabled() {
851 return false;
854 public boolean isModified() {
855 return myGetSetBackground != null && myGetSetBackground.isModified()
856 || myGetSetForeground != null && myGetSetForeground.isModified();
859 public void apply(EditorColorsScheme scheme) {
860 if (myGetSetBackground != null) {
861 myGetSetBackground.apply(scheme);
863 if (myGetSetForeground != null) {
864 myGetSetForeground.apply(scheme);
869 public String getHelpTopic() {
870 return "reference.settingsdialog.IDE.editor.colors";
873 private static class MyColorScheme extends EditorColorsSchemeImpl {
874 private int myFontSize;
875 private float myLineSpacing;
876 private String myFontName;
877 private EditorSchemeAttributeDescriptor[] myDescriptors;
878 private String myName;
879 private boolean myIsNew = false;
881 public MyColorScheme(EditorColorsScheme parenScheme) {
882 super(parenScheme, DefaultColorSchemesManager.getInstance());
883 myFontSize = parenScheme.getEditorFontSize();
884 myLineSpacing = parenScheme.getLineSpacing();
885 myFontName = parenScheme.getEditorFontName();
886 myName = parenScheme.getName();
887 if (parenScheme instanceof ExternalizableScheme) {
888 getExternalInfo().copy(((ExternalizableScheme)parenScheme).getExternalInfo());
890 initFonts();
893 public String getName() {
894 return myName;
897 public void setName(String name) {
898 myName = name;
901 public void setDescriptors(EditorSchemeAttributeDescriptor[] descriptors) {
902 myDescriptors = descriptors;
905 public EditorSchemeAttributeDescriptor[] getDescriptors() {
906 return myDescriptors;
909 public boolean isDefault() {
910 return myParentScheme instanceof DefaultColorsScheme;
913 public boolean isReadOnly() {
914 return myParentScheme instanceof ReadOnlyColorsScheme;
917 public boolean isModified() {
918 if (isFontModified()) return true;
920 for (EditorSchemeAttributeDescriptor descriptor : myDescriptors) {
921 if (descriptor.isModified()) {
922 return true;
926 return false;
929 private boolean isFontModified() {
930 if (myFontSize != myParentScheme.getEditorFontSize()) return true;
931 if (myLineSpacing != myParentScheme.getLineSpacing()) return true;
932 if (!myFontName.equals(myParentScheme.getEditorFontName())) return true;
933 return false;
936 public void apply() {
937 apply(myParentScheme);
940 public void apply(EditorColorsScheme scheme) {
941 scheme.setEditorFontSize(myFontSize);
942 scheme.setEditorFontName(myFontName);
943 scheme.setLineSpacing(myLineSpacing);
945 for (EditorSchemeAttributeDescriptor descriptor : myDescriptors) {
946 descriptor.apply(scheme);
950 public String getEditorFontName() {
951 return myFontName;
954 public int getEditorFontSize() {
955 return myFontSize;
958 public float getLineSpacing() {
959 return myLineSpacing;
962 public void setEditorFontSize(int fontSize) {
963 myFontSize = fontSize;
964 initFonts();
967 public void setLineSpacing(float lineSpacing) {
968 myLineSpacing = lineSpacing;
971 public void setEditorFontName(String fontName) {
972 myFontName = fontName;
973 initFonts();
976 public Object clone() {
977 return null;
980 public EditorColorsScheme getOriginalScheme() {
981 return myParentScheme;
984 public void setIsNew() {
985 myIsNew = true;
988 public boolean isNew() {
989 return myIsNew;
993 public String getId() {
994 return getHelpTopic();
997 @Nullable
998 public Runnable enableSearch(final String option) {
999 return null;
1002 @Nullable
1003 public SearchableConfigurable findSubConfigurable(String id) {
1004 for (SearchableConfigurable configurable : mySubPanels.values()) {
1005 if (Comparing.strEqual(configurable.getId(), id)){
1006 return configurable;
1009 return null;
1012 private class InnerSearchableConfigurable implements SearchableConfigurable, OptionsContainingConfigurable {
1013 private final NewColorAndFontPanel mySubPanel;
1014 private boolean mySubInitInvoked = false;
1016 public InnerSearchableConfigurable(final NewColorAndFontPanel subPanel) {
1017 mySubPanel = subPanel;
1020 @Nls
1021 public String getDisplayName() {
1022 return mySubPanel.getDisplayName();
1025 public Icon getIcon() {
1026 return null;
1029 public String getHelpTopic() {
1030 return null;
1033 public JComponent createComponent() {
1034 return mySubPanel.getPanel();
1037 public boolean isModified() {
1038 for (MyColorScheme scheme : mySchemes.values()) {
1039 if (mySubPanel.containsFontOptions()) {
1040 if (scheme.isFontModified()) {
1041 myRevertChangesCompleted = false;
1042 return true;
1045 else {
1046 for (EditorSchemeAttributeDescriptor descriptor : scheme.getDescriptors()) {
1047 if (mySubPanel.contains(descriptor) && descriptor.isModified()) {
1048 myRevertChangesCompleted = false;
1049 return true;
1056 return false;
1060 public void apply() throws ConfigurationException {
1061 ColorAndFontOptions.this.apply();
1064 public void reset() {
1065 if (!mySubInitInvoked) {
1066 if (!myInitResetCompleted) {
1067 ColorAndFontOptions.this.resetFromChild();
1069 mySubInitInvoked = true;
1071 else {
1072 ColorAndFontOptions.this.revertChanges();
1076 public void disposeUIResources() {
1077 ColorAndFontOptions.this.disposeUIResources();
1080 public String getId() {
1081 return ColorAndFontOptions.this.getId() + "." + getDisplayName();
1084 public Runnable enableSearch(final String option) {
1085 return mySubPanel.showOption(option);
1088 public Set<String> processListOptions() {
1089 return mySubPanel.processListOptions();