diff --git a/components/tachart/languages/tachartstrconsts.de.po b/components/tachart/languages/tachartstrconsts.de.po index 4219303b3c..18e3c31ce6 100644 --- a/components/tachart/languages/tachartstrconsts.de.po +++ b/components/tachart/languages/tachartstrconsts.de.po @@ -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" - diff --git a/components/tachart/languages/tachartstrconsts.fi.po b/components/tachart/languages/tachartstrconsts.fi.po index aef8ceb0e9..6b45ed9127 100644 --- a/components/tachart/languages/tachartstrconsts.fi.po +++ b/components/tachart/languages/tachartstrconsts.fi.po @@ -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" diff --git a/components/tachart/languages/tachartstrconsts.fr.po b/components/tachart/languages/tachartstrconsts.fr.po index e03a4d0cb9..18eeee83d4 100644 --- a/components/tachart/languages/tachartstrconsts.fr.po +++ b/components/tachart/languages/tachartstrconsts.fr.po @@ -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" diff --git a/components/tachart/languages/tachartstrconsts.hu.po b/components/tachart/languages/tachartstrconsts.hu.po index 928844cf44..39d4b9c204 100644 --- a/components/tachart/languages/tachartstrconsts.hu.po +++ b/components/tachart/languages/tachartstrconsts.hu.po @@ -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" diff --git a/components/tachart/languages/tachartstrconsts.lt.po b/components/tachart/languages/tachartstrconsts.lt.po index ce21f8c7e3..e78f97549c 100644 --- a/components/tachart/languages/tachartstrconsts.lt.po +++ b/components/tachart/languages/tachartstrconsts.lt.po @@ -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" diff --git a/components/tachart/languages/tachartstrconsts.pl.po b/components/tachart/languages/tachartstrconsts.pl.po index 0a6a198001..46e062b181 100644 --- a/components/tachart/languages/tachartstrconsts.pl.po +++ b/components/tachart/languages/tachartstrconsts.pl.po @@ -164,6 +164,10 @@ msgstr "" msgid "Data point hint" msgstr "" +#: tachartstrconsts.rsdatapointmarksclicktool +msgid "Data point marks click" +msgstr "" + #: tachartstrconsts.rsdelete msgid "Delete" msgstr "Usuń" diff --git a/components/tachart/languages/tachartstrconsts.pot b/components/tachart/languages/tachartstrconsts.pot index e0ad0d50fd..af57b718eb 100644 --- a/components/tachart/languages/tachartstrconsts.pot +++ b/components/tachart/languages/tachartstrconsts.pot @@ -154,6 +154,10 @@ msgstr "" msgid "Data point hint" msgstr "" +#: tachartstrconsts.rsdatapointmarksclicktool +msgid "Data point marks click" +msgstr "" + #: tachartstrconsts.rsdelete msgid "Delete" msgstr "" diff --git a/components/tachart/languages/tachartstrconsts.pt_BR.po b/components/tachart/languages/tachartstrconsts.pt_BR.po index fa33a112cb..dfbd77a1db 100644 --- a/components/tachart/languages/tachartstrconsts.pt_BR.po +++ b/components/tachart/languages/tachartstrconsts.pt_BR.po @@ -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" diff --git a/components/tachart/languages/tachartstrconsts.ru.po b/components/tachart/languages/tachartstrconsts.ru.po index 121fa473b5..0631ff3881 100644 --- a/components/tachart/languages/tachartstrconsts.ru.po +++ b/components/tachart/languages/tachartstrconsts.ru.po @@ -164,6 +164,10 @@ msgstr "Перетаскивание величины" msgid "Data point hint" msgstr "Всплывающая подсказка для величины" +#: tachartstrconsts.rsdatapointmarksclicktool +msgid "Data point marks click" +msgstr "" + #: tachartstrconsts.rsdelete msgid "Delete" msgstr "Удалить" diff --git a/components/tachart/languages/tachartstrconsts.se.po b/components/tachart/languages/tachartstrconsts.se.po index d1b70a09e5..7c7ced1337 100644 --- a/components/tachart/languages/tachartstrconsts.se.po +++ b/components/tachart/languages/tachartstrconsts.se.po @@ -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" diff --git a/components/tachart/languages/tachartstrconsts.uk.po b/components/tachart/languages/tachartstrconsts.uk.po index 5026093b43..bb63964fb5 100644 --- a/components/tachart/languages/tachartstrconsts.uk.po +++ b/components/tachart/languages/tachartstrconsts.uk.po @@ -167,6 +167,10 @@ msgstr "Перетягування точки даних" msgid "Data point hint" msgstr "Спливна підказка точки даних" +#: tachartstrconsts.rsdatapointmarksclicktool +msgid "Data point marks click" +msgstr "" + #: tachartstrconsts.rsdelete msgid "Delete" msgstr "Видалити" diff --git a/components/tachart/languages/tachartstrconsts.zh_CN.po b/components/tachart/languages/tachartstrconsts.zh_CN.po index 812583c0fd..1e92f2de3b 100644 --- a/components/tachart/languages/tachartstrconsts.zh_CN.po +++ b/components/tachart/languages/tachartstrconsts.zh_CN.po @@ -165,6 +165,10 @@ msgstr "数据点拖拽" msgid "Data point hint" msgstr "数据点提示" +#: tachartstrconsts.rsdatapointmarksclicktool +msgid "Data point marks click" +msgstr "" + #: tachartstrconsts.rsdelete msgid "Delete" msgstr "删除" diff --git a/components/tachart/tachartstrconsts.pas b/components/tachart/tachartstrconsts.pas index bb9a1372f9..4fd6563e42 100644 --- a/components/tachart/tachartstrconsts.pas +++ b/components/tachart/tachartstrconsts.pas @@ -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'; diff --git a/components/tachart/tacustomseries.pas b/components/tachart/tacustomseries.pas index a51551794b..7ee834910b 100644 --- a/components/tachart/tacustomseries.pas +++ b/components/tachart/tacustomseries.pas @@ -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 diff --git a/components/tachart/taseries.pas b/components/tachart/taseries.pas index 566574bdb5..bfb5d38323 100644 --- a/components/tachart/taseries.pas +++ b/components/tachart/taseries.pas @@ -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; diff --git a/components/tachart/tatextelements.pas b/components/tachart/tatextelements.pas index 58cea71c64..a705e93478 100644 --- a/components/tachart/tatextelements.pas +++ b/components/tachart/tatextelements.pas @@ -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; diff --git a/components/tachart/tatools.pas b/components/tachart/tatools.pas index 2a9a392ef3..0a8908c191 100644 --- a/components/tachart/tatools.pas +++ b/components/tachart/tatools.pas @@ -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);