1 {
2 Copyright (C) Alexey Torgashin, uvviewsoft.com
3 License: MPL 2.0 or LGPL
4 }
5 unit ATSynEdit_Gaps;
6
7 {$mode objfpc}{$H+}
8
9 interface
10
11 uses
12 SysUtils, Classes, Graphics, Controls, Forms,
13 Math,
14 ATStringProc;
15
16 type
17 { TATGapItem }
18
19 TATGapItem = class
20 public
21 LineIndex: integer;
22 Size: integer;
23 Color: TColor;
24 Bitmap: TBitmap;
25 Form: TCustomForm;
26 FormVisible: boolean;
27 Tag: Int64;
28 DeleteOnDelLine: boolean;
29 constructor Create; virtual;
30 destructor Destroy; override;
GetObjectWidthnull31 function GetObjectWidth: integer;
32 end;
33
34 type
35 TATGapDeleteEvent = procedure(Sender: TObject; ALineIndex: integer) of object;
36
37 type
38 { TATGaps }
39
40 TATGaps = class
41 private
42 FList: TFPList;
43 FOnDelete: TATGapDeleteEvent;
44 FSizeOfGapTop: integer;
45 FSizeOfGap0: integer;
GetItemnull46 function GetItem(N: integer): TATGapItem;
47 public
48 constructor Create; virtual;
49 destructor Destroy; override;
50 procedure Clear;
Countnull51 function Count: integer; inline;
IsIndexValidnull52 function IsIndexValid(N: integer): boolean; inline;
53 property Items[N: integer]: TATGapItem read GetItem; default;
54 procedure Delete(N: integer);
Addnull55 function Add(ALineIndex, ASize: integer; ABitmap: TBitmap; AForm: TCustomForm;
56 const ATag: Int64;
57 AColor: TColor=clNone; ADeleteOnDelLine: boolean=true): boolean;
Findnull58 function Find(ALineIndex: integer; ATag: Int64=-1): TATGapItem;
DeleteForLineRangenull59 function DeleteForLineRange(ALineFrom, ALineTo: integer): boolean;
DeleteWithTagnull60 function DeleteWithTag(const ATag: Int64): boolean;
SizeForLineRangenull61 function SizeForLineRange(ALineFrom, ALineTo: integer): integer;
SizeForAllnull62 function SizeForAll: integer;
63 property SizeOfGapTop: integer read FSizeOfGapTop;
64 property SizeOfGap0: integer read FSizeOfGap0;
65 procedure Update(AChange: TATLineChangeKind; ALine, AItemCount: integer);
66 property OnDelete: TATGapDeleteEvent read FOnDelete write FOnDelete;
67 end;
68
GetGapBitmapPosLeftnull69 function GetGapBitmapPosLeft(const ARect: TRect; AObjectWidth: integer): integer;
70
71
72 implementation
73
GetGapBitmapPosLeftnull74 function GetGapBitmapPosLeft(const ARect: TRect; AObjectWidth: integer): integer;
75 begin
76 Result:= Max(ARect.Left, (ARect.Left+ARect.Right-AObjectWidth) div 2);
77 end;
78
79
80 { TATGapItem }
81
82 constructor TATGapItem.Create;
83 begin
84 Bitmap:= nil;
85 DeleteOnDelLine:= true;
86 Color:= clNone;
87 end;
88
89 destructor TATGapItem.Destroy;
90 begin
91 if Bitmap<>nil then
92 FreeAndNil(Bitmap);
93 inherited;
94 end;
95
GetObjectWidthnull96 function TATGapItem.GetObjectWidth: integer;
97 begin
98 if Assigned(Bitmap) then
99 Result:= Bitmap.Width
100 else
101 if Assigned(Form) then
102 Result:= Form.Width
103 else
104 Result:= 0;
105 end;
106
107 { TATGaps }
108
109 constructor TATGaps.Create;
110 begin
111 inherited;
112 FList:= TFPList.Create;
113 FSizeOfGapTop:= 0;
114 FSizeOfGap0:= 0;
115 end;
116
117 destructor TATGaps.Destroy;
118 begin
119 Clear;
120 FreeAndNil(FList);
121 inherited;
122 end;
123
124 procedure TATGaps.Clear;
125 var
126 i: integer;
127 begin
128 for i:= FList.Count-1 downto 0 do
129 begin
130 if Assigned(FOnDelete) then
131 FOnDelete(Self, Items[i].LineIndex);
132 TObject(FList[i]).Free;
133 end;
134 FList.Clear;
135 FSizeOfGapTop:= 0;
136 FSizeOfGap0:= 0;
137 end;
138
TATGaps.Countnull139 function TATGaps.Count: integer; inline;
140 begin
141 Result:= FList.Count;
142 end;
143
TATGaps.IsIndexValidnull144 function TATGaps.IsIndexValid(N: integer): boolean; inline;
145 begin
146 Result:= (N>=0) and (N<FList.Count);
147 end;
148
GetItemnull149 function TATGaps.GetItem(N: integer): TATGapItem;
150 begin
151 Result:= TATGapItem(FList[N]);
152 end;
153
154 procedure TATGaps.Delete(N: integer);
155 var
156 Item: TATGapItem;
157 begin
158 Item:= Items[N];
159 if Assigned(FOnDelete) then
160 FOnDelete(Self, Item.LineIndex);
161
162 if Item.LineIndex=-1 then
163 FSizeOfGapTop:= 0
164 else
165 if Item.LineIndex=0 then
166 FSizeOfGap0:= 0;
167
168 Item.Free;
169 FList.Delete(N);
170 end;
171
TATGaps.DeleteForLineRangenull172 function TATGaps.DeleteForLineRange(ALineFrom, ALineTo: integer): boolean;
173 var
174 Item: TATGapItem;
175 i: integer;
176 begin
177 Result:= false;
178 for i:= FList.Count-1 downto 0 do
179 begin
180 Item:= Items[i];
181 if (Item.LineIndex>=ALineFrom) and (Item.LineIndex<=ALineTo) then
182 begin
183 Delete(i);
184 Result:= true;
185 end;
186 end;
187 end;
188
TATGaps.DeleteWithTagnull189 function TATGaps.DeleteWithTag(const ATag: Int64): boolean;
190 var
191 Item: TATGapItem;
192 i: integer;
193 begin
194 Result:= false;
195 for i:= FList.Count-1 downto 0 do
196 begin
197 Item:= Items[i];
198 if Item.Tag=ATag then
199 begin
200 Delete(i);
201 Result:= true;
202 end;
203 end;
204 end;
205
Addnull206 function TATGaps.Add(ALineIndex, ASize: integer; ABitmap: TBitmap;
207 AForm: TCustomForm; const ATag: Int64; AColor: TColor;
208 ADeleteOnDelLine: boolean): boolean;
209 var
210 Item: TATGapItem;
211 begin
212 Result:= false;
213 if (ALineIndex<-1) then exit;
214 if Find(ALineIndex)<>nil then exit;
215
216 Item:= TATGapItem.Create;
217 Item.LineIndex:= ALineIndex;
218 Item.Size:= ASize;
219 Item.Bitmap:= ABitmap;
220 Item.Form:= AForm;
221 Item.Tag:= ATag;
222 Item.Color:= AColor;
223 Item.DeleteOnDelLine:= ADeleteOnDelLine;
224
225 if ALineIndex=-1 then
226 FSizeOfGapTop:= ASize
227 else
228 if ALineIndex=0 then
229 FSizeOfGap0:= ASize;
230
231 FList.Add(Item);
232 Result:= true;
233 end;
234
TATGaps.Findnull235 function TATGaps.Find(ALineIndex: integer; ATag: Int64=-1): TATGapItem;
236 var
237 Item: TATGapItem;
238 i: integer;
239 begin
240 Result:= nil;
241 for i:= 0 to FList.Count-1 do
242 begin
243 Item:= Items[i];
244 if (Item.LineIndex=ALineIndex) and ((ATag<0) or (Item.Tag=ATag)) then exit(Item);
245 end;
246 end;
247
SizeForLineRangenull248 function TATGaps.SizeForLineRange(ALineFrom, ALineTo: integer): integer;
249 var
250 Item: TATGapItem;
251 i: integer;
252 begin
253 Result:= 0;
254 for i:= 0 to FList.Count-1 do
255 begin
256 Item:= Items[i];
257 if (Item.LineIndex>=ALineFrom) and (Item.LineIndex<=ALineTo) then
258 Inc(Result, Item.Size);
259 end;
260 end;
261
TATGaps.SizeForAllnull262 function TATGaps.SizeForAll: integer;
263 var
264 Item: TATGapItem;
265 i: integer;
266 begin
267 Result:= 0;
268 for i:= 0 to FList.Count-1 do
269 begin
270 Item:= Items[i];
271 Inc(Result, Item.Size);
272 end;
273 end;
274
275 procedure TATGaps.Update(AChange: TATLineChangeKind; ALine, AItemCount: integer);
276 var
277 Item: TATGapItem;
278 i: integer;
279 begin
280 case AChange of
281 cLineChangeEdited:
282 begin
283 end;
284 cLineChangeAdded:
285 begin
286 for i:= 0 to Count-1 do
287 begin
288 Item:= Items[i];
289 if Item.LineIndex>=ALine then
290 Item.LineIndex:= Item.LineIndex+AItemCount;
291 end;
292 end;
293 cLineChangeDeletedAll:
294 begin
295 Clear;
296 end;
297 cLineChangeDeleted:
298 begin
299 for i:= Count-1 downto 0 do
300 begin
301 Item:= Items[i];
302 if (Item.LineIndex>=ALine) and (Item.LineIndex<ALine+AItemCount) then
303 begin
304 if Item.DeleteOnDelLine then
305 Delete(i);
306 end
307 else
308 if Item.LineIndex>ALine then
309 Item.LineIndex:= Item.LineIndex-AItemCount;
310 end;
311 end;
312 end;
313 end;
314
315
316 end.
317
318