TAChart: Add TChartAxisMarks.AtDataOnly property

git-svn-id: trunk@26930 -
This commit is contained in:
ask 2010-07-31 13:35:24 +00:00
parent c3e010c4ba
commit 0e1bfb75c2
4 changed files with 121 additions and 12 deletions

View File

@ -88,10 +88,13 @@ type
TChartAxisMarks = class( TChartAxisMarks = class(
specialize TGenericChartMarks<TChartAxisBrush, TChartPen, TChartAxisFramePen>) specialize TGenericChartMarks<TChartAxisBrush, TChartPen, TChartAxisFramePen>)
private private
FAtDataOnly: Boolean;
FDefaultSource: TIntervalChartSource; FDefaultSource: TIntervalChartSource;
FListener: TListener; FListener: TListener;
FSource: TCustomChartSource; FSource: TCustomChartSource;
function IsFormatStored: Boolean; function IsFormatStored: Boolean;
procedure SetAtDataOnly(AValue: Boolean);
procedure SetSource(AValue: TCustomChartSource); procedure SetSource(AValue: TCustomChartSource);
public public
constructor Create(AOwner: TCustomChart); constructor Create(AOwner: TCustomChart);
@ -99,6 +102,8 @@ type
function SourceDef: TCustomChartSource; function SourceDef: TCustomChartSource;
published published
property AtDataOnly: Boolean
read FAtDataOnly write SetAtDataOnly default false;
property Distance default 1; property Distance default 1;
property Format stored IsFormatStored; property Format stored IsFormatStored;
property Frame; property Frame;
@ -118,6 +123,7 @@ type
FSize: Integer; FSize: Integer;
FTitleSize: Integer; FTitleSize: Integer;
procedure VisitSource(ASource: TCustomChartSource; var AData);
procedure GetMarkValues(AMin, AMax: Double); procedure GetMarkValues(AMin, AMax: Double);
private private
FAlignment: TChartAxisAlignment; FAlignment: TChartAxisAlignment;
@ -179,11 +185,17 @@ type
read FOnMarkToText write SetOnMarkToText; read FOnMarkToText write SetOnMarkToText;
end; end;
TChartOnSourceVisitor =
procedure (ASource: TCustomChartSource; var AData) of object;
TChartOnVisitSources = procedure (
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData) of object;
{ TChartAxisList } { TChartAxisList }
TChartAxisList = class(TCollection) TChartAxisList = class(TCollection)
private private
FChart: TCustomChart; FChart: TCustomChart;
FOnVisitSources: TChartOnVisitSources;
function GetAxes(AIndex: Integer): TChartAxis; function GetAxes(AIndex: Integer): TChartAxis;
protected protected
function GetOwner: TPersistent; override; function GetOwner: TPersistent; override;
@ -197,6 +209,8 @@ type
property Axes[AIndex: Integer]: TChartAxis read GetAxes; default; property Axes[AIndex: Integer]: TChartAxis read GetAxes; default;
property BottomAxis: TChartAxis index 1 read GetAxis write SetAxis; property BottomAxis: TChartAxis index 1 read GetAxis write SetAxis;
property LeftAxis: TChartAxis index 2 read GetAxis write SetAxis; property LeftAxis: TChartAxis index 2 read GetAxis write SetAxis;
property OnVisitSources: TChartOnVisitSources
read FOnVisitSources write FOnVisitSources;
end; end;
function SideByAlignment( function SideByAlignment(
@ -209,6 +223,11 @@ implementation
uses uses
LResources, Math, PropEdits, TADrawUtils; LResources, Math, PropEdits, TADrawUtils;
type
TAxisDataExtent = record
FMin, FMax: Double;
end;
var var
VIdentityTransform: TChartAxisTransformations; VIdentityTransform: TChartAxisTransformations;
@ -295,6 +314,13 @@ begin
Result := FStyle <> smsValue; Result := FStyle <> smsValue;
end; end;
procedure TChartAxisMarks.SetAtDataOnly(AValue: Boolean);
begin
if FAtDataOnly = AValue then exit;
FAtDataOnly := AValue;
StyleChanged(Self);
end;
procedure TChartAxisMarks.SetSource(AValue: TCustomChartSource); procedure TChartAxisMarks.SetSource(AValue: TCustomChartSource);
begin begin
if FSource = AValue then exit; if FSource = AValue then exit;
@ -462,12 +488,23 @@ end;
procedure TChartAxis.GetMarkValues(AMin, AMax: Double); procedure TChartAxis.GetMarkValues(AMin, AMax: Double);
var var
i: Integer; i: Integer;
d: TAxisDataExtent;
vis: TChartOnVisitSources;
begin begin
AMin := GetTransform.GraphToAxis(AMin); AMin := GetTransform.GraphToAxis(AMin);
AMax := GetTransform.GraphToAxis(AMax); AMax := GetTransform.GraphToAxis(AMax);
EnsureOrder(AMin, AMax); EnsureOrder(AMin, AMax);
Marks.SourceDef.ValuesInRange( SetLength(FMarkValues, 0);
AMin, AMax, Marks.Format, IsVertical, FMarkValues, FMarkTexts); SetLength(FMarkTexts, 0);
vis := TChartAxisList(Collection).OnVisitSources;
if Marks.AtDataOnly and Assigned(vis) then begin
d.FMin := AMin;
d.FMax := AMax;
vis(@VisitSource, Self, d);
end
else
Marks.SourceDef.ValuesInRange(
AMin, AMax, Marks.Format, IsVertical, FMarkValues, FMarkTexts);
if Inverted then if Inverted then
for i := 0 to High(FMarkValues) div 2 do begin for i := 0 to High(FMarkValues) div 2 do begin
Exchange(FMarkValues[i], FMarkValues[High(FMarkValues) - i]); Exchange(FMarkValues[i], FMarkValues[High(FMarkValues) - i]);
@ -626,6 +663,26 @@ begin
end; end;
end; end;
procedure TChartAxis.VisitSource(ASource: TCustomChartSource; var AData);
var
lmin, lmax: Double;
ext: TDoubleRect;
begin
ext := ASource.Extent;
with TAxisDataExtent(AData) do begin
if IsVertical then begin
lmin := Max(ext.a.Y, FMin);
lmax := Min(ext.b.Y, FMax);
end
else begin
lmin := Max(ext.a.X, FMin);
lmax := Min(ext.b.X, FMax);
end;
Marks.SourceDef.ValuesInRange(
lmin, lmax, Marks.Format, IsVertical, FMarkValues, FMarkTexts);
end;
end;
const const
AXIS_INDEX: array [1..2] of TChartAxisAlignment = (calBottom, calLeft); AXIS_INDEX: array [1..2] of TChartAxisAlignment = (calBottom, calLeft);

View File

@ -24,7 +24,7 @@ interface
uses uses
Classes, Graphics, SysUtils, Classes, Graphics, SysUtils,
TAChartUtils, TAGraph, TASources, TATypes; TAChartAxis, TAChartUtils, TAGraph, TASources, TATypes;
const const
DEF_AXIS_INDEX = -1; DEF_AXIS_INDEX = -1;
@ -60,6 +60,8 @@ type
function AxisToGraph(const APoint: TDoublePoint): TDoublePoint; function AxisToGraph(const APoint: TDoublePoint): TDoublePoint;
function AxisToGraphX(AX: Double): Double; override; function AxisToGraphX(AX: Double): Double; override;
function AxisToGraphY(AY: Double): Double; override; function AxisToGraphY(AY: Double): Double; override;
function GetAxisX: TChartAxis;
function GetAxisY: TChartAxis;
function GraphToAxisX(AX: Double): Double; override; function GraphToAxisX(AX: Double): Double; override;
function GraphToAxisY(AY: Double): Double; override; function GraphToAxisY(AY: Double): Double; override;
@ -103,6 +105,8 @@ type
function GetGraphPointY(AIndex: Integer): Double; inline; function GetGraphPointY(AIndex: Integer): Double; inline;
function GetSeriesColor: TColor; virtual; function GetSeriesColor: TColor; virtual;
function GetXMaxVal: Integer; function GetXMaxVal: Integer;
procedure VisitSources(
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData); override;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
@ -124,7 +128,8 @@ type
procedure SetYValue(AIndex: Integer; AValue: Double); inline; procedure SetYValue(AIndex: Integer; AValue: Double); inline;
public public
function Add(AValue: Double; XLabel: String; Color: TColor): Integer; inline; function Add(AValue: Double; XLabel: String; Color: TColor): Integer; inline;
function AddXY(X, Y: Double; XLabel: String; Color: TColor): Integer; virtual; overload; function AddXY(
X, Y: Double; XLabel: String; Color: TColor): Integer; virtual; overload;
function AddXY(X, Y: Double): Integer; overload; inline; function AddXY(X, Y: Double): Integer; overload; inline;
procedure Clear; inline; procedure Clear; inline;
function Count: Integer; inline; function Count: Integer; inline;
@ -148,7 +153,7 @@ type
implementation implementation
uses uses
Math, TAChartAxis; Math;
{ TCustomChartSeries } { TCustomChartSeries }
@ -179,6 +184,22 @@ begin
FAxisIndexY := DEF_AXIS_INDEX; FAxisIndexY := DEF_AXIS_INDEX;
end; end;
function TCustomChartSeries.GetAxisX: TChartAxis;
begin
if InRange(AxisIndexX, 0, FChart.AxisList.Count - 1) then
Result := FChart.AxisList[AxisIndexX]
else
Result := FChart.BottomAxis;
end;
function TCustomChartSeries.GetAxisY: TChartAxis;
begin
if InRange(AxisIndexY, 0, FChart.AxisList.Count - 1) then
Result := FChart.AxisList[AxisIndexY]
else
Result := FChart.LeftAxis;
end;
procedure TCustomChartSeries.GetGraphBounds(var ABounds: TDoubleRect); procedure TCustomChartSeries.GetGraphBounds(var ABounds: TDoubleRect);
begin begin
GetBounds(ABounds); GetBounds(ABounds);
@ -544,5 +565,12 @@ begin
ListSource.SetYValue(AIndex, AValue); ListSource.SetYValue(AIndex, AValue);
end; end;
procedure TChartSeries.VisitSources(
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData);
begin
if (AAxis = GetAxisX) or (AAxis = GetAxisY) then
AVisitor(Source, AData);
end;
end. end.

View File

@ -65,6 +65,8 @@ type
procedure SetShowInLegend(AValue: Boolean); virtual; abstract; procedure SetShowInLegend(AValue: Boolean); virtual; abstract;
procedure SetZPosition(AValue: TChartDistance); virtual; abstract; procedure SetZPosition(AValue: TChartDistance); virtual; abstract;
procedure UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); virtual; procedure UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); virtual;
procedure VisitSources(
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData); virtual;
protected protected
function AxisToGraphX(AX: Double): Double; virtual; function AxisToGraphX(AX: Double): Double; virtual;
@ -196,6 +198,8 @@ type
procedure SetTitle(Value: TChartTitle); procedure SetTitle(Value: TChartTitle);
procedure SetToolset(const AValue: TBasicChartToolset); procedure SetToolset(const AValue: TBasicChartToolset);
procedure UpdateExtent; procedure UpdateExtent;
procedure VisitSources(
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData);
protected protected
procedure Clean(ACanvas: TCanvas; ARect: TRect); procedure Clean(ACanvas: TCanvas; ARect: TRect);
procedure DisplaySeries(ACanvas: TCanvas); procedure DisplaySeries(ACanvas: TCanvas);
@ -389,6 +393,7 @@ begin
FFoot := TChartTitle.Create(Self); FFoot := TChartTitle.Create(Self);
FAxisList := TChartAxisList.Create(Self); FAxisList := TChartAxisList.Create(Self);
FAxisList.OnVisitSources := @VisitSources;
with TChartAxis.Create(FAxisList) do begin with TChartAxis.Create(FAxisList) do begin
Alignment := calLeft; Alignment := calLeft;
Title.LabelFont.Orientation := FONT_VERTICAL; Title.LabelFont.Orientation := FONT_VERTICAL;
@ -1067,6 +1072,17 @@ begin
end; end;
end; end;
procedure TChart.VisitSources(
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData);
var
i: Integer;
begin
for i := 0 to SeriesCount - 1 do
with Series[i] do
if Active then
VisitSources(AVisitor, AAxis, AData);
end;
procedure TChart.ZoomFull; procedure TChart.ZoomFull;
begin begin
if not FIsZoomed then exit; if not FIsZoomed then exit;
@ -1142,6 +1158,13 @@ begin
Unused(ACanvas, AMargins); Unused(ACanvas, AMargins);
end; end;
procedure TBasicChartSeries.VisitSources(
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData);
begin
Unused(AVisitor, AAxis);
Unused(AData);
end;
{ TChartSeriesList } { TChartSeriesList }
procedure TChartSeriesList.Clear; procedure TChartSeriesList.Clear;

