-
Notifications
You must be signed in to change notification settings - Fork 0
/
mv.FMX.StyleMaker.pas
205 lines (175 loc) · 6.76 KB
/
mv.FMX.StyleMaker.pas
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
unit mv.FMX.StyleMaker;
interface
uses
{system}
System.SysUtils, System.Types, System.UITypes, System.Classes,
System.IOUtils, System.UIConsts, System.Rtti, System.StrUtils,
{framework}
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.Edit, FMX.StdCtrls, FMX.Styles,
FMX.Utils,
{custom}
mv.InputQueryDropdown;
function ModifyAndApplyStyleToForm(AForm: TCommonCustomForm): string;
function AdjustColor(const AColor: TAlphaColor; const Amount: Single): TAlphaColor;
procedure CreateModifiedStyle(const SourceStyleFile: string; const DestStyleFile: string);
implementation
// Allows user to pick a form style, and optionally randomize it, then returns
// the resulting style as a string for saving.
function ModifyAndApplyStyleToForm(AForm: TCommonCustomForm): string;
var
StylesArray: TStringDynArray;
StylesList: TStringList;
ChosenStyle, ModifiedStyleFile: string;
StyleIndex: Integer;
I: Integer;
dlgResult: TModalResult;
StylesDir: string;
IterCount: Integer;
StyleValid: boolean;
begin
Result := '';
StylesList := TStringList.Create;
try
// Scan for .style files in the application directory
StylesDir := 'C:\Users\Public\Documents\Embarcadero\Studio\22.0\Styles';
StylesArray := TDirectory.GetFiles(StylesDir, '*.style');
for I := Low(StylesArray) to High(StylesArray) do
StylesList.Add(ExtractFileName(StylesArray[I]));
// Ask the user which style they want to modify
if StylesList.Count > 0 then
begin
ChosenStyle := InputQuery('Choose a style (modified styles will be applied immediately)', StylesList);
if ('' <> ChosenStyle) then
begin
ChosenStyle := StylesDir + '\' + ChosenStyle;
if not ChosenStyle.Contains('_modified') then
dlgResult := MessageDlg('Do you want to modify the style before applying it?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo, TMsgDlgBtn.mbCancel], 0)
else
dlgResult := mrNo;
repeat
case dlgResult of
mrYes: begin // Modify style first
// Define a path to save the modified style
ModifiedStyleFile := ChosenStyle + '_modified.style';
// Modify the chosen style and save it to ModifiedStyleFile
CreateModifiedStyle(ChosenStyle, ModifiedStyleFile);
IterCount := 1;
StyleValid := False;
// Apply the new style to the current form
repeat
try
TStyleManager.SetStyleFromFile(ModifiedStyleFile);
// If we get here then the style did not cause an EReadError
// and is therefore valid.
StyleValid := true;
Result := TFile.ReadAllText(ModifiedStyleFile);
except on EReadError do begin
// If we get here then the style could not be read, some
// color is likely out of range, etc. So we need to try
// again, unless we have run out of attempts.
if IterCount < 100 then
begin
CreateModifiedStyle(ChosenStyle, ModifiedStyleFile);
Result := TFile.ReadAllText(ModifiedStyleFile);
Inc(IterCount);
end else begin
TStyleManager.SetStyleFromFile(ChosenStyle);
ShowMessage('Unable to generate new style, out of iterations. Please try again.');
end;
end;
end;
until StyleValid;
end;
mrNo: begin // Use style as-is
TStyleManager.SetStyleFromFile(ChosenStyle);
Result := TFile.ReadAllText(ChosenStyle);
end;
mrCancel: ; // Do nothing
end;
dlgResult := MessageDlg('Do you want to modify the style again?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0)
until dlgResult <> mrYes;
end;
end else begin
ShowMessage('No styles found.');
end;
finally
StylesList.Free;
end;
end;
function AdjustColor(const AColor: TAlphaColor; const Amount: Single): TAlphaColor;
var
H, S, L: Single;
RandomShift: Single;
begin
RGBtoHSL(AColor, H, S, L);
(*
// If the color is dark (e.g., L < 0.5), then we lighten it.
// Otherwise, we darken it.
if L < 0.5 then
begin
L := L + Amount;
if L > 1 then L := 1;
end
else
begin
L := L - Amount;
if L < 0 then L := 0;
end;
*)
// Randomly vary the hue by +/- 50%
H := H + (-0.5 + Random * 0.5);
if H > 1.0 then H := H - 1; // Wrap around if hue goes beyond 1.0
if H < 0.0 then H := H + 1; // Wrap around if hue goes below 0.0
Result := HSLtoRGB(H, S, L);
end;
procedure CreateModifiedStyle(const SourceStyleFile: string; const DestStyleFile: string);
var
StyleList: TStringList;
I: Integer;
Line: string;
ColorPos: Integer;
OriginalColor, NewColor: TAlphaColor;
OriginalColorString, NewColorString: string;
begin
StyleList := TStringList.Create;
try
// Load the .style file into the TStringList
StyleList.LoadFromFile(SourceStyleFile);
for I := 0 to StyleList.Count - 1 do
begin
Line := StyleList.Strings[I];
// Search for the pattern "xFF" which denotes the start of a color code
ColorPos := Pos('xFF', Line);
if ColorPos > 0 then
begin
// If the line is long enough to contain the full color code
if Length(Line) >= (ColorPos + 7) then
begin
// Extract the color code
OriginalColorString := Copy(Line, ColorPos, 8);
OriginalColor := StringToAlphaColor(OriginalColorString);
NewColorString := AlphaColorToString(OriginalColor).Replace('#0', 'x');
// Modify the color
NewColor := AdjustColor(OriginalColor, 0.1+Random*0.1);
NewColorString := AlphaColorToString(NewColor).Replace('#', 'x');
if Length(NewColorString) > Length(OriginalColorString) then
begin
NewColorString := NewColorString.Replace('xF', 'x');
end;
// Replace the old color with the new one in the line
Line := StringReplace(Line, OriginalColorString, NewColorString, []);
// Update the TStringList entry
StyleList.Strings[I] := Line;
end;
end;
end;
// Save the modified style to a new .style file
StyleList.SaveToFile(DestStyleFile);
finally
StyleList.Free;
end;
end;
end.