diff --git a/.gitattributes b/.gitattributes index 14f1617bcb..8f15541ba7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2996,6 +2996,7 @@ components/tachart/numlib_fix/ipf.pas svneol=native#text/pascal components/tachart/numlib_fix/mdt.pas svneol=native#text/pascal components/tachart/numlib_fix/sle.pas svneol=native#text/pascal components/tachart/numlib_fix/spe.pas svneol=native#text/pascal +components/tachart/taanimatedsource.pas svneol=native#text/pascal components/tachart/tachartaggpas.lpk svneol=native#text/pascal components/tachart/tachartaggpas.pas svneol=native#text/pascal components/tachart/tachartaxis.pas svneol=native#text/pascal diff --git a/components/tachart/taanimatedsource.pas b/components/tachart/taanimatedsource.pas new file mode 100644 index 0000000000..1f0b85f53f --- /dev/null +++ b/components/tachart/taanimatedsource.pas @@ -0,0 +1,222 @@ +{ + + ***************************************************************************** + * * + * See the file COPYING.modifiedLGPL.txt, included in this distribution, * + * for details about the copyright. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * * + ***************************************************************************** + + Authors: Alexander Klenin + +} + +unit TAAnimatedSource; + +{$H+} + +interface + +uses + Classes, CustomTimer, + TAChartUtils, TACustomSource; + +type + TCustomAnimatedChartSource = class; + + TAnimatedChartSourceItemEvent = procedure ( + ASender: TCustomAnimatedChartSource; + AIndex: Integer; var AItem: TChartDataItem) of object; + TAnimatedChartSourceEvent = procedure ( + ASender: TCustomAnimatedChartSource) of object; + + TCustomAnimatedChartSource = class(TCustomChartSource) + strict private + FAnimationInterval: Cardinal; + FAnimationTime: Cardinal; + FCurrentStep: Cardinal; + FItem: TChartDataItem; + FListener: TListener; + FOnGetItem: TAnimatedChartSourceItemEvent; + FOnStop: TAnimatedChartSourceEvent; + FOrigin: TCustomChartSource; + FProjectedSteps: Cardinal; + FSkippedFramesCount: Cardinal; + FStartTime: Cardinal; + FTimer: TCustomTimer; + procedure Changed(ASender: TObject); + procedure OnTimer(ASender: TObject); + procedure SetOrigin(AValue: TCustomChartSource); + protected + function GetCount: Integer; override; + function GetItem(AIndex: Integer): PChartDataItem; override; + procedure SetYCount(AValue: Cardinal); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + + function Extent: TDoubleRect; override; + function ExtentCumulative: TDoubleRect; override; + function ExtentList: TDoubleRect; override; + + function IsAnimating: Boolean; inline; + function Progress: Double; inline; + procedure Start; + procedure Stop(ACallEvent: Boolean = false); + + property CurrentStep: Cardinal read FCurrentStep; + property ProjectedSteps: Cardinal read FProjectedSteps; + property SkippedFramesCount: Cardinal read FSkippedFramesCount; + published + property AnimationInterval: Cardinal + read FAnimationInterval write FAnimationInterval default 0; + property AnimationTime: Cardinal + read FAnimationTime write FAnimationTime default 0; + property Origin: TCustomChartSource read FOrigin write SetOrigin; + published + property OnGetItem: TAnimatedChartSourceItemEvent + read FOnGetItem write FOnGetItem; + property OnStop: TAnimatedChartSourceEvent read FOnStop write FOnStop; + end; + +implementation + +uses + LCLIntf, Math, SysUtils; + +{ TCustomAnimatedChartSource } + +procedure TCustomAnimatedChartSource.Changed(ASender: TObject); +begin + Notify; +end; + +constructor TCustomAnimatedChartSource.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FListener := TListener.Create(@FOrigin, @Changed); + FTimer := TCustomTimer.Create(nil); + FTimer.Enabled := false; + FTimer.OnTimer := @OnTimer; +end; + +destructor TCustomAnimatedChartSource.Destroy; +begin + FreeAndNil(FTimer); + FreeAndNil(FListener); + inherited; +end; + +function TCustomAnimatedChartSource.Extent: TDoubleRect; +begin + if Origin = nil then + Result := EmptyExtent + else + Result := Origin.Extent; +end; + +function TCustomAnimatedChartSource.ExtentCumulative: TDoubleRect; +begin + if Origin = nil then + Result := EmptyExtent + else + Result := Origin.ExtentCumulative; +end; + +function TCustomAnimatedChartSource.ExtentList: TDoubleRect; +begin + if Origin = nil then + Result := EmptyExtent + else + Result := Origin.ExtentList; +end; + +function TCustomAnimatedChartSource.GetCount: Integer; +begin + if Origin = nil then + Result := 0 + else + Result := Origin.Count; +end; + +function TCustomAnimatedChartSource.GetItem(AIndex: Integer): PChartDataItem; +begin + if Origin = nil then exit(nil); + if not IsAnimating then exit(Origin.Item[AIndex]); + FItem := Origin.Item[AIndex]^; + Result := @FItem; + if Assigned(OnGetItem) then + OnGetItem(Self, AIndex, FItem); +end; + +function TCustomAnimatedChartSource.IsAnimating: Boolean; +begin + Result := FTimer.Enabled; +end; + +procedure TCustomAnimatedChartSource.OnTimer(ASender: TObject); +var + d, s: Cardinal; +begin + Unused(ASender); + d := GetTickCount - FStartTime; + if d >= AnimationTime then + Stop(true); + s := Round(d * ProjectedSteps / AnimationTime); + if FCurrentStep + 1 <> s then + FSkippedFramesCount += 1; + FCurrentStep := s; + Notify; +end; + +function TCustomAnimatedChartSource.Progress: Double; +begin + if ProjectedSteps = 0 then + Result := 0 + else + Result := (FCurrentStep - 1) / ProjectedSteps; +end; + +procedure TCustomAnimatedChartSource.SetOrigin(AValue: TCustomChartSource); +begin + if AValue = Self then + AValue := nil; + if FOrigin = AValue then exit; + if FOrigin <> nil then + FOrigin.Broadcaster.Unsubscribe(FListener); + FOrigin := AValue; + if FOrigin <> nil then + FOrigin.Broadcaster.Subscribe(FListener); +end; + +procedure TCustomAnimatedChartSource.SetYCount(AValue: Cardinal); +begin + Unused(AValue); + raise EYCountError.Create('Can not set YCount'); +end; + +procedure TCustomAnimatedChartSource.Start; +begin + Stop; + FSkippedFramesCount := 0; + if (AnimationInterval = 0) or (AnimationTime <= AnimationInterval) then exit; + FProjectedSteps := Round(AnimationTime / AnimationInterval); + FStartTime := GetTickCount; + FTimer.Interval := AnimationInterval; + FTimer.Enabled := true; +end; + +procedure TCustomAnimatedChartSource.Stop(ACallEvent: Boolean); +begin + FTimer.Enabled := false; + FCurrentStep := 0; + if ACallEvent and Assigned(OnStop) then + OnStop(Self); +end; + +end. + diff --git a/components/tachart/tachartlazaruspkg.lpk b/components/tachart/tachartlazaruspkg.lpk index 20e43818c4..464edf5922 100644 --- a/components/tachart/tachartlazaruspkg.lpk +++ b/components/tachart/tachartlazaruspkg.lpk @@ -34,7 +34,7 @@ for details about the copyright. "/> - + @@ -205,6 +205,10 @@ + + + + diff --git a/components/tachart/tachartlazaruspkg.pas b/components/tachart/tachartlazaruspkg.pas index 263d13beb4..62c50f3cb1 100644 --- a/components/tachart/tachartlazaruspkg.pas +++ b/components/tachart/tachartlazaruspkg.pas @@ -13,7 +13,8 @@ uses TALegendPanel, TARadialSeries, TACustomSource, TAGeometry, TANavigation, TADrawerCanvas, TADrawerSVG, TAIntervalSources, TAChartAxisUtils, TAChartListbox, TAEnumerators, TADataPointsEditor, TAChartExtentLink, - TAToolEditors, TAMath, TAChartImageList, TADataTools, LazarusPackageIntf; + TAToolEditors, TAMath, TAChartImageList, TADataTools, TAAnimatedSource, + LazarusPackageIntf; implementation diff --git a/components/tachart/tacustomsource.pas b/components/tachart/tacustomsource.pas index f119afb477..6bf0bb104f 100644 --- a/components/tachart/tacustomsource.pas +++ b/components/tachart/tacustomsource.pas @@ -163,9 +163,9 @@ type function IsUpdating: Boolean; inline; public class procedure CheckFormat(const AFormat: String); - function Extent: TDoubleRect; - function ExtentCumulative: TDoubleRect; - function ExtentList: TDoubleRect; + function Extent: TDoubleRect; virtual; + function ExtentCumulative: TDoubleRect; virtual; + function ExtentList: TDoubleRect; virtual; procedure FindBounds(AXMin, AXMax: Double; out ALB, AUB: Integer); function FormatItem( const AFormat: String; AIndex, AYIndex: Integer): String; diff --git a/components/tachart/tasources.pas b/components/tachart/tasources.pas index 1bb51e07ce..3fa71bf2ad 100644 --- a/components/tachart/tasources.pas +++ b/components/tachart/tasources.pas @@ -1082,7 +1082,7 @@ destructor TCalculatedChartSource.Destroy; begin FreeAndNil(FHistory); FreeAndNil(FListener); - inherited Destroy; + inherited; end; function TCalculatedChartSource.EffectiveAccumulationRange: Cardinal; diff --git a/components/tachart/tatools.pas b/components/tachart/tatools.pas index df2b00715b..edb365f769 100644 --- a/components/tachart/tatools.pas +++ b/components/tachart/tatools.pas @@ -478,7 +478,6 @@ type destructor Destroy; override; procedure Draw(AChart: TChart; ADrawer: IChartDrawer); override; procedure Hide; virtual; - procedure KeyDown(APoint: TPoint); override; published property DrawingMode; property GrabRadius default 20; @@ -500,6 +499,7 @@ type public constructor Create(AOwner: TComponent); override; procedure Draw(AChart: TChart; ADrawer: IChartDrawer); override; + procedure KeyDown(APoint: TPoint); override; procedure MouseMove(APoint: TPoint); override; property Position: TDoublePoint read FPosition; published @@ -1661,11 +1661,6 @@ begin Deactivate; end; -procedure TDataPointDrawTool.KeyDown(APoint: TPoint); -begin - MouseMove(APoint); -end; - procedure TDataPointDrawTool.SetPen(AValue: TChartPen); begin FPen.Assign(AValue); @@ -1711,6 +1706,11 @@ begin inherited; end; +procedure TDataPointCrosshairTool.KeyDown(APoint: TPoint); +begin + MouseMove(APoint); +end; + procedure TDataPointCrosshairTool.MouseMove(APoint: TPoint); begin DoHide;