1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11 Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12
13 End User License Agreement: www.juce.com/juce-6-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24 */
25
26 #include "../Application/jucer_Headers.h"
27 #include "../Application/jucer_Application.h"
28 #include "jucer_AppearanceSettings.h"
29
30 //==============================================================================
AppearanceSettings(bool updateAppWhenChanged)31 AppearanceSettings::AppearanceSettings (bool updateAppWhenChanged)
32 : settings ("COLOUR_SCHEME")
33 {
34 CodeDocument doc;
35 CPlusPlusCodeTokeniser tokeniser;
36 CodeEditorComponent editor (doc, &tokeniser);
37
38 CodeEditorComponent::ColourScheme cs (editor.getColourScheme());
39
40 for (int i = cs.types.size(); --i >= 0;)
41 {
42 auto& t = cs.types.getReference(i);
43 getColourValue (t.name) = t.colour.toString();
44 }
45
46 getCodeFontValue() = getDefaultCodeFont().toString();
47
48 if (updateAppWhenChanged)
49 settings.addListener (this);
50 }
51
getSchemesFolder()52 File AppearanceSettings::getSchemesFolder()
53 {
54 File f (getGlobalProperties().getFile().getSiblingFile ("Schemes"));
55 f.createDirectory();
56 return f;
57 }
58
writeDefaultSchemeFile(const String & xmlString,const String & name)59 void AppearanceSettings::writeDefaultSchemeFile (const String& xmlString, const String& name)
60 {
61 auto file = getSchemesFolder().getChildFile (name).withFileExtension (getSchemeFileSuffix());
62
63 AppearanceSettings settings (false);
64
65 if (auto xml = parseXML (xmlString))
66 settings.readFromXML (*xml);
67
68 settings.writeToFile (file);
69 }
70
refreshPresetSchemeList()71 void AppearanceSettings::refreshPresetSchemeList()
72 {
73 writeDefaultSchemeFile (BinaryData::colourscheme_dark_xml, "Default (Dark)");
74 writeDefaultSchemeFile (BinaryData::colourscheme_light_xml, "Default (Light)");
75
76 auto newSchemes = getSchemesFolder().findChildFiles (File::findFiles, false, String ("*") + getSchemeFileSuffix());
77
78 if (newSchemes != presetSchemeFiles)
79 {
80 presetSchemeFiles.swapWith (newSchemes);
81 ProjucerApplication::getCommandManager().commandStatusChanged();
82 }
83 }
84
getPresetSchemes()85 StringArray AppearanceSettings::getPresetSchemes()
86 {
87 StringArray s;
88 for (int i = 0; i < presetSchemeFiles.size(); ++i)
89 s.add (presetSchemeFiles.getReference(i).getFileNameWithoutExtension());
90
91 return s;
92 }
93
selectPresetScheme(int index)94 void AppearanceSettings::selectPresetScheme (int index)
95 {
96 readFromFile (presetSchemeFiles [index]);
97 }
98
readFromXML(const XmlElement & xml)99 bool AppearanceSettings::readFromXML (const XmlElement& xml)
100 {
101 if (xml.hasTagName (settings.getType().toString()))
102 {
103 const ValueTree newSettings (ValueTree::fromXml (xml));
104
105 // we'll manually copy across the new properties to the existing tree so that
106 // any open editors will be kept up to date..
107 settings.copyPropertiesFrom (newSettings, nullptr);
108
109 for (int i = settings.getNumChildren(); --i >= 0;)
110 {
111 ValueTree c (settings.getChild (i));
112
113 const ValueTree newValue (newSettings.getChildWithProperty (Ids::name, c.getProperty (Ids::name)));
114
115 if (newValue.isValid())
116 c.copyPropertiesFrom (newValue, nullptr);
117 }
118
119 return true;
120 }
121
122 return false;
123 }
124
readFromFile(const File & file)125 bool AppearanceSettings::readFromFile (const File& file)
126 {
127 if (auto xml = parseXML (file))
128 return readFromXML (*xml);
129
130 return false;
131 }
132
writeToFile(const File & file) const133 bool AppearanceSettings::writeToFile (const File& file) const
134 {
135 if (auto xml = settings.createXml())
136 return xml->writeTo (file, {});
137
138 return false;
139 }
140
getDefaultCodeFont()141 Font AppearanceSettings::getDefaultCodeFont()
142 {
143 return Font (Font::getDefaultMonospacedFontName(), Font::getDefaultStyle(), 13.0f);
144 }
145
getColourNames() const146 StringArray AppearanceSettings::getColourNames() const
147 {
148 StringArray s;
149
150 for (auto c : settings)
151 if (c.hasType ("COLOUR"))
152 s.add (c[Ids::name]);
153
154 return s;
155 }
156
updateColourScheme()157 void AppearanceSettings::updateColourScheme()
158 {
159 ProjucerApplication::getApp().mainWindowList.sendLookAndFeelChange();
160 }
161
applyToCodeEditor(CodeEditorComponent & editor) const162 void AppearanceSettings::applyToCodeEditor (CodeEditorComponent& editor) const
163 {
164 CodeEditorComponent::ColourScheme cs (editor.getColourScheme());
165
166 for (int i = cs.types.size(); --i >= 0;)
167 {
168 CodeEditorComponent::ColourScheme::TokenType& t = cs.types.getReference(i);
169 getColour (t.name, t.colour);
170 }
171
172 editor.setColourScheme (cs);
173 editor.setFont (getCodeFont());
174
175 editor.setColour (ScrollBar::thumbColourId, editor.findColour (CodeEditorComponent::backgroundColourId)
176 .contrasting()
177 .withAlpha (0.13f));
178 }
179
getCodeFont() const180 Font AppearanceSettings::getCodeFont() const
181 {
182 const String fontString (settings [Ids::font].toString());
183
184 if (fontString.isEmpty())
185 return getDefaultCodeFont();
186
187 return Font::fromString (fontString);
188 }
189
getCodeFontValue()190 Value AppearanceSettings::getCodeFontValue()
191 {
192 return settings.getPropertyAsValue (Ids::font, nullptr);
193 }
194
getColourValue(const String & colourName)195 Value AppearanceSettings::getColourValue (const String& colourName)
196 {
197 ValueTree c (settings.getChildWithProperty (Ids::name, colourName));
198
199 if (! c.isValid())
200 {
201 c = ValueTree ("COLOUR");
202 c.setProperty (Ids::name, colourName, nullptr);
203 settings.appendChild (c, nullptr);
204 }
205
206 return c.getPropertyAsValue (Ids::colour, nullptr);
207 }
208
getColour(const String & name,Colour & result) const209 bool AppearanceSettings::getColour (const String& name, Colour& result) const
210 {
211 const ValueTree colour (settings.getChildWithProperty (Ids::name, name));
212
213 if (colour.isValid())
214 {
215 result = Colour::fromString (colour [Ids::colour].toString());
216 return true;
217 }
218
219 return false;
220 }
221