Browse Source

* finished observables

master
bergmann 7 years ago
parent
commit
c8ab34ffcc
10 changed files with 983 additions and 168 deletions
  1. +9
    -1
      tests/tests.lpi
  2. +2
    -1
      tests/tests.lpr
  3. +162
    -134
      tests/tests.lps
  4. +159
    -0
      tests/uutlObservableHashSetTests.pas
  5. +1
    -0
      tests/uutlObservableListTests.pas
  6. +163
    -0
      tests/uutlObservableMapTests.pas
  7. +11
    -6
      uutlEnumerator.pas
  8. +29
    -25
      uutlGenerics.pas
  9. +1
    -0
      uutlListBase.pas
  10. +446
    -1
      uutlObservable.pas

+ 9
- 1
tests/tests.lpi View File

@@ -37,7 +37,7 @@
<PackageName Value="FCL"/>
</Item3>
</RequiredPackages>
<Units Count="35">
<Units Count="37">
<Unit0>
<Filename Value="tests.lpr"/>
<IsPartOfProject Value="True"/>
@@ -178,6 +178,14 @@
<Filename Value="uutlObservableListTests.pas"/>
<IsPartOfProject Value="True"/>
</Unit34>
<Unit35>
<Filename Value="uutlObservableHashSetTests.pas"/>
<IsPartOfProject Value="True"/>
</Unit35>
<Unit36>
<Filename Value="uutlObservableMapTests.pas"/>
<IsPartOfProject Value="True"/>
</Unit36>
</Units>
</ProjectOptions>
<CompilerOptions>


+ 2
- 1
tests/tests.lpr View File

@@ -16,7 +16,8 @@ uses
// units unter test
uutlAlgorithm, uutlArrayContainer, uutlCommon, uutlComparer, uutlEnumerator,
uutlFilter, uutlGenerics, uutlInterfaces, uutlLinq, uutlListBase, uutlLogger,
uutlStreamHelper, uutlSyncObjs, uutlTypes, uutlXmlHelper, uutlObservable;
uutlStreamHelper, uutlSyncObjs, uutlTypes, uutlXmlHelper, uutlObservable, uutlObservableHashSetTests,
uutlObservableMapTests;

{$R *.res}



+ 162
- 134
tests/tests.lps View File

