forked from fantaisie-software/purebasic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathColorSchemes.pb
309 lines (257 loc) · 11.1 KB
/
ColorSchemes.pb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
; --------------------------------------------------------------------------------------------
; Copyright (c) Fantaisie Software. All rights reserved.
; Dual licensed under the GPL and Fantaisie Software licenses.
; See LICENSE and LICENSE-FANTAISIE in the project root for license information.
; --------------------------------------------------------------------------------------------
; Store color names in an array, for indexable lookup
Global Dim ColorName.s(#COLOR_Last_IncludingToolsPanel)
; Color Scheme structure
Structure ColorSchemeStruct
Name$
File$
ColorValue.l[#COLOR_Last_IncludingToolsPanel + 1]
IsIDEDefault.i
IsAccessibility.i
EndStructure
; Global list of built-in / found schemes
Global NewList ColorScheme.ColorSchemeStruct()
; Color values with special meanings
#ColorSchemeValue_UseSysColor = -1
#ColorSchemeValue_Undefined = -2
; Returns #True if the specified color scheme matches the user's current color settings, otherwise #False
Procedure ColorSchemeMatchesCurrentSettings(*ColorScheme.ColorSchemeStruct)
Protected Result = #True
For i = 0 To #COLOR_Last
If i <> #COLOR_Selection And i <> #COLOR_SelectionFront ; selection colors may follow OS, so skip them for scheme match check
If *ColorScheme\ColorValue[i] >= 0
If *ColorScheme\ColorValue[i] <> Colors(i)\UserValue
Result = #False
Break
EndIf
EndIf
EndIf
Next i
ProcedureReturn Result
EndProcedure
; Returns *ColorScheme which matches the user's current settings, otherwise #Null if no match
Procedure FindCurrentColorScheme()
Protected *ColorScheme.ColorSchemeStruct = #Null
ForEach ColorScheme()
If ColorSchemeMatchesCurrentSettings(@ColorScheme())
*ColorScheme = @ColorScheme()
Break
EndIf
Next
ProcedureReturn *ColorScheme
EndProcedure
; Guess the specified color for a given Color Scheme, falling back to its basic background/text colors
Procedure GuessColorSchemeColor(*ColorScheme.ColorSchemeStruct, index)
Select index
Case #COLOR_GlobalBackground
Color = #White
Case #COLOR_NormalText
Color = $FFFFFF - *ColorScheme\ColorValue[#COLOR_GlobalBackground]
Case #COLOR_CurrentLine, #COLOR_DisabledBack, #COLOR_LineNumberBack, #COLOR_PlainBackground, #COLOR_ProcedureBack, #COLOR_ToolsPanelBackColor
Color = *ColorScheme\ColorValue[#COLOR_GlobalBackground] ; assume it should match global background
Case #COLOR_DebuggerBreakPoint, #COLOR_DebuggerError, #COLOR_DebuggerLine, #COLOR_DebuggerWarning
Color = *ColorScheme\ColorValue[#COLOR_GlobalBackground]
Case #COLOR_SelectionFront
CompilerIf #CompileWindows
Color = GetSysColor_(#COLOR_HIGHLIGHTTEXT)
CompilerElse
Color = *ColorScheme\ColorValue[#COLOR_GlobalBackground]
CompilerEndIf
Case #COLOR_Selection, #COLOR_SelectionRepeat
CompilerIf #CompileWindows
Color = GetSysColor_(#COLOR_HIGHLIGHT)
CompilerElse
Color = *ColorScheme\ColorValue[#COLOR_NormalText]
CompilerEndIf
Default
Color = *ColorScheme\ColorValue[#COLOR_NormalText] ; otherwise, assume it should match normal foreground color
EndSelect
ProcedureReturn Color
EndProcedure
; Disable color preference gadgets if appropriate (eg. disable Selection and SelectionFront when Accessibility mode expects them to match system colors)
Procedure DisableSelectionColorGadgets(*ColorScheme.ColorSchemeStruct)
CompilerIf #CompileWindows
ShouldDisable = #False
If EnableAccessibility
ShouldDisable = #True ; Accessibility mode enabled - use system selection colors, don't allow user to change them
Else
If *ColorScheme
If *ColorScheme\IsAccessibility
ShouldDisable = #True ; Accessibility scheme selected - use system selection colors, don't allow user to change them
ElseIf *ColorScheme\ColorValue[#COLOR_Selection] = #ColorSchemeValue_UseSysColor Or *ColorScheme\ColorValue[#COLOR_SelectionFront] = #ColorSchemeValue_UseSysColor
ShouldDisable = #True ; Value of -1 (use system color) specified
EndIf
EndIf
EndIf
DisableGadget(#GADGET_Preferences_FirstColorText + #COLOR_Selection, ShouldDisable)
DisableGadget(#GADGET_Preferences_FirstSelectColor + #COLOR_Selection, ShouldDisable)
DisableGadget(#GADGET_Preferences_FirstColorText + #COLOR_SelectionFront, ShouldDisable)
DisableGadget(#GADGET_Preferences_FirstSelectColor + #COLOR_SelectionFront, ShouldDisable)
CompilerEndIf
EndProcedure
; Load the specified *ColorScheme to the Preferences gadgets
Procedure LoadColorSchemeToPreferencesWindow(*ColorScheme.ColorSchemeStruct)
If *ColorScheme
PreferenceToolsPanelFrontColor = *ColorScheme\ColorValue[#COLOR_ToolsPanelFrontColor]
PreferenceToolsPanelBackColor = *ColorScheme\ColorValue[#COLOR_ToolsPanelBackColor]
For i = 0 To #COLOR_Last
Colors(i)\PrefsValue = *ColorScheme\ColorValue[i]
Next i
CompilerIf #CompileWindows
; Special thing: On windows we always default back to the system colors in
; the PB standard scheme for screenreader support. The 'Accessibility'
; scheme has a special option to always use these colors, so it is not needed here.
;
If *ColorScheme\IsIDEDefault Or *ColorScheme\IsAccessibility Or EnableAccessibility Or (Colors(#COLOR_Selection)\PrefsValue = #ColorSchemeValue_UseSysColor)
Colors(#COLOR_Selection)\PrefsValue = GetSysColor_(#COLOR_HIGHLIGHT)
Colors(#COLOR_SelectionFront)\PrefsValue = GetSysColor_(#COLOR_HIGHLIGHTTEXT)
EndIf
CompilerEndIf
For i = 0 To #COLOR_Last
If Colors(i)\PrefsValue >= 0
UpdatePreferenceSyntaxColor(i, Colors(i)\PrefsValue)
Else
Colors(i)\PrefsValue = GuessColorSchemeColor(*ColorScheme, i)
UpdatePreferenceSyntaxColor(i, Colors(i)\PrefsValue)
EndIf
Next i
DisableSelectionColorGadgets(*ColorScheme)
If PreferenceToolsPanelFrontColor < 0
PreferenceToolsPanelFrontColor = GuessColorSchemeColor(*ColorScheme, #COLOR_ToolsPanelFrontColor)
EndIf
If PreferenceToolsPanelBackColor < 0
PreferenceToolsPanelBackColor = GuessColorSchemeColor(*ColorScheme, #COLOR_ToolsPanelBackColor)
EndIf
If IsImage(#IMAGE_Preferences_ToolsPanelFrontColor)
UpdateImageColorGadget(#GADGET_Preferences_ToolsPanelFrontColor, #IMAGE_Preferences_ToolsPanelFrontColor, PreferenceToolsPanelFrontColor)
EndIf
If IsImage(#IMAGE_Preferences_ToolsPanelBackColor)
UpdateImageColorGadget(#GADGET_Preferences_ToolsPanelBackColor, #IMAGE_Preferences_ToolsPanelBackColor, PreferenceToolsPanelBackColor)
EndIf
EndIf
EndProcedure
; Find and remove a known color scheme by its name
Procedure RemoveColorSchemeIfExists(Name$)
If Name$ <> ""
ForEach ColorScheme()
If ColorScheme()\Name$ = Name$
DeleteElement(ColorScheme())
Break
EndIf
Next
EndIf
EndProcedure
; Read the specified *ColorScheme from data section (for built-in schemes)
Procedure ReadColorSchemeFromDataSection(*ColorScheme.ColorSchemeStruct)
If *ColorScheme
; This assumes the NAME STRING data has already been read!
*ColorScheme\File$ = ""
Read.l *ColorScheme\ColorValue[#COLOR_ToolsPanelFrontColor]
Read.l *ColorScheme\ColorValue[#COLOR_ToolsPanelBackColor]
For i = 0 To #COLOR_Last
Read.l *ColorScheme\ColorValue[i]
Next i
EndIf
ProcedureReturn *ColorScheme
EndProcedure
; Load the specified *ColorScheme from file on disk (for external schemes)
Procedure LoadColorSchemeFromFile(*ColorScheme.ColorSchemeStruct, File$)
Protected Result = #Null
If File$
; Basic validation of color scheme file...
If OpenPreferences(File$)
Name$ = GetFilePart(File$, #PB_FileSystem_NoExtension)
If PreferenceGroup("Sections") And (ReadPreferenceLong("IncludeColors", 0) = 1)
If PreferenceGroup("Colors")
If *ColorScheme
RemoveColorSchemeIfExists(Name$)
*ColorScheme\Name$ = Name$
*ColorScheme\File$ = File$
; Load all defined colors into map...
For i = 0 To #COLOR_Last_IncludingToolsPanel
*ColorScheme\ColorValue[i] = #ColorSchemeValue_Undefined
ColorValueString$ = ReadPreferenceString(ColorName(i), "")
If ColorValueString$ <> ""
If ReadPreferenceLong(ColorName(i) + "_Used", 1) = 1
If FindString(ColorValueString$, "RGB", 1, #PB_String_NoCase)
*ColorScheme\ColorValue[i] = ColorFromRGBString(ColorValueString$)
Else
*ColorScheme\ColorValue[i] = Val(ColorValueString$) & $00FFFFFF
EndIf
EndIf
EndIf
Next i
Result = *ColorScheme
EndIf
EndIf
EndIf
ClosePreferences()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
; Initialize color names, built-in color schemes, and external found color schemes
Procedure InitColorSchemes()
; Only need to initialize color schemes once
If NbSchemes > 0
ProcedureReturn
EndIf
; Read color key names into indexable array
Restore ColorKeys
For i = 0 To #COLOR_Last
Read.s ColorName(i)
Next i
ColorName(#COLOR_ToolsPanelFrontColor) = "ToolsPanel_FrontColor"
ColorName(#COLOR_ToolsPanelBackColor) = "ToolsPanel_BackColor"
; First, load embedded DataSection default color schemes
ClearList(ColorScheme())
Restore DefaultColorSchemes
Read.s Name$
While Name$ <> ""
AddElement(ColorScheme())
ColorScheme()\Name$ = Name$
ReadColorSchemeFromDataSection(@ColorScheme())
If ListIndex(ColorScheme()) = 0
ColorScheme()\IsIDEDefault = #True
EndIf
Read.s Name$
Wend
NbSchemes = ListSize(ColorScheme())
; Then, scan 'ColorSchemes' subfolder!
If PureBasicPath$
Dir = ExamineDirectory(#PB_Any, PureBasicPath$ + #DEFAULT_ColorSchemePath, "*")
If Dir
While NextDirectoryEntry(Dir)
If DirectoryEntryType(Dir) = #PB_DirectoryEntry_File
File$ = PureBasicPath$ + #DEFAULT_ColorSchemePath + #PS$ + DirectoryEntryName(Dir)
Select LCase(GetExtensionPart(File$))
Case "prefs"
AddElement(ColorScheme())
If LoadColorSchemeFromFile(@ColorScheme(), File$)
; OK
Else
DeleteElement(ColorScheme())
EndIf
EndSelect
EndIf
Wend
FinishDirectory(Dir)
EndIf
EndIf
; If additional schemes were found, sort schemes alphabetically, because it could become a long list
If ListSize(ColorScheme()) > NbSchemes
NbSchemes = ListSize(ColorScheme())
SortStructuredList(ColorScheme(), #PB_Sort_Ascending | #PB_Sort_NoCase, OffsetOf(ColorSchemeStruct\Name$), #PB_String)
EndIf
; Ensure "Accessibility" scheme always at bottom of list, for special handling
ForEach ColorScheme()
If ColorScheme()\Name$ = "Accessibility"
ColorScheme()\IsAccessibility = #True
MoveElement(ColorScheme(), #PB_List_Last)
EndIf
Next
EndProcedure