mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-10 03:35:58 +02:00
TAChart: Extract TBroadcaster from TCustomChartSource
* Move TBroadcaster and TListener to TAChartUtils git-svn-id: trunk@24466 -
This commit is contained in:
parent
9b01c35ba3
commit
cd0c7d799e
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user