@@ -4,48 +4,47 @@
<PathDelim Value="\"/>
<Version Value="9"/>
<BuildModes Active="Default"/>
<Units Count="60">
<Units Count="62">
<Unit0>
<Filename Value="tests.lpr"/>
<IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="8"/>
<CursorPos X="87" Y="18"/>
<UsageCount Value="72"/>
<EditorIndex Value="12"/>
<CursorPos X="33" Y="13"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="..\uutlGenerics.pas"/>
<IsPartOfProject Value="True"/>
<TopLine Value="310"/>
<CursorPos X="65" Y="333"/>
<UsageCount Value="72"/>
<TopLine Value="1297"/>
<CursorPos Y="1322"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\uutlArrayContainer.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="6"/>
<EditorIndex Value="10"/>
<CursorPos X="11" Y="13"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\uutlCommon.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="9"/>
<EditorIndex Value="15"/>
<TopLine Value="44"/>
<CursorPos X="3" Y="59"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit3>
<Unit4>
<Filename Value="..\uutlListBase.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="1"/>
<TopLine Value="41"/>
<CursorPos X="14" Y="54"/>
<UsageCount Value="72"/>
<EditorIndex Value="2"/>
<TopLine Value="155"/>
<CursorPos Y="170"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
@@ -55,24 +54,24 @@
<WindowIndex Value="1"/>
<TopLine Value="357"/>
<CursorPos X="7" Y="376"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
</Unit5>
<Unit6>
<Filename Value="uutlQueueTests.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="7"/>
<EditorIndex Value="11"/>
<TopLine Value="250"/>
<CursorPos X="49" Y="260"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit6>
<Unit7>
<Filename Value="uutlStackTests.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="2"/>
<EditorIndex Value="6"/>
<TopLine Value="246"/>
<CursorPos X="24" Y="263"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit7>
<Unit8>
@@ -80,29 +79,30 @@
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<CursorPos X="3" Y="12"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
</Unit8>
<Unit9>
<Filename Value="..\uutlComparer.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<CursorPos X="90" Y="6"/>
<UsageCount Value="62"/>
<UsageCount Value="65"/>
</Unit9>
<Unit10>
<Filename Value="..\uutlAlgorithm.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="115"/>
<CursorPos Y="132"/>
<UsageCount Value="72"/>
<EditorIndex Value="5"/>
<TopLine Value="138"/>
<CursorPos Y="153"/>
<UsageCount Value="75"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
<Filename Value="uutlHashSetTests.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<CursorPos X="32" Y="13"/>
<UsageCount Value="72"/>
<UsageCount Value="75"/>
</Unit11>
<Unit12>
<Filename Value="uutlAlgorithmTests.pas"/>
@@ -110,7 +110,7 @@
<EditorIndex Value="-1"/>
<TopLine Value="72"/>
<CursorPos X="43" Y="87"/>
<UsageCount Value="71"/>
<UsageCount Value="74"/>
</Unit12>
<Unit13>
<Filename Value="uutlMapTests.pas"/>
@@ -118,24 +118,24 @@
<EditorIndex Value="-1"/>
<TopLine Value="206"/>
<CursorPos X="66" Y="221"/>
<UsageCount Value="70"/>
<UsageCount Value="73"/>
</Unit13>
<Unit14>
<Filename Value="..\uutlEnumerator.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="3"/>
<TopLine Value="118"/>
<CursorPos X="18" Y="127"/>
<UsageCount Value="69"/>
<EditorIndex Value="7"/>
<TopLine Value="469"/>
<CursorPos Y="489"/>
<UsageCount Value="72"/>
<Loaded Value="True"/>
</Unit14>
<Unit15>
<Filename Value="uutlEnumeratorTests.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="4"/>
<EditorIndex Value="8"/>
<TopLine Value="49"/>
<CursorPos X="8" Y="66"/>
<UsageCount Value="69"/>
<UsageCount Value="72"/>
<Loaded Value="True"/>
</Unit15>
<Unit16>
@@ -144,26 +144,25 @@
<EditorIndex Value="-1"/>
<TopLine Value="17"/>
<CursorPos X="13" Y="159"/>
<UsageCount Value="65"/>
<UsageCount Value="68"/>
</Unit16>
<Unit17>
<Filename Value="..\uutlInterfaces.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="10"/>
<EditorIndex Value="16"/>
<TopLine Value="22"/>
<CursorPos X="11" Y="37"/>
<UsageCount Value="65"/>
<UsageCount Value="68"/>
<Loaded Value="True"/>
</Unit17>
<Unit18>
<Filename Value="..\uutlLinq.pas"/>
<IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<WindowIndex Value="-1"/>
<TopLine Value="31"/>
<CursorPos X="3" Y="52"/>
<UsageCount Value="56"/>
<UsageCount Value="59"/>
</Unit18>
<Unit19>
<Filename Value="uutlLinqTests.pas"/>
@@ -171,13 +170,13 @@
<EditorIndex Value="-1"/>
<TopLine Value="252"/>
<CursorPos X="30" Y="264"/>
<UsageCount Value="56"/>
<UsageCount Value="59"/>
</Unit19>
<Unit20>
<Filename Value="..\uutlTypes.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="11"/>
<UsageCount Value="56"/>
<EditorIndex Value="17"/>
<UsageCount Value="59"/>
<Loaded Value="True"/>
</Unit20>
<Unit21>
@@ -186,7 +185,7 @@
<EditorIndex Value="-1"/>
<TopLine Value="241"/>
<CursorPos X="20" Y="263"/>
<UsageCount Value="50"/>
<UsageCount Value="53"/>
</Unit21>
<Unit22>
<Filename Value="..\uutlLogger.pas"/>
@@ -194,7 +193,7 @@
<EditorIndex Value="-1"/>
<TopLine Value="419"/>
<CursorPos X="55" Y="434"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit22>
<Unit23>
<Filename Value="..\uutlXmlHelper.pas"/>
@@ -202,7 +201,7 @@
<EditorIndex Value="-1"/>
<TopLine Value="188"/>
<CursorPos X="26" Y="203"/>
<UsageCount Value="49"/>
<UsageCount Value="52"/>
</Unit23>
<Unit24>
<Filename Value="..\uutlStreamHelper.pas"/>
@@ -210,7 +209,7 @@
<EditorIndex Value="-1"/>
<TopLine Value="216"/>
<CursorPos X="10" Y="241"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit24>
<Unit25>
<Filename Value="..\uutlCompression.pas"/>
@@ -219,7 +218,7 @@
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit25>
<Unit26>
<Filename Value="..\uutlEmbeddedProfiler.pas"/>
@@ -228,7 +227,7 @@
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit26>
<Unit27>
<Filename Value="..\uutlKeyCodes.pas"/>
@@ -237,7 +236,7 @@
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit27>
<Unit28>
<Filename Value="..\uutlMCF.pas"/>
@@ -246,7 +245,7 @@
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit28>
<Unit29>
<Filename Value="..\uutlSScanf.pas"/>
@@ -255,7 +254,7 @@
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit29>
<Unit30>
<Filename Value="..\uutlThreads.pas"/>
@@ -264,14 +263,15 @@
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="48"/>
<UsageCount Value="51"/>
</Unit30>
<Unit31>
<Filename Value="..\uutlEvent.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<CursorPos X="54" Y="9"/>
<UsageCount Value="47"/>
<EditorIndex Value="14"/>
<CursorPos X="11" Y="35"/>
<UsageCount Value="50"/>
<Loaded Value="True"/>
</Unit31>
<Unit32>
<Filename Value="..\uutlEventManager.pas"/>
@@ -279,23 +279,25 @@
<EditorIndex Value="-1"/>
<TopLine Value="246"/>
<CursorPos X="39" Y="264"/>
<UsageCount Value="47"/>
<UsageCount Value="50"/>
</Unit32>
<Unit33>
<Filename Value="..\uutlObservable.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="134"/>
<CursorPos X="13" Y="147"/>
<UsageCount Value="47"/>
<EditorIndex Value="1"/>
<TopLine Value="556"/>
<CursorPos X="45" Y="572"/>
<UsageCount Value="50"/>
<Loaded Value="True"/>
</Unit33>
<Unit34>
<Filename Value="uutlObservableListTests.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="24"/>
<CursorPos X="76" Y="130"/>
<UsageCount Value="39"/>
<WindowIndex Value="1"/>
<TopLine Value="49"/>
<CursorPos Y="65"/>
<UsageCount Value="42"/>
</Unit34>
<Unit35>
<Filename Value="..\uutlExceptions.pas"/>
@@ -350,10 +352,10 @@
</Unit41>
<Unit42>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\objpas\objpas.pp"/>
<EditorIndex Value="5"/>
<EditorIndex Value="9"/>
<TopLine Value="64"/>
<CursorPos X="19" Y="79"/>
<UsageCount Value="12"/>
<UsageCount Value="13"/>
<Loaded Value="True"/>
</Unit42>
<Unit43>
@@ -374,16 +376,18 @@
</Unit44>
<Unit45>
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\FPCUnitCompatibleInterface.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="64"/>
<EditorIndex Value="4"/>
<TopLine Value="90"/>
<CursorPos Y="105"/>
<UsageCount Value="14"/>
<Loaded Value="True"/>
</Unit45>
<Unit46>
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\TestFramework.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="2963"/>
<CursorPos Y="2979"/>
<WindowIndex Value="1"/>
<TopLine Value="2692"/>
<CursorPos Y="2705"/>
<UsageCount Value="10"/>
</Unit46>
<Unit47>
@@ -464,10 +468,11 @@
</Unit57>
<Unit58>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\inc\objpash.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="181"/>
<CursorPos X="10" Y="196"/>
<UsageCount Value="12"/>
<EditorIndex Value="13"/>
<TopLine Value="190"/>
<CursorPos X="23" Y="205"/>
<UsageCount Value="13"/>
<Loaded Value="True"/>
</Unit58>
<Unit59>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\objpas\sysutils\osutilsh.inc"/>
@@ -476,6 +481,26 @@
<CursorPos X="3" Y="62"/>
<UsageCount Value="12"/>
</Unit59>
<Unit60>
<Filename Value="uutlObservableHashSetTests.pas"/>
<IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="129"/>
<CursorPos Y="146"/>
<UsageCount Value="21"/>
</Unit60>
<Unit61>
<Filename Value="uutlObservableMapTests.pas"/>
<IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="3"/>
<TopLine Value="113"/>
<CursorPos X="57" Y="130"/>
<UsageCount Value="21"/>
<Loaded Value="True"/>
</Unit61>
</Units>
<OtherDefines Count="4">
<Define0 Value="UTL_ADVANCED_ENUMERATORS"/>
@@ -485,132 +510,135 @@
</OtherDefines>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1120" Column="38" TopLine="1109"/>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="487" TopLine="469"/>
</Position1>
<Position2>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="315" Column="46" TopLine="299"/>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="488" TopLine="469"/>
</Position2>
<Position3>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="491" TopLine="483"/>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="489" TopLine="469"/>
</Position3>
<Position4>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1278" Column="26" TopLine="1265"/>
<Filename Value="..\uutlObservable.pas"/>
<Caret Line="639" TopLine="618"/>
</Position4>
<Position5>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="333" Column="23" TopLine="310"/>
<Filename Value="..\uutlObservable.pas"/>
<Caret Line="559" TopLine="544"/>
</Position5>
<Position6>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="411" Column="22" TopLine="398"/>
<Caret Line="1012" TopLine="994"/>
</Position6>
<Position7>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1333" Column="64" TopLine="1330"/>
<Caret Line="1361" TopLine="1346"/>
</Position7>
<Position8>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1339" Column="3" TopLine="1336"/>
<Caret Line="1351" TopLine="1345"/>
</Position8>
<Position9>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1578" TopLine="1549"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="70" TopLine="55"/>
</Position9>
<Position10>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="328" Column="33" TopLine="306"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="72" TopLine="55"/>
</Position10>
<Position11>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1115" Column="36" TopLine="1100"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="73" TopLine="55"/>
</Position11>
<Position12>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="333" Column="65" TopLine="310"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="74" TopLine="55"/>
</Position12>
<Position13>
<Filename Value="..\uutlInterfaces.pas"/>
<Caret Line="12" Column="41"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="68" TopLine="55"/>
</Position13>
<Position14>
<Filename Value="..\uutlInterfaces.pas"/>
<Caret Line="64" Column="124" TopLine="34"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="107" Column="16" TopLine="113"/>
</Position14>
<Position15>
<Filename Value="..\uutlInterfaces.pas"/>
<Caret Line="38" Column="5" TopLine="32"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="123" TopLine="113"/>
</Position15>
<Position16>
<Filename Value="..\uutlInterfaces.pas"/>
<Caret Line="11" Column="10"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1312" TopLine="1297"/>
</Position16>
<Position17>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="10" Column="14"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1314" TopLine="1297"/>
</Position17>
<Position18>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="485" Column="3" TopLine="500"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1315" TopLine="1297"/>
</Position18>
<Position19>
<Filename Value="uutlEnumeratorTests.pas"/>
<Caret Line="16" Column="45"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1316" TopLine="1297"/>
</Position19>
<Position20>
<Filename Value="uutlEnumeratorTests.pas"/>
<Caret Line="80" Column="32" TopLine="65"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1317" TopLine="1297"/>
</Position20>
<Position21>
<Filename Value="uutlEnumeratorTests.pas"/>
<Caret TopLine="63"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="128" Column="36" TopLine="113"/>
</Position21>
<Position22>
<Filename Value="uutlEnumeratorTests.pas"/>
<Caret Line="80" Column="32" TopLine="65"/>
<Filename Value="uutlObservableMapTests.pas"/>
<Caret Line="123" TopLine="113"/>
</Position22>
<Position23>
<Filename Value="uutlEnumeratorTests.pas"/>
<Caret Line="67" Column="3" TopLine="52"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1312" TopLine="1297"/>
</Position23>
<Position24>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="107" Column="11" TopLine="92"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1314" TopLine="1297"/>
</Position24>
<Position25>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="64" Column="11" TopLine="49"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1315" TopLine="1297"/>
</Position25>
<Position26>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="21" Column="35" TopLine="3"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1316" TopLine="1297"/>
</Position26>
<Position27>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="13" Column="3" TopLine="4"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1317" TopLine="1297"/>
</Position27>
<Position28>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="162" TopLine="146"/>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1322" TopLine="1297"/>
</Position28>
<Position29>
<Filename Value="uutlEnumeratorTests.pas"/>
<Caret Line="66" Column="8" TopLine="49"/>
<Filename Value="..\uutlObservable.pas"/>
<Caret Line="573" TopLine="556"/>
</Position29>
<Position30>
<Filename Value="..\uutlEnumerator.pas"/>
<Caret Line="127" Column="18" TopLine="118"/>
<Filename Value="..\uutlObservable.pas"/>
<Caret Line="572" Column="45" TopLine="556"/>
</Position30>
</JumpHistory>
</ProjectSession>
<Debugging>
<Watches Count="1">
<Watches Count="2">
<Item1>
<Expression Value="fCount"/>
</Item1>
<Item2>
<Expression Value="fLast"/>
</Item2>
</Watches>
</Debugging>
</CONFIG>

