mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-30 22:22:40 +02:00
TAChart: Add new TDataPointMarksClickTool
This commit is contained in:
parent
6c59e95098
commit
9f08e2006b
@ -1,16 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Project-Id-Version: tachartlazaruspkg\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: de\n"
|
||||
"X-Generator: Poedit 2.4.2\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.1\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
||||
#: tachartstrconsts.descolor
|
||||
@ -166,6 +166,10 @@ msgstr "Datenpunkt verschieben"
|
||||
msgid "Data point hint"
|
||||
msgstr "Datenpunkt-Hinweis"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr "Klick auf Datenpunkt-Markierungen"
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Entf"
|
||||
@ -217,7 +221,7 @@ msgstr "Der Typ des Ausdrucksergebnisses muss integer oder float sein, ist aber
|
||||
|
||||
#: tachartstrconsts.rserrnumericaloverflow
|
||||
msgid "Numerical overflow."
|
||||
msgstr ""
|
||||
msgstr "Numerischer Überlauf."
|
||||
|
||||
#: tachartstrconsts.rsexpressioncolormapseries
|
||||
msgid "Math expression color map series"
|
||||
@ -281,7 +285,7 @@ msgstr "Gesamte Quadratsumme (SST)"
|
||||
|
||||
#: tachartstrconsts.rsfittvalue
|
||||
msgid "t value"
|
||||
msgstr ""
|
||||
msgstr "t-Wert"
|
||||
|
||||
#: tachartstrconsts.rsfitvarianceratio
|
||||
msgid "Variance ratio F"
|
||||
@ -492,7 +496,7 @@ msgstr "Editierbare Chart-Datenquelle erforderlich"
|
||||
#: tachartstrconsts.rssourcesorterror
|
||||
#, object-pascal-format
|
||||
msgid "Selected sorting parameters are not supported by %s."
|
||||
msgstr ""
|
||||
msgstr "Die ausgewählten Sortier-Parameter werden von %s nicht unterstützt."
|
||||
|
||||
#: tachartstrconsts.rsstarsymbol
|
||||
msgid "Star (lines)"
|
||||
@ -552,4 +556,3 @@ msgstr "Fehler beim Umbenennen von Komponenten: %s"
|
||||
#: tachartstrconsts.tastoolseditortitle
|
||||
msgid "Edit tools"
|
||||
msgstr "Werkzeuge bearbeiten"
|
||||
|
||||
|
@ -154,6 +154,10 @@ msgstr "Datapisteen vetäminen"
|
||||
msgid "Data point hint"
|
||||
msgstr "Datapisteen vihje"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Poista"
|
||||
|
@ -164,6 +164,10 @@ msgstr "Glissement de point de donnée"
|
||||
msgid "Data point hint"
|
||||
msgstr "Indicateur de point de données"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
@ -164,6 +164,10 @@ msgstr "Adatpont húzása"
|
||||
msgid "Data point hint"
|
||||
msgstr "Adatpont tipp"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Törlés"
|
||||
|
@ -165,6 +165,10 @@ msgstr "Duomenų taško vilkimas"
|
||||
msgid "Data point hint"
|
||||
msgstr "Duomenų taško sufleris"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Naikinti"
|
||||
|
@ -164,6 +164,10 @@ msgstr ""
|
||||
msgid "Data point hint"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Usuń"
|
||||
|
@ -154,6 +154,10 @@ msgstr ""
|
||||
msgid "Data point hint"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
@ -164,6 +164,10 @@ msgstr "Arrasto ponto de dados"
|
||||
msgid "Data point hint"
|
||||
msgstr "Dica ponto de dados"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Excluir"
|
||||
|
@ -164,6 +164,10 @@ msgstr "Перетаскивание величины"
|
||||
msgid "Data point hint"
|
||||
msgstr "Всплывающая подсказка для величины"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Удалить"
|
||||
|
@ -167,6 +167,10 @@ msgstr "Flytta datapunkt"
|
||||
msgid "Data point hint"
|
||||
msgstr "Datapunkt tips"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Radera"
|
||||
|
@ -167,6 +167,10 @@ msgstr "Перетягування точки даних"
|
||||
msgid "Data point hint"
|
||||
msgstr "Спливна підказка точки даних"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "Видалити"
|
||||
|
@ -165,6 +165,10 @@ msgstr "数据点拖拽"
|
||||
msgid "Data point hint"
|
||||
msgstr "数据点提示"
|
||||
|
||||
#: tachartstrconsts.rsdatapointmarksclicktool
|
||||
msgid "Data point marks click"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rsdelete
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
@ -69,6 +69,7 @@ resourcestring
|
||||
rsDataPointDrag = 'Data point drag';
|
||||
rsDataPointHint = 'Data point hint';
|
||||
rsDataPointCrossHair = 'Data point crosshair';
|
||||
rsDataPointMarksClickTool = 'Data point marks click';
|
||||
rsUserDefinedTool = 'User-defined';
|
||||
rsDistanceMeasurement = 'Distance measurement';
|
||||
rsAxisClickTool = 'Axis click';
|
||||
|
@ -352,6 +352,8 @@ type
|
||||
function GetNearestPoint(
|
||||
const AParams: TNearestPointParams;
|
||||
out AResults: TNearestPointResults): Boolean; override;
|
||||
function IsPointInLabel(ADrawer: IChartDrawer; const APoint: TPoint;
|
||||
var APointIndex, AYIndex: Integer): Boolean;
|
||||
procedure MovePoint(var AIndex: Integer; const ANewPos: TDoublePoint); override;
|
||||
procedure MovePointEx(var AIndex: Integer; AXIndex, AYIndex: Integer;
|
||||
const ANewPos: TDoublePoint); override;
|
||||
@ -1321,6 +1323,135 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBasicPointSeries.IsPointInLabel(ADrawer: IChartDrawer;
|
||||
const APoint: TPoint; var APointIndex, AYIndex: Integer): Boolean;
|
||||
const
|
||||
OFFSETS: array [TLabelDirection] of TPoint = (
|
||||
(X: -1; Y: 0),
|
||||
(X: 0; Y: -1),
|
||||
(X: 1; Y: 0),
|
||||
(X: 0; Y: 1)
|
||||
);
|
||||
var
|
||||
y, ysum: Double;
|
||||
g: TDoublePoint;
|
||||
pt: TPoint;
|
||||
i, si: Integer;
|
||||
style: TChartStyle;
|
||||
lfont: TFont;
|
||||
curr, prev: Double;
|
||||
ext: TDoubleRect;
|
||||
yIsNaN: Boolean;
|
||||
centerLvl: Double;
|
||||
center: TPoint;
|
||||
dir: TLabelDirection;
|
||||
txt: String;
|
||||
begin
|
||||
Result := false;
|
||||
if not Marks.IsMarkLabelsVisible then exit;
|
||||
|
||||
lfont := TFont.Create;
|
||||
try
|
||||
lfont.Assign(Marks.LabelFont);
|
||||
ext := Extent;
|
||||
centerLvl := AxisToGraphY((ext.a.y + ext.b.y) * 0.5);
|
||||
UpdateLabelDirectionReferenceLevel(0, 0, centerLvl);
|
||||
|
||||
for i := FLoBound to FUpBound do begin
|
||||
if SkipMissingValues(i) then
|
||||
continue;
|
||||
prev := IfThen(FSupportsZeroLevel, GetZeroLevel, 0.0);
|
||||
for si := 0 to Source.YCount - 1 do begin
|
||||
g := GetLabelDataPoint(i, si);
|
||||
if FStacked then begin
|
||||
if si = 0 then begin
|
||||
y := Source[i]^.Y;
|
||||
yIsNaN := IsNaN(y);
|
||||
ysum := IfThen(yIsNaN, prev, y);
|
||||
end else begin
|
||||
y := Source[i]^.YList[si-1];
|
||||
yIsNaN := IsNaN(y);
|
||||
if yIsNaN then y := 0.0;
|
||||
if Stacked then begin
|
||||
ysum += y;
|
||||
y := ysum;
|
||||
end;
|
||||
end;
|
||||
if IsRotated then
|
||||
g.X := AxisToGraphY(y)
|
||||
// Axis-to-graph transformation is independent of axis rotation ->
|
||||
// Using AxisToGraph_Y_ is correct!
|
||||
else
|
||||
g.Y := AxisToGraphY(y);
|
||||
end else
|
||||
yIsNaN := IsNaN(g.y);
|
||||
|
||||
txt := FormattedMark(i, '', si);
|
||||
if txt = '' then
|
||||
continue;
|
||||
|
||||
curr := TDoublePointBoolArr(g)[not IsRotated];
|
||||
if FMarkPositionCentered then begin
|
||||
if IsRotated then
|
||||
g := DoublePoint((curr + prev) * 0.5, g.y)
|
||||
else
|
||||
g := DoublePoint(g.x, (curr + prev) * 0.5);
|
||||
end;
|
||||
if Stacked then
|
||||
prev := curr;
|
||||
|
||||
// check only the requested y index
|
||||
if (AYIndex >= 0) then begin
|
||||
if si < AYIndex then
|
||||
Continue
|
||||
else if si > AYIndex then
|
||||
break;
|
||||
end;
|
||||
|
||||
with ParentChart do
|
||||
if
|
||||
((Marks.YIndex = MARKS_YINDEX_ALL) or (Marks.YIndex = si)) and
|
||||
IsPointInViewPort(g) and (not yIsNaN)
|
||||
then begin
|
||||
if Styles <> nil then begin
|
||||
style := Styles.StyleByIndex(si);
|
||||
if style.UseFont then
|
||||
Marks.LabelFont.Assign(style.Font)
|
||||
else
|
||||
Marks.LabelFont.Assign(lfont);
|
||||
end;
|
||||
UpdateLabelDirectionReferenceLevel(i, si, centerLvl);
|
||||
dir := GetLabelDirection(IfThen(IsRotated, g.X, g.Y), centerLvl);
|
||||
pt := GraphToImage(g);
|
||||
if Marks.RotationCenter = rcCenter then
|
||||
center := pt + OFFSETS[dir] * Marks.CenterOffset(ADrawer, txt)
|
||||
else
|
||||
center := pt + OFFSETS[dir] * Marks.CenterHeightOffset(ADrawer, txt);
|
||||
|
||||
Result := Marks.IsPointInLabel(
|
||||
ADrawer,
|
||||
APoint,
|
||||
pt,
|
||||
center,
|
||||
txt
|
||||
);
|
||||
if Result then
|
||||
begin
|
||||
APointIndex := i;
|
||||
AYIndex := si;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
finally
|
||||
Marks.LabelFont.Assign(lfont);
|
||||
ParentChart.EnableRedrawing;
|
||||
lfont.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBasicPointSeries.DrawLabels(ADrawer: IChartDrawer; AYIndex: Integer = -1);
|
||||
// Using AYIndex is workaround for issue #35077
|
||||
var
|
||||
|
@ -352,7 +352,7 @@ type
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Draw(ADrawer: IChartDrawer); override;
|
||||
function GetAxisBounds(AAxis: TChartAxis; out AMin, AMax: Double): Boolean; override;
|
||||
function GetAxisBounds({%H-}AAxis: TChartAxis; out {%H-}AMin, {%H-}AMax: Double): Boolean; override;
|
||||
function GetNearestPoint(
|
||||
const AParams: TNearestPointParams;
|
||||
out AResults: TNearestPointResults): Boolean; override;
|
||||
|
@ -97,6 +97,8 @@ type
|
||||
function GetLabelPolygon(
|
||||
ADrawer: IChartDrawer; ASize: TPoint): TPointArray;
|
||||
function GetTextRect: TRect;
|
||||
function IsPointInLabel(ADrawer: IChartDrawer;
|
||||
const APoint, ADataPoint, ALabelCenter: TPoint; const AText: String): Boolean;
|
||||
function MeasureLabel(ADrawer: IChartDrawer; const AText: String): TSize;
|
||||
function MeasureLabelHeight(ADrawer: IChartDrawer; const AText: String): TSize;
|
||||
procedure SetInsideDir(dx, dy: Double);
|
||||
@ -497,6 +499,24 @@ begin
|
||||
Result := DotProduct(textdir, FInsideDir) > 0;
|
||||
end;
|
||||
|
||||
function TChartTextElement.IsPointInLabel(ADrawer: IChartDrawer;
|
||||
const APoint, ADataPoint, ALabelCenter: TPoint; const AText: String): Boolean;
|
||||
var
|
||||
labelPoly: TPointArray;
|
||||
ptText: TPoint;
|
||||
i: Integer;
|
||||
begin
|
||||
ApplyLabelFont(ADrawer);
|
||||
ptText := ADrawer.TextExtent(AText, FTextFormat);
|
||||
labelPoly := GetLabelPolygon(ADrawer, ptText);
|
||||
for i := 0 to High(labelPoly) do
|
||||
labelPoly[i] += ALabelCenter;
|
||||
if CalloutAngle > 0 then
|
||||
labelPoly := MakeCallout(labelPoly, ALabelCenter, ADataPoint, OrientToRad(CalloutAngle));
|
||||
|
||||
Result := IsPointInPolygon(APoint, labelPoly);
|
||||
end;
|
||||
|
||||
function TChartTextElement.IsMarginRequired: Boolean;
|
||||
begin
|
||||
Result := (GetLabelBrush.Style <> bsClear) or GetFrame.EffVisible;
|
||||
|
@ -22,7 +22,7 @@ uses
|
||||
Controls, CustomTimer, {GraphMath,} Forms, LCLPlatformDef, InterfaceBase,
|
||||
LCLType, LCLIntf,
|
||||
// TAChart
|
||||
TAChartUtils, TADrawUtils, TAChartAxis, TALegend, TAGraph,
|
||||
TAChartUtils, TADrawUtils, TAChartAxis, TALegend, TACustomSeries, TAGraph,
|
||||
TATypes, TATextElements;
|
||||
|
||||
type
|
||||
@ -427,7 +427,7 @@ type
|
||||
FXIndex: Integer;
|
||||
FYIndex: Integer;
|
||||
FSeries: TBasicChartSeries;
|
||||
procedure FindNearestPoint(APoint: TPoint);
|
||||
procedure FindNearestPoint(APoint: TPoint); virtual;
|
||||
property MouseInsideOnly: Boolean
|
||||
read FMouseInsideOnly write FMouseInsideOnly default false;
|
||||
property Targets: TNearestPointTargets
|
||||
@ -481,6 +481,7 @@ type
|
||||
read FOnDragStart write FOnDragStart;
|
||||
end;
|
||||
|
||||
|
||||
{ TDataPointClickTool }
|
||||
|
||||
TDataPointClickTool = class(TDataPointTool)
|
||||
@ -497,6 +498,14 @@ type
|
||||
read FOnPointClick write FOnPointClick;
|
||||
end;
|
||||
|
||||
|
||||
{ TDataPointMarksClickTool }
|
||||
|
||||
TDataPointMarksClickTool = class(TDataPointClickTool)
|
||||
strict protected
|
||||
procedure FindNearestPoint(APoint: TPoint); override;
|
||||
end;
|
||||
|
||||
TDataPointHintTool = class;
|
||||
|
||||
TChartToolHintEvent = procedure (
|
||||
@ -583,10 +592,10 @@ type
|
||||
property MouseInsideOnly;
|
||||
end;
|
||||
|
||||
TChartCrosshairShape = (ccsNone, ccsVertical, ccsHorizontal, ccsCross);
|
||||
|
||||
{ TDataPointCrossHairTool }
|
||||
|
||||
TChartCrosshairShape = (ccsNone, ccsVertical, ccsHorizontal, ccsCross);
|
||||
|
||||
TDataPointCrosshairTool = class(TDataPointDrawTool)
|
||||
strict private
|
||||
FPosition: TDoublePoint;
|
||||
@ -609,7 +618,10 @@ type
|
||||
property Size: Integer read FSize write FSize default -1;
|
||||
property Targets;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ TAxisClickTool }
|
||||
|
||||
TAxisClickEvent = procedure (ASender: TChartTool; Axis: TChartAxis;
|
||||
AHitInfo: TChartAxisHitTests) of object;
|
||||
|
||||
@ -630,6 +642,8 @@ type
|
||||
property OnClick: TAxisClickEvent read FOnClick write FOnClick;
|
||||
end;
|
||||
|
||||
{ TTitleFootClickTool }
|
||||
|
||||
TTitleFootClickEvent = procedure (ASender: TChartTool;
|
||||
ATitle: TChartTitle) of object;
|
||||
|
||||
@ -647,6 +661,8 @@ type
|
||||
property OnClick: TTitleFootClickEvent read FOnClick write FOnClick;
|
||||
end;
|
||||
|
||||
{ TLegendClickTool }
|
||||
|
||||
TLegendClickEvent = procedure (ASender: TChartTool;
|
||||
ALegend: TChartLegend) of object;
|
||||
TLegendSeriesClickEvent = procedure (ASender: TChartTool;
|
||||
@ -681,7 +697,7 @@ implementation
|
||||
|
||||
uses
|
||||
LResources,
|
||||
TAChartStrConsts, TACustomSeries, TAEnumerators, TAGeometry, TAMath;
|
||||
TAChartStrConsts, TAEnumerators, TAGeometry, TAMath;
|
||||
|
||||
function InitBuiltinTools(AChart: TChart): TBasicChartToolset;
|
||||
var
|
||||
@ -1997,6 +2013,34 @@ begin
|
||||
Handled;
|
||||
end;
|
||||
|
||||
|
||||
{ TDataPointMarksClickTool }
|
||||
|
||||
procedure TDataPointMarksClickTool.FindNearestPoint(APoint: TPoint);
|
||||
var
|
||||
ser: TBasicPointSeries;
|
||||
i: Integer;
|
||||
begin
|
||||
FSeries := nil;
|
||||
FPointIndex := -1;
|
||||
FYIndex := -1;
|
||||
|
||||
for i := 0 to FChart.SeriesCount-1 do
|
||||
begin
|
||||
if not (FChart.Series[i] is TBasicChartSeries) then
|
||||
continue;
|
||||
ser := TBasicPointSeries(FChart.Series[i]);
|
||||
if ser.Active and ser.IsPointInLabel(FChart.Drawer, APoint, FPointIndex, FYIndex) then
|
||||
begin
|
||||
FSeries := ser;
|
||||
FXIndex := 0; // to do: fix X index
|
||||
FNearestGraphPoint := FChart.ImageToGraph(APoint);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ TDataPointHintTool }
|
||||
|
||||
constructor TDataPointHintTool.Create(AOwner: TComponent);
|
||||
@ -2421,6 +2465,7 @@ initialization
|
||||
RegisterChartToolClass(TDataPointDragTool, @rsDataPointDrag);
|
||||
RegisterChartToolClass(TDataPointHintTool, @rsDataPointHint);
|
||||
RegisterChartToolClass(TDataPointCrosshairTool, @rsDataPointCrosshair);
|
||||
RegisterChartToolClass(TDataPointMarksClickTool, @rsDataPointMarksClickTool);
|
||||
RegisterChartToolClass(TAxisClickTool, @rsAxisClickTool);
|
||||
RegisterChartToolClass(TTitleFootClickTool, @rsHeaderFooterClickTool);
|
||||
RegisterChartToolClass(TLegendClickTool, @rsLegendClickTool);
|
||||
|
Loading…
Reference in New Issue
Block a user