View File

@ -69,7 +69,7 @@ type
function IsSorted: Boolean; virtual; function IsSorted: Boolean; virtual;
procedure ValuesInRange( procedure ValuesInRange(
AMin, AMax: Double; const AFormat: String; AUseY: Boolean; AMin, AMax: Double; const AFormat: String; AUseY: Boolean;
out AValues: TDoubleDynArray; out ATexts: TStringDynArray); virtual; var AValues: TDoubleDynArray; var ATexts: TStringDynArray); virtual;
function ValuesTotal: Double; virtual; function ValuesTotal: Double; virtual;
function XOfMax: Double; function XOfMax: Double;
function XOfMin: Double; function XOfMin: Double;
@ -181,7 +181,7 @@ type
public public
procedure ValuesInRange( procedure ValuesInRange(
AMin, AMax: Double; const AFormat: String; AUseY: Boolean; AMin, AMax: Double; const AFormat: String; AUseY: Boolean;
out AValues: TDoubleDynArray; out ATexts: TStringDynArray); override; var AValues: TDoubleDynArray; var ATexts: TStringDynArray); override;
end; end;
TUserDefinedChartSource = class; TUserDefinedChartSource = class;
@ -397,14 +397,14 @@ end;
procedure TCustomChartSource.ValuesInRange( procedure TCustomChartSource.ValuesInRange(
AMin, AMax: Double; const AFormat: String; AUseY: Boolean; AMin, AMax: Double; const AFormat: String; AUseY: Boolean;
out AValues: TDoubleDynArray; out ATexts: TStringDynArray); var AValues: TDoubleDynArray; var ATexts: TStringDynArray);
var var
i, cnt: Integer; i, cnt: Integer;
v: Double; v: Double;
begin begin
cnt := 0; cnt := Length(AValues);
SetLength(AValues, Count); SetLength(AValues, cnt + Count);
SetLength(ATexts, Count); SetLength(ATexts, cnt + Count);
for i := 0 to Count - 1 do begin for i := 0 to Count - 1 do begin
v := IfThen(AUseY, Item[i]^.Y, Item[i]^.X); v := IfThen(AUseY, Item[i]^.Y, Item[i]^.X);
if not InRange(v, AMin, AMax) then continue; if not InRange(v, AMin, AMax) then continue;
@ -901,11 +901,12 @@ end;
procedure TIntervalChartSource.ValuesInRange( procedure TIntervalChartSource.ValuesInRange(
AMin, AMax: Double; const AFormat: String; AUseY: Boolean; AMin, AMax: Double; const AFormat: String; AUseY: Boolean;
out AValues: TDoubleDynArray; out ATexts: TStringDynArray); var AValues: TDoubleDynArray; var ATexts: TStringDynArray);
var var
i: Integer; i: Integer;
begin begin
Unused(AUseY); Unused(AUseY);
if AMin > AMax then exit;
AValues := GetIntervals(AMin, AMax, false); AValues := GetIntervals(AMin, AMax, false);
SetLength(ATexts, Length(AValues)); SetLength(ATexts, Length(AValues));
for i := 0 to High(AValues) do for i := 0 to High(AValues) do