TAChart: Fix positioning of series labels for stacked series and axis transformations.

git-svn-id: trunk@60403 -
This commit is contained in:
wp 2019-02-10 23:35:27 +00:00
parent 08360d70cd
commit f5f55eaf16

View File

@ -264,7 +264,7 @@ type
FOnCustomDrawPointer: TSeriesPointerCustomDrawEvent; FOnCustomDrawPointer: TSeriesPointerCustomDrawEvent;
FOnGetPointerStyle: TSeriesPointerStyleEvent; FOnGetPointerStyle: TSeriesPointerStyleEvent;
function GetErrorBars(AIndex: Integer): TChartErrorBar; function GetErrorBars(AIndex: Integer): TChartErrorBar;
function GetLabelDirection(AIndex: Integer; function GetLabelDirection(AValue: Double;
const ACenterLevel: Double): TLabelDirection; const ACenterLevel: Double): TLabelDirection;
function IsErrorBarsStored(AIndex: Integer): Boolean; function IsErrorBarsStored(AIndex: Integer): Boolean;
procedure SetErrorBars(AIndex: Integer; AValue: TChartErrorBar); procedure SetErrorBars(AIndex: Integer; AValue: TChartErrorBar);
@ -1282,12 +1282,12 @@ begin
lfont.Assign(Marks.LabelFont); lfont.Assign(Marks.LabelFont);
ParentChart.DisableRedrawing; ParentChart.DisableRedrawing;
ext := Extent; ext := Extent;
centerLvl := (ext.a.y + ext.b.y) * 0.5; centerLvl := AxisToGraphY((ext.a.y + ext.b.y) * 0.5);
for i := FLoBound to FUpBound do begin for i := FLoBound to FUpBound do begin
if SkipMissingValues(i) then if SkipMissingValues(i) then
continue; continue;
prev := IfThen(FSupportsZeroLevel, GetZeroLevel, TDoublePointBoolArr(ext.a)[not IsRotated]); prev := IfThen(FSupportsZeroLevel, GetZeroLevel, 0.0);
for si := 0 to Source.YCount - 1 do begin for si := 0 to Source.YCount - 1 do begin
g := GetLabelDataPoint(i, si); g := GetLabelDataPoint(i, si);
if si = 0 then begin if si = 0 then begin
@ -1335,7 +1335,7 @@ begin
DrawLabel( DrawLabel(
FormattedMark(i, '', si), FormattedMark(i, '', si),
GraphToImage(g), GraphToImage(g),
GetLabelDirection(i, centerLvl) GetLabelDirection(IfThen(IsRotated, g.X, g.Y), centerLvl)
); );
end; end;
end; end;
@ -1432,7 +1432,7 @@ begin
Result := GetGraphPoint(AIndex, 0, AYIndex); Result := GetGraphPoint(AIndex, 0, AYIndex);
end; end;
function TBasicPointSeries.GetLabelDirection(AIndex: Integer; function TBasicPointSeries.GetLabelDirection(AValue: Double;
const ACenterLevel: Double): TLabelDirection; const ACenterLevel: Double): TLabelDirection;
const const
DIR: array [Boolean, Boolean] of TLabelDirection = DIR: array [Boolean, Boolean] of TLabelDirection =
@ -1447,17 +1447,17 @@ begin
lmpOutside, lmpOutside,
lmpInside : lmpInside :
begin begin
ref := IfThen(FSupportsZeroLevel, GetZeroLevel, ACenterLevel); ref := IfThen(FSupportsZeroLevel, AxisToGraphY(GetZeroLevel), ACenterLevel);
if Source[AIndex]^.Y < ref then if AValue < ref then
isNeg := true isNeg := true
else else
if Source[AIndex]^.Y > ref then if AValue > ref then
isNeg := false isNeg := false
else else
if not FSupportsZeroLevel then if not FSupportsZeroLevel then
isNeg := false isNeg := false
else else
isNeg := Source[AIndex]^.Y < ACenterLevel; isNeg := AValue < ACenterLevel;
if MarkPositions = lmpInside then if MarkPositions = lmpInside then
isNeg := not isNeg; isNeg := not isNeg;
end; end;
@ -1859,13 +1859,14 @@ end;
procedure TBasicPointSeries.UpdateMargins( procedure TBasicPointSeries.UpdateMargins(
ADrawer: IChartDrawer; var AMargins: TRect); ADrawer: IChartDrawer; var AMargins: TRect);
var var
i, dist: Integer; i, dist, j: Integer;
labelText: String; labelText: String;
dir: TLabelDirection; dir: TLabelDirection;
m: array [TLabelDirection] of Integer absolute AMargins; m: array [TLabelDirection] of Integer absolute AMargins;
gp: TDoublePoint; gp: TDoublePoint;
scMarksDistance: Integer; scMarksDistance: Integer;
center: Double; center: Double;
ysum: Double;
begin begin
if not Marks.IsMarkLabelsVisible or not Marks.AutoMargins then exit; if not Marks.IsMarkLabelsVisible or not Marks.AutoMargins then exit;
if Count = 0 then exit; if Count = 0 then exit;
@ -1884,21 +1885,37 @@ begin
FindExtentInterval(ParentChart.CurrentExtent, Source.IsSorted); FindExtentInterval(ParentChart.CurrentExtent, Source.IsSorted);
with Extent do with Extent do
center := (a.y + b.y) * 0.5; center := AxisToGraphY((a.y + b.y) * 0.5);
scMarksDistance := ADrawer.Scale(Marks.Distance); scMarksDistance := ADrawer.Scale(Marks.Distance);
for i := FLoBound to FUpBound do begin for i := FLoBound to FUpBound do begin
j := 0;
gp := GetGraphPoint(i); gp := GetGraphPoint(i);
if not ParentChart.IsPointInViewPort(gp) then continue; while true do begin
labelText := FormattedMark(i); if not ParentChart.IsPointInViewPort(gp) then break;
if labelText = '' then continue; labelText := FormattedMark(i, '', j);
if labelText = '' then break;
dir := GetLabelDirection(i, center); dir := GetLabelDirection(TDoublePointBoolArr(gp)[not IsRotated], center);
// dir := GetLabelDirection(IfThen(IsRotated, gp.X, gp.Y), center);
with Marks.MeasureLabel(ADrawer, labelText) do with Marks.MeasureLabel(ADrawer, labelText) do
dist := IfThen(dir in [ldLeft, ldRight], cx, cy); dist := IfThen(dir in [ldLeft, ldRight], cx, cy);
if Marks.DistanceToCenter then if Marks.DistanceToCenter then
dist := dist div 2; dist := dist div 2;
m[dir] := Max(m[dir], dist + scMarksDistance); m[dir] := Max(m[dir], dist + scMarksDistance);
if (Source.YCount > 0) and (j = 0) then begin
if FStacked then begin
ysum := 0;
for j := 0 to Source.YCount-1 do
ysum += NumberOr(Source.Item[i]^.GetY(j), 0.0);
TDoublePointBoolArr(gp)[not IsRotated] := AxisToGraphY(ysum);
end else
gp := GetGraphPoint(i, 0, Source.YCount-1);
j := Source.YCount-1;
end else
break;
end;
end; end;
end; end;