From cd0c7d799e5fb98084b68b342d8f751f2927e436 Mon Sep 17 00:00:00 2001 From: ask Date: Tue, 6 Apr 2010 12:27:20 +0000 Subject: [PATCH] TAChart: Extract TBroadcaster from TCustomChartSource * Move TBroadcaster and TListener to TAChartUtils git-svn-id: trunk@24466 - --- components/tachart/tachartutils.pas | 72 +++++++++++++++++++++++ components/tachart/tacustomseries.pas | 10 ++-- components/tachart/tasources.pas | 82 +++++---------------------- 3 files changed, 91 insertions(+), 73 deletions(-) diff --git a/components/tachart/tachartutils.pas b/components/tachart/tachartutils.pas index 3e7ca1d1d2..de6933c492 100644 --- a/components/tachart/tachartutils.pas +++ b/components/tachart/tachartutils.pas @@ -42,6 +42,7 @@ const type EChartError = class(Exception); EChartIntervalError = class(EChartError); + EListenerError = class(EChartError); TDoublePoint = record X, Y: Double; @@ -139,6 +140,28 @@ type property Index: Integer read GetIndex write SetIndex; end; + { TListener } + + TListener = class + private + FIsListening: Boolean; + public + procedure Forget; virtual; + procedure Notify; virtual; abstract; + property IsListening: Boolean read FIsListening; + end; + + { TBroadcaster } + + TBroadcaster = class(TFPList) + public + destructor Destroy; override; + public + procedure Broadcast; + procedure Subscribe(AListener: TListener); + procedure Unsubscribe(AListener: TListener); + end; + const // 0-value, 1-percent, 2-label, 3-total, 4-xvalue SERIES_MARK_FORMATS: array [TSeriesMarksStyle] of String = ( @@ -703,4 +726,53 @@ begin FOnChange := AValue; end; +{ TListener } + +procedure TListener.Forget; +begin + FIsListening := false; +end; + +{ TBroadcaster } + +procedure TBroadcaster.Broadcast; +var + i: Integer; +begin + for i := 0 to Count - 1 do + TListener(Items[i]).Notify; +end; + +destructor TBroadcaster.Destroy; +var + i: Integer; +begin + for i := 0 to Count - 1 do + TListener(Items[i]).Forget; + inherited Destroy; +end; + +procedure TBroadcaster.Subscribe(AListener: TListener); +begin + if AListener.IsListening then + raise EListenerError.Create('Listener subscribed twice'); + if IndexOf(AListener) >= 0 then + raise EListenerError.Create('Duplicate listener'); + AListener.FIsListening := true; + Add(AListener); +end; + +procedure TBroadcaster.Unsubscribe(AListener: TListener); +var + i: Integer; +begin + if not AListener.IsListening then + raise EListenerError.Create('Listener not subscribed'); + AListener.FIsListening := false; + i := IndexOf(AListener); + if i < 0 then + raise EListenerError.Create('Listener not found'); + Delete(i); +end; + end. diff --git a/components/tachart/tacustomseries.pas b/components/tachart/tacustomseries.pas index 047650f642..4520ee7a3c 100644 --- a/components/tachart/tacustomseries.pas +++ b/components/tachart/tacustomseries.pas @@ -96,12 +96,12 @@ type procedure AfterDraw; override; procedure BeforeDraw; override; function ColorOrDefault(AColor: TColor; ADefault: TColor = clTAColor): TColor; + procedure GetBounds(out ABounds: TDoubleRect); override; function GetGraphPoint(AIndex: Integer): TDoublePoint; function GetGraphPointX(AIndex: Integer): Double; inline; function GetGraphPointY(AIndex: Integer): Double; inline; function GetSeriesColor: TColor; virtual; function GetXMaxVal: Integer; - procedure GetBounds(out ABounds: TDoubleRect); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -379,7 +379,7 @@ begin FListener := TChartSeriesListener.Create(Self); FBuiltinSource := TListChartSource.Create(Self); FBuiltinSource.Name := BUILTIN_SOURCE_NAME; - FBuiltinSource.Subscribe(FListener); + FBuiltinSource.Broadcaster.Subscribe(FListener); FMarks := TChartMarks.Create(FChart); end; @@ -391,7 +391,7 @@ end; destructor TChartSeries.Destroy; begin if FListener.IsListening then - Source.Unsubscribe(FListener); + Source.Broadcaster.Unsubscribe(FListener); FBuiltinSource.Free; FMarks.Free; FListener.Free; @@ -553,9 +553,9 @@ procedure TChartSeries.SetSource(AValue: TCustomChartSource); begin if FSource = AValue then exit; if FListener.IsListening then - Source.Unsubscribe(FListener); + Source.Broadcaster.Unsubscribe(FListener); FSource := AValue; - Source.Subscribe(FListener); + Source.Broadcaster.Subscribe(FListener); UpdateParentChart; end; diff --git a/components/tachart/tasources.pas b/components/tachart/tasources.pas index 3b0edf05b5..61426e36ff 100644 --- a/components/tachart/tasources.pas +++ b/components/tachart/tasources.pas @@ -26,7 +26,6 @@ uses type EEditableSourceRequired = class(EChartError); - EListenerError = class(EChartError); TChartDataItem = record X, Y: Double; @@ -35,24 +34,12 @@ type end; PChartDataItem = ^TChartDataItem; - { TListener } - - TListener = class - private - FIsListening: Boolean; - public - procedure Forget; virtual; - procedure Notify; virtual; abstract; - property IsListening: Boolean read FIsListening; - end; - { TCustomChartSource } TCustomChartSource = class(TComponent) private - FListeners: array of TListener; + FBroadcaster: TBroadcaster; FUpdateCount: Integer; - function FindListener(AListener: TListener): Integer; protected FExtent: TDoubleRect; FExtentIsValid: Boolean; @@ -63,6 +50,7 @@ type procedure InvalidateCaches; procedure Notify; public + constructor Create(AOwner: TComponent); override; destructor Destroy; override; public procedure AfterDraw; virtual; @@ -70,8 +58,6 @@ type procedure BeginUpdate; procedure EndUpdate; function IsUpdating: Boolean; inline; - procedure Subscribe(AListener: TListener); - procedure Unsubscribe(AListener: TListener); public function Extent: TDoubleRect; virtual; function FormatItem(const AFormat: String; AIndex: Integer): String; @@ -79,6 +65,7 @@ type function XOfMax: Double; function XOfMin: Double; + property Broadcaster: TBroadcaster read FBroadcaster; property Count: Integer read GetCount; property Item[AIndex: Integer]: PChartDataItem read GetItem; default; end; @@ -252,14 +239,16 @@ begin Inc(FUpdateCount); end; -destructor TCustomChartSource.Destroy; -var - i: Integer; +constructor TCustomChartSource.Create(AOwner: TComponent); begin - for i := 0 to High(FListeners) do - FListeners[i].Forget; - FListeners := nil; - inherited Destroy; + inherited Create(AOwner); + FBroadcaster := TBroadcaster.Create; +end; + +destructor TCustomChartSource.Destroy; +begin + FBroadcaster.Free; + inherited; end; procedure TCustomChartSource.EndUpdate; @@ -283,13 +272,6 @@ begin Result := FExtent; end; -function TCustomChartSource.FindListener(AListener: TListener): Integer; -begin - for Result := 0 to High(FListeners) do - if FListeners[Result] = AListener then exit; - Result := -1; -end; - function TCustomChartSource.FormatItem( const AFormat: String; AIndex: Integer): String; const @@ -319,38 +301,9 @@ begin end; procedure TCustomChartSource.Notify; -var - i: Integer; begin - if IsUpdating then exit; - for i := 0 to High(FListeners) do - FListeners[i].Notify; -end; - -procedure TCustomChartSource.Subscribe(AListener: TListener); -begin - if AListener.IsListening then - raise EListenerError.Create('Listener subscribed twice'); - if FindListener(AListener) >= 0 then - raise EListenerError.Create('Duplicate listener'); - AListener.FIsListening := true; - SetLength(FListeners, Length(FListeners) + 1); - FListeners[High(FListeners)] := AListener; -end; - -procedure TCustomChartSource.Unsubscribe(AListener: TListener); -var - i, j: Integer; -begin - if not AListener.IsListening then - raise EListenerError.Create('Listener not subscribed'); - AListener.FIsListening := false; - j := FindListener(AListener); - if j < 0 then - raise EListenerError.Create('Listener not found'); - for i := j to High(FListeners) - 1 do - FListeners[i] := FListeners[i + 1]; - SetLength(FListeners, Length(FListeners) - 1); + if not IsUpdating then + FBroadcaster.Broadcast; end; function TCustomChartSource.ValuesTotal: Double; @@ -774,13 +727,6 @@ begin Notify; end; -{ TListener } - -procedure TListener.Forget; -begin - FIsListening := false; -end; - { TUserDefinedChartSource } function TUserDefinedChartSource.GetCount: Integer;