-
-
Notifications
You must be signed in to change notification settings - Fork 50
/
FMX.RichEdit.Style.pas
128 lines (106 loc) · 3.63 KB
/
FMX.RichEdit.Style.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
unit FMX.RichEdit.Style;
interface
uses
FMX.Text.TextEditor, FMX.Text.LinesLayout, FMX.TextLayout, ChatGPT.Code, FMX.Memo.Style.New,
FMX.Controls.Presentation, FMX.Text, FMX.ScrollBox.Style, FMX.Controls,
FMX.Graphics, System.UITypes;
type
TRichEditLinesLayout = class(TLinesLayout)
private
FCodeSyntax: TCodeSyntax;
protected
procedure UpdateLayoutParams(const ALineIndex: Integer; const ALayout: TTextLayout); override;
public
constructor Create(const ALineSource: ITextLinesSource; const AScrollableContent: IScrollableContent);
destructor Destroy; override;
procedure ReplaceLine(const AIndex: Integer; const ALine: string); override;
public
procedure SetCodeSyntaxName(const Lang: string; const DefFont: TFont; DefColor: TAlphaColor);
end;
TRichEditTextEditor = class(TTextEditor)
protected
function CreateLinesLayout: TLinesLayout; override;
end;
TRichEditStyled = class(TStyledMemo)
protected
function CreateEditor: TTextEditor; override;
public
procedure UpdateVisibleLayoutParams;
procedure SetCodeSyntaxName(const Lang: string; const DefFont: TFont; DefColor: TAlphaColor);
end;
implementation
uses
System.SysUtils, FMX.Presentation.Style, FMX.Presentation.Factory;
{ TRichEditTextEditor }
function TRichEditTextEditor.CreateLinesLayout: TLinesLayout;
begin
Result := TRichEditLinesLayout.Create(Lines, ScrollableContent);
end;
{ TRichEditLinesLayout }
constructor TRichEditLinesLayout.Create(const ALineSource: ITextLinesSource;
const AScrollableContent: IScrollableContent);
begin
inherited;
end;
destructor TRichEditLinesLayout.Destroy;
begin
FreeAndNil(FCodeSyntax);
inherited;
end;
procedure TRichEditLinesLayout.ReplaceLine(const AIndex: Integer; const ALine: string);
begin
inherited;
// We have to reapply style attributes after line modification
Items[AIndex].InvalidateLayout;
end;
procedure TRichEditLinesLayout.SetCodeSyntaxName(const Lang: string; const DefFont: TFont; DefColor: TAlphaColor);
begin
if Assigned(FCodeSyntax) then
begin
FCodeSyntax.Free;
FCodeSyntax := nil;
end;
FCodeSyntax := TCodeSyntax.FindSyntax(Lang, DefFont, DefColor);
if not Assigned(FCodeSyntax) then
FCodeSyntax := TCodeSyntax.FindSyntax('md', DefFont, DefColor);
end;
procedure TRichEditLinesLayout.UpdateLayoutParams(const ALineIndex: Integer; const ALayout: TTextLayout);
begin
if not Assigned(FCodeSyntax) then
Exit;
ALayout.BeginUpdate;
try
inherited;
ALayout.ClearAttributes;
for var Attr in FCodeSyntax.GetAttributesForLine(LinesSource[ALineIndex], ALineIndex) do
begin
Attr.Attribute.Font.Family := TextSettings.Font.Family;
ALayout.AddAttribute(Attr.Range, Attr.Attribute);
end;
finally
ALayout.EndUpdate;
end;
end;
{ TRichEditStyled }
function TRichEditStyled.CreateEditor: TTextEditor;
begin
Result := TRichEditTextEditor.Create(Self, Memo.Content, Model, Self);
end;
procedure TRichEditStyled.SetCodeSyntaxName(const Lang: string; const DefFont: TFont; DefColor: TAlphaColor);
begin
TRichEditLinesLayout(Editor.LinesLayout).SetCodeSyntaxName(Lang, DefFont, DefColor);
end;
procedure TRichEditStyled.UpdateVisibleLayoutParams;
begin
for var I := 0 to Editor.LinesLayout.Count - 1 do
begin
var Line := Editor.LinesLayout.Items[I];
if Line.Layout <> nil then
TRichEditLinesLayout(Editor.LinesLayout).UpdateLayoutParams(I, Line.Layout);
end;
end;
initialization
TPresentationProxyFactory.Current.Register('RichEditStyled', TStyledPresentationProxy<TRichEditStyled>);
finalization
TPresentationProxyFactory.Current.Unregister('RichEditStyled', TStyledPresentationProxy<TRichEditStyled>);
end.