2 * Copyright 2000-2016 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.application.options.colors;
18 import com.intellij.application.options.colors.highlighting.HighlightData;
19 import com.intellij.codeHighlighting.RainbowHighlighter;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.editor.colors.EditorColorsScheme;
22 import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor;
23 import com.intellij.openapi.editor.colors.TextAttributesKey;
24 import com.intellij.openapi.editor.ex.DocumentEx;
25 import com.intellij.openapi.editor.ex.EditorEx;
26 import com.intellij.openapi.options.colors.ColorSettingsPage;
27 import com.intellij.openapi.options.colors.RainbowColorSettingsPage;
28 import com.intellij.openapi.util.Pair;
29 import com.intellij.openapi.util.TextRange;
30 import com.intellij.util.ui.UIUtil;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
37 import java.util.List;
39 class CustomizedSwitcherPanel extends JPanel implements OptionsPanelImpl.ColorDescriptionPanel {
40 private ColorSettingsPage myPage;
42 private PreviewPanel myPreviewPanel;
43 private ColorAndFontDescriptionPanel myColorAndFontPanel;
44 private RainbowDescriptionPanel myRainbowPanel;
46 private OptionsPanelImpl.ColorDescriptionPanel myActive;
48 public CustomizedSwitcherPanel(ColorAndFontGlobalState options, @Nullable PreviewPanel previewPanel, ColorSettingsPage page) {
51 myPreviewPanel = previewPanel;
53 myRainbowPanel = new RainbowDescriptionPanel(options);
54 myColorAndFontPanel = new ColorAndFontDescriptionPanel();
56 Dimension sizeR = myRainbowPanel.getPreferredSize();
57 Dimension sizeC = myColorAndFontPanel.getPreferredSize();
58 Dimension preferredSize = new Dimension();
59 preferredSize.setSize(Math.max(sizeR.getWidth(), sizeC.getWidth()),
60 Math.max(sizeR.getHeight(), sizeC.getHeight()));
61 setPreferredSize(preferredSize);
66 public JComponent getPanel() {
71 public void resetDefault() {
73 if (getComponentCount() != 0) {
74 final PaintLocker locker = new PaintLocker(this);
76 setPreferredSize(getSize());
86 public void reset(@NotNull EditorSchemeAttributeDescriptor descriptor) {
88 if (descriptor instanceof RainbowAttributeDescriptor) {
89 myActive = myRainbowPanel;
91 else if (descriptor instanceof ColorAndFontDescription) {
92 myActive = myColorAndFontPanel;
95 if (getComponentCount() == 0 || myActive != getComponent(0)) {
96 final PaintLocker locker = new PaintLocker(this);
98 if (getComponentCount() != 0) {
101 setPreferredSize(null);
102 add((JPanel)myActive);
108 myActive.reset(descriptor);
109 updatePreviewPanel(descriptor);
112 private void addRainbowHighlighting(@NotNull DocumentEx document,
113 @Nullable 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>();
119 if (showLineData != null) newData.addAll(showLineData);
121 HashMap<String, Integer> id2index = new HashMap<String, Integer>();
123 for (HighlightData d : data) {
124 if (((RainbowColorSettingsPage)myPage).isRainbowType(d.getHighlightKey())) {
125 String id = document.getText(TextRange.create(d.getStartOffset(), d.getEndOffset()));
127 int index = rainbowHighlighter.getColorIndex(id2index, id, RainbowHighlighter.getRainbowHash(id));
128 HighlightData rainbow = new HighlightData(d.getStartOffset(), d.getEndOffset(), rainbowTempKeys.get(index));
130 //fixme: twisted coloring in editor. We need add rainbow-tag twice.
131 newData.add(rainbow);
133 newData.add(rainbow);
135 else if (!RainbowHighlighter.isRainbowTempKey(d.getHighlightKey())) {
140 data.addAll(newData);
144 private static void removeRainbowHighlighting(@NotNull List<HighlightData> data) {
145 List<TextAttributesKey> keys = RainbowHighlighter.getRainbowKeys();
146 if (!keys.isEmpty()) {
147 List<HighlightData> newData = new ArrayList<HighlightData>();
148 for (HighlightData d : data) {
149 if (!keys.contains(d.getHighlightKey())) {
154 data.addAll(newData);
159 public void apply(@NotNull EditorSchemeAttributeDescriptor descriptor, EditorColorsScheme scheme) {
160 if (myActive != null) {
161 myActive.apply(descriptor, scheme);
162 updatePreviewPanel(descriptor);
166 protected void updatePreviewPanel(@NotNull EditorSchemeAttributeDescriptor descriptor) {
167 if (!(myPreviewPanel instanceof SimpleEditorPreview)) return;
168 UIUtil.invokeAndWaitIfNeeded((Runnable)() -> ApplicationManager.getApplication().runWriteAction(() -> {
169 SimpleEditorPreview simpleEditorPreview = (SimpleEditorPreview)myPreviewPanel;
170 String demoText = (myPage instanceof RainbowColorSettingsPage
171 && descriptor instanceof RainbowAttributeDescriptor)
172 ? ((RainbowColorSettingsPage)myPage).getRainbowDemoText()
173 : myPage.getDemoText();
174 List<HighlightData> showLineData = null;
176 if (myPage instanceof RainbowColorSettingsPage && myRainbowPanel.myGlobalState.isRainbowOn) {
177 RainbowHighlighter highlighter = new RainbowHighlighter(descriptor.getScheme());
178 List<TextAttributesKey> tempKeys = highlighter.getRainbowTempKeys();
179 EditorEx editor = simpleEditorPreview.getEditor();
180 if (myActive == myRainbowPanel) {
181 Pair<String, List<HighlightData>> demo = getColorDemoLine(highlighter, tempKeys);
182 simpleEditorPreview.setDemoText(demo.first + "\n" + demoText);
183 showLineData = demo.second;
186 simpleEditorPreview.setDemoText(demoText);
188 addRainbowHighlighting(editor.getDocument(),
190 simpleEditorPreview.getHighlightDataForExtension(),
195 simpleEditorPreview.setDemoText(demoText);
196 removeRainbowHighlighting(simpleEditorPreview.getHighlightDataForExtension());
199 simpleEditorPreview.updateView();
200 if (descriptor instanceof RainbowAttributeDescriptor) {
201 simpleEditorPreview.scrollHighlightInView(showLineData);
207 private static Pair<String, List<HighlightData>> getColorDemoLine(RainbowHighlighter highlighter, List<TextAttributesKey> tempKeys) {
208 int colorsCount = highlighter.getColorsCount();
209 int stopCount = RainbowHighlighter.getRainbowKeys().size();
210 List<HighlightData> markup = new ArrayList<HighlightData>(colorsCount);
211 StringBuilder sb = new StringBuilder();
214 for (TextAttributesKey key : tempKeys) {
215 String toAdd = (i % stopCount == 0) ? "Stop#" + String.valueOf(i / stopCount + 1) : "T";
216 int end = pos + toAdd.length();
217 markup.add(new HighlightData(pos, end, key));
218 if (sb.length() != 0) {
225 return Pair.create(sb.toString(), markup);
229 public void addListener(@NotNull Listener listener) {
230 myRainbowPanel.addListener(listener);
231 myColorAndFontPanel.addListener(listener);
234 private static class PaintLocker {
235 private Container myPaintHolder;
236 private boolean myPaintState;
238 public PaintLocker(@NotNull JComponent component) {
239 myPaintHolder = component.getParent();
240 myPaintState = myPaintHolder.getIgnoreRepaint();
241 myPaintHolder.setIgnoreRepaint(true);
244 public void release() {
245 myPaintHolder.validate();
246 myPaintHolder.setIgnoreRepaint(myPaintState);
247 myPaintHolder.repaint();