TAChart: add code to legenddemo to demonstrate the ownerdrawn legend, fix some layout issues.

git-svn-id: trunk@44588 -
This commit is contained in:
wp 2014-04-02 21:35:16 +00:00
parent e7ed3a5bce
commit de8f43032c
3 changed files with 432 additions and 250 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>

View File

@ -1,257 +1,320 @@
object Form1: TForm1
Left = 1322
Height = 438
Top = 181
Width = 510
Left = 529
Height = 511
Top = 174
Width = 590
Caption = 'Form1'
ClientHeight = 438
ClientWidth = 510
ClientHeight = 511
ClientWidth = 590
OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poScreenCenter
LCLVersion = '1.1'
object Chart1: TChart
LCLVersion = '1.3'
object PageControl1: TPageControl
Left = 0
Height = 304
Height = 511
Top = 0
Width = 510
AxisList = <
item
Visible = False
Minors = <>
Title.LabelFont.Orientation = 900
end
item
Visible = False
Alignment = calBottom
Minors = <>
end>
BackColor = clSkyBlue
Foot.Brush.Color = clBtnFace
Foot.Font.Color = clBlue
Legend.BackgroundBrush.Color = clMoneyGreen
Legend.GridHorizontal.Style = psDot
Legend.GridVertical.Style = psDot
Legend.GroupFont.Style = [fsBold]
Legend.GroupTitles.Strings = (
'Pie'
)
Legend.Visible = True
Title.Brush.Color = clBtnFace
Title.Font.Color = clBlue
Title.Text.Strings = (
'TAChart'
)
Width = 590
ActivePage = TabSheet1
Align = alClient
Color = clOlive
ParentColor = False
object Chart1LineSeries1: TLineSeries
Title = 'Line'
LinePen.Color = clRed
Pointer.Brush.Color = clRed
ShowPoints = True
TabIndex = 0
TabOrder = 0
object TabSheet1: TTabSheet
Caption = 'Basic'
ClientHeight = 483
ClientWidth = 582
object pnControls: TPanel
Left = 0
Height = 134
Top = 349
Width = 582
Align = alBottom
ClientHeight = 134
ClientWidth = 582
TabOrder = 0
object lblMarginY: TLabel
Left = 8
Height = 15
Top = 33
Width = 48
Caption = 'Y margin'
ParentColor = False
end
object seMarginY: TSpinEdit
Left = 68
Height = 23
Top = 33
Width = 54
MaxValue = 20
OnChange = seMarginYChange
TabOrder = 0
Value = 4
end
object seSymbolWidth: TSpinEdit
Left = 212
Height = 23
Top = 8
Width = 54
MaxValue = 50
OnChange = seSymbolWidthChange
TabOrder = 1
Value = 20
end
object lblSymbolWidth: TLabel
Left = 128
Height = 15
Top = 8
Width = 73
Caption = 'Symbol width'
ParentColor = False
end
object rgAlignment: TRadioGroup
Left = 283
Height = 132
Top = 1
Width = 298
Align = alRight
AutoFill = True
Caption = ' Alignment '
ChildSizing.LeftRightSpacing = 6
ChildSizing.TopBottomSpacing = 6
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
ChildSizing.EnlargeVertical = crsHomogenousChildResize
ChildSizing.ShrinkHorizontal = crsScaleChilds
ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclTopToBottomThenLeftToRight
ChildSizing.ControlsPerLine = 3
ClientHeight = 114
ClientWidth = 294
Columns = 3
ItemIndex = 6
Items.Strings = (
'TopLeft'
'CenterLeft'
'BottomLeft'
'TopCenter'
''
'BottomCenter'
'TopRight'
'CenterRight'
'BottomRight'
)
OnClick = rgAlignmentClick
TabOrder = 2
end
object cbUseSidebar: TCheckBox
Left = 8
Height = 19
Top = 60
Width = 59
Caption = 'Sidebar'
Checked = True
OnChange = cbUseSidebarChange
State = cbChecked
TabOrder = 3
end
object lblSpacing: TLabel
Left = 128
Height = 15
Top = 33
Width = 42
Caption = 'Spacing'
ParentColor = False
end
object seSpacing: TSpinEdit
Left = 212
Height = 23
Top = 33
Width = 54
MaxValue = 20
OnChange = seSpacingChange
TabOrder = 4
Value = 4
end
object lblMarginX: TLabel
Left = 8
Height = 15
Top = 8
Width = 48
Caption = 'X margin'
ParentColor = False
end
object seMarginX: TSpinEdit
Left = 68
Height = 23
Top = 8
Width = 54
MaxValue = 20
OnChange = seMarginXChange
TabOrder = 5
Value = 4
end
object cbSeries: TComboBox
Left = 102
Height = 22
Top = 91
Width = 164
ItemHeight = 16
OnDrawItem = cbSeriesDrawItem
ReadOnly = True
Style = csOwnerDrawFixed
TabOrder = 6
end
object lblColumnCount: TLabel
Left = 128
Height = 15
Top = 60
Width = 48
Caption = 'Columns'
ParentColor = False
end
object seColumnCount: TSpinEdit
Left = 212
Height = 23
Top = 60
Width = 54
MinValue = 1
OnChange = seColumnCountChange
TabOrder = 7
Value = 1
end
object cbByRows: TCheckBox
Left = 8
Height = 19
Top = 84
Width = 61
Caption = 'By rows'
OnChange = cbByRowsChange
TabOrder = 8
end
object cbGrid: TCheckBox
Left = 8
Height = 19
Top = 108
Width = 42
Caption = 'Grid'
OnChange = cbGridChange
TabOrder = 9
end
end
object Chart1: TChart
Left = 0
Height = 349
Top = 0
Width = 582
AxisList = <
item
Visible = False
Minors = <>
Title.LabelFont.Orientation = 900
end
item
Visible = False
Alignment = calBottom
Minors = <>
end>
BackColor = clSkyBlue
Foot.Brush.Color = clBtnFace
Foot.Font.Color = clBlue
Legend.BackgroundBrush.Color = clMoneyGreen
Legend.GridHorizontal.Style = psDot
Legend.GridVertical.Style = psDot
Legend.GroupFont.Style = [fsBold]
Legend.GroupTitles.Strings = (
'Pie'
)
Legend.Visible = True
Title.Brush.Color = clBtnFace
Title.Font.Color = clBlue
Title.Text.Strings = (
'TAChart'
)
Align = alClient
Color = clOlive
ParentColor = False
object Chart1LineSeries1: TLineSeries
Title = 'Line'
LinePen.Color = clRed
Pointer.Brush.Color = clRed
ShowPoints = True
end
object Chart1AreaSeries1: TAreaSeries
Title = 'Area'
AreaBrush.Color = clGreen
AreaBrush.Style = bsCross
Source = RandomChartSource1
end
object Chart1PieSeries1: TPieSeries
Legend.Format = '%2:s %1:.2f%%'
Legend.GroupIndex = 0
Legend.Multiplicity = lmPoint
Marks.Format = '%2:s'
Marks.Style = smsLabel
Title = 'Pie'
Exploded = True
Source = ListChartSource2
end
object Chart1FuncSeries1: TFuncSeries
Legend.Order = 1
Legend.UserItemsCount = 2
Legend.OnDraw = Chart1FuncSeries1DrawLegend
Extent.UseXMax = True
Extent.UseXMin = True
Extent.XMax = 5
Title = 'Function'
OnCalculate = Chart1FuncSeries1Calculate
Pen.Color = clPurple
Pen.Width = 2
end
end
end
object Chart1AreaSeries1: TAreaSeries
Title = 'Area'
AreaBrush.Color = clGreen
AreaBrush.Style = bsCross
Source = RandomChartSource1
end
object Chart1PieSeries1: TPieSeries
Legend.Format = '%2:s %1:.2f%%'
Legend.GroupIndex = 0
Legend.Multiplicity = lmPoint
Marks.Format = '%2:s'
Marks.Style = smsLabel
Title = 'Pie'
Exploded = True
Source = ListChartSource2
end
object Chart1FuncSeries1: TFuncSeries
Legend.Order = 1
Legend.UserItemsCount = 2
Legend.OnDraw = Chart1FuncSeries1DrawLegend
Extent.UseXMax = True
Extent.UseXMin = True
Extent.XMax = 5
Title = 'Function'
OnCalculate = Chart1FuncSeries1Calculate
Pen.Color = clPurple
Pen.Width = 2
end
end
object pnControls: TPanel
Left = 0
Height = 134
Top = 304
Width = 510
Align = alBottom
ClientHeight = 134
ClientWidth = 510
TabOrder = 1
object lblMarginY: TLabel
Left = 8
Height = 13
Top = 33
Width = 41
Caption = 'Y margin'
ParentColor = False
end
object seMarginY: TSpinEdit
Left = 60
Height = 21
Top = 33
Width = 54
MaxValue = 20
OnChange = seMarginYChange
TabOrder = 0
Value = 4
end
object seSymbolWidth: TSpinEdit
Left = 196
Height = 21
Top = 8
Width = 54
MaxValue = 50
OnChange = seSymbolWidthChange
TabOrder = 1
Value = 20
end
object lblSymbolWidth: TLabel
Left = 128
Height = 13
Top = 8
Width = 63
Caption = 'Symbol width'
ParentColor = False
end
object rgAlignment: TRadioGroup
Left = 264
Height = 132
Top = 1
Width = 245
Align = alRight
AutoFill = True
Caption = ' Alignment '
ChildSizing.LeftRightSpacing = 6
ChildSizing.TopBottomSpacing = 6
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
ChildSizing.EnlargeVertical = crsHomogenousChildResize
ChildSizing.ShrinkHorizontal = crsScaleChilds
ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclTopToBottomThenLeftToRight
ChildSizing.ControlsPerLine = 3
ClientHeight = 114
ClientWidth = 241
Columns = 3
ItemIndex = 6
Items.Strings = (
'TopLeft'
'CenterLeft'
'BottomLeft'
'TopCenter'
''
'BottomCenter'
'TopRight'
'CenterRight'
'BottomRight'
)
OnClick = rgAlignmentClick
TabOrder = 2
end
object cbUseSidebar: TCheckBox
Left = 8
Height = 17
Top = 60
Width = 56
Caption = 'Sidebar'
Checked = True
OnChange = cbUseSidebarChange
State = cbChecked
TabOrder = 3
end
object lblSpacing: TLabel
Left = 128
Height = 13
Top = 33
Width = 37
Caption = 'Spacing'
ParentColor = False
end
object seSpacing: TSpinEdit
Left = 196
Height = 21
Top = 33
Width = 54
MaxValue = 20
OnChange = seSpacingChange
TabOrder = 4
Value = 4
end
object lblMarginX: TLabel
Left = 8
Height = 13
Top = 8
Width = 41
Caption = 'X margin'
ParentColor = False
end
object seMarginX: TSpinEdit
Left = 60
Height = 21
Top = 8
Width = 54
MaxValue = 20
OnChange = seMarginXChange
TabOrder = 5
Value = 4
end
object cbSeries: TComboBox
Left = 102
Height = 22
Top = 88
Width = 148
ItemHeight = 16
OnDrawItem = cbSeriesDrawItem
ReadOnly = True
Style = csOwnerDrawFixed
TabOrder = 6
end
object lblColumnCount: TLabel
Left = 128
Height = 13
Top = 60
Width = 40
Caption = 'Columns'
ParentColor = False
end
object seColumnCount: TSpinEdit
Left = 196
Height = 21
Top = 60
Width = 54
MinValue = 1
OnChange = seColumnCountChange
TabOrder = 7
Value = 1
end
object cbByRows: TCheckBox
Left = 8
Height = 17
Top = 84
Width = 58
Caption = 'By rows'
OnChange = cbByRowsChange
TabOrder = 8
end
object cbGrid: TCheckBox
Left = 8
Height = 17
Top = 108
Width = 39
Caption = 'Grid'
OnChange = cbGridChange
TabOrder = 9
object TabSheet2: TTabSheet
Caption = 'OwnerDraw'
ClientHeight = 483
ClientWidth = 582
object Chart2: TChart
Left = 0
Height = 483
Top = 0
Width = 582
AxisList = <
item
Grid.Color = clSilver
Minors = <>
Title.LabelFont.Height = -16
Title.LabelFont.Orientation = 900
Title.LabelFont.Style = [fsBold]
Title.Visible = True
Title.Caption = 'y axis'
end
item
Grid.Visible = False
Alignment = calBottom
Minors = <>
Title.LabelFont.Height = -16
Title.LabelFont.Style = [fsBold]
Title.Visible = True
Title.Caption = 'x axis'
end>
BackColor = clWhite
Foot.Brush.Color = clBtnFace
Foot.Font.Color = clBlue
Legend.Visible = True
Title.Brush.Color = clBtnFace
Title.Font.Color = clBlue
Title.Text.Strings = (
'TAChart'
)
OnDrawLegend = Chart2DrawLegend
Align = alClient
ParentColor = False
object GradientLineSeries: TLineSeries
Title = '1.0'
LineType = ltNone
Pointer.Style = psCircle
ShowPoints = True
end
end
end
end
object RandomChartSource1: TRandomChartSource
@ -279,7 +342,7 @@ object Form1: TForm1
DataPoints.Strings = (
'0|5|?|abcc'
'0|6|?|def'
'0.2|4|?|пример'
'0.20000000000000001|4|?|пример'
'0|7|?|ещё'
'0|2|?|два слова'
)

