4 package com
.intellij
.openapi
.editor
.colors
.impl
;
6 import com
.intellij
.openapi
.application
.ApplicationManager
;
7 import com
.intellij
.openapi
.application
.PathManager
;
8 import com
.intellij
.openapi
.application
.ex
.DecodeDefaultsUtil
;
9 import com
.intellij
.openapi
.components
.ExportableApplicationComponent
;
10 import com
.intellij
.openapi
.components
.RoamingType
;
11 import com
.intellij
.openapi
.diagnostic
.Logger
;
12 import com
.intellij
.openapi
.editor
.colors
.EditorColorsListener
;
13 import com
.intellij
.openapi
.editor
.colors
.EditorColorsManager
;
14 import com
.intellij
.openapi
.editor
.colors
.EditorColorsScheme
;
15 import com
.intellij
.openapi
.editor
.colors
.ex
.DefaultColorSchemesManager
;
16 import com
.intellij
.openapi
.options
.*;
17 import com
.intellij
.openapi
.util
.*;
18 import org
.jdom
.Document
;
19 import org
.jdom
.Element
;
20 import org
.jdom
.JDOMException
;
21 import org
.jetbrains
.annotations
.NonNls
;
22 import org
.jetbrains
.annotations
.NotNull
;
25 import java
.io
.IOException
;
26 import java
.io
.InputStream
;
27 import java
.util
.ArrayList
;
28 import java
.util
.Collection
;
29 import java
.util
.Collections
;
30 import java
.util
.Comparator
;
32 public class EditorColorsManagerImpl
extends EditorColorsManager
33 implements NamedJDOMExternalizable
, ExportableApplicationComponent
{
34 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl");
36 private Collection
<EditorColorsListener
> myListeners
= new ArrayList
<EditorColorsListener
>();
39 @NonNls private static final String NODE_NAME
= "global_color_scheme";
40 @NonNls private static final String SCHEME_NODE_NAME
= "scheme";
42 private String myGlobalSchemeName
;
43 public boolean USE_ONLY_MONOSPACED_FONTS
= true;
44 private DefaultColorSchemesManager myDefaultColorSchemesManager
;
45 private final SchemesManager
<EditorColorsScheme
, EditorColorsSchemeImpl
> mySchemesManager
;
46 @NonNls private static final String NAME_ATTR
= "name";
47 private static final String FILE_SPEC
= "$ROOT_CONFIG$/colors";
49 public EditorColorsManagerImpl(DefaultColorSchemesManager defaultColorSchemesManager
, SchemesManagerFactory schemesManagerFactory
) {
50 myDefaultColorSchemesManager
= defaultColorSchemesManager
;
52 mySchemesManager
= schemesManagerFactory
.createSchemesManager(
54 new SchemeProcessor
<EditorColorsSchemeImpl
>() {
55 public EditorColorsSchemeImpl
readScheme(final Document document
)
56 throws InvalidDataException
, IOException
, JDOMException
{
58 return loadSchemeFromDocument(document
, true);
61 public Document
writeScheme(final EditorColorsSchemeImpl scheme
) throws WriteExternalException
{
62 Element root
= new Element(SCHEME_NODE_NAME
);
64 scheme
.writeExternal(root
);
66 catch (WriteExternalException e
) {
71 return new Document(root
);
74 public void renameScheme(final String name
, final EditorColorsScheme scheme
) {
78 public boolean shouldBeSaved(final EditorColorsSchemeImpl scheme
) {
79 return !(scheme
instanceof ReadOnlyColorsScheme
);
82 public void initScheme(final EditorColorsSchemeImpl scheme
) {
86 public void onSchemeAdded(final EditorColorsSchemeImpl scheme
) {
90 public void onSchemeDeleted(final EditorColorsSchemeImpl scheme
) {
93 public void onCurrentSchemeChanged(final Scheme newCurrentScheme
) {
94 fireChanges(mySchemesManager
.getCurrentScheme());
96 }, RoamingType
.PER_USER
);
100 // Load default schemes from providers
101 loadAdditionalDefaultSchemes();
104 setGlobalScheme(myDefaultColorSchemesManager
.getAllSchemes()[0]);
107 private void loadAdditionalDefaultSchemes() {
108 //Get color schemes from EPs
109 for (BundledColorSchemesProvider provider
: BundledColorSchemesProvider
.EP_NAME
.getExtensions()) {
110 final String
[] schemesPaths
= provider
.getBundledSchemesRelativePaths();
112 for (final String schemePath
: schemesPaths
) {
114 final InputStream inputStream
= DecodeDefaultsUtil
.getDefaultsInputStream(provider
, schemePath
);
115 if (inputStream
== null) {
116 // Error shouldn't occur during this operation
117 // thus we report error instead of info
118 LOG
.error("Cannot read scheme from " + schemePath
);
122 final Document document
;
124 document
= JDOMUtil
.loadDocument(inputStream
);
126 catch (JDOMException e
) {
127 LOG
.info("Error reading scheme from " + schemePath
+ ": " + e
.getLocalizedMessage());
130 final EditorColorsSchemeImpl scheme
= loadSchemeFromDocument(document
, false);
131 mySchemesManager
.addNewScheme(scheme
, false);
133 catch (final Exception e
) {
134 ApplicationManager
.getApplication().invokeLater(
137 // Error shouldn't occur during this operation
138 // thus we report error instead of info
139 LOG
.error("Cannot read scheme from " + schemePath
+ ": " + e
.getLocalizedMessage(), e
);
148 private EditorColorsSchemeImpl
loadSchemeFromDocument(final Document document
,
149 final boolean isEditable
)
150 throws InvalidDataException
{
152 final Element root
= document
.getRootElement();
154 if (root
== null || !SCHEME_NODE_NAME
.equals(root
.getName())) {
155 throw new InvalidDataException();
158 final EditorColorsSchemeImpl scheme
= isEditable
160 ?
new EditorColorsSchemeImpl(null, DefaultColorSchemesManager
.getInstance())
161 //not editable scheme
162 : new ReadOnlyColorsSchemeImpl(null, DefaultColorSchemesManager
.getInstance());
163 scheme
.readExternal(root
);
167 // -------------------------------------------------------------------------
168 // ApplicationComponent interface implementation
169 // -------------------------------------------------------------------------
171 public void disposeComponent() {
174 public void initComponent() {
177 // -------------------------------------------------------------------------
178 // Schemes manipulation routines
179 // -------------------------------------------------------------------------
181 public void addColorsScheme(EditorColorsScheme scheme
) {
182 if (!isDefaultScheme(scheme
) && scheme
.getName().trim().length() > 0) {
183 mySchemesManager
.addNewScheme(scheme
, true);
187 public void removeAllSchemes() {
188 mySchemesManager
.clearAllSchemes();
192 private void addDefaultSchemes() {
193 DefaultColorsScheme
[] allDefaultSchemes
= myDefaultColorSchemesManager
.getAllSchemes();
194 for (DefaultColorsScheme defaultScheme
: allDefaultSchemes
) {
195 mySchemesManager
.addNewScheme(defaultScheme
, true);
199 // -------------------------------------------------------------------------
201 // -------------------------------------------------------------------------
203 public EditorColorsScheme
[] getAllSchemes() {
204 ArrayList
<EditorColorsScheme
> schemes
= new ArrayList
<EditorColorsScheme
>(mySchemesManager
.getAllSchemes());
205 Collections
.sort(schemes
, new Comparator
<EditorColorsScheme
>() {
206 public int compare(EditorColorsScheme s1
, EditorColorsScheme s2
) {
207 if (isDefaultScheme(s1
) && !isDefaultScheme(s2
)) return -1;
208 if (!isDefaultScheme(s1
) && isDefaultScheme(s2
)) return 1;
210 return s1
.getName().compareToIgnoreCase(s2
.getName());
214 return schemes
.toArray(new EditorColorsScheme
[schemes
.size()]);
217 public void setGlobalScheme(EditorColorsScheme scheme
) {
218 mySchemesManager
.setCurrentSchemeName(scheme
== null ? DefaultColorSchemesManager
.getInstance().getAllSchemes()[0].getName() : scheme
.getName());
222 public EditorColorsScheme
getGlobalScheme() {
223 return mySchemesManager
.getCurrentScheme();
226 public EditorColorsScheme
getScheme(String schemeName
) {
227 return mySchemesManager
.findSchemeByName(schemeName
);
230 private void fireChanges(EditorColorsScheme scheme
) {
231 EditorColorsListener
[] colorsListeners
= myListeners
.toArray(new EditorColorsListener
[myListeners
.size()]);
232 for (EditorColorsListener colorsListener
: colorsListeners
) {
233 colorsListener
.globalSchemeChange(scheme
);
237 // -------------------------------------------------------------------------
238 // Routines responsible for loading & saving colors schemes.
239 // -------------------------------------------------------------------------
241 private void loadAllSchemes() {
242 mySchemesManager
.loadSchemes();
245 private static File
getColorsDir(boolean create
) {
246 @NonNls String directoryPath
= PathManager
.getConfigPath() + File
.separator
+ "colors";
247 File directory
= new File(directoryPath
);
248 if (!directory
.exists()) {
249 if (!create
) return null;
250 if (!directory
.mkdir()) {
251 LOG
.error("Cannot create directory: " + directory
.getAbsolutePath());
259 public void addEditorColorsListener(EditorColorsListener listener
) {
260 myListeners
.add(listener
);
263 public void removeEditorColorsListener(EditorColorsListener listener
) {
264 myListeners
.remove(listener
);
267 public void setUseOnlyMonospacedFonts(boolean b
) {
268 USE_ONLY_MONOSPACED_FONTS
= b
;
271 public boolean isUseOnlyMonospacedFonts() {
272 return USE_ONLY_MONOSPACED_FONTS
;
275 public String
getExternalFileName() {
276 return "colors.scheme";
280 public File
[] getExportFiles() {
281 return new File
[]{getColorsDir(true), PathManager
.getOptionsFile(this)};
285 public String
getPresentableName() {
286 return OptionsBundle
.message("options.color.schemes.presentable.name");
289 public void readExternal(Element parentNode
) throws InvalidDataException
{
290 DefaultJDOMExternalizer
.readExternal(this, parentNode
);
291 Element element
= parentNode
.getChild(NODE_NAME
);
292 if (element
!= null) {
293 String name
= element
.getAttributeValue(NAME_ATTR
);
294 if (name
!= null && !"".equals(name
.trim())) {
295 myGlobalSchemeName
= name
;
302 private void initGlobalScheme() {
303 if (myGlobalSchemeName
!= null) {
304 setGlobalSchemeByName(myGlobalSchemeName
);
307 setGlobalScheme(myDefaultColorSchemesManager
.getAllSchemes()[0]);
311 private void setGlobalSchemeByName(String schemeName
) {
312 setGlobalScheme(mySchemesManager
.findSchemeByName(schemeName
));
315 public void writeExternal(Element parentNode
) throws WriteExternalException
{
316 DefaultJDOMExternalizer
.writeExternal(this, parentNode
);
317 if (mySchemesManager
.getCurrentScheme() != null) {
318 Element element
= new Element(NODE_NAME
);
319 element
.setAttribute(NAME_ATTR
, mySchemesManager
.getCurrentScheme().getName());
320 parentNode
.addContent(element
);
324 public boolean isDefaultScheme(EditorColorsScheme scheme
) {
325 return scheme
instanceof DefaultColorsScheme
;
328 public String
getComponentName() {
329 return "EditorColorsManagerImpl";
332 public SchemesManager
<EditorColorsScheme
, EditorColorsSchemeImpl
> getSchemesManager() {
333 return mySchemesManager
;