1 { PropertyEditor
2 
3   Copyright (C) <year> <name of author> <contact>
4 
5   This library is free software; you can redistribute it and/or modify it
6   under the terms of the GNU Library General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or (at your
8   option) any later version.
9 
10   This program is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
13   for more details.
14 
15   You should have received a copy of the GNU Library General Public License
16   along with this library; if not, write to the Free Software Foundation,
17   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
18 }
19 unit SynPropertyEditObjectList;
20 
21 {$mode objfpc}{$H+}
22 
23 interface
24 
25 uses
26   Classes, SysUtils, LCLProc,
27   SynEdit, SynGutterBase, SynEditMiscClasses, SynEditMouseCmds, SynEditKeyCmds,
28   SynDesignStringConstants,
29   PropEdits, PropEditUtils, Forms, StdCtrls, ComCtrls, Dialogs, ComponentEditors,
30   ObjInspStrConsts, Controls, IDEImagesIntf, typinfo, FormEditingIntf, SynEditTypes;
31 
32 type
33 
34   { TSynEdOptionsPropertyEditor }
35 
36   TSynEdOptionsPropertyEditor = class(TSetPropertyEditor)
37   public
38     procedure GetProperties(Proc: TGetPropEditProc); override;
39   end;
40 
41   { TSynPropertEditClassList }
42 
43   TSynPropertyEditObjectList = class(TListPropertyEditor)
44   protected
ReadElementCountnull45     function ReadElementCount: integer; override;
ReadElementnull46     function ReadElement(Index: integer): TPersistent; override;
ClassListnull47     class function ClassList: TStringList; virtual; abstract;
48   public
GetAttributesnull49     function GetAttributes: TPropertyAttributes; override;
50     procedure Edit; override;
ShowClassListEditornull51     class function ShowClassListEditor(AClassList: TSynObjectList;
52       OwnerPersistent: TPersistent; const PropName: String): TCustomForm;
53   end;
54 
55   { TSynPropertyEditGutterPartList }
56 
57   TSynPropertyEditGutterPartList = class(TSynPropertyEditObjectList)
58   protected
ClassListnull59     class function ClassList: TStringList; override;
60   end;
61 
62   { TSynObjectPartListPropertyEditorForm }
63 
64   TSynObjectPartListPropertyEditorForm = class(TForm)
65     SynObjectPartsListBox: TListBox;
66     ToolBar1: TToolBar;
67     AddButton: TToolButton;
68     ClassComboBox: TComboBox;
69     DeleteButton: TToolButton;
70     ToolButton3: TToolButton;
71     MoveUpButton: TToolButton;
72     MoveDownButton: TToolButton;
73     procedure AddButtonClick(Sender: TObject);
74     procedure SynObjectPartsListBoxClick(Sender: TObject);
75     procedure DeleteButtonClick(Sender: TObject);
76     procedure FormCreate(Sender: TObject);
77     procedure FormDestroy(Sender: TObject);
78     procedure MoveDownButtonClick(Sender: TObject);
79     procedure MoveUpButtonClick(Sender: TObject);
80   private
81     FSynObjectPartList: TSynObjectList;
82     FOwnerPersistent: TPersistent;
83     FPropertyName: String;
84     FClassesList: TStringList;
85   protected
86     procedure UpdateCaption;
87     procedure UpdateButtons;
88     procedure ComponentRenamed(AComponent: TComponent);
89     procedure PersistentDeleting(APersistent: TPersistent);
90     procedure RefreshPropertyValues;
91   public
92     procedure FillSynObjectPartsListBox;
93     procedure SelectInObjectInspector(UnselectAll: Boolean);
94     procedure SetSynObjectPartList(NewSynObjectPartList: TSynObjectList;
95                     NewClassesList: TStringList;
96                     NewOwnerPersistent: TPersistent; const NewPropName: String);
97     procedure Modified;
98   public
99     property SynObjectPartList: TSynObjectList read FSynObjectPartList;
100     property OwnerPersistent: TPersistent read FOwnerPersistent;
101     property PropertyName: String read FPropertyName;
102   end;
103 
104   { TSynKeyCommandPropertyEditor }
105 
106   TSynKeyCommandPropertyEditor = class(TIntegerPropertyEditor)
107   public
GetAttributesnull108     function GetAttributes: TPropertyAttributes; override;
OrdValueToVisualValuenull109     function OrdValueToVisualValue(OrdValue: longint): string; override;
110     procedure GetValues(Proc: TGetStrProc); override;
111     procedure SetValue(const NewValue: ansistring); override;
112   end;
113 
114   { TSynMouseCommandPropertyEditor }
115 
116   TSynMouseCommandPropertyEditor = class(TIntegerPropertyEditor)
117   public
GetAttributesnull118     function GetAttributes: TPropertyAttributes; override;
OrdValueToVisualValuenull119     function OrdValueToVisualValue(OrdValue: longint): string; override;
120     procedure GetValues(Proc: TGetStrProc); override;
121     procedure SetValue(const NewValue: ansistring); override;
122   end;
123 
124   { TSynEditComponentEditor }
125 
126   TSynEditComponentEditor = class(TDefaultComponentEditor)
127   public
GetVerbCountnull128     function GetVerbCount: Integer; override;
GetVerbnull129     function GetVerb(Index: Integer): string; override;
130     procedure ExecuteVerb(Index: Integer); override;
131   end;
132 
133   procedure RegisterGutterPartClass(AClass: TSynGutterPartBaseClass; AName: String);
134 
135 implementation
136 
137 {$R *.lfm}
138 
139 const
140   SynObjectPartListForm: TSynObjectPartListPropertyEditorForm = nil;
141   KnownSynGutterPartClasses: TStringList = nil;
142 
143 procedure RegisterGutterPartClass(AClass: TSynGutterPartBaseClass; AName: String);
144 begin
145   if KnownSynGutterPartClasses = nil then
146     KnownSynGutterPartClasses := TStringList.Create;
147   KnownSynGutterPartClasses.AddObject(AName, TObject(Pointer(AClass)));
148 end;
149 
150 { TSynEditComponentEditor }
151 
GetVerbCountnull152 function TSynEditComponentEditor.GetVerbCount: Integer;
153 begin
154   Result := inherited GetVerbCount;
155   Result := Result + 1;
156 end;
157 
TSynEditComponentEditor.GetVerbnull158 function TSynEditComponentEditor.GetVerb(Index: Integer): string;
159 begin
160   case Index - (inherited GetVerbCount) of
161     0: Result := syndsResetMouseActions;
162     else
163       Result := inherited GetVerb(Index);
164   end;
165 end;
166 
167 procedure TSynEditComponentEditor.ExecuteVerb(Index: Integer);
168 var
169   Hook: TPropertyEditorHook;
170 begin
171   case Index - (inherited GetVerbCount) of
172     0: begin
173         if Component is TCustomSynEdit then
174           TCustomSynEdit(Component).ResetMouseActions;
175         Modified;
176         GetHook(Hook);
177         if Assigned(Hook) then Hook.Modified(Self);
178       end;
179     else
180       inherited ExecuteVerb(Index);
181   end;
182 end;
183 
184 { TSynEdOptionsPropertyEditor }
185 
186 procedure TSynEdOptionsPropertyEditor.GetProperties(Proc: TGetPropEditProc);
187 var
188   I: Integer;
189 begin
190   with GetTypeData(GetTypeData(GetPropType)^.CompType)^ do
191     for I := MinValue to MaxValue do
192       if not(TSynEditorOption(I) in SYNEDIT_UNIMPLEMENTED_OPTIONS)
193       then
194         Proc(TSetElementPropertyEditor.Create(Self, I));
195 end;
196 
197 { TSynKeyCommandPropertyEditor }
198 
GetAttributesnull199 function TSynKeyCommandPropertyEditor.GetAttributes: TPropertyAttributes;
200 begin
201   Result := [paMultiSelect, paValueList, paRevertable];
202 end;
203 
OrdValueToVisualValuenull204 function TSynKeyCommandPropertyEditor.OrdValueToVisualValue(OrdValue: longint): string;
205 begin
206   Result:='';
207   if not EditorCommandToIdent(OrdValue, Result) then
208     Result := inherited OrdValueToVisualValue(OrdValue);
209 end;
210 
211 procedure TSynKeyCommandPropertyEditor.GetValues(Proc: TGetStrProc);
212 var
213   CValue: Integer;
214 begin
215   CValue:=0;
216   if not IdentToSynMouseCmd(GetVisualValue, CValue) then Proc(GetVisualValue);
217   GetEditorCommandValues(Proc);
218 end;
219 
220 procedure TSynKeyCommandPropertyEditor.SetValue(const NewValue: ansistring);
221 var
222   CValue: Integer;
223 begin
224   CValue:=0;
225   if IdentToEditorCommand(NewValue, CValue) then SetOrdValue(CValue)
226   else inherited SetValue(NewValue);
227 end;
228 
229 { TSynMouseCommandPropertyEditor }
230 
GetAttributesnull231 function TSynMouseCommandPropertyEditor.GetAttributes: TPropertyAttributes;
232 begin
233   Result := [paMultiSelect, paValueList, paRevertable];
234 end;
235 
OrdValueToVisualValuenull236 function TSynMouseCommandPropertyEditor.OrdValueToVisualValue(OrdValue: longint): string;
237 begin
238   Result:='';
239   if not SynMouseCmdToIdent(OrdValue, Result) then
240     Result := inherited OrdValueToVisualValue(OrdValue);
241 end;
242 
243 procedure TSynMouseCommandPropertyEditor.GetValues(Proc: TGetStrProc);
244 var
245   CValue: Integer;
246   CName: String;
247   i: TSynEditorMouseCommand;
248 begin
249   CValue:=0;
250   CName:='';
251   if not IdentToSynMouseCmd(GetVisualValue, CValue) then Proc(GetVisualValue);
252   for i := 0 to emcMax do
253     if SynMouseCmdToIdent(i, CName) then Proc(CName);
254 end;
255 
256 procedure TSynMouseCommandPropertyEditor.SetValue(const NewValue: ansistring);
257 var
258   CValue: Integer;
259 begin
260   CValue:=0;
261   if IdentToSynMouseCmd(NewValue, CValue) then SetOrdValue(CValue)
262   else inherited SetValue(NewValue);
263 end;
264 
265 { TSynObjectPartListPropertyEditorForm }
266 
267 procedure TSynObjectPartListPropertyEditorForm.AddButtonClick(Sender: TObject);
268 var
269   i: Integer;
270   NewPart: TSynObjectListItem;
271 begin
272   if (SynObjectPartList = nil) or (FClassesList = nil) then Exit;
273 
274   i := ClassComboBox.ItemIndex;
275   if (i < 0) or (i >= FClassesList.Count) then
276     exit;
277   NewPart := TSynObjectListItemClass(Pointer(FClassesList.Objects[i])).Create(SynObjectPartList);
278   NewPart.Name := FormEditingHook.CreateUniqueComponentName(NewPart.ClassName, SynObjectPartList);
279 
280   FillSynObjectPartsListBox;
281   if SynObjectPartsListBox.Items.Count > 0 then
282     SynObjectPartsListBox.ItemIndex := SynObjectPartsListBox.Items.Count - 1;
283   SelectInObjectInspector(False);
284   UpdateButtons;
285   UpdateCaption;
286   Modified;
287 end;
288 
289 procedure TSynObjectPartListPropertyEditorForm.SynObjectPartsListBoxClick(Sender: TObject);
290 begin
291   UpdateButtons;
292   UpdateCaption;
293   SelectInObjectInspector(False);
294 end;
295 
296 procedure TSynObjectPartListPropertyEditorForm.DeleteButtonClick(Sender: TObject);
297 var
298   I : Integer;
299   NewItemIndex: Integer;
300 begin
301   if SynObjectPartList = nil then Exit;
302 
303   I := SynObjectPartsListBox.ItemIndex;
304   if (I >= 0) and (I < SynObjectPartList.Count) then
305   begin
306     if MessageDlg(oisConfirmDelete,
307       Format(oisDeleteItem, [SynObjectPartList.BaseItems[I].DisplayName]),
308       mtConfirmation, [mbYes, mbNo], 0) = mrYes then
309     begin
310       // select other item, or unselect
311       NewItemIndex := I + 1;
312       while (NewItemIndex < SynObjectPartsListBox.Items.Count)
313       and (SynObjectPartsListBox.Selected[NewItemIndex]) do Inc(NewItemIndex);
314 
315       if NewItemIndex = SynObjectPartsListBox.Items.Count then
316       begin
317         NewItemIndex := 0;
318         while (NewItemIndex < Pred(I))
319         and not (SynObjectPartsListBox.Selected[NewItemIndex]) do Inc(NewItemIndex);
320 
321         if NewItemIndex = I then NewItemIndex := -1;
322       end;
323 
324       SynObjectPartsListBox.ItemIndex := -1;
325 
326       if NewItemIndex > I then Dec(NewItemIndex);
327       // unselect all items in OI
328       SelectInObjectInspector(True);
329       // now delete
330       SynObjectPartList.BaseItems[I].Free;
331       // update listbox after whatever happened
332       FillSynObjectPartsListBox;
333       // set NewItemIndex
334       if NewItemIndex < SynObjectPartsListBox.Items.Count then
335       begin
336         SynObjectPartsListBox.ItemIndex := NewItemIndex;
337         SelectInObjectInspector(False);
338       end;
339       Modified;
340     end;
341   end;
342   UpdateButtons;
343   UpdateCaption;
344 end;
345 
346 procedure TSynObjectPartListPropertyEditorForm.FormCreate(Sender: TObject);
347 begin
348   ToolBar1.Images := IDEImages.Images_16;
349   AddButton.Caption := oiColEditAdd;
350   DeleteButton.Caption := oiColEditDelete;
351   MoveUpButton.Caption := oiColEditUp;
352   MoveDownButton.Caption := oiColEditDown;
353   AddButton.ImageIndex := IDEImages.LoadImage('laz_add');
354   DeleteButton.ImageIndex := IDEImages.LoadImage('laz_delete');
355   MoveUpButton.ImageIndex := IDEImages.LoadImage('arrow_up');
356   MoveDownButton.ImageIndex := IDEImages.LoadImage('arrow_down');
357 end;
358 
359 procedure TSynObjectPartListPropertyEditorForm.FormDestroy(Sender: TObject);
360 begin
361   if GlobalDesignHook <> nil then
362     GlobalDesignHook.RemoveAllHandlersForObject(Self);
363 end;
364 
365 procedure TSynObjectPartListPropertyEditorForm.MoveDownButtonClick(Sender: TObject);
366 var
367   I: Integer;
368 begin
369   if SynObjectPartList = nil then Exit;
370 
371   I := SynObjectPartsListBox.ItemIndex;
372   if I >= SynObjectPartList.Count - 1 then Exit;
373 
374   SynObjectPartList.BaseItems[I].Index := I + 1;
375   SynObjectPartsListBox.ItemIndex := I + 1;
376 
377   FillSynObjectPartsListBox;
378   SelectInObjectInspector(False);
379   Modified;
380 end;
381 
382 procedure TSynObjectPartListPropertyEditorForm.MoveUpButtonClick(Sender: TObject);
383 var
384   I: Integer;
385 begin
386   if SynObjectPartList = nil then Exit;
387 
388   I := SynObjectPartsListBox.ItemIndex;
389   if I < 0 then Exit;
390 
391   SynObjectPartList.BaseItems[I].Index := I - 1;
392   SynObjectPartsListBox.ItemIndex := I - 1;
393 
394   FillSynObjectPartsListBox;
395   SelectInObjectInspector(False);
396   Modified;
397 end;
398 
399 procedure TSynObjectPartListPropertyEditorForm.UpdateCaption;
400 var
401   NewCaption: String;
402 begin
403   //"Editing ComponentName.PropertyName[Index]"
404   if OwnerPersistent is TComponent then
405     NewCaption := TComponent(OwnerPersistent).Name
406   else
407     if OwnerPersistent <> nil then
408       NewCaption := OwnerPersistent.GetNamePath
409     else
410       NewCaption := '';
411 
412   if NewCaption <> '' then NewCaption := NewCaption + '.';
413   NewCaption := oiColEditEditing + ' ' + NewCaption + PropertyName;
414 
415   if SynObjectPartsListBox.ItemIndex > -1 then
416     NewCaption := NewCaption + '[' + IntToStr(SynObjectPartsListBox.ItemIndex) + ']';
417   Caption := NewCaption;
418 end;
419 
420 procedure TSynObjectPartListPropertyEditorForm.UpdateButtons;
421 var
422   I: Integer;
423 begin
424   if SynObjectPartList = nil then begin
425     AddButton.Enabled := False;
426     DeleteButton.Enabled := False;
427     MoveUpButton.Enabled := False;
428     MoveDownButton.Enabled := False;
429     exit;
430   end;
431   I := SynObjectPartsListBox.ItemIndex;
432   AddButton.Enabled := True;
433   DeleteButton.Enabled := I > -1;
434   MoveUpButton.Enabled := I > 0;
435   MoveDownButton.Enabled := (I >= 0) and (I < SynObjectPartList.Count - 1);
436 end;
437 
438 procedure TSynObjectPartListPropertyEditorForm.ComponentRenamed(AComponent: TComponent);
439 begin
440   if AComponent = OwnerPersistent then UpdateCaption;
441 end;
442 
443 procedure TSynObjectPartListPropertyEditorForm.PersistentDeleting(APersistent: TPersistent);
444 var
445   OldSynObjectPartList: TSynObjectList;
446   I: Integer;
447 begin
448   debugln(['TSynObjectPartListPropertyEditorForm.PersistentDeleting ']);
449   if APersistent = OwnerPersistent then
450   begin
451     OldSynObjectPartList := SynObjectPartList;
452     SetSynObjectPartList(nil, nil, nil, '');
453     GlobalDesignHook.Unselect(OldSynObjectPartList);
454     for I := 0 to OldSynObjectPartList.Count - 1 do
455       GlobalDesignHook.Unselect(OldSynObjectPartList.BaseItems[I]);
456     if GlobalDesignHook.LookupRoot = OldSynObjectPartList then
457       GlobalDesignHook.LookupRoot := nil;
458     Hide;
459   end;
460 end;
461 
462 
463 procedure TSynObjectPartListPropertyEditorForm.RefreshPropertyValues;
464 begin
465   FillSynObjectPartsListBox;
466   Modified;
467 end;
468 
469 procedure TSynObjectPartListPropertyEditorForm.FillSynObjectPartsListBox;
470 var
471   I: Integer;
472   CurItem: String;
473   Cnt: Integer;
474 begin
475   SynObjectPartsListBox.Items.BeginUpdate;
476   try
477     if SynObjectPartList <> nil then Cnt := SynObjectPartList.Count
478     else Cnt := 0;
479 
480     // add or replace list items
481     for I := 0 to Cnt - 1 do
482     begin
483       CurItem := IntToStr(I) + ' - ' + SynObjectPartList.BaseItems[I].DisplayName;
484       if I >= SynObjectPartsListBox.Items.Count then
485         SynObjectPartsListBox.Items.Add(CurItem)
486       else
487         SynObjectPartsListBox.Items[I] := CurItem;
488     end;
489 
490     // delete unneeded list items
491     if Cnt > 0 then
492     begin
493       while SynObjectPartsListBox.Items.Count > Cnt do
494       begin
495         SynObjectPartsListBox.Items.Delete(SynObjectPartsListBox.Items.Count - 1);
496       end;
497     end
498     else
499     begin
500       SynObjectPartsListBox.Items.Clear;
501     end;
502   finally
503     SynObjectPartsListBox.Items.EndUpdate;
504     UpdateButtons;
505     UpdateCaption;
506   end;
507 end;
508 
509 procedure TSynObjectPartListPropertyEditorForm.SelectInObjectInspector(UnselectAll: Boolean);
510 var
511   I: Integer;
512   NewSelection: TPersistentSelectionList;
513 begin
514   if SynObjectPartList = nil then Exit;
515   // select in OI
516   NewSelection := TPersistentSelectionList.Create;
517   try
518     if not UnselectAll then
519     begin
520       for I := 0 to SynObjectPartsListBox.Items.Count - 1 do
521         if SynObjectPartsListBox.Selected[I] then
522           NewSelection.Add(SynObjectPartList.BaseItems[I]);
523     end;
524     GlobalDesignHook.SetSelection(NewSelection);
525     GlobalDesignHook.LookupRoot := GetLookupRootForComponent(OwnerPersistent);
526   finally
527     NewSelection.Free;
528   end;
529 end;
530 
531 procedure TSynObjectPartListPropertyEditorForm.SetSynObjectPartList
532   (NewSynObjectPartList: TSynObjectList; NewClassesList: TStringList;
533    NewOwnerPersistent: TPersistent; const NewPropName: String);
534 begin
535   if (FSynObjectPartList = NewSynObjectPartList)
536     and (FClassesList = NewClassesList)
537     and (FOwnerPersistent = NewOwnerPersistent)
538     and (FPropertyName = NewPropName) then Exit;
539 
540   FSynObjectPartList := NewSynObjectPartList;
541   FClassesList := NewClassesList;
542   if assigned(FClassesList) then
543     ClassComboBox.Items.Assign(FClassesList)
544   else
545     ClassComboBox.Clear;
546   if ClassComboBox.Items.Count >0 then
547     ClassComboBox.ItemIndex := 0;
548 
549   // Can not use NewOwnerPersistent since it points to the SynGutter
550   if NewSynObjectPartList <> nil then
551     FOwnerPersistent := NewSynObjectPartList.Owner // The SynEdit
552   else
553     FOwnerPersistent := nil;
554 
555   FPropertyName := NewPropName;
556   //debugln('TSynObjectPartListPropertyEditorForm.SetSynObjectPartList A SynObjectPartList=',dbgsName(FSynObjectPartList),' OwnerPersistent=',dbgsName(OwnerPersistent),' PropName=',PropertyName);
557   if GlobalDesignHook <> nil then
558   begin
559     if FOwnerPersistent <> nil then
560     begin
561       GlobalDesignHook.AddHandlerComponentRenamed(@ComponentRenamed);
562       GlobalDesignHook.AddHandlerPersistentDeleting(@PersistentDeleting);
563       GlobalDesignHook.AddHandlerRefreshPropertyValues(@RefreshPropertyValues);
564     end
565     else
566     begin
567       GlobalDesignHook.RemoveAllHandlersForObject(Self);
568     end;
569   end;
570 
571   FillSynObjectPartsListBox;
572   UpdateCaption;
573 end;
574 
575 procedure TSynObjectPartListPropertyEditorForm.Modified;
576 begin
577   GlobalDesignHook.Modified(Self);
578   //SelectInObjectInspector(False);
579 end;
580 
581 { TSynPropertyEditObjectList }
582 
ReadElementCountnull583 function TSynPropertyEditObjectList.ReadElementCount: integer;
584 var
585   SynObjectList: TObject;
586 begin
587   SynObjectList := GetObjectValue;
588   if SynObjectList is TSynObjectList then
589     Result := TSynObjectList(SynObjectList).Count
590   else
591     Result:=0;
592 end;
593 
TSynPropertyEditObjectList.ReadElementnull594 function TSynPropertyEditObjectList.ReadElement(Index: integer): TPersistent;
595 var
596   SynObjectList: TSynObjectList;
597 begin
598   SynObjectList := TSynObjectList(GetObjectValue);
599   Result := SynObjectList.BaseItems[Index];
600 end;
601 
GetAttributesnull602 function TSynPropertyEditObjectList.GetAttributes: TPropertyAttributes;
603 begin
604   Result := [paDialog, paReadOnly];
605 end;
606 
607 procedure TSynPropertyEditObjectList.Edit;
608 var
609   TheSynObjectList: TSynObjectList;
610 begin
611   TheSynObjectList := TSynObjectList(GetObjectValue);
612   if TheSynObjectList = nil then
613     raise Exception.Create('ObjectPartList=nil');
614   ShowClassListEditor(TheSynObjectList, GetComponent(0), GetName);
615 end;
616 
TSynPropertyEditObjectList.ShowClassListEditornull617 class function TSynPropertyEditObjectList.ShowClassListEditor(AClassList: TSynObjectList;
618   OwnerPersistent: TPersistent; const PropName: String): TCustomForm;
619 begin
620   if SynObjectPartListForm = nil then
621     SynObjectPartListForm := TSynObjectPartListPropertyEditorForm.Create(Application);
622   SynObjectPartListForm.SetSynObjectPartList(AClassList, ClassList, OwnerPersistent, PropName);
623   SynObjectPartListForm.EnsureVisible;
624   Result := SynObjectPartListForm;
625 end;
626 
627 { TSynPropertyEditGutterPartList }
628 
TSynPropertyEditGutterPartList.ClassListnull629 class function TSynPropertyEditGutterPartList.ClassList: TStringList;
630 begin
631   Result := KnownSynGutterPartClasses;
632 end;
633 
634 initialization
635   if KnownSynGutterPartClasses = nil then
636     KnownSynGutterPartClasses := TStringList.Create;
637 
638 finalization
639   FreeAndNil(KnownSynGutterPartClasses);
640 
641 end.
642 
643