mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-30 12:12:47 +02:00
TAChart: New event OnSeriesClick for TLegendClickTool to report series of clicked legend item. Issue #39437.
This commit is contained in:
parent
49a220e7c3
commit
6422aaa213
@ -173,6 +173,7 @@ type
|
||||
strict private
|
||||
FAlignment: TLegendAlignment;
|
||||
FBackgroundBrush: TChartLegendBrush;
|
||||
FColCount: Integer;
|
||||
FColumnCount: TLegendColumnCount;
|
||||
FFixedItemWidth: Cardinal;
|
||||
FFixedItemHeight: Cardinal;
|
||||
@ -184,9 +185,11 @@ type
|
||||
FGroupTitles: TStrings;
|
||||
FInverted: Boolean;
|
||||
FItemFillOrder: TLegendItemFillOrder;
|
||||
FItemSize: TPoint;
|
||||
FLegendRect: TRect;
|
||||
FMarginX: TChartDistance;
|
||||
FMarginY: TChartDistance;
|
||||
FRowCount: Integer;
|
||||
FSpacing: TChartDistance;
|
||||
FSymbolFrame: TChartPen;
|
||||
FSymbolWidth: TChartDistance;
|
||||
@ -227,6 +230,7 @@ type
|
||||
procedure Assign(Source: TPersistent); override;
|
||||
procedure Draw(var AData: TChartLegendDrawingData);
|
||||
function IsPointInBounds(APoint: TPoint): Boolean;
|
||||
function ItemClicked(ADrawer: IChartDrawer; APoint: TPoint; AItems: TChartLegendItems): Integer;
|
||||
procedure Prepare(var AData: TChartLegendDrawingData; var AClipRect: TRect);
|
||||
procedure SortItemsByOrder(AItems: TChartLegendItems);
|
||||
procedure UpdateBidiMode;
|
||||
@ -731,6 +735,62 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TChartLegend.IsPointInBounds(APoint: TPoint): Boolean;
|
||||
begin
|
||||
Result := IsPointInRect(APoint, FLegendRect);
|
||||
end;
|
||||
|
||||
function TChartLegend.ItemClicked(ADrawer: IChartDrawer; APoint: TPoint;
|
||||
AItems: TChartLegendItems): Integer;
|
||||
var
|
||||
i, x, y: Integer;
|
||||
prevFont: TFont = nil;
|
||||
r: TRect;
|
||||
isRTL: Boolean;
|
||||
space, symwid: Integer;
|
||||
data: TChartLegendDrawingData;
|
||||
begin
|
||||
with data do begin
|
||||
FDrawer := ADrawer;
|
||||
FBounds := Self.FLegendRect;
|
||||
FColCount := Self.FColCount;
|
||||
FItems := AItems;
|
||||
FItemSize := Self.FItemSize;
|
||||
FRowCount := Self.FRowCount;
|
||||
isRTL := FDrawer.GetRightToLeft;
|
||||
space := FDrawer.Scale(Spacing);
|
||||
symwid := FDrawer.Scale(SymbolWidth);
|
||||
for i := 0 to FItems.Count - 1 do begin
|
||||
FItems[i].UpdateFont(FDrawer, prevFont);
|
||||
x := 0;
|
||||
y := 0;
|
||||
case ItemFillOrder of
|
||||
lfoColRow: DivMod(i, FRowCount, x, y);
|
||||
lfoRowCol: DivMod(i, FColCount, y, x);
|
||||
end;
|
||||
if isRTL then
|
||||
r := Bounds(
|
||||
FBounds.Right - space - (x+1) * (FItemSize.X + space),
|
||||
FBounds.Top + space + y * (FItemSize.Y + space),
|
||||
symwid + Space + FItemSize.X,
|
||||
FItemSize.Y)
|
||||
else
|
||||
r := Bounds(
|
||||
FBounds.Left + space + x * (FItemSize.X + space) - symwid,
|
||||
FBounds.Top + space + y * (FItemSize.Y + space),
|
||||
symwid + space + FItemSize.X ,
|
||||
FItemSize.Y);
|
||||
if PtInRect(r, APoint) then
|
||||
begin
|
||||
Result := i;
|
||||
exit;
|
||||
end;
|
||||
OffsetRect(r, 0, FItemSize.Y + space);
|
||||
end;
|
||||
end;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TChartLegend.MeasureItem(
|
||||
ADrawer: IChartDrawer; AItems: TChartLegendItems): TPoint;
|
||||
var
|
||||
@ -756,11 +816,6 @@ begin
|
||||
Result.Y := ADrawer.Scale(FixedItemHeight);
|
||||
end;
|
||||
|
||||
function TChartLegend.IsPointInBounds(APoint: TPoint): Boolean;
|
||||
begin
|
||||
Result := IsPointInRect(APoint, FLegendRect);
|
||||
end;
|
||||
|
||||
procedure TChartLegend.Prepare(
|
||||
var AData: TChartLegendDrawingData; var AClipRect: TRect);
|
||||
var
|
||||
@ -775,6 +830,9 @@ begin
|
||||
FColCount := Max(Min(ColumnCount, FItems.Count), 1);
|
||||
FRowCount := (FItems.Count - 1) div FColCount + 1;
|
||||
FItemSize := MeasureItem(FDrawer, FItems);
|
||||
Self.FItemSize := FItemSize;
|
||||
Self.FColCount := FColCount;
|
||||
Self.FRowCount := FRowCount;
|
||||
legendSize.X := (FItemSize.X + space) * FColCount + space;
|
||||
legendSize.Y := (FItemSize.Y + space) * FRowCount + space;
|
||||
end;
|
||||
|
@ -649,10 +649,13 @@ type
|
||||
|
||||
TLegendClickEvent = procedure (ASender: TChartTool;
|
||||
ALegend: TChartLegend) of object;
|
||||
TLegendSeriesClickEvent = procedure (ASender: TChartTool;
|
||||
ALegend: TChartLegend; ASeries: TBasicChartSeries) of object;
|
||||
|
||||
TLegendClickTool = class(TChartTool)
|
||||
private
|
||||
FOnClick: TLegendClickEvent;
|
||||
FOnSeriesClick: TLegendSeriesClickEvent;
|
||||
FLegend: TChartLegend;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
@ -660,6 +663,7 @@ type
|
||||
procedure MouseUp(APoint: TPoint); override;
|
||||
published
|
||||
property OnClick: TLegendClickEvent read FOnClick write FOnClick;
|
||||
property OnSeriesClick: TLegendSeriesClickEvent read FOnSeriesClick write FOnSeriesClick;
|
||||
end;
|
||||
|
||||
|
||||
@ -2339,19 +2343,45 @@ end;
|
||||
|
||||
procedure TLegendClickTool.MouseDown(APoint: TPoint);
|
||||
begin
|
||||
if FChart.Legend.IsPointInBounds(APoint) then begin
|
||||
if Assigned(FChart.Legend) and FChart.Legend.IsPointInBounds(APoint) then begin
|
||||
Activate;
|
||||
Handled;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLegendClickTool.MouseUp(APoint: TPoint);
|
||||
var
|
||||
li: TLegendItem;
|
||||
idx: Integer;
|
||||
ser: TBasicChartSeries;
|
||||
items: TChartLegendItems;
|
||||
begin
|
||||
if IsActive and FChart.Legend.IsPointInBounds(APoint) then begin
|
||||
FLegend := FChart.Legend;
|
||||
if Assigned(FOnClick) and (FLegend <> nil) then FOnClick(Self, FLegend);
|
||||
end else
|
||||
if not (IsActive and Assigned(FChart.Legend)) then
|
||||
begin
|
||||
FLegend := nil;
|
||||
exit;
|
||||
end;
|
||||
|
||||
FLegend := FChart.Legend;
|
||||
|
||||
if Assigned(FOnClick) and FLegend.IsPointInBounds(APoint) then
|
||||
FOnClick(Self, FLegend);
|
||||
|
||||
if Assigned(FOnSeriesClick) then
|
||||
begin
|
||||
try
|
||||
items := FChart.GetLegendItems;
|
||||
idx := FLegend.ItemClicked(FChart.Drawer, APoint, items);
|
||||
if idx <> -1 then
|
||||
begin
|
||||
ser := TBasicChartSeries(items[idx].Owner);
|
||||
if Assigned(ser) then
|
||||
FOnSeriesClick(Self, FLegend, ser);
|
||||
end;
|
||||
finally
|
||||
items.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ -------- }
|
||||
|
Loading…
Reference in New Issue
Block a user