TAChart: Add Marks.YIndex property, implement labels for stacked series

git-svn-id: trunk@30588 -
This commit is contained in:
ask 2011-05-06 15:27:27 +00:00
parent 88a88c1b2b
commit 553a073919
4 changed files with 58 additions and 19 deletions

View File

@ -165,7 +165,7 @@ type
function Count: Integer; inline;
procedure Delete(AIndex: Integer); virtual;
function Extent: TDoubleRect; virtual;
function FormattedMark(AIndex: Integer): String;
function FormattedMark(AIndex: Integer; AYIndex: Integer = 0): String;
function IsEmpty: Boolean; override;
function ListSource: TListChartSource;
property Source: TCustomChartSource
@ -192,7 +192,6 @@ type
function GetLabelDirection(AIndex: Integer): TLabelDirection;
procedure SetMarkPositions(AValue: TLinearMarkPositions);
procedure SetUseReticule(AValue: Boolean);
protected
FGraphPoints: array of TDoublePoint;
FLoBound: Integer;
@ -555,12 +554,12 @@ begin
Result := Source.ExtentCumulative;
end;
function TChartSeries.FormattedMark(AIndex: integer): String;
function TChartSeries.FormattedMark(AIndex, AYIndex: Integer): String;
begin
if Assigned(FOnGetMark) then
FOnGetMark(Result, AIndex)
else
Result := Source.FormatItem(Marks.Format, AIndex);
Result := Source.FormatItem(Marks.Format, AIndex, AYIndex);
end;
procedure TChartSeries.GetBounds(var ABounds: TDoubleRect);
@ -767,14 +766,26 @@ var
var
g: TDoublePoint;
i: Integer;
i, si: Integer;
ld: TLabelDirection;
begin
if not Marks.IsMarkLabelsVisible then exit;
for i := 0 to Count - 1 do begin
g := GetGraphPoint(i);
with ParentChart do
if IsPointInViewPort(g) then
DrawLabel(FormattedMark(i), GraphToImage(g), GetLabelDirection(i));
ld := GetLabelDirection(i);
for si := 0 to Source.YCount - 1 do begin
if si > 0 then
if IsRotated then
g.X += AxisToGraphY(Source[i]^.YList[si - 1])
else
g.Y += AxisToGraphY(Source[i]^.YList[si - 1]);
with ParentChart do
if
(Marks.YIndex = MARKS_YINDEX_ALL) or (Marks.YIndex = si) and
IsPointInViewPort(g)
then
DrawLabel(FormattedMark(i, si), GraphToImage(g), ld);
end;
end;
end;

View File

@ -32,11 +32,15 @@ type
// Like TColor, but avoiding dependency on Graphics.
TChartColor = -$7FFFFFFF-1..$7FFFFFFF;
TChartDataItem = record
{ TChartDataItem }
TChartDataItem = object
public
X, Y: Double;
Color: TChartColor;
Text: String;
YList: TDoubleDynArray;
function GetY(AIndex: Integer): Double;
end;
PChartDataItem = ^TChartDataItem;
@ -73,7 +77,8 @@ type
function ExtentCumulative: TDoubleRect;
function ExtentList: TDoubleRect;
procedure FindBounds(AXMin, AXMax: Double; out ALB, AUB: Integer);
function FormatItem(const AFormat: String; AIndex: Integer): String;
function FormatItem(
const AFormat: String; AIndex, AYIndex: Integer): String;
function IsSorted: Boolean; virtual;
procedure ValuesInRange(
AMin, AMax: Double; const AFormat: String; AUseY: Boolean;
@ -130,6 +135,17 @@ begin
AItem.YList[i] := 0;
end;
{ TChartDataItem }
function TChartDataItem.GetY(AIndex: Integer): Double;
begin
AIndex := EnsureRange(AIndex, 0, Length(YList));
if AIndex = 0 then
Result := Y
else
Result := YList[AIndex - 1];
end;
{ TChartSourceBuffer }
procedure TChartSourceBuffer.AddFirst(const AItem: TChartDataItem);
@ -357,19 +373,20 @@ begin
end;
function TCustomChartSource.FormatItem(
const AFormat: String; AIndex: Integer): String;
const AFormat: String; AIndex, AYIndex: Integer): String;
const
TO_PERCENT = 100;
var
total, percent: Double;
total, percent, vy: Double;
begin
total := ValuesTotal;
if total = 0 then
percent := 0
else
percent := TO_PERCENT / total;
with Item[AIndex]^ do begin
if total = 0 then
percent := 0
else
percent := Y / total * TO_PERCENT;
Result := Format(AFormat, [y, percent, Text, total, X]);
vy := GetY(AYIndex);
Result := Format(AFormat, [vy, vy * percent, Text, total, X]);
end;
end;
@ -409,7 +426,7 @@ begin
v := IfThen(AUseY, Item[i]^.Y, Item[i]^.X);
if not InRange(v, AMin, AMax) then continue;
AValues[cnt] := v;
ATexts[cnt] := FormatItem(AFormat, i);
ATexts[cnt] := FormatItem(AFormat, i, 0);
cnt += 1;
end;
SetLength(AValues, cnt);

View File

@ -1089,7 +1089,6 @@ begin
for i := 1 to n2 - 2 do
ADrawer.DrawLineDepth(pts[i], pts[i + 1], Depth);
ADrawer.Polygon(pts, 0, numPts);
DrawLabels(ADrawer);
end;
if AreaLinesPen.Style <> psClear then begin
ADrawer.Pen := AreaLinesPen;
@ -1099,6 +1098,7 @@ begin
ADrawer.Line(ParentChart.GraphToImage(a), ParentChart.GraphToImage(b));
end;
end;
DrawLabels(ADrawer);
end;
function TAreaSeries.Extent: TDoubleRect;

View File

@ -37,6 +37,7 @@ const
DEF_MARGIN = 4;
DEF_MARKS_DISTANCE = 20;
DEF_POINTER_SIZE = 4;
MARKS_YINDEX_ALL = -1;
type
TCustomChart = class(TCustomControl)
@ -130,12 +131,14 @@ type
TGenericChartMarks = class(TChartElement)
{$ENDIF}
private
FYIndex: Integer;
procedure AddMargins(ADrawer: IChartDrawer; var ASize: TPoint);
function GetDistanceToCenter: Boolean;
function LabelAngle: Double; inline;
procedure PutLabelFontTo(ADrawer: IChartDrawer);
procedure SetAttachment(AValue: TChartMarkAttachment);
procedure SetDistanceToCenter(AValue: Boolean);
procedure SetYIndex(AValue: Integer);
protected
FAdditionalAngle: Double;
FAttachment: TChartMarkAttachment;
@ -194,6 +197,7 @@ type
property Distance: TChartDistance read FDistance write SetDistance;
property LabelFont: TFont read FLabelFont write SetLabelFont;
property Visible default true;
property YIndex: Integer read FYIndex write SetYIndex default 0;
end;
TChartLinkPen = class(TChartPen)
@ -728,6 +732,13 @@ begin
StyleChanged(Self);
end;
procedure TGenericChartMarks.SetYIndex(AValue: Integer);
begin
if FYIndex = AValue then exit;
FYIndex := AValue;
StyleChanged(Self);
end;
{ TChartMarks }
procedure TChartMarks.Assign(Source: TPersistent);