2 * Copyright 2000-2009 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
;
18 import com
.intellij
.application
.options
.codeStyle
.CodeStyleSchemesModel
;
19 import com
.intellij
.ide
.DataManager
;
20 import com
.intellij
.openapi
.Disposable
;
21 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
22 import com
.intellij
.openapi
.application
.ApplicationBundle
;
23 import com
.intellij
.openapi
.application
.ApplicationManager
;
24 import com
.intellij
.openapi
.command
.CommandProcessor
;
25 import com
.intellij
.openapi
.diagnostic
.Logger
;
26 import com
.intellij
.openapi
.editor
.Document
;
27 import com
.intellij
.openapi
.editor
.Editor
;
28 import com
.intellij
.openapi
.editor
.EditorFactory
;
29 import com
.intellij
.openapi
.editor
.EditorSettings
;
30 import com
.intellij
.openapi
.editor
.colors
.EditorColors
;
31 import com
.intellij
.openapi
.editor
.colors
.EditorColorsScheme
;
32 import com
.intellij
.openapi
.editor
.ex
.EditorEx
;
33 import com
.intellij
.openapi
.editor
.highlighter
.EditorHighlighter
;
34 import com
.intellij
.openapi
.fileTypes
.FileType
;
35 import com
.intellij
.openapi
.project
.Project
;
36 import com
.intellij
.openapi
.project
.ProjectManager
;
37 import com
.intellij
.psi
.PsiFile
;
38 import com
.intellij
.psi
.PsiFileFactory
;
39 import com
.intellij
.psi
.codeStyle
.CodeStyleManager
;
40 import com
.intellij
.psi
.codeStyle
.CodeStyleSettings
;
41 import com
.intellij
.psi
.codeStyle
.CodeStyleSettingsManager
;
42 import com
.intellij
.ui
.UserActivityListener
;
43 import com
.intellij
.ui
.UserActivityWatcher
;
44 import com
.intellij
.util
.Alarm
;
45 import com
.intellij
.util
.IncorrectOperationException
;
46 import com
.intellij
.util
.LocalTimeCounter
;
47 import com
.intellij
.util
.ui
.update
.UiNotifyConnector
;
48 import org
.jetbrains
.annotations
.NonNls
;
49 import org
.jetbrains
.annotations
.NotNull
;
53 import java
.io
.IOException
;
54 import java
.io
.InputStream
;
55 import java
.io
.InputStreamReader
;
56 import java
.io
.LineNumberReader
;
58 public abstract class CodeStyleAbstractPanel
implements Disposable
{
59 private static final Logger LOG
= Logger
.getInstance("#com.intellij.application.options.CodeStyleXmlPanel");
60 private final Editor myEditor
;
61 private final CodeStyleSettings mySettings
;
62 private boolean myShouldUpdatePreview
;
63 protected static final int[] ourWrappings
=
64 {CodeStyleSettings
.DO_NOT_WRAP
, CodeStyleSettings
.WRAP_AS_NEEDED
, CodeStyleSettings
.WRAP_ON_EVERY_ITEM
, CodeStyleSettings
.WRAP_ALWAYS
};
65 private long myLastDocumentModificationStamp
;
66 private String myTextToReformat
= null;
67 private final UserActivityWatcher myUserActivityWatcher
= new UserActivityWatcher();
69 private final Alarm myUpdateAlarm
= new Alarm(Alarm
.ThreadToUse
.SWING_THREAD
);
71 private CodeStyleSchemesModel myModel
;
72 private boolean mySomethingChanged
= false;
74 private synchronized void setSomethingChanged(final boolean b
) {
75 mySomethingChanged
= b
;
78 private synchronized boolean isSomethingChanged() {
79 return mySomethingChanged
;
82 protected CodeStyleAbstractPanel(CodeStyleSettings settings
) {
83 mySettings
= settings
;
84 myEditor
= createEditor();
86 myUpdateAlarm
.setActivationComponent(myEditor
.getComponent());
87 myUserActivityWatcher
.addUserActivityListener(new UserActivityListener() {
88 public void stateChanged() {
94 public void setModel(final CodeStyleSchemesModel model
) {
98 protected void somethingChanged() {
99 if (myModel
!= null) {
100 myModel
.fireCurrentSettingsChanged();
104 protected void addPanelToWatch(Component component
) {
105 myUserActivityWatcher
.register(component
);
108 private Editor
createEditor() {
109 EditorFactory editorFactory
= EditorFactory
.getInstance();
110 myTextToReformat
= getPreviewText();
111 Document editorDocument
= editorFactory
.createDocument(myTextToReformat
);
112 EditorEx editor
= (EditorEx
)editorFactory
.createViewer(editorDocument
);
114 myLastDocumentModificationStamp
= editor
.getDocument().getModificationStamp();
116 EditorSettings editorSettings
= editor
.getSettings();
117 fillEditorSettings(editorSettings
);
119 updatePreviewHighlighter(editor
);
124 private void updatePreviewHighlighter(final EditorEx editor
) {
125 EditorColorsScheme scheme
= editor
.getColorsScheme();
126 scheme
.setColor(EditorColors
.CARET_ROW_COLOR
, null);
128 editor
.setHighlighter(createHighlighter(scheme
));
131 protected void updatePreviewEditor() {
132 myTextToReformat
= getPreviewText();
134 updatePreviewHighlighter((EditorEx
)myEditor
);
137 protected abstract EditorHighlighter
createHighlighter(final EditorColorsScheme scheme
);
139 private void fillEditorSettings(final EditorSettings editorSettings
) {
140 editorSettings
.setWhitespacesShown(true);
141 editorSettings
.setLineMarkerAreaShown(false);
142 editorSettings
.setLineNumbersShown(false);
143 editorSettings
.setFoldingOutlineShown(false);
144 editorSettings
.setAdditionalColumnsCount(0);
145 editorSettings
.setAdditionalLinesCount(1);
146 final int rightMargin
= getRightMargin();
147 if (rightMargin
> 0) {
148 editorSettings
.setRightMargin(rightMargin
);
152 protected abstract int getRightMargin();
154 public final void updatePreview() {
155 if (!myShouldUpdatePreview
|| !myEditor
.getComponent().isShowing()) {
159 if (myLastDocumentModificationStamp
!= myEditor
.getDocument().getModificationStamp()) {
160 myTextToReformat
= myEditor
.getDocument().getText();
163 Project project
= PlatformDataKeys
.PROJECT
.getData(DataManager
.getInstance().getDataContext());
164 if (project
== null) {
165 project
= ProjectManager
.getInstance().getDefaultProject();
167 final Project finalProject
= project
;
168 CommandProcessor
.getInstance().executeCommand(finalProject
, new Runnable() {
170 replaceText(finalProject
);
173 myEditor
.getSettings().setRightMargin(getRightMargin());
174 myLastDocumentModificationStamp
= myEditor
.getDocument().getModificationStamp();
177 private void replaceText(final Project project
) {
178 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
181 //important not mark as generated not to get the classes before setting language level
182 PsiFile psiFile
= PsiFileFactory
.getInstance(project
)
183 .createFileFromText("a." + getFileTypeExtension(getFileType()), getFileType(), myTextToReformat
, LocalTimeCounter
.currentTime(),
186 prepareForReformat(psiFile
);
188 CodeStyleSettings clone
= mySettings
.clone();
189 if (getRightMargin() > 0) {
190 clone
.RIGHT_MARGIN
= getRightMargin();
194 CodeStyleSettingsManager
.getInstance(project
).setTemporarySettings(clone
);
195 CodeStyleManager
.getInstance(project
).reformat(psiFile
);
196 CodeStyleSettingsManager
.getInstance(project
).dropTemporarySettings();
198 myEditor
.getSettings().setTabSize(clone
.getTabSize(getFileType()));
199 Document document
= myEditor
.getDocument();
200 document
.replaceString(0, document
.getTextLength(), psiFile
.getText());
202 catch (IncorrectOperationException e
) {
209 protected abstract void prepareForReformat(PsiFile psiFile
);
212 protected abstract FileType
getFileType();
215 protected abstract String
getPreviewText();
217 public abstract void apply(CodeStyleSettings settings
);
219 public final void reset(final CodeStyleSettings settings
) {
220 myShouldUpdatePreview
= false;
225 myShouldUpdatePreview
= true;
229 protected static int getIndexForWrapping(int value
) {
230 for (int i
= 0; i
< ourWrappings
.length
; i
++) {
231 int ourWrapping
= ourWrappings
[i
];
232 if (ourWrapping
== value
) return i
;
234 LOG
.assertTrue(false);
238 public abstract boolean isModified(CodeStyleSettings settings
);
240 public abstract JComponent
getPanel();
242 public final void dispose() {
243 myUpdateAlarm
.cancelAllRequests();
244 EditorFactory
.getInstance().releaseEditor(myEditor
);
247 protected abstract void resetImpl(final CodeStyleSettings settings
);
249 protected static void fillWrappingCombo(final JComboBox wrapCombo
) {
250 wrapCombo
.addItem(ApplicationBundle
.message("combobox.codestyle.do.not.wrap"));
251 wrapCombo
.addItem(ApplicationBundle
.message("combobox.codestyle.wrap.if.long"));
252 wrapCombo
.addItem(ApplicationBundle
.message("combobox.codestyle.chop.down.if.long"));
253 wrapCombo
.addItem(ApplicationBundle
.message("combobox.codestyle.wrap.always"));
256 public static String
readFromFile(final Class resourceContainerClass
, @NonNls final String fileName
) {
258 final InputStream stream
= resourceContainerClass
.getClassLoader().getResourceAsStream("codeStyle/preview/" + fileName
);
259 final InputStreamReader reader
= new InputStreamReader(stream
);
260 final LineNumberReader lineNumberReader
= new LineNumberReader(reader
);
261 final StringBuffer result
;
263 result
= new StringBuffer();
265 while ((line
= lineNumberReader
.readLine()) != null) {
271 lineNumberReader
.close();
274 return result
.toString();
276 catch (IOException e
) {
281 protected void installPreviewPanel(final JPanel previewPanel
) {
282 previewPanel
.setLayout(new BorderLayout());
283 previewPanel
.add(myEditor
.getComponent(), BorderLayout
.CENTER
);
288 String
getFileTypeExtension(FileType fileType
) {
289 return fileType
.getDefaultExtension();
292 public void onSomethingChanged() {
293 setSomethingChanged(true);
294 UiNotifyConnector
.doWhenFirstShown(myEditor
.getComponent(), new Runnable(){
296 addUpdatePreviewRequest();
301 private void addUpdatePreviewRequest() {
302 myUpdateAlarm
.addComponentRequest(new Runnable() {
305 myUpdateAlarm
.cancelAllRequests();
306 if (isSomethingChanged()) {
311 setSomethingChanged(false);