no more dummy project / problems with formatting when using it
[idea/community.git] / platform / lang-impl / src / com / intellij / application / options / codeStyle / MultilanguageCodeStyleAbstractPanel.java
1 /*
2  * Copyright 2010 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.codeStyle;
17
18 import com.intellij.application.options.CodeStyleAbstractPanel;
19 import com.intellij.ide.DataManager;
20 import com.intellij.lang.Language;
21 import com.intellij.openapi.actionSystem.PlatformDataKeys;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.command.CommandProcessor;
24 import com.intellij.openapi.diagnostic.Logger;
25 import com.intellij.openapi.editor.Document;
26 import com.intellij.openapi.editor.colors.EditorColorsScheme;
27 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
28 import com.intellij.openapi.fileTypes.FileType;
29 import com.intellij.openapi.fileTypes.LanguageFileType;
30 import com.intellij.openapi.fileTypes.StdFileTypes;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.project.ProjectManager;
33 import com.intellij.psi.PsiDocumentManager;
34 import com.intellij.psi.PsiFile;
35 import com.intellij.psi.PsiFileFactory;
36 import com.intellij.psi.codeStyle.CodeStyleManager;
37 import com.intellij.psi.codeStyle.CodeStyleSettings;
38 import com.intellij.ui.IdeBorderFactory;
39 import com.intellij.util.IncorrectOperationException;
40 import com.intellij.util.LocalTimeCounter;
41 import org.jetbrains.annotations.NotNull;
42
43 import javax.swing.*;
44 import javax.swing.event.AncestorEvent;
45 import javax.swing.event.AncestorListener;
46 import javax.swing.event.ChangeEvent;
47 import javax.swing.event.ChangeListener;
48 import java.awt.*;
49
50 /**
51  * Base class for code style settings panels supporting multiple programming languages.
52  *
53  * @author rvishnyakov
54  */
55 public abstract class MultilanguageCodeStyleAbstractPanel extends CodeStyleAbstractPanel {
56
57   private static Language myLanguage;
58   private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.codeStyle.MultilanguageCodeStyleAbstractPanel");
59   private int myLangSelectionIndex;
60   private JTabbedPane tabbedPane;
61
62   protected MultilanguageCodeStyleAbstractPanel(CodeStyleSettings settings) {
63     super(settings);
64   }
65
66   /**
67    * @return Always true for multilanguage panel.
68    */
69   @Override
70   protected final boolean isMultilanguage() {
71     return true;
72   }
73
74   public void setLanguage(Language language) {
75     myLanguage = language;
76     updatePreviewEditor();
77   }
78
79   protected abstract LanguageCodeStyleSettingsProvider.SettingsType getSettingsType();
80
81   @Override
82   protected String getPreviewText() {
83     if (myLanguage == null) return "";
84     return LanguageCodeStyleSettingsProvider.getCodeSample(myLanguage, getSettingsType());
85   }
86
87   @NotNull
88   @Override
89   protected final FileType getFileType() {
90     if (myLanguage != null) {
91       return myLanguage.getAssociatedFileType();
92     }
93     Language langs[] = LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings();
94     if (langs.length > 0) {
95       myLanguage = langs[0];
96       FileType type = langs[0].getAssociatedFileType();
97       if (type != null) return type;
98     }
99     return StdFileTypes.JAVA;
100   }
101
102   protected EditorHighlighter createHighlighter(final EditorColorsScheme scheme) {
103     Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
104     if (project == null) {
105       project = ProjectManager.getInstance().getDefaultProject();
106     }
107     if (getFileType() instanceof LanguageFileType) {
108       return ((LanguageFileType)getFileType()).getEditorHighlighter(project, null, scheme);
109     }
110     return null;
111   }
112
113
114   protected PsiFile createFileFromText(Project project, String text) {
115     final PsiFile psiFile =
116       PsiFileFactory.getInstance(project).createFileFromText("a", getFileType(), text, LocalTimeCounter.currentTime(), true);
117     return psiFile;
118   }
119
120   @Override
121   protected PsiFile doReformat(final Project project, final PsiFile psiFile) {
122     final String text = psiFile.getText();
123     final PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
124     final Document doc = manager.getDocument(psiFile);
125     CommandProcessor.getInstance().executeCommand(project, new Runnable() {
126       public void run() {
127         ApplicationManager.getApplication().runWriteAction(new Runnable() {
128           public void run() {
129             doc.replaceString(0, doc.getTextLength(), text);
130             manager.commitDocument(doc);
131             try {
132               CodeStyleManager.getInstance(project).reformat(psiFile);
133             }
134             catch (IncorrectOperationException e) {
135               LOG.error(e);
136             }
137           }
138         });
139       }
140     }, "", "");
141     manager.commitDocument(doc);
142     return psiFile;
143   }
144
145   protected static JPanel createPreviewPanel() {
146     JPanel panel = new JPanel(new BorderLayout());
147     panel.setBorder(IdeBorderFactory.createTitledBorder("Preview"));
148     panel.setPreferredSize(new Dimension(200, 0));
149     return panel;
150   }
151
152
153   @Override
154   protected void installPreviewPanel(final JPanel previewPanel) {
155     tabbedPane = new JTabbedPane();
156     tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
157     Language[] langs = LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings();
158     if (langs.length == 0) return;
159     for (Language lang : langs) {
160       tabbedPane.addTab(lang.getDisplayName(), createDummy());
161     }
162     tabbedPane.setComponentAt(0, getEditor().getComponent());
163     myLangSelectionIndex = 0;
164     if (myLanguage == null) {
165       setLanguage(langs[0]);
166     }
167     else {
168       updatePreviewEditor();
169     }
170     tabbedPane.addChangeListener(new ChangeListener() {
171       public void stateChanged(ChangeEvent e) {
172         onTabSelection((JTabbedPane)e.getSource());        
173       }
174     });
175     previewPanel.add(tabbedPane, BorderLayout.CENTER);
176     previewPanel.addAncestorListener(new AncestorListener(){
177       public void ancestorAdded(AncestorEvent event) {
178         selectCurrentLanguageTab();
179       }
180
181       public void ancestorRemoved(AncestorEvent event) {
182         // Do nothing
183       }
184
185       public void ancestorMoved(AncestorEvent event) {
186         // Do nothing
187       }
188     });
189   }
190
191   private void selectCurrentLanguageTab() {
192     for(int i = 0; i < tabbedPane.getTabCount(); i ++) {
193       if (myLanguage.getDisplayName().equals(tabbedPane.getTitleAt(i))) {
194         tabbedPane.setSelectedIndex(i);
195         return;
196       }
197     }
198   }
199
200
201   private void onTabSelection(JTabbedPane tabs) {
202     int i = tabs.getSelectedIndex();
203     tabs.setComponentAt(myLangSelectionIndex, createDummy());
204     tabs.setComponentAt(i, getEditor().getComponent());
205     myLangSelectionIndex = i;
206     String selectionTitle = tabs.getTitleAt(i);
207     Language lang = LanguageCodeStyleSettingsProvider.getLanguage(selectionTitle);
208     if (lang != null) {
209       setLanguage(lang);
210     }
211   }
212
213
214   private JComponent createDummy() {
215     return new JLabel("");
216   }
217
218
219 }