babd1ad7a4648c5cbf246f9cb8a085d1d4a45325
[idea/community.git] / platform / lang-impl / src / com / intellij / application / options / colors / CustomizedSwitcherPanel.java
1 /*
2  * Copyright 2000-2016 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 package com.intellij.application.options.colors;
17
18 import com.intellij.application.options.colors.highlighting.HighlightData;
19 import com.intellij.codeHighlighting.RainbowHighlighter;
20 import com.intellij.openapi.editor.colors.EditorColorsScheme;
21 import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor;
22 import com.intellij.openapi.editor.colors.TextAttributesKey;
23 import com.intellij.openapi.editor.ex.DocumentEx;
24 import com.intellij.openapi.options.colors.ColorSettingsPage;
25 import com.intellij.openapi.options.colors.RainbowColorSettingsPage;
26 import com.intellij.openapi.util.Pair;
27 import com.intellij.openapi.util.TextRange;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
30
31 import javax.swing.*;
32 import java.awt.*;
33 import java.util.*;
34 import java.util.List;
35
36 class CustomizedSwitcherPanel extends JPanel implements OptionsPanelImpl.ColorDescriptionPanel {
37   private ColorSettingsPage myPage;
38
39   private PreviewPanel myPreviewPanel;
40   private ColorAndFontDescriptionPanel myColorAndFontPanel;
41   private RainbowDescriptionPanel myRainbowPanel;
42
43   private OptionsPanelImpl.ColorDescriptionPanel myActive;
44
45   public CustomizedSwitcherPanel(ColorAndFontGlobalState options, @Nullable PreviewPanel previewPanel, ColorSettingsPage page) {
46     super();
47     myPage = page;
48     myPreviewPanel = previewPanel;
49
50     myRainbowPanel = new RainbowDescriptionPanel(options);
51     myColorAndFontPanel = new ColorAndFontDescriptionPanel();
52
53     Dimension sizeR = myRainbowPanel.getPreferredSize();
54     Dimension sizeC = myColorAndFontPanel.getPreferredSize();
55     Dimension preferredSize = new Dimension();
56     preferredSize.setSize(Math.max(sizeR.getWidth(), sizeC.getWidth()),
57                           Math.max(sizeR.getHeight(), sizeC.getHeight()));
58     setPreferredSize(preferredSize);
59   }
60
61   @NotNull
62   @Override
63   public JComponent getPanel() {
64     return this;
65   }
66
67   @Override
68   public void resetDefault() {
69     myActive = null;
70     if (getComponentCount() != 0) {
71       try {
72         setIgnoreRepaint(true);
73         setPreferredSize(getSize());
74         remove(0);
75       }
76       finally {
77         setIgnoreRepaint(false);
78         revalidate();
79       }
80     }
81   }
82
83   @Override
84   public void reset(@NotNull EditorSchemeAttributeDescriptor descriptor) {
85     myActive = null;
86     if (descriptor instanceof RainbowAttributeDescriptor) {
87       myActive = myRainbowPanel;
88     }
89     else if (descriptor instanceof ColorAndFontDescription) {
90       myActive = myColorAndFontPanel;
91     }
92
93     if (getComponentCount() == 0 || myActive != getComponent(0)) {
94       boolean ignoreRepaint = getIgnoreRepaint();
95       try {
96         setIgnoreRepaint(true);
97         if (getComponentCount() != 0) {
98           remove(0);
99         }
100         setPreferredSize(null);
101         add((JPanel)myActive);
102       }
103       finally {
104         setIgnoreRepaint(ignoreRepaint);
105         revalidate();
106       }
107     }
108     myActive.reset(descriptor);
109     updatePreviewPanel(descriptor);
110   }
111
112   private void addRainbowHighlighting(@NotNull DocumentEx document,
113                                       @NotNull List<HighlightData> showLineData,
114                                       @NotNull List<HighlightData> data,
115                                       @NotNull RainbowHighlighter rainbowHighlighter,
116                                       @NotNull List<TextAttributesKey> rainbowTempKeys) {
117     if (!rainbowTempKeys.isEmpty()) {
118       List<HighlightData> newData = new ArrayList<HighlightData>(showLineData);
119       HashMap<String, Integer> id2index = new HashMap<String, Integer>();
120
121       for (HighlightData d : data) {
122         if (((RainbowColorSettingsPage)myPage).isRainbowType(d.getHighlightKey())) {
123           String id = document.getText(TextRange.create(d.getStartOffset(), d.getEndOffset()));
124
125           int index = rainbowHighlighter.getColorIndex(id2index, id, RainbowHighlighter.getRainbowHash(id));
126           HighlightData rainbow = new HighlightData(d.getStartOffset(), d.getEndOffset(), rainbowTempKeys.get(index));
127
128           //fixme: twisted coloring in editor. We need add rainbow-tag twice.
129           newData.add(rainbow);
130           newData.add(d);
131           newData.add(rainbow);
132         }
133         else if (!RainbowHighlighter.isRainbowTempKey(d.getHighlightKey())) {
134           newData.add(d);
135         }
136       }
137       data.clear();
138       data.addAll(newData);
139     }
140   }
141
142   private static void removeRainbowHighlighting(@NotNull List<HighlightData> data) {
143     List<TextAttributesKey> keys = RainbowHighlighter.getRainbowKeys();
144     if (!keys.isEmpty()) {
145       List<HighlightData> newData = new ArrayList<HighlightData>();
146       for (HighlightData d : data) {
147         if (!keys.contains(d.getHighlightKey())) {
148           newData.add(d);
149         }
150       }
151       data.clear();
152       data.addAll(newData);
153     }
154   }
155
156   @Override
157   public void apply(@NotNull EditorSchemeAttributeDescriptor descriptor, EditorColorsScheme scheme) {
158     if (myActive != null) {
159       myActive.apply(descriptor, scheme);
160       updatePreviewPanel(descriptor);
161     }
162   }
163
164   protected void updatePreviewPanel(@NotNull EditorSchemeAttributeDescriptor descriptor) {
165     if (!(myPreviewPanel instanceof SimpleEditorPreview)) return;
166
167     SimpleEditorPreview simpleEditorPreview = (SimpleEditorPreview)myPreviewPanel;
168
169     if (myActive == myRainbowPanel
170         && myPage instanceof RainbowColorSettingsPage
171         && descriptor instanceof RainbowAttributeDescriptor) {
172       if (myRainbowPanel.myGlobalState.isRainbowOn) {
173         RainbowHighlighter highlighter = new RainbowHighlighter(descriptor.getScheme());
174         List<TextAttributesKey> tempKeys = highlighter.getRainbowTempKeys();
175         Pair<String, List<HighlightData>> demo = getColorDemoLine(highlighter, tempKeys);
176         simpleEditorPreview.setDemoText(demo.first + "\n" + ((RainbowColorSettingsPage)myPage).getRainbowDemoText());
177         addRainbowHighlighting(simpleEditorPreview.getEditor().getDocument(),
178                                demo.second,
179                                simpleEditorPreview.getHighlightDataForExtension(),
180                                highlighter,
181                                tempKeys);
182       }
183       else {
184         simpleEditorPreview.setDemoText(((RainbowColorSettingsPage)myPage).getRainbowDemoText());
185         removeRainbowHighlighting(simpleEditorPreview.getHighlightDataForExtension());
186       }
187     }
188     else {
189       simpleEditorPreview.setDemoText(myPage.getDemoText());
190     }
191   }
192
193   @NotNull
194   private static Pair<String, List<HighlightData>> getColorDemoLine(RainbowHighlighter highlighter, List<TextAttributesKey> tempKeys) {
195     int colorsCount = highlighter.getColorsCount();
196     int stopCount = RainbowHighlighter.getRainbowKeys().size();
197     List<HighlightData> markup = new ArrayList<HighlightData>(colorsCount);
198     StringBuilder sb = new StringBuilder();
199     int pos = 0;
200     int i = 0;
201     for (TextAttributesKey key : tempKeys) {
202       String toAdd = (i % stopCount == 0) ? "Stop#" + String.valueOf(i / stopCount + 1) : "T";
203       int end = pos + toAdd.length();
204       markup.add(new HighlightData(pos, end, key));
205       if (sb.length() != 0) {
206         sb.append(" ");
207       }
208       sb.append(toAdd);
209       pos = end + 1;
210       ++i;
211     }
212     return Pair.create(sb.toString(), markup);
213   }
214
215   @Override
216   public void addListener(@NotNull Listener listener) {
217     myRainbowPanel.addListener(listener);
218     myColorAndFontPanel.addListener(listener);
219   }
220 }