source: trunk/Packages/Common/ItemList.pas

Last change on this file was 219, checked in by chronos, 5 days ago
  • Modified: Updated Common package.
  • Modified: Remove U prefix from unit names.
  • Modified: Use Gneeric.Collections instead of fgl.
  • Modified: Do not use global form variables.
File size: 23.2 KB
Line 
1unit ItemList;
2
3interface
4
5uses
6 Classes, SysUtils, Generics.Collections, DOM, XML, Common, Graphics, Math;
7
8type
9 TUndefinedEnum = (eeNone);
10
11 TDataType = (dtNone, dtString, dtBoolean, dtInteger, dtFloat, dtColor,
12 dtTime, dtDate, dtDateTime, dtEnumeration, dtReference);
13
14 { TItemField }
15
16 TItemField = class
17 SysName: string;
18 Name: string;
19 Index: Integer;
20 DataType: TDataType;
21 Position: TPoint;
22 Size: TPoint;
23 EnumStates: TStringList;
24 VisibleIfIndex: Integer;
25 constructor Create;
26 destructor Destroy; override;
27 procedure Assign(Source: TItemField);
28 end;
29
30 { TItemFields }
31
32 TItemFields = class(TObjectList<TItemField>)
33 function AddField(Index: Integer; SysName, Name: string; DataType: TDataType): TItemField;
34 function SearchByIndex(Index: Integer): TItemField;
35 end;
36
37 TBaseItemList = class;
38
39 { TItem }
40
41 TItem = class
42 private
43 procedure AssignValue(Source: TItem; Field: TItemField);
44 function CompareValue(Item: TItem; Field: TItemField): Boolean;
45 procedure LoadValueFromNode(Node: TDOMNode; Field: TItemField); virtual;
46 procedure SaveValueToNode(Node: TDOMNode; Field: TItemField); virtual;
47 public
48 Id: Integer;
49 Name: string;
50 class function GetFields: TItemFields; virtual;
51 function GetField(Index: Integer): TItemField;
52 procedure GetValue(Index: Integer; out Value); virtual;
53 function GetValueInteger(Index: Integer): Integer;
54 function GetValueString(Index: Integer): string;
55 function GetValueColor(Index: Integer): TColor;
56 function GetValueBoolean(Index: Integer): Boolean;
57 function GetValueEnumeration(Index: Integer): TUndefinedEnum;
58 function GetValueReference(Index: Integer): TItem;
59 function GetValueAsText(Index: Integer): string;
60 procedure SetValue(Index: Integer; var Value); virtual;
61 procedure SetValueInteger(Index: Integer; Value: Integer);
62 procedure SetValueString(Index: Integer; Value: string);
63 procedure SetValueColor(Index: Integer; Value: TColor);
64 procedure SetValueBoolean(Index: Integer; Value: Boolean);
65 procedure SetValueEnumeration(Index: Integer; Value: TUndefinedEnum);
66 procedure SetValueReference(Index: Integer; Value: TItem);
67 procedure Assign(Source: TItem); virtual;
68 function Compare(Item: TItem): Boolean; virtual;
69 function ToString: string; override;
70 procedure LoadFromNode(Node: TDOMNode); virtual;
71 procedure SaveToNode(Node: TDOMNode); virtual;
72 class function GetClassSysName: string; virtual;
73 class function GetClassName: string; virtual;
74 function GetReferenceList(Index: Integer): TBaseItemList; virtual;
75 constructor Create; virtual;
76 end;
77
78 TItemClass = class of TItem;
79
80 { TBaseItemList }
81
82 TBaseItemList = class
83 public
84 type
85 TAddEvent = function(constref AValue: TItem): SizeInt of object;
86 TGetCountEvent = function: SizeInt of object;
87 TSetItemEvent = procedure(Index: SizeInt; AValue: TItem) of object;
88 TGetNameEvent = procedure(out Name: string) of object;
89 TGetItemEvent = function(Index: SizeInt): TItem of object;
90 TGetItemFieldsEvent = function: TItemFields of object;
91 TRemoveEvent = function(constref AValue: TItem): SizeInt of object;
92 TGetNextAvailableNameEvent = procedure(Name: string; out NewName: string) of object;
93 TCreateItemEvent = function(Name: string = ''): TItem of object;
94 TFindByIdEvent = function(Id: Integer): TItem of object;
95 private
96 FOnAdd: TAddEvent;
97 FOnCreateItem: TCreateItemEvent;
98 FOnFindById: TFindByIdEvent;
99 FOnGetCount: TGetCountEvent;
100 FOnGetItem: TGetItemEvent;
101 FOnGetItemFields: TGetItemFieldsEvent;
102 FOnGetName: TGetNameEvent;
103 FOnGetNextAvailableName: TGetNextAvailableNameEvent;
104 FOnRemove: TRemoveEvent;
105 FOnSetItem: TSetItemEvent;
106 procedure SetItem(Index: SizeInt; AValue: TItem);
107 function GetItem(Index: SizeInt): TItem;
108 public
109 function GetName: string;
110 function GetCount: SizeInt;
111 function Remove(constref AValue: TItem): SizeInt;
112 function Add(constref AValue: TItem): SizeInt;
113 function CreateItem(Name: string = ''): TItem;
114 function GetNextAvailableName(Name: string): string;
115 function GetItemFields: TItemFields;
116 function FindById(Id: Integer): TItem;
117 property Count: SizeInt read GetCount;
118 property Items[Index: SizeInt]: TItem read GetItem write SetItem; default;
119 property OnAdd: TAddEvent read FOnAdd write FOnAdd;
120 property OnGetCount: TGetCountEvent read FOnGetCount write FOnGetCount;
121 property OnSetItem: TSetItemEvent read FOnSetItem write FOnSetItem;
122 property OnGetItem: TGetItemEvent read FOnGetItem write FOnGetItem;
123 property OnGetName: TGetNameEvent read FOnGetName write FOnGetName;
124 property OnRemove: TRemoveEvent read FOnRemove write FOnRemove;
125 property OnGetItemFields: TGetItemFieldsEvent read FOnGetItemFields write FOnGetItemFields;
126 property OnGetNextAvailableName: TGetNextAvailableNameEvent read
127 FOnGetNextAvailableName write FOnGetNextAvailableName;
128 property OnCreateItem: TCreateItemEvent read FOnCreateItem
129 write FOnCreateItem;
130 property OnFindById: TFindByIdEvent read FOnFindById
131 write FOnFindById;
132 end;
133
134 { TItemList }
135
136 TItemList<T: TItem> = class(TObjectList<T>)
137 private
138 FBaseItemList: TBaseItemList;
139 procedure RecalculateNewId(Reset: Boolean);
140 function BaseGetItem(Index: SizeInt): TItem;
141 procedure BaseSetItem(Index: SizeInt; AValue: TItem);
142 function BaseAdd(constref AValue: TItem): SizeInt;
143 function BaseGetCount: SizeInt;
144 procedure BaseGetName(out Name: string);
145 function BaseRemove(constref AValue: TItem): SizeInt;
146 function BaseGetItemFields: TItemFields;
147 function BaseCreateItem(Name: string = ''): TItem;
148 function BaseFindById(Id: Integer): TItem;
149 procedure BaseGetNextAvailableName(Name: string; out NewName: string);
150 public
151 NewId: Integer;
152 procedure RecalculateItemsId;
153 function CreateItem(Name: string = ''): T; virtual;
154 function IncrementName(Name: string): string;
155 function FindById(Id: Integer): T;
156 function FindByName(Name: string): T;
157 function GetNewId: Integer;
158 function ToString: string; override;
159 procedure Assign(Source: TItemList<T>); virtual;
160 function Compare(ItemList: TItemList<T>): Boolean; virtual;
161 function AddItem(Name: string = ''): T; virtual;
162 procedure LoadFromNode(Node: TDOMNode); virtual;
163 procedure SaveToNode(Node: TDOMNode); virtual;
164 constructor Create(FreeObjects: Boolean = True);
165 destructor Destroy; override;
166 property BaseItemList: TBaseItemList read FBaseItemList;
167 end;
168
169const
170 DataTypeStr: array[TDataType] of string = ('None', 'String', 'Boolean',
171 'Integer', 'Float', 'Color', 'Time', 'Date', 'DateTime', 'Enumeration',
172 'Reference');
173
174resourcestring
175 SUnsupportedDataType = 'Unsupported field value data type %s';
176 SUnsupportedValueIndex = 'Unsupported value index %d';
177
178
179implementation
180
181resourcestring
182 SYes = 'Yes';
183 SNo = 'No';
184 SItem = 'Item';
185 SName = 'Name';
186
187{ TItemField }
188
189constructor TItemField.Create;
190begin
191 EnumStates := TStringList.Create;
192end;
193
194destructor TItemField.Destroy;
195begin
196 FreeAndNil(EnumStates);
197 inherited;
198end;
199
200procedure TItemField.Assign(Source: TItemField);
201begin
202 SysName := Source.SysName;
203 Name := Source.Name;
204 Index := Source.Index;
205 DataType := Source.DataType;
206 Position := Source.Position;
207 Size := Source.Size;
208 EnumStates.Assign(Source.EnumStates);
209end;
210
211{ TItemList }
212
213procedure TItemList<T>.Assign(Source: TItemList<T>);
214var
215 I: Integer;
216begin
217 while Count > Source.Count do Delete(Count - 1);
218 while Count < Source.Count do AddItem('');
219 for I := 0 to Count - 1 do
220 Items[I].Assign(Source.Items[I]);
221end;
222
223function TItemList<T>.Compare(ItemList: TItemList<T>): Boolean;
224var
225 I: Integer;
226begin
227 Result := Count = ItemList.Count;
228 if not Result then Exit;
229 for I := 0 to Count - 1 do begin
230 Result := Result and TItem(Items[I]).Compare(ItemList.Items[I]);
231 if not Result then Break;
232 end;
233end;
234
235function TItemList<T>.AddItem(Name: string): T;
236begin
237 Result := CreateItem(Name);
238 Result.Id := GetNewId;
239 Add(Result);
240end;
241
242function TItemList<T>.CreateItem(Name: string): T;
243begin
244 Result := T.Create;
245 Result.Name := Name;
246end;
247
248function TItemList<T>.BaseCreateItem(Name: string): TItem;
249begin
250 Result := TItem(CreateItem(Name));
251end;
252
253function TItemList<T>.BaseFindById(Id: Integer): TItem;
254begin
255 Result := FindById(Id);
256end;
257
258procedure TItemList<T>.LoadFromNode(Node: TDOMNode);
259var
260 Node2: TDOMNode;
261 NewItem: T;
262begin
263 Count := 0;
264 Node2 := Node.FirstChild;
265 while Assigned(Node2) and (Node2.NodeName = UnicodeString(T.GetClassSysName)) do begin
266 NewItem := CreateItem;
267 NewItem.LoadFromNode(Node2);
268 Add(NewItem);
269 Node2 := Node2.NextSibling;
270 end;
271end;
272
273procedure TItemList<T>.SaveToNode(Node: TDOMNode);
274var
275 I: Integer;
276 NewNode2: TDOMNode;
277begin
278 for I := 0 to Count - 1 do
279 with TItem(Items[I]) do begin
280 NewNode2 := Node.OwnerDocument.CreateElement(UnicodeString(T.GetClassSysName));
281 Node.AppendChild(NewNode2);
282 SaveToNode(NewNode2);
283 end;
284end;
285
286constructor TItemList<T>.Create(FreeObjects: Boolean);
287begin
288 inherited;
289 FBaseItemList := TBaseItemList.Create;
290 FBaseItemList.OnAdd := BaseAdd;
291 FBaseItemList.OnGetCount := BaseGetCount;
292 FBaseItemList.OnSetItem := BaseSetItem;
293 FBaseItemList.OnGetItem := BaseGetItem;
294 FBaseItemList.OnRemove := BaseRemove;
295 FBaseItemList.OnGetItemFields := BaseGetItemFields;
296 FBaseItemList.OnCreateItem := BaseCreateItem;
297 FBaseItemList.OnGetNextAvailableName := BaseGetNextAvailableName;
298 FBaseItemList.OnGetName := BaseGetName;
299 FBaseItemList.OnFindById := BaseFindById;
300 NewId := 1;
301end;
302
303destructor TItemList<T>.Destroy;
304begin
305 FreeAndNil(FBaseItemList);
306 inherited;
307end;
308
309function TItemList<T>.BaseGetCount: SizeInt;
310begin
311 Result := Count;
312end;
313
314procedure TItemList<T>.BaseGetName(out Name: string);
315begin
316 Name := T.GetClassName;
317end;
318
319function TItemList<T>.BaseGetItemFields: TItemFields;
320begin
321 Result := T.GetFields;
322end;
323
324function TItemList<T>.BaseRemove(constref AValue: TItem): SizeInt;
325begin
326 Result := inherited Remove(T(AValue));
327end;
328
329function TItemList<T>.BaseAdd(constref AValue: TItem): SizeInt;
330begin
331 Result := inherited Add(T(AValue));
332 AValue.Id := GetNewId;
333end;
334
335procedure TItemList<T>.RecalculateNewId(Reset: Boolean);
336var
337 I: Integer;
338begin
339 NewId := 1;
340 for I := 0 to Count - 1 do
341 with TItem(Items[I]) do begin
342 NewId := Max(NewId, Id + 1);
343 end;
344end;
345
346procedure TItemList<T>.RecalculateItemsId;
347var
348 I: Integer;
349begin
350 for I := 0 to Count - 1 do
351 Items[I].Id := I + 1;
352 NewId := Count + 1;
353end;
354
355function TItemList<T>.BaseGetItem(Index: SizeInt): TItem;
356begin
357 Result := inherited GetItem(Index);
358end;
359
360procedure TItemList<T>.BaseSetItem(Index: SizeInt; AValue: TItem);
361begin
362 inherited SetItem(Index, T(AValue));
363end;
364
365function TItemList<T>.IncrementName(Name: string): string;
366var
367 I: Integer;
368 Num: Integer;
369begin
370 I := LastPos(' ', Name);
371 if I > 0 then begin
372 if TryStrToInt(Copy(Name, I + 1, Length(Name)), Num) then
373 Result := Trim(Copy(Name, 1, I - 1)) + ' ' + IntToStr(Num + 1)
374 else Result := Name + ' 2';
375 end else Result := Name + ' 2';
376end;
377
378procedure TItemList<T>.BaseGetNextAvailableName(Name: string; out
379 NewName: string);
380begin
381 NewName := Name + ' 1';
382 while Assigned(FindByName(NewName)) do
383 NewName := IncrementName(NewName);
384end;
385
386function TItemList<T>.FindById(Id: Integer): T;
387var
388 I: Integer;
389begin
390 I := 0;
391 while (I < Count) and (Items[I].Id <> Id) do Inc(I);
392 if I < Count then Result := Items[I]
393 else Result := nil;
394end;
395
396function TItemList<T>.FindByName(Name: string): T;
397var
398 I: Integer;
399begin
400 I := 0;
401 while (I < Count) and (Items[I].Name <> Name) do Inc(I);
402 if I < Count then Result := Items[I]
403 else Result := nil;
404end;
405
406function TItemList<T>.GetNewId: Integer;
407begin
408 Result := NewId;
409 Inc(NewId);
410end;
411
412function TItemList<T>.ToString: string;
413var
414 I: Integer;
415begin
416 Result := '';
417 for I := 0 to Count - 1 do
418 with TItem(Items[I]) do begin
419 Result := Result + ToString + LineEnding;
420 end;
421end;
422
423{ TItemFields }
424
425function TItemFields.AddField(Index: Integer; SysName, Name: string; DataType: TDataType): TItemField;
426begin
427 Result := TItemField.Create;
428 Result.Index := Index;
429 Result.Name := Name;
430 Result.SysName := SysName;
431 Result.DataType := DataType;
432 Add(Result);
433end;
434
435function TItemFields.SearchByIndex(Index: Integer): TItemField;
436var
437 I: Integer;
438begin
439 I := 0;
440 while (I < Count) and (Items[I].Index <> Index) do Inc(I);
441 if I < Count then Result := Items[I]
442 else Result := nil;
443end;
444
445{ TItem }
446
447procedure TItem.AssignValue(Source: TItem; Field: TItemField);
448begin
449 if Field.DataType = dtString then begin
450 SetValueString(Field.Index, Source.GetValueString(Field.Index));
451 end else
452 if Field.DataType = dtColor then begin
453 SetValueColor(Field.Index, Source.GetValueColor(Field.Index));
454 end else
455 if Field.DataType = dtInteger then begin
456 SetValueInteger(Field.Index, Source.GetValueInteger(Field.Index));
457 end else
458 if Field.DataType = dtBoolean then begin
459 SetValueBoolean(Field.Index, Source.GetValueBoolean(Field.Index));
460 end else
461 if Field.DataType = dtEnumeration then begin
462 SetValueEnumeration(Field.Index, Source.GetValueEnumeration(Field.Index));
463 end else
464 if Field.DataType = dtReference then begin
465 SetValueReference(Field.Index, Source.GetValueReference(Field.Index));
466 end else
467 raise Exception.Create(Format(SUnsupportedDataType, [DataTypeStr[Field.DataType]]));
468end;
469
470function TItem.CompareValue(Item: TItem; Field: TItemField): Boolean;
471begin
472 if Field.DataType = dtString then begin
473 Result := GetValueString(Field.Index) = Item.GetValueString(Field.Index);
474 end else
475 if Field.DataType = dtColor then begin
476 Result := GetValueColor(Field.Index) = Item.GetValueColor(Field.Index);
477 end else
478 if Field.DataType = dtInteger then begin
479 Result := GetValueInteger(Field.Index) = Item.GetValueInteger(Field.Index);
480 end else
481 if Field.DataType = dtBoolean then begin
482 Result := GetValueBoolean(Field.Index) = Item.GetValueBoolean(Field.Index);
483 end else
484 if Field.DataType = dtEnumeration then begin
485 Result := GetValueEnumeration(Field.Index) = Item.GetValueEnumeration(Field.Index);
486 end else
487 if Field.DataType = dtReference then begin
488 Result := GetValueReference(Field.Index) = Item.GetValueReference(Field.Index);
489 end else
490 raise Exception.Create(Format(SUnsupportedDataType, [DataTypeStr[Field.DataType]]));
491end;
492
493procedure TItem.LoadValueFromNode(Node: TDOMNode; Field: TItemField);
494var
495 ReadId: Integer;
496 ReferenceList: TBaseItemList;
497 RefItem: TItem;
498begin
499 if Field.DataType = dtString then begin
500 SetValueString(Field.Index, ReadString(Node, Field.SysName, ''));
501 end else
502 if Field.DataType = dtColor then begin
503 SetValueColor(Field.Index, ReadInteger(Node, Field.SysName, 0));
504 end else
505 if Field.DataType = dtInteger then begin
506 SetValueInteger(Field.Index, ReadInteger(Node, Field.SysName, 0));
507 end else
508 if Field.DataType = dtBoolean then begin
509 SetValueBoolean(Field.Index, ReadBoolean(Node, Field.SysName, False));
510 end else
511 if Field.DataType = dtEnumeration then begin
512 SetValueEnumeration(Field.Index, TUndefinedEnum(ReadInteger(Node, Field.SysName, 0)));
513 end else
514 if Field.DataType = dtReference then begin
515 ReadId := ReadInteger(Node, Field.SysName, 0);
516 ReferenceList := GetReferenceList(Field.Index);
517 if (ReadId > 0) and Assigned(ReferenceList) then begin
518 RefItem := ReferenceList.FindById(ReadId);
519 if Assigned(RefItem) then
520 SetValueReference(Field.Index, RefItem)
521 else raise Exception.Create('Reference id ' + IntToStr(ReadId) + ' not found.');
522 end;
523 end else
524 raise Exception.Create(Format(SUnsupportedDataType, [DataTypeStr[Field.DataType]]));
525end;
526
527procedure TItem.SaveValueToNode(Node: TDOMNode; Field: TItemField);
528var
529 Item: TItem;
530begin
531 if Field.DataType = dtString then begin
532 WriteString(Node, Field.SysName, GetValueString(Field.Index));
533 end else
534 if Field.DataType = dtColor then begin
535 WriteInteger(Node, Field.SysName, GetValueColor(Field.Index));
536 end else
537 if Field.DataType = dtInteger then begin
538 WriteInteger(Node, Field.SysName, GetValueInteger(Field.Index));
539 end else
540 if Field.DataType = dtBoolean then begin
541 WriteBoolean(Node, Field.SysName, GetValueBoolean(Field.Index));
542 end else
543 if Field.DataType = dtEnumeration then begin
544 WriteInteger(Node, Field.SysName, Integer(GetValueEnumeration(Field.Index)));
545 end else
546 if Field.DataType = dtReference then begin
547 Item := TItem(GetValueReference(Field.Index));
548 if Assigned(Item) then WriteInteger(Node, Field.SysName, Item.Id)
549 else WriteInteger(Node, Field.SysName, 0);
550 end else
551 raise Exception.Create(Format(SUnsupportedDataType, [DataTypeStr[Field.DataType]]));
552end;
553
554class function TItem.GetFields: TItemFields;
555begin
556 Result := TItemFields.Create;
557 Result.AddField(1, 'Name', SName, dtString);
558end;
559
560function TItem.GetField(Index: Integer): TItemField;
561var
562 Fields: TItemFields;
563begin
564 Result := TItemField.Create;
565 Fields := GetFields;
566 try
567 Result.Assign(Fields.SearchByIndex(Index));
568 finally
569 Fields.Free;
570 end;
571end;
572
573procedure TItem.GetValue(Index: Integer; out Value);
574begin
575 raise Exception.Create(Format(SUnsupportedValueIndex, [Index]));
576end;
577
578function TItem.GetValueString(Index: Integer): string;
579begin
580 GetValue(Index, Result);
581end;
582
583function TItem.GetValueInteger(Index: Integer): Integer;
584begin
585 GetValue(Index, Result);
586end;
587
588function TItem.GetValueColor(Index: Integer): TColor;
589begin
590 GetValue(Index, Result);
591end;
592
593function TItem.GetValueBoolean(Index: Integer): Boolean;
594begin
595 GetValue(Index, Result);
596end;
597
598function TItem.GetValueEnumeration(Index: Integer): TUndefinedEnum;
599begin
600 GetValue(Index, Result);
601end;
602
603function TItem.GetValueReference(Index: Integer): TItem;
604begin
605 GetValue(Index, Result);
606end;
607
608function TItem.GetValueAsText(Index: Integer): string;
609var
610 Field: TItemField;
611 Item: TItem;
612begin
613 Field := GetField(Index);
614 try
615 if Field.DataType = dtInteger then Result := IntToStr(GetValueInteger(Index))
616 else if Field.DataType = dtString then Result := GetValueString(Index)
617 else if Field.DataType = dtColor then Result := ''
618 else if Field.DataType = dtEnumeration then Result := Field.EnumStates[Integer(GetValueEnumeration(Index))]
619 else if Field.DataType = dtReference then begin
620 Item := TItem(GetValueReference(Index));
621 if Assigned(Item) then Result := Item.Name
622 else Result := '';
623 end else if Field.DataType = dtBoolean then begin
624 if GetValueBoolean(Index) then Result := SYes else Result := SNo;
625 end else
626 raise Exception.Create(Format(SUnsupportedDataType, [DataTypeStr[Field.DataType]]));
627 finally
628 Field.Free;
629 end;
630end;
631
632procedure TItem.SetValue(Index: Integer; var Value);
633begin
634 raise Exception.Create(Format(SUnsupportedValueIndex, [Index]));
635end;
636
637procedure TItem.SetValueInteger(Index: Integer; Value: Integer);
638begin
639 SetValue(Index, Value);
640end;
641
642procedure TItem.SetValueString(Index: Integer; Value: string);
643begin
644 SetValue(Index, Value);
645end;
646
647procedure TItem.SetValueColor(Index: Integer; Value: TColor);
648begin
649 SetValue(Index, Value);
650end;
651
652procedure TItem.SetValueBoolean(Index: Integer; Value: Boolean);
653begin
654 SetValue(Index, Value);
655end;
656
657procedure TItem.SetValueEnumeration(Index: Integer;
658 Value: TUndefinedEnum);
659begin
660 SetValue(Index, Value);
661end;
662
663procedure TItem.SetValueReference(Index: Integer; Value: TItem);
664begin
665 SetValue(Index, Value);
666end;
667
668procedure TItem.Assign(Source: TItem);
669var
670 I: Integer;
671 Fields: TItemFields;
672begin
673 Id := Source.Id;
674 if Source is ClassType then begin
675 Fields := GetFields;
676 try
677 for I := 0 to Fields.Count - 1 do
678 AssignValue(Source, Fields[I]);
679 finally
680 Fields.Free;
681 end;
682 end;
683end;
684
685function TItem.Compare(Item: TItem): Boolean;
686var
687 I: Integer;
688 Fields: TItemFields;
689begin
690 Result := True;
691 Result := Result and (Id = Item.Id);
692 if Item is ClassType then begin
693 Fields := GetFields;
694 try
695 for I := 0 to Fields.Count - 1 do begin
696 Result := Result and CompareValue(Item, Fields[I]);
697 if not Result then Break;
698 end;
699 finally
700 Fields.Free;
701 end;
702 end;
703end;
704
705function TItem.ToString: string;
706var
707 Fields: TItemFields;
708 I: Integer;
709begin
710 Result := 'Id: ' + IntToStr(Id) + LineEnding;
711 Fields := GetFields;
712 try
713 for I := 0 to Fields.Count - 1 do begin
714 Result := Result + Fields[I].SysName + ': ' + GetValueAsText(Fields[I].Index) + LineEnding;
715 end;
716 finally
717 Fields.Free;
718 end;
719end;
720
721procedure TItem.LoadFromNode(Node: TDOMNode);
722var
723 Fields: TItemFields;
724 I: Integer;
725begin
726 Id := ReadInteger(Node, 'Id', 0);
727 Fields := GetFields;
728 try
729 for I := 0 to Fields.Count - 1 do begin
730 LoadValueFromNode(Node, Fields[I]);
731 end;
732 finally
733 Fields.Free;
734 end;
735end;
736
737procedure TItem.SaveToNode(Node: TDOMNode);
738var
739 Fields: TItemFields;
740 I: Integer;
741begin
742 WriteInteger(Node, 'Id', Id);
743 Fields := GetFields;
744 try
745 for I := 0 to Fields.Count - 1 do begin
746 SaveValueToNode(Node, Fields[I]);
747 end;
748 finally
749 Fields.Free;
750 end;
751end;
752
753class function TItem.GetClassSysName: string;
754begin
755 Result := 'Item';
756end;
757
758class function TItem.GetClassName: string;
759begin
760 Result := SItem;
761end;
762
763function TItem.GetReferenceList(Index: Integer): TBaseItemList;
764begin
765 Result := nil;
766end;
767
768constructor TItem.Create;
769begin
770end;
771
772{ TBaseItemList }
773
774procedure TBaseItemList.SetItem(Index: SizeInt; AValue: TItem);
775begin
776 if Assigned(FOnSetItem) then FOnSetItem(Index, AValue)
777 else raise Exception.Create('Undefined SetItem handler');
778end;
779
780function TBaseItemList.GetName: string;
781var
782 Name: string;
783begin
784 if Assigned(FOnGetName) then begin
785 FOnGetName(Name);
786 Result := Name;
787 end else raise Exception.Create('Undefined GetName handler');
788end;
789
790function TBaseItemList.GetCount: SizeInt;
791begin
792 if Assigned(FOnGetCount) then Result := FOnGetCount
793 else raise Exception.Create('Undefined GetCount handler');
794end;
795
796function TBaseItemList.GetItem(Index: SizeInt): TItem;
797begin
798 if Assigned(FOnGetItem) then Result := FOnGetItem(Index)
799 else raise Exception.Create('Undefined GetItem handler');
800end;
801
802function TBaseItemList.Remove(constref AValue: TItem): SizeInt;
803begin
804 if Assigned(FOnRemove) then Result := FOnRemove(AValue)
805 else raise Exception.Create('Undefined Remove handler');
806end;
807
808function TBaseItemList.Add(constref AValue: TItem): SizeInt;
809begin
810 if Assigned(FOnAdd) then Result := FOnAdd(AValue)
811 else raise Exception.Create('Undefined Add handler');
812end;
813
814function TBaseItemList.CreateItem(Name: string): TItem;
815begin
816 if Assigned(FOnCreateItem) then Result := FOnCreateItem(Name)
817 else raise Exception.Create('Undefined CreateItem handler');
818end;
819
820function TBaseItemList.GetNextAvailableName(Name: string): string;
821var
822 NewName: string;
823begin
824 if Assigned(FOnGetNextAvailableName) then begin
825 FOnGetNextAvailableName(Name, NewName);
826 Result := NewName;
827 end else raise Exception.Create('Undefined GetNextAvailableName handler');
828end;
829
830function TBaseItemList.GetItemFields: TItemFields;
831begin
832 if Assigned(FOnGetItemFields) then Result := FOnGetItemFields
833 else raise Exception.Create('Undefined GetItemFields handler');
834end;
835
836function TBaseItemList.FindById(Id: Integer): TItem;
837begin
838 if Assigned(FOnFindById) then Result := FOnFindById(Id)
839 else raise Exception.Create('Undefined FindById handler');
840end;
841
842end.
843
Note: See TracBrowser for help on using the repository browser.