+ 159
- 0
tests/uutlObservableHashSetTests.pas View File

@@ -0,0 +1,159 @@
unit uutlObservableHashSetTests;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, TestFramework,
uutlGenerics, uutlObservable, uutlEvent;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TObservableIntSet = specialize TutlObservableHashSet<Integer>;
TEventArgList = specialize TutlList<IutlEventArgs>;
TutlObservableHashSetTests = class(TTestCase)
private
fCaptureEvents: Boolean;
fSet: TObservableIntSet;
fEventArgs: TEventArgList;

procedure EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs);

public
procedure SetUp; override;
procedure TearDown; override;

published
procedure Add;
procedure Remove;
procedure ReplaceItem;
procedure Clear;
end;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableHashSetTests////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs);
begin
if fCaptureEvents then
fEventArgs.Add(aEventArgs);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.SetUp;
begin
inherited SetUp;
fCaptureEvents := false;
fEventArgs := TEventArgList.Create(true);
fSet := TObservableIntSet.Create(true);
fSet.RegisterEventHandler(@EventHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.TearDown;
begin
FreeAndNil(fSet);
FreeAndNil(fEventArgs);
inherited TearDown;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.Add;
var
ea: TObservableIntSet.TItemEventArgs;
begin
fCaptureEvents := true;
fSet.Add(5);
fSet.Add(7);
fSet.Add(5);

AssertEquals(2, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TObservableIntSet.TItemEventArgs, ea));
AssertTrue (oetAdd = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(5, ea.Item);
AssertTrue (Supports(fEventArgs[1], TObservableIntSet.TItemEventArgs, ea));
AssertTrue (oetAdd = ea.EventType);
AssertEquals(1, ea.Index);
AssertEquals(7, ea.Item);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.Remove;
var
ea: TObservableIntSet.TItemEventArgs;
begin
fSet.Add(5);
fSet.Add(10);
fSet.Add(15);

fCaptureEvents := true;

fSet.Remove(5);
fSet.Remove(10);
fSet.Remove(5);

AssertEquals(2, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TObservableIntSet.TItemEventArgs, ea));
AssertTrue (oetRemove = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(5, ea.Item);
AssertTrue (Supports(fEventArgs[1], TObservableIntSet.TItemEventArgs, ea));
AssertTrue (oetRemove = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(10, ea.Item);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.ReplaceItem;
var
ea: TObservableIntSet.TReplaceEventArgs;
begin
fSet.Add(5);
fSet.Add(10);
fSet.Add(15);

fCaptureEvents := true;

fSet[0] := 5;
fSet[1] := 10;

AssertEquals(2, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TObservableIntSet.TReplaceEventArgs, ea));
AssertTrue (oetReplace = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(5, ea.OldItem);
AssertEquals(5, ea.NewItem);
AssertTrue (Supports(fEventArgs[1], TObservableIntSet.TReplaceEventArgs, ea));
AssertTrue (oetReplace = ea.EventType);
AssertEquals(1, ea.Index);
AssertEquals(10, ea.OldItem);
AssertEquals(10, ea.NewItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableHashSetTests.Clear;
var
ea: TutlObservableEventArgs;
begin
fSet.Add(5);
fSet.Add(10);
fSet.Add(15);

fCaptureEvents := true;

fSet.Clear;

AssertEquals(1, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TutlObservableEventArgs, ea));
AssertTrue (oetClear = ea.EventType);
end;

initialization
RegisterTest(TutlObservableHashSetTests.Suite);

end.


+ 1
- 0
tests/uutlObservableListTests.pas View File

@@ -136,5 +136,6 @@ end;

initialization
RegisterTest(TutlObservableListTests.Suite);

end.


+ 163
- 0
tests/uutlObservableMapTests.pas View File

@@ -0,0 +1,163 @@
unit uutlObservableMapTests;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, TestFramework,
uutlGenerics, uutlObservable, uutlEvent;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TObservableIntStringMap = specialize TutlObservableMap<Integer, String>;
TEventArgList = specialize TutlList<IutlEventArgs>;
TutlObservableMapTests = class(TTestCase)
private
fCaptureEvents: Boolean;
fMap: TObservableIntStringMap;
fEventArgs: TEventArgList;

procedure EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs);

public
procedure SetUp; override;
procedure TearDown; override;

published
procedure Add;
procedure Delete;
procedure ReplaceItem;
procedure Clear;
end;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableMapTests////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs);
begin
if fCaptureEvents then
fEventArgs.Add(aEventArgs);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.SetUp;
begin
inherited SetUp;
fCaptureEvents := false;
fEventArgs := TEventArgList.Create(true);
fMap := TObservableIntStringMap.Create(true, true);
fMap.RegisterEventHandler(@EventHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.TearDown;
begin
FreeAndNil(fMap);
FreeAndNil(fEventArgs);
inherited TearDown;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.Add;
var
ea: TObservableIntStringMap.TItemEventArgs;
begin
fCaptureEvents := true;
fMap.Add(5, 'Test1');
fMap.Add(7, 'Test2');

AssertEquals(2, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TObservableIntStringMap.TItemEventArgs, ea));
AssertTrue (oetAdd = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(5, ea.Key);
AssertEquals('Test1', ea.Item);
AssertTrue (Supports(fEventArgs[1], TObservableIntStringMap.TItemEventArgs, ea));
AssertTrue (oetAdd = ea.EventType);
AssertEquals(1, ea.Index);
AssertEquals(7, ea.Key);
AssertEquals('Test2', ea.Item);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.Delete;
var
ea: TObservableIntStringMap.TItemEventArgs;
begin
fMap.Add(5, 'Test1');
fMap.Add(10, 'Test2');
fMap.Add(15, 'Test3');

fCaptureEvents := true;

fMap.Delete(5);
fMap.Delete(10);

AssertEquals(2, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TObservableIntStringMap.TItemEventArgs, ea));
AssertTrue (oetRemove = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(5, ea.Key);
AssertEquals('Test1', ea.Item);
AssertTrue (Supports(fEventArgs[1], TObservableIntStringMap.TItemEventArgs, ea));
AssertTrue (oetRemove = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(10, ea.Key);
AssertEquals('Test2', ea.Item);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.ReplaceItem;
var
ea: TObservableIntStringMap.TReplaceEventArgs;
begin
fMap.Add(5, 'Test1');
fMap.Add(10, 'Test2');
fMap.Add(15, 'Test3');

fCaptureEvents := true;

fMap[ 5] := 'Replace1';
fMap[10] := 'Replace2';

AssertEquals(2, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TObservableIntStringMap.TReplaceEventArgs, ea));
AssertTrue (oetReplace = ea.EventType);
AssertEquals(0, ea.Index);
AssertEquals(5, ea.Key);
AssertEquals('Test1', ea.OldItem);
AssertEquals('Replace1', ea.NewItem);
AssertTrue (Supports(fEventArgs[1], TObservableIntStringMap.TReplaceEventArgs, ea));
AssertTrue (oetReplace = ea.EventType);
AssertEquals(1, ea.Index);
AssertEquals(10, ea.Key);
AssertEquals('Test2', ea.OldItem);
AssertEquals('Replace2', ea.NewItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableMapTests.Clear;
var
ea: TObservableIntStringMap.TReplaceEventArgs;
begin
fMap.Add(5, 'Test1');
fMap.Add(10, 'Test2');
fMap.Add(15, 'Test3');

fCaptureEvents := true;

fMap.Clear;

AssertEquals(1, fEventArgs.Count);
AssertTrue (Supports(fEventArgs[0], TutlObservableEventArgs, ea));
AssertTrue (oetClear = ea.EventType);
end;

initialization
RegisterTest(TutlObservableMapTests.Suite);

end.


+ 11
- 6
uutlEnumerator.pas View File

@@ -57,6 +57,9 @@ type
function Without (aEnumerator: IEnumerator; aComparer: IComparer): IEnumerator; virtual;
{$ENDIF}
{$ENDIF}

public
constructor Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -459,6 +462,13 @@ end;
{$ENDIF}
{$ENDIF}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlEnumerator.Create;
begin
inherited Create;
Reset;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMemoryEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -529,16 +539,11 @@ constructor TutlMemoryEnumerator.Create(
const aFirst: Integer;
const aLast: Integer);
begin
inherited Create;

fMemory := aMemory;
fReverse := aReverse;
fFirst := aFirst;
fLast := aLast;

if fReverse
then fCurrent := fLast + 1
else fCurrent := fFirst - 1;
inherited Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 29
- 25
uutlGenerics.pas View File

@@ -401,12 +401,14 @@ type
function GetCanShrink: Boolean; inline;
function GetCanExpand: Boolean; inline;

procedure SetValue (aKey: TKey; const aValue: TValue); inline;
procedure SetValueAt (const aIndex: Integer; const aValue: TValue); inline;
procedure SetCapacity (const aValue: Integer); inline;
procedure SetCanShrink (const aValue: Boolean); inline;
procedure SetCanExpand (const aValue: Boolean); inline;

protected
procedure SetValue (aKey: TKey; const aValue: TValue); virtual;
procedure SetValueAt (const aIndex: Integer; const aValue: TValue); virtual;

public { IEnumerable }
function GetEnumerator: IValueEnumerator;

@@ -514,8 +516,8 @@ constructor TutlQueue.TEnumerator.Create(const aOwner: TutlQueue);
begin
if not Assigned(aOwner) then
raise EArgumentNilException.Create('aOwner');
inherited Create;
fOwner := aOwner;
inherited Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -592,12 +594,14 @@ end;
function TutlQueue.GetEnumerator: IEnumerator;
begin
result := TEnumerator.Create(self);
result.Reset;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlQueue.GetUtlEnumerator: IutlEnumerator;
begin
result := TEnumerator.Create(self);
result.Reset;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -693,8 +697,8 @@ constructor TutlStack.TEnumerator.Create(const aOwner: TutlStack);
begin
if not Assigned(aOwner) then
raise EArgumentNilException.Create('aOwner');
inherited Create(nil, 0);
fOwner := aOwner;
inherited Create(nil, 0);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1132,8 +1136,8 @@ constructor TutlCustomMap.TKeyEnumerator.Create(aEnumerator: IutlKeyValuePairEnu
begin
if not Assigned(aEnumerator) then
raise EArgumentNilException.Create('aEnumerator');
inherited Create;
fEnumerator := aEnumerator;
inherited Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1161,8 +1165,8 @@ constructor TutlCustomMap.TValueEnumerator.Create(aEnumerator: IutlKeyValuePairE
begin
if not Assigned(aEnumerator) then
raise EArgumentNilException.Create('aEnumerator');
inherited Create;
fEnumerator := aEnumerator;
inherited Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1282,6 +1286,24 @@ begin
result := fHashSetRef.CanExpand;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetCapacity(const aValue: Integer);
begin
fHashSetRef.Capacity := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetCanShrink(const aValue: Boolean);
begin
fHashSetRef.CanShrink := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetCanExpand(const aValue: Boolean);
begin
fHashSetRef.CanExpand := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetValue(aKey: TKey; const aValue: TValue);
var
@@ -1309,24 +1331,6 @@ begin
fHashSetRef[aIndex] := kvp;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetCapacity(const aValue: Integer);
begin
fHashSetRef.Capacity := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetCanShrink(const aValue: Boolean);
begin
fHashSetRef.CanShrink := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetCanExpand(const aValue: Boolean);
begin
fHashSetRef.CanExpand := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.GetEnumerator: IValueEnumerator;
begin
@@ -1343,7 +1347,7 @@ end;
procedure TutlCustomMap.Add(constref aKey: TKey; constref aValue: TValue);
begin
if not TryAdd(aKey, aValue) then
raise EInvalidOperation.Create('key already exists');
raise EInvalidOperation.Create('key already exists');
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 1
- 0
uutlListBase.pas View File

@@ -91,6 +91,7 @@ constructor TutlListBase.TEnumerator.Create(const aOwner: TutlListBase);
begin
if not Assigned(aOwner) then
raise EArgumentNilException.Create('aOwner');
fOwner := aOwner;
inherited Create(nil, 0);
end;



+ 446
- 1
uutlObservable.pas View File

@@ -113,6 +113,130 @@ type
constructor Create(const aOwnsObjects: Boolean);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableCustomHashSet<T> = class(specialize TutlCustomHashSet<T>)
private type
TEventHandlerList = specialize TutlEventList<TutlEventHandler>;

public type
TItemEventArgs = class(specialize TutlObservableItemEventArgs<T>)
private
fIndex: Integer;
public
property Index: Integer read fIndex;
constructor Create(const aEventType: TutlObservableEventType; const aIndex: Integer; constref aItem: T);
end;

TReplaceEventArgs = class(specialize TutlObservableReplaceEventArgs<T>)
private
fIndex: Integer;
public
property Index: Integer read fIndex;
constructor Create(const aEventType: TutlObservableEventType; const aIndex: Integer; constref aOldItem: T; constref aNewItem: T);
end;

private
fEventHandler: TEventHandlerList;

protected
procedure InsertIntern(const aIndex: Integer; constref aValue: T); override;
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean); override;
procedure SetItem (const aIndex: Integer; aValue: T); override;

procedure DoAddItem (const aIndex: Integer; constref aItem: T); virtual;
procedure DoRemoveItem(const aIndex: Integer; constref aItem: T); virtual;
procedure DoChangeItem(const aIndex: Integer; constref aOldItem: T; constref aNewItem: T); virtual;
procedure DoClear (); virtual;

public { IutlObservable }
procedure RegisterEventHandler (const aHandler: TutlEventHandler);
procedure UnregisterEventHandler(const aHandler: TutlEventHandler);

public
procedure Clear; override;

constructor Create(const aComparer: IComparer; const aOwnsItems: Boolean);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableHashSet<T> = class(specialize TutlObservableCustomHashSet<T>)
public
constructor Create(const aOwnsItems: Boolean);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableCustomMap<TKey, TValue> = class(specialize TutlCustomMap<TKey, TValue>)
private type
TEventHandlerList = specialize TutlEventList<TutlEventHandler>;

public type
TObservableHashSet = class(THashSet)
strict private
fOwner: TutlObservableCustomMap;

protected
procedure InsertIntern(const aIndex: Integer; constref aValue: TKeyValuePair); override;
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean); override;
procedure SetItem(const aIndex: Integer; aValue: TKeyValuePair); override;

public
procedure Clear; override;

constructor Create(const aOwner: TutlObservableCustomMap; const aComparer: IComparer); reintroduce;
end;

TItemEventArgs = class(specialize TutlObservableItemEventArgs<TValue>)
private
fIndex: Integer;
fKey: TKey;
public
property Index: Integer read fIndex;
property Key: TKey read fKey;
constructor Create(const aEventType: TutlObservableEventType; const aIndex: Integer; constref aKey: TKey; constref aItem: TValue);
end;

TReplaceEventArgs = class(specialize TutlObservableReplaceEventArgs<TValue>)
private
fIndex: Integer;
fKey: TKey;
public
property Index: Integer read fIndex;
property Key: TKey read fKey;
constructor Create(const aEventType: TutlObservableEventType; const aIndex: Integer; constref aKey: TKey; constref aOldItem: TValue; constref aNewItem: TValue);
end;

private
fEventHandler: TEventHandlerList;

protected
procedure DoAddItem (const aIndex: Integer; constref aKey: TKey; constref aItem: TValue); virtual;
procedure DoRemoveItem(const aIndex: Integer; constref aKey: TKey; constref aItem: TValue); virtual;
procedure DoChangeItem(const aIndex: Integer; constref aKey: TKey; constref aOldItem: TValue; constref aNewItem: TValue); virtual;
procedure DoClear (); virtual;

public { IutlObservable }
procedure RegisterEventHandler (const aHandler: TutlEventHandler);
procedure UnregisterEventHandler(const aHandler: TutlEventHandler);

public
constructor Create(const aHashSet: TObservableHashSet; const aOwnsKeys: Boolean; const aOwnsValues: Boolean); reintroduce;
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableMap<TKey, TValue> = class(specialize TutlObservableCustomMap<TKey, TValue>)
public type
TComparer = specialize TutlComparer<TKey>;

strict private
fHashSetImpl: TObservableHashSet;

public
constructor Create(const aOwnsKeys: Boolean; const aOwnsValues: Boolean);
destructor Destroy; override;
end;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -258,7 +382,7 @@ end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.Clear;
begin
DoClear();
DoClear;
inherited Clear;
end;

@@ -284,5 +408,326 @@ begin
inherited Create(TEqualityComparer.Create, aOwnsObjects);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomHashSet.TItemEventArgs////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomHashSet.TItemEventArgs.Create(
const aEventType: TutlObservableEventType;
const aIndex: Integer;
constref aItem: T);
begin
inherited Create(aEventType, aItem);
fIndex := aIndex;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomHashSet.TReplaceEventArgs/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomHashSet.TReplaceEventArgs.Create(
const aEventType: TutlObservableEventType;
const aIndex: Integer;
constref aOldItem: T;
constref aNewItem: T);
begin
inherited Create(aEventType, aOldItem, aNewItem);
fIndex := aIndex;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomHashSet///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.InsertIntern(const aIndex: Integer; constref aValue: T);
begin
inherited InsertIntern(aIndex, aValue);
DoAddItem(aIndex, aValue);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
begin
DoRemoveItem(aIndex, GetItem(aIndex));
inherited DeleteIntern(aIndex, aFreeItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.SetItem(const aIndex: Integer; aValue: T);
begin
DoChangeItem(aIndex, GetItem(aIndex), aValue);
inherited SetItem(aIndex, aValue);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoAddItem(const aIndex: Integer; constref aItem: T);
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TItemEventArgs.Create(oetAdd, aIndex, aItem);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoRemoveItem(const aIndex: Integer; constref aItem: T);
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TItemEventArgs.Create(oetRemove, aIndex, aItem);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoChangeItem(const aIndex: Integer; constref aOldItem: T; constref aNewItem: T);
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoClear;
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TutlObservableEventArgs.Create(oetClear);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.RegisterEventHandler(const aHandler: TutlEventHandler);
begin
fEventHandler.Add(aHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.UnregisterEventHandler(const aHandler: TutlEventHandler);
begin
fEventHandler.Remove(aHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.Clear;
begin
DoClear;
inherited Clear;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomHashSet.Create(const aComparer: IComparer; const aOwnsItems: Boolean);
begin
fEventHandler := TEventHandlerList.Create;
inherited Create(aComparer, aOwnsItems);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlObservableCustomHashSet.Destroy;
begin
inherited Destroy;
FreeAndNil(fEventHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableHashSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableHashSet.Create(const aOwnsItems: Boolean);
begin
inherited Create(specialize TutlComparer<T>.Create, aOwnsItems);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomMap.TObservableHashSet////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.TObservableHashSet.InsertIntern(const aIndex: Integer; constref aValue: TKeyValuePair);
begin
inherited InsertIntern(aIndex, aValue);
fOwner.DoAddItem(aIndex, aValue.Key, aValue.Value);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.TObservableHashSet.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
var
kvp: TKeyValuePair;
begin
kvp := GetItem(aIndex);
fOwner.DoRemoveItem(aIndex, kvp.Key, kvp.Value);
inherited DeleteIntern(aIndex, aFreeItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.TObservableHashSet.SetItem(const aIndex: Integer; aValue: TKeyValuePair);
begin
fOwner.DoChangeItem(aIndex, aValue.Key, GetItem(aIndex).Value, aValue.Value);
inherited SetItem(aIndex, aValue);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.TObservableHashSet.Clear;
begin
fOwner.DoClear;
inherited Clear;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomMap.TObservableHashSet.Create(
const aOwner: TutlObservableCustomMap;
const aComparer: IComparer);
begin
inherited Create(aOwner, aComparer);
fOwner := aOwner;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomMap.TItemEventArgs////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomMap.TItemEventArgs.Create(
const aEventType: TutlObservableEventType;
const aIndex: Integer;
constref aKey: TKey;
constref aItem: TValue);
begin
inherited Create(aEventType, aItem);
fIndex := aIndex;
fKey := aKey;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomMap.TReplaceEventArgs/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomMap.TReplaceEventArgs.Create(
const aEventType: TutlObservableEventType;
const aIndex: Integer;
constref aKey: TKey;
constref aOldItem: TValue;
constref aNewItem: TValue);
begin
inherited Create(aEventType, aOldItem, aNewItem);
fIndex := aIndex;
fKey := aKey;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.DoAddItem(
const aIndex: Integer;
constref aKey: TKey;
constref aItem: TValue);
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TItemEventArgs.Create(oetAdd, aIndex, aKey, aItem);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.DoRemoveItem(
const aIndex: Integer;
constref aKey: TKey;
constref aItem: TValue);
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TItemEventArgs.Create(oetRemove, aIndex, aKey, aItem);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.DoChangeItem(
const aIndex: Integer;
constref aKey: TKey;
constref aOldItem: TValue;
constref aNewItem: TValue);
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TReplaceEventArgs.Create(oetReplace, aIndex, aKey, aOldItem, aNewItem);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.DoClear;
var
args: IutlEventArgs;
e: TutlEventHandler;
begin
if not Assigned(fEventHandler) or fEventHandler.IsEmpty then
exit;
args := TutlObservableEventArgs.Create(oetClear);
for e in fEventHandler do
e(self, args);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.RegisterEventHandler(const aHandler: TutlEventHandler);
begin
fEventHandler.Add(aHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.UnregisterEventHandler(const aHandler: TutlEventHandler);
begin
fEventHandler.Remove(aHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomMap.Create(
const aHashSet: TObservableHashSet;
const aOwnsKeys: Boolean;
const aOwnsValues: Boolean);
begin
fEventHandler := TEventHandlerList.Create;
inherited Create(aHashSet, aOwnsKeys, aOwnsValues);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlObservableCustomMap.Destroy;
begin
inherited Destroy;
FreeAndNil(fEventHandler);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableMap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableMap.Create(const aOwnsKeys: Boolean; const aOwnsValues: Boolean);
begin
fHashSetImpl := TObservableHashSet.Create(self, TKeyValuePairComparer.Create(TComparer.Create));
inherited Create(fHashSetImpl, aOwnsKeys, aOwnsValues);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlObservableMap.Destroy;
begin
inherited Destroy;
FreeAndNil(fHashSetImpl);
end;

end.


Loading…
Cancel
Save