View File

@ -5,8 +5,8 @@ unit main;
interface
uses
Controls, ExtCtrls, Graphics, Spin, StdCtrls, Forms,
TAGraph, TASeries, TASources, Classes, TALegend, TAFuncSeries;
Controls, ExtCtrls, Graphics, Spin, StdCtrls, Forms, ComCtrls,
TAGraph, TASeries, TASources, Classes, TALegend, TAFuncSeries, TADrawUtils;
type
@ -22,6 +22,8 @@ type
Chart1PieSeries1: TPieSeries;
cbUseSidebar: TCheckBox;
cbSeries: TComboBox;
Chart2: TChart;
GradientLineSeries: TLineSeries;
lblColumnCount: TLabel;
lblSpacing: TLabel;
lblMarginX: TLabel;
@ -29,6 +31,7 @@ type
lblMarginY: TLabel;
ListChartSource1: TListChartSource;
ListChartSource2: TListChartSource;
PageControl1: TPageControl;
pnControls: TPanel;
rgAlignment: TRadioGroup;
RandomChartSource1: TRandomChartSource;
@ -37,6 +40,8 @@ type
seColumnCount: TSpinEdit;
seSymbolWidth: TSpinEdit;
seMarginY: TSpinEdit;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
procedure cbByRowsChange(Sender: TObject);
procedure cbGridChange(Sender: TObject);
procedure cbSeriesDrawItem(Control: TWinControl; Index: Integer;
@ -47,6 +52,9 @@ type
ACanvas: TCanvas; const ARect: TRect; AIndex: Integer; AItem: TLegendItem);
procedure Chart1FuncSeries1LegendCreate(
AItem: TLegendItem; AIndex: Integer);
procedure Chart2DrawLegend(ASender: TChart; ADrawer: IChartDrawer;
ALegendItems: TChartLegendItems; ALegendItemSize: TPoint;
const ALegendRect: TRect; AColCount, ARowCount: Integer);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure rgAlignmentClick(Sender: TObject);
@ -57,6 +65,8 @@ type
procedure seColumnCountChange(Sender: TObject);
private
FItems: TChartLegendItems;
FGradientMinValue: Double;
FGradientMaxValue: Double;
end;
var
@ -67,7 +77,29 @@ implementation
{$R *.lfm}
uses
SysUtils, TAChartUtils, TADrawerCanvas, TADrawUtils;
SysUtils, Math, TAChartUtils, TADrawerCanvas;
const
START_COLOR = $007777FF;
END_COLOR = $00FF7777;
{ Helper for ownerdrawn legend }
procedure DrawGradient(ADrawer: IChartDrawer; ARect: TRect;
AStartColor, AEndColor: TColor);
var
h: Integer;
y: Integer;
c: TColor;
begin
h := ARect.Bottom - ARect.Top;
if h <= 0 then exit;
for y := ARect.Bottom-1 downto ARect.Top do begin
c := InterpolateRGB(AStartColor, AEndColor, (ARect.Bottom - y) / h);
ADrawer.SetPenParams(psSolid, c);
ADrawer.Line(ARect.Left, y, ARect.Right, y);
end;
end;
{ TForm1 }
@ -93,6 +125,13 @@ var
r: TRect;
begin
Unused(Control, State);
{
if Index = cbSeries.ItemIndex then
cbSeries.Canvas.Brush.Color := clHighlight
else
cbSeries.Canvas.Brush.Color := clWindow;
}
cbSeries.Canvas.FillRect(ARect);
id := TCanvasDrawer.Create(cbSeries.Canvas);
r := Bounds(
ARect.Left + 2, ARect.Top, Chart1.Legend.SymbolWidth, cbSeries.ItemHeight);
@ -134,7 +173,84 @@ begin
Round(Sin(x / w * 2 * Pi) * (ARect.Bottom - ARect.Top) / 2) + y0);
end;
{ This event handler draws the legend completely on its own.
You can draw anything here - it's your responsibility...
Here we draw a color gradient to explain the symbol colors of the datapoints. }
procedure TForm1.Chart2DrawLegend(ASender: TChart; ADrawer: IChartDrawer;
ALegendItems: TChartLegendItems; ALegendItemSize: TPoint;
const ALegendRect: TRect; AColCount, ARowCount: Integer);
var
xg1, xg2, yg1, yg2, y: Integer;
s: String;
yval: Double;
i: Integer;
P: array[0..3] of TPoint;
ts: TPoint;
begin
xg1 := ALegendRect.Left + 4; // left edge of gradient
xg2 := xg1 + ASender.Legend.SymbolWidth; // right edge of gradient
yg1 := ASender.ClipRect.Top; // top edge of gradient
yg2 := ASender.ClipRect.Bottom; // bottom edge of gradient
// Draw border around gradient bar
ADrawer.SetPenParams(psSolid, clBlack);
ADrawer.Rectangle(xg1-1, yg1-1, xg2+1, yg2+1);
// Draw gradient bar
DrawGradient(ADrawer, Rect(xg1, yg1, xg2, yg2), START_COLOR, END_COLOR);
// Draw axis labels along gradient bar, with a short marker line
ADrawer.SetBrushParams(bsSolid, clBlack);
ADrawer.SetPenParams(psSolid, clBlack);
ADrawer.SetFont(ASender.Legend.Font);
ts := ADrawer.TextExtent('1');
for i:=0 to ASender.LeftAxis.ValueCount-1 do begin
// Read y axis labels
yval := ASender.LeftAxis.Value[i].FValue;
// make sure that label is visible
if InRange(yval, FGradientMinValue, FGradientMaxValue) then begin
s := Format('%.1f', [yval]);
{ or:
s := ASender.LeftAxis.Value[i].FText; }
y := ASender.YGraphToImage(yval);
ADrawer.Line(xg2-2, y, xg2+4, y);
// draw label text
ADrawer.TextOut.Pos(xg2+12, y-ts.y div 2).Text(s).Done;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
procedure PrepareData;
const
XMIN = -10;
XMAX = +10;
N = 30;
var
i: Integer;
x, y: Double;
ynorm: Double;
c: TColor;
begin
// Create some data and store in series' internal listsource
for i:=0 to N-1 do begin
x := XMIN + (XMAX - XMIN) * i / (N-1) + (random - 0.5) * 0.5;
y := exp(-0.2*sqr(x)) + (random-0.5) * 0.1;
GradientLineSeries.AddXY(x, y);
end;
// Here we define the value range mapped to the gradient
FGradientMinValue := GradientLineSeries.ListSource.Extent.a.y;
FGradientMaxValue := GradientLineSeries.ListSource.Extent.b.y;
// Colorize the data points
for i:=0 to N-1 do begin
y := GradientLineSeries.ListSource.Item[i]^.Y;
ynorm := (y - FGradientMinValue) / (FGradientMaxValue - FGradientMinValue);
c := InterpolateRGB(START_COLOR, END_COLOR, ynorm);
GradientLineSeries.ListSource.Item[i]^.Color := c;
end;
end;
var
li: TLegendItem;
begin
@ -144,6 +260,9 @@ begin
Chart1.Legend.SortItemsByOrder(FItems);
for li in FItems do
cbSeries.AddItem('', nil);
// Prepare data for chart with owner-drawn legend
PrepareData;
end;
procedure TForm1.FormDestroy(Sender: TObject);