Merged revision(s) 48496 #7b6b5c3ce1, 48501 #feb46ca59a, 48510-48511 #489724243b-#489724243b, 48531 #3459fff08c, 48534 #5fdf172812, 48594 #c95cc0db19 from trunk:

TAChart: Fix arrows at axes and constant line series with respect to rtl bidi mode and line flips
........
TAChart: Fix centering of axis title for chart panes
........
TAChart: Fix paned charts to draw axis lines only in data range.
........
TAChart: Add new demo for paned charts (demo/panes-2)
........
TAChart: Fix TFuncSeries hanging in case of inverted x axis
........
TAChart: Fix panes to work with TFuncSeries. Update panes-2 demo.
........
TAChart: Fix ColorMapSeries painting failure in case of StepY=1
........

git-svn-id: branches/fixes_1_4@48596 -
This commit is contained in:
maxim 2015-04-02 22:03:21 +00:00
parent 0556ef8219
commit 33a2c1d453
13 changed files with 1231 additions and 54 deletions

4
.gitattributes vendored
View File

@ -3690,6 +3690,10 @@ components/tachart/demo/opengl/Main.lfm svneol=native#text/plain
components/tachart/demo/opengl/Main.pas svneol=native#text/pascal
components/tachart/demo/opengl/opengldemo.lpi svneol=native#text/plain
components/tachart/demo/opengl/opengldemo.lpr svneol=native#text/pascal
components/tachart/demo/panes-2/project1.lpi svneol=native#text/pascal
components/tachart/demo/panes-2/project1.lpr svneol=native#text/pascal
components/tachart/demo/panes-2/unit1.lfm svneol=native#text/pascal
components/tachart/demo/panes-2/unit1.pas svneol=native#text/pascal
components/tachart/demo/panes/Main.lfm svneol=native#text/plain
components/tachart/demo/panes/Main.pas svneol=native#text/pascal
components/tachart/demo/panes/panes.lpi svneol=native#text/plain

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="project1"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="TAChartLazarusPkg"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="project1.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="unit1.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="Unit1"/>
</Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="project1"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,21 @@
program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, Unit1, tachartlazaruspkg
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@ -0,0 +1,603 @@
object Form1: TForm1
Left = 394
Height = 492
Top = 225
Width = 881
Caption = 'Form1'
ClientHeight = 492
ClientWidth = 881
OnCreate = FormCreate
LCLVersion = '1.5'
object Panel1: TPanel
Left = 0
Height = 492
Top = 0
Width = 160
Align = alLeft
ClientHeight = 492
ClientWidth = 160
TabOrder = 0
object CbLineAtDataOnly: TCheckBox
Left = 12
Height = 19
Top = 10
Width = 107
Caption = 'Line at data only'
Checked = True
OnChange = CbLineAtDataOnlyChange
State = cbChecked
TabOrder = 0
end
object CbShowHorGrid: TCheckBox
Left = 12
Height = 19
Top = 184
Width = 62
Caption = 'hor grid'
OnChange = CbShowGridChange
TabOrder = 1
end
object CbShowArrow: TCheckBox
Left = 12
Height = 19
Top = 112
Width = 52
Caption = 'Arrow'
OnChange = CbShowArrowChange
TabOrder = 2
end
object CbInverted: TCheckBox
Left = 12
Height = 19
Top = 136
Width = 63
Caption = 'Inverted'
OnChange = CbInvertedChange
TabOrder = 3
end
object CbBiDiMode: TCheckBox
Left = 12
Height = 19
Top = 160
Width = 83
Caption = 'right-to-left'
OnChange = CbBiDiModeChange
TabOrder = 4
end
object CbMarksAtDataOnly: TCheckBox
Left = 12
Height = 19
Top = 37
Width = 117
Caption = 'Marks at data only'
Checked = True
OnChange = CbMarksAtDataOnlyChange
State = cbChecked
TabOrder = 5
end
object Label1: TLabel
Left = 12
Height = 15
Top = 256
Width = 36
Caption = 'Range:'
ParentColor = False
end
object CbUseMax: TCheckBox
Left = 12
Height = 19
Top = 272
Width = 61
Caption = 'UseMax'
OnChange = CbUseMaxChange
TabOrder = 6
end
object CbUseMin: TCheckBox
Left = 12
Height = 19
Top = 296
Width = 60
Caption = 'UseMin'
OnChange = CbUseMinChange
TabOrder = 7
end
object CbGrouped: TCheckBox
Left = 12
Height = 19
Top = 64
Width = 66
Caption = 'Grouped'
OnChange = CbGroupedChange
TabOrder = 8
end
object CbShowFrame: TCheckBox
Left = 12
Height = 19
Top = 88
Width = 53
Caption = 'Frame'
Checked = True
OnChange = CbShowFrameChange
State = cbChecked
TabOrder = 9
end
object CbShowVertGrid: TCheckBox
Left = 12
Height = 19
Top = 208
Width = 64
Caption = 'vert grid'
OnChange = CbShowGridChange
TabOrder = 10
end
object Label2: TLabel
Left = 12
Height = 51
Top = 424
Width = 135
Anchors = [akTop, akLeft, akRight]
AutoSize = False
Caption = 'Drag the dashed lines...'
ParentColor = False
WordWrap = True
end
object CheckBox1: TCheckBox
Left = 12
Height = 19
Top = 336
Width = 132
Caption = 'TFuncSeries in center'
OnChange = CheckBox1Change
TabOrder = 11
end
object LblXExtentIgnored: TLabel
Left = 12
Height = 52
Top = 356
Width = 140
AutoSize = False
Caption = '(x extent ignored - see docs)'
ParentColor = False
WordWrap = True
end
end
object PageControl1: TPageControl
Left = 160
Height = 492
Top = 0
Width = 721
ActivePage = TabSheet1
Align = alClient
TabIndex = 0
TabOrder = 1
OnChange = PageControl1Change
OnChanging = PageControl1Changing
object TabSheet1: TTabSheet
Caption = 'Horizontal panes'
ClientHeight = 464
ClientWidth = 713
object Chart1: TChart
Left = 0
Height = 464
Top = 0
Width = 713
AxisList = <
item
Grid.Color = clGray
Grid.Visible = False
Alignment = calBottom
AxisPen.Visible = True
Minors = <>
Title.Visible = True
Title.Caption = 'x axis'
end
item
Grid.Color = clGray
Grid.Visible = False
Intervals.MaxLength = 40
TickColor = clBlue
AtDataOnly = True
AxisPen.Color = clBlue
AxisPen.Visible = True
Marks.LabelFont.Color = clBlue
Marks.AtDataOnly = True
Minors = <>
Range.Max = 5
Range.Min = -5
Title.LabelFont.Color = clBlue
Title.LabelFont.Orientation = 900
Title.Visible = True
Title.Caption = 'y1 axis'
Title.PositionOnMarks = True
Transformations = ChartAxisTransformations1
end
item
Grid.Color = clGray
Grid.Visible = False
TickColor = clRed
AtDataOnly = True
AxisPen.Color = clRed
AxisPen.Visible = True
Marks.LabelFont.Color = clRed
Marks.AtDataOnly = True
Minors = <>
Range.Max = 20
Title.LabelFont.Color = clRed
Title.LabelFont.Orientation = 900
Title.Visible = True
Title.Caption = 'y2 axis'
Title.PositionOnMarks = True
Transformations = ChartAxisTransformations2
end
item
Grid.Color = clGray
Grid.Visible = False
AtDataOnly = True
AxisPen.Color = clFuchsia
AxisPen.Visible = True
Marks.LabelFont.Color = clFuchsia
Marks.AtDataOnly = True
Minors = <>
Range.Max = 100
Range.Min = -100
Title.LabelFont.Color = clFuchsia
Title.LabelFont.Orientation = 900
Title.Visible = True
Title.Caption = 'y3 axis'
Title.PositionOnMarks = True
Transformations = ChartAxisTransformations3
end>
BackColor = clNone
Extent.UseYMax = True
Extent.UseYMin = True
Extent.YMax = 10
Foot.Brush.Color = clBtnFace
Foot.Font.Color = clBlue
Title.Brush.Color = clBtnFace
Title.Font.Color = clBlue
Title.Text.Strings = (
'TAChart'
)
Toolset = ChartToolset1
Align = alClient
Color = clNone
ParentColor = False
object Chart1LineSeries1: TLineSeries
AxisIndexX = 0
AxisIndexY = 1
LinePen.Color = clBlue
Source = RandomChartSource11
end
object Chart1LineSeries2: TLineSeries
AxisIndexX = 0
AxisIndexY = 2
LinePen.Color = clRed
Source = RandomChartSource12
end
object Chart1LineSeries3: TLineSeries
AxisIndexX = 0
AxisIndexY = 3
LinePen.Color = clFuchsia
Source = RandomChartSource13
end
object Chart1LineSeries4: TLineSeries
AxisIndexX = 0
AxisIndexY = 3
LinePen.Color = clFuchsia
LinePen.Style = psDot
Source = RandomChartSource14
end
object Chart1ConstantLine1: TConstantLine
Pen.Color = clBlue
Pen.Style = psDash
Position = 2
end
object Chart1ConstantLine2: TConstantLine
Pen.Color = clRed
Pen.Style = psDash
Position = 3
end
object Chart1ConstantLine3: TConstantLine
Pen.Color = clRed
Pen.Style = psDash
Position = 5
end
object Chart1ConstantLine4: TConstantLine
Pen.Color = clFuchsia
Pen.Style = psDash
Position = 6
end
object Chart1FuncSeries2: TFuncSeries
Active = False
Extent.UseYMax = True
Extent.UseYMin = True
Extent.YMax = 1
Extent.YMin = -1
AxisIndexX = 0
AxisIndexY = 2
OnCalculate = Chart1FuncSeries2Calculate
ExtentAutoY = True
Pen.Color = clRed
Step = 1
end
end
end
object TabSheet2: TTabSheet
Caption = 'Vertical panes'
ClientHeight = 464
ClientWidth = 713
object Chart2: TChart
Left = 0
Height = 464
Top = 0
Width = 713
AxisList = <
item
Grid.Color = clGray
Grid.Visible = False
AxisPen.Visible = True
Minors = <>
Title.LabelFont.Orientation = 900
Title.Visible = True
Title.Caption = 'y axis'
end
item
Grid.Color = clGray
Grid.Visible = False
TickColor = clBlue
Alignment = calBottom
AtDataOnly = True
AxisPen.Color = clBlue
AxisPen.Visible = True
Marks.LabelFont.Color = clBlue
Marks.AtDataOnly = True
Minors = <>
Range.Max = 5
Range.Min = -5
Title.LabelFont.Color = clBlue
Title.Visible = True
Title.Caption = 'x1 axis'
Title.PositionOnMarks = True
Transformations = ChartAxisTransformations1
end
item
Grid.Color = clGray
Grid.Visible = False
TickColor = clRed
Alignment = calBottom
AtDataOnly = True
AxisPen.Color = clRed
AxisPen.Visible = True
Marks.LabelFont.Color = clRed
Marks.AtDataOnly = True
Minors = <>
Range.Max = 20
Title.LabelFont.Color = clRed
Title.Visible = True
Title.Caption = 'x2 axis'
Title.PositionOnMarks = True
Transformations = ChartAxisTransformations2
end
item
Grid.Color = clGray
Grid.Visible = False
Alignment = calBottom
AtDataOnly = True
AxisPen.Color = clFuchsia
AxisPen.Visible = True
Marks.LabelFont.Color = clFuchsia
Marks.AtDataOnly = True
Minors = <>
Range.Max = 100
Range.Min = -100
Title.LabelFont.Color = clFuchsia
Title.Visible = True
Title.Caption = 'x3 axis'
Title.PositionOnMarks = True
Transformations = ChartAxisTransformations3
end>
BackColor = clNone
Extent.UseXMax = True
Extent.UseXMin = True
Extent.XMax = 10
Foot.Brush.Color = clBtnFace
Foot.Font.Color = clBlue
Title.Brush.Color = clBtnFace
Title.Font.Color = clBlue
Title.Text.Strings = (
'TAChart'
)
Toolset = ChartToolset2
Align = alClient
Color = clNone
ParentColor = False
object Chart2LineSeries1: TLineSeries
AxisIndexX = 1
AxisIndexY = 0
LinePen.Color = clBlue
Source = RandomChartSource21
end
object Chart2LineSeries2: TLineSeries
AxisIndexX = 2
AxisIndexY = 0
LinePen.Color = clRed
Source = RandomChartSource22
end
object Chart2LineSeries3: TLineSeries
AxisIndexX = 3
AxisIndexY = 0
LinePen.Color = clFuchsia
Source = RandomChartSource23
end
object Chart2LineSeries4: TLineSeries
AxisIndexX = 3
AxisIndexY = 0
LinePen.Color = clFuchsia
LinePen.Style = psDot
Source = RandomChartSource24
end
object Chart2ConstantLine1: TConstantLine
LineStyle = lsVertical
Pen.Color = clBlue
Pen.Style = psDash
Position = 2
end
object Chart2ConstantLine2: TConstantLine
LineStyle = lsVertical
Pen.Color = clRed
Pen.Style = psDash
Position = 3
end
object Chart2ConstantLine3: TConstantLine
LineStyle = lsVertical
Pen.Color = clRed
Pen.Style = psDash
Position = 5
end
object Chart2ConstantLine4: TConstantLine
LineStyle = lsVertical
Pen.Color = clFuchsia
Pen.Style = psDash
Position = 6
end
object Chart2FuncSeries2: TFuncSeries
Active = False
Extent.UseXMax = True
Extent.UseXMin = True
Extent.UseYMax = True
Extent.UseYMin = True
Extent.XMax = 1
Extent.YMax = 1
AxisIndexX = 2
AxisIndexY = 0
OnCalculate = Chart2FuncSeries2Calculate
Pen.Color = clRed
Step = 1
end
end
end
end
object RandomChartSource11: TRandomChartSource
PointsNumber = 10
RandSeed = 2088531169
XMax = 1
XMin = 0
YMax = 1
YMin = 0
left = 200
top = 48
end
object RandomChartSource12: TRandomChartSource
PointsNumber = 10
RandSeed = 2088635735
XMax = 1
XMin = 0
YMax = 10
YMin = 0
left = 200
top = 115
end
object RandomChartSource13: TRandomChartSource
PointsNumber = 10
RandSeed = 2088693796
XMax = 1
XMin = 0
YMax = 10
YMin = 0
left = 200
top = 188
end
object ChartAxisTransformations1: TChartAxisTransformations
left = 776
top = 48
object ChartAxisTransformations1AutoScaleAxisTransform1: TAutoScaleAxisTransform
MaxValue = 2
end
end
object ChartAxisTransformations2: TChartAxisTransformations
left = 776
top = 115
object ChartAxisTransformations2AutoScaleAxisTransform1: TAutoScaleAxisTransform
MaxValue = 5
MinValue = 3
end
end
object ChartAxisTransformations3: TChartAxisTransformations
left = 776
top = 188
object ChartAxisTransformations3AutoScaleAxisTransform1: TAutoScaleAxisTransform
MaxValue = 10
MinValue = 6
end
end
object RandomChartSource14: TRandomChartSource
PointsNumber = 5
RandSeed = 999856828
XMax = 1
XMin = 0
YMax = 100
YMin = 0
left = 200
top = 256
end
object RandomChartSource21: TRandomChartSource
PointsNumber = 10
RandSeed = 2088531169
XMax = 1
XMin = 0
YMax = 1
YMin = 0
left = 336
top = 48
end
object RandomChartSource22: TRandomChartSource
PointsNumber = 10
RandSeed = 2088635735
XMax = 10
XMin = 0
YMax = 1
YMin = 0
left = 336
top = 115
end
object RandomChartSource23: TRandomChartSource
PointsNumber = 10
RandSeed = 2088693796
XMax = 10
XMin = 0
YMax = 1
YMin = 0
left = 336
top = 188
end
object RandomChartSource24: TRandomChartSource
PointsNumber = 5
RandSeed = 999856828
XMax = 100
XMin = 0
YMax = 1
YMin = 0
left = 336
top = 256
end
object ChartToolset1: TChartToolset
left = 200
top = 392
object ChartToolset1DataPointDragTool1: TDataPointDragTool
Shift = [ssLeft]
OnAfterMouseMove = DataPointDragTool_AfterMouseMove
AffectedSeries = '4,5,6,7'
ActiveCursor = crSizeNS
end
end
object ChartToolset2: TChartToolset
left = 336
top = 392
object ChartToolset2DataPointDragTool1: TDataPointDragTool
Shift = [ssLeft]
OnAfterMouseMove = DataPointDragTool_AfterMouseMove
AffectedSeries = '4,5,6,7'
ActiveCursor = crSizeWE
end
end
end

View File

@ -0,0 +1,323 @@
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, TAGraph, TASources, TASeries, TATransformations,
Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, ComCtrls, types,
TACustomSeries, TATools, TAFuncSeries;
type
{ TForm1 }
TForm1 = class(TForm)
CbShowVertGrid: TCheckBox;
Chart1ConstantLine2: TConstantLine;
Chart1ConstantLine3: TConstantLine;
Chart1ConstantLine4: TConstantLine;
Chart1FuncSeries2: TFuncSeries;
Chart2ConstantLine1: TConstantLine;
Chart2ConstantLine2: TConstantLine;
Chart2ConstantLine3: TConstantLine;
Chart2ConstantLine4: TConstantLine;
Chart1ConstantLine1: TConstantLine;
Chart1LineSeries2: TLineSeries;
Chart1LineSeries3: TLineSeries;
Chart1LineSeries4: TLineSeries;
Chart2FuncSeries2: TFuncSeries;
Chart2LineSeries1: TLineSeries;
Chart2LineSeries2: TLineSeries;
Chart2LineSeries3: TLineSeries;
Chart2LineSeries4: TLineSeries;
Chart1LineSeries1: TLineSeries;
Chart2: TChart;
Chart1: TChart;
ChartAxisTransformations1: TChartAxisTransformations;
ChartAxisTransformations1AutoScaleAxisTransform1: TAutoScaleAxisTransform;
ChartAxisTransformations2: TChartAxisTransformations;
ChartAxisTransformations2AutoScaleAxisTransform1: TAutoScaleAxisTransform;
ChartAxisTransformations3: TChartAxisTransformations;
ChartAxisTransformations3AutoScaleAxisTransform1: TAutoScaleAxisTransform;
ChartToolset1: TChartToolset;
ChartToolset1DataPointDragTool1: TDataPointDragTool;
ChartToolset2: TChartToolset;
ChartToolset2DataPointDragTool1: TDataPointDragTool;
CbLineAtDataOnly: TCheckBox;
CbShowHorGrid: TCheckBox;
CbShowArrow: TCheckBox;
CbInverted: TCheckBox;
CbBiDiMode: TCheckBox;
CbMarksAtDataOnly: TCheckBox;
CbUseMax: TCheckBox;
CbUseMin: TCheckBox;
CbGrouped: TCheckBox;
CbShowFrame: TCheckBox;
CheckBox1: TCheckBox;
Label1: TLabel;
Label2: TLabel;
LblXExtentIgnored: TLabel;
PageControl1: TPageControl;
Panel1: TPanel;
RandomChartSource11: TRandomChartSource;
RandomChartSource12: TRandomChartSource;
RandomChartSource13: TRandomChartSource;
RandomChartSource14: TRandomChartSource;
RandomChartSource21: TRandomChartSource;
RandomChartSource22: TRandomChartSource;
RandomChartSource23: TRandomChartSource;
RandomChartSource24: TRandomChartSource;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
procedure CbShowFrameChange(Sender: TObject);
procedure CbGroupedChange(Sender: TObject);
procedure CbUseMaxChange(Sender: TObject);
procedure CbUseMinChange(Sender: TObject);
procedure Chart1FuncSeries2Calculate(const AX: Double; out AY: Double);
procedure Chart2FuncSeries2Calculate(const AX: Double; out AY: Double);
procedure CheckBox1Change(Sender: TObject);
procedure DataPointDragTool_AfterMouseMove(ATool: TChartTool; APoint: TPoint);
procedure CbLineAtDataOnlyChange(Sender: TObject);
procedure CbShowGridChange(Sender: TObject);
procedure CbShowArrowChange(Sender: TObject);
procedure CbInvertedChange(Sender: TObject);
procedure CbBiDiModeChange(Sender: TObject);
procedure CbMarksAtDataOnlyChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure PageControl1Change(Sender: TObject);
procedure PageControl1Changing(Sender: TObject; var AllowChange: Boolean);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses
Math, TAChartUtils;
{ TForm1 }
procedure TForm1.CbLineAtDataOnlyChange(Sender: TObject);
var
i: Integer;
begin
for i:=1 to 3 do begin
Chart1.AxisList[i].AtDataOnly := CbLineAtDataOnly.Checked;
Chart2.AxisList[i].AtDataOnly := CbLineAtDataOnly.Checked;
end;
end;
procedure TForm1.CbUseMaxChange(Sender: TObject);
var
i: Integer;
begin
for i:=1 to 3 do begin
Chart1.AxisList[i].Range.UseMax := CbUseMax.Checked;
Chart2.AxisList[i].Range.UseMax := CbUseMax.Checked;
end;
end;
procedure TForm1.CbGroupedChange(Sender: TObject);
var
i: Integer;
begin
if CbGrouped.Checked then begin
for i:=1 to 3 do begin
Chart1.AxisList[i].Group := 1;
Chart2.AxisList[i].Group := 1;
end;
end else begin
for i:=1 to 3 do begin
Chart1.AxisList[i].Group := 0;
Chart2.AxisList[i].Group := 0;
end;
end;
end;
procedure TForm1.CbShowFrameChange(Sender: TObject);
begin
Chart1.Frame.Visible := CbShowFrame.Checked;
Chart2.Frame.Visible := CbShowFrame.Checked;
end;
procedure TForm1.CbUseMinChange(Sender: TObject);
var
i: Integer;
begin
for i:=1 to 3 do begin
Chart1.AxisList[i].Range.UseMin := CbUseMin.Checked;
Chart2.AxisList[i].Range.UseMin := CbUseMin.Checked;
end;
end;
procedure TForm1.Chart1FuncSeries2Calculate(const AX: Double; out AY: Double);
begin
AY := sin(5 * AX);
end;
procedure TForm1.Chart2FuncSeries2Calculate(const AX: Double; out AY: Double);
begin
AY := sin(5*AX)*0.5 + 0.5;
end;
procedure TForm1.CheckBox1Change(Sender: TObject);
begin
Chart1FuncSeries2.Active := Checkbox1.Checked;
Chart1LineSeries2.Active := not Checkbox1.Checked;
Chart2FuncSeries2.Active := Checkbox1.Checked;
Chart2LineSeries2.Active := not Checkbox1.Checked;
end;
// This code is used by both ChartToolSets, for Chart1 and Chart2.
procedure TForm1.DataPointDragTool_AfterMouseMove(ATool: TChartTool;
APoint: TPoint);
const
MIN_SIZE = 0.5;
MIN_DISTANCE = 0.1;
var
pos, prevPos, nextPos: Double;
ser: TConstantLine;
ex: TDoubleRect;
ls: array[1..4] of TConstantLine;
begin
UnUsed(APoint);
ser := TConstantLine(TDataPointDragTool(ATool).Series);
if ser = nil then
exit;
pos := ser.Position;
ex := ser.ParentChart.GetFullExtent;
if ser.ParentChart = Chart1 then begin
ls[1] := Chart1ConstantLine1;
ls[2] := Chart1ConstantLine2;
ls[3] := Chart1ConstantLine3;
ls[4] := Chart1ConstantLine4;
end else begin
ls[1] := Chart2ConstantLine1;
ls[2] := Chart2ConstantLine2;
ls[3] := Chart2ConstantLine3;
ls[4] := Chart2ConstantLine4;
end;
if ser = ls[1] then begin
prevPos := TDoublePointBoolArr(ex.a)[PageControl1.ActivepageIndex=0] + MIN_SIZE;
nextPos := ls[2].Position - MIN_DISTANCE;
ser.Position := EnsureRange(pos, prevPos, nextPos);
ChartAxisTransformations1AutoscaleAxisTransform1.MaxValue := ser.Position;
end else
if ser = ls[2] then begin
prevPos := ls[1].Position + MIN_DISTANCE;
nextPos := ls[3].Position - MIN_SIZE;
ser.Position := EnsureRange(pos, prevPos, nextPos);
ChartAxisTransformations2AutoscaleAxisTransform1.MinValue := ser.Position;
end else
if ser = ls[3] then begin
prevPos := ls[2].Position + MIN_SIZE;
nextPos := ls[4].Position - MIN_DISTANCE;
ser.Position := EnsureRange(pos, prevPos, nextPos);
ChartAxisTransformations2AutoscaleAxisTransform1.MaxValue := ser.Position;
end else
if ser = ls[4] then begin
prevPos := ls[3].Position + MIN_DISTANCE;
nextPos := TDoublePointBoolArr(ex.b)[PageControl1.ActivepageIndex=0] - MIN_SIZE;
ser.Position := EnsureRange(pos, prevPos, nextPos);
ChartAxisTransformations3AutoscaleAxisTransform1.MinValue := ser.Position;
end;
end;
procedure TForm1.CbShowGridChange(Sender: TObject);
var
i: Integer;
begin
Chart1.AxisList[0].Grid.Visible := CbShowVertGrid.Checked;
Chart2.AxisList[0].Grid.Visible := cbShowHorGrid.Checked;
for i:=1 to 3 do begin
Chart1.AxisList[i].Grid.Visible := CbShowHorGrid.Checked;
Chart2.AxisList[i].Grid.Visible := CbShowVertGrid.Checked;
end;
end;
procedure TForm1.CbShowArrowChange(Sender: TObject);
var
i: Integer;
begin
for i:=0 to 3 do begin
Chart1.AxisList[i].Arrow.Visible := CbShowArrow.Checked;
Chart2.AxisList[i].Arrow.Visible := CbShowArrow.Checked;
end;
end;
procedure TForm1.CbInvertedChange(Sender: TObject);
var
i: Integer;
begin
for i:=0 to 3 do begin
Chart1.AxisList[i].Inverted := CbInverted.Checked;
Chart2.AxisList[i].Inverted := CbInverted.Checked;
end;
end;
procedure TForm1.CbBiDiModeChange(Sender: TObject);
begin
if CbBiDiMode.Checked then
Chart1.BiDiMode := bdRightToLeft
else
Chart1.BiDiMode := bdLeftToRight;
Chart2.BiDiMode := Chart1.BiDiMode;
end;
procedure TForm1.CbMarksAtDataOnlyChange(Sender: TObject);
var
i: Integer;
begin
for i:=0 to 3 do begin
Chart1.AxisList[i].Marks.AtDataOnly := CbMarksAtDataOnly.Checked;
Chart2.AxisList[i].Marks.AtDataOnly := CbMarksAtDataOnly.Checked;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
PageControl1.ActivePageIndex := 0;
end;
procedure TForm1.PageControl1Change(Sender: TObject);
begin
LblXExtentIgnored.Visible := PageControl1.ActivePageIndex = 1;
end;
{ The autoscale transformations are shared between both pages. Before changing
to the new page we make sure that the constant lines series which indicate the
pane limits are at the correct position. }
procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean);
begin
UnUsed(AllowChange);
case PageControl1.ActivePageIndex of
0: begin
Chart2ConstantLine1.Position := ChartAxisTransformations1AutoScaleAxisTransform1.Maxvalue;
Chart2ConstantLine2.Position := ChartAxisTransformations2AutoScaleAxisTransform1.MinValue;
Chart2ConstantLine3.Position := ChartAxisTransformations2AutoScaleAxisTransform1.Maxvalue;
Chart2ConstantLine4.Position := ChartAxisTransformations3AutoScaleAxisTransform1.Minvalue;
end;
1: begin
Chart1ConstantLine1.Position := ChartAxisTransformations1AutoScaleAxisTransform1.Maxvalue;
Chart1ConstantLine2.Position := ChartAxisTransformations2AutoScaleAxisTransform1.MinValue;
Chart1ConstantLine3.Position := ChartAxisTransformations2AutoScaleAxisTransform1.Maxvalue;
Chart1ConstantLine4.Position := ChartAxisTransformations3AutoScaleAxisTransform1.Minvalue;
end;
end;
end;
end.

View File

@ -87,7 +87,7 @@ type
FMarkValues: TChartValueTextArray;
FTitlePos: Integer;
procedure GetMarkValues;
procedure VisitSource(ASource: TCustomChartSource; var AData);
// procedure VisitSource(ASource: TCustomChartSource; var AData);
private
FAxisRect: TRect;
FGroupIndex: Integer;
@ -95,6 +95,7 @@ type
function MakeValuesInRangeParams(AMin, AMax: Double): TValuesInRangeParams;
strict private
FAlignment: TChartAxisAlignment;
FAtDataOnly: Boolean;
FAxisPen: TChartAxisPen;
FGroup: Integer;
FHelper: TAxisDrawHelper;
@ -115,6 +116,7 @@ type
function GetValue(AIndex: Integer): TChartValueText; inline;
function GetValueCount: Integer; inline;
function PositionIsStored: Boolean;
procedure SetAtDataOnly(AValue: Boolean);
procedure SetAxisPen(AValue: TChartAxisPen);
procedure SetGroup(AValue: Integer);
procedure SetInverted(AValue: Boolean);
@ -147,6 +149,7 @@ type
function GetChart: TCustomChart; inline;
function GetTransform: TChartAxisTransformations;
function IsDefaultPosition: Boolean;
function IsFlipped: Boolean; override;
function IsPointInside(const APoint: TPoint): Boolean;
function IsVertical: Boolean; inline;
procedure Measure(
@ -163,6 +166,7 @@ type
published
property Alignment default calLeft;
property Arrow;
property AtDataOnly: Boolean read FAtDataOnly write SetAtDataOnly default false;
property AxisPen: TChartAxisPen read FAxisPen write SetAxisPen;
property Group: Integer read FGroup write SetGroup default 0;
// Inverts the axis scale from increasing to decreasing.
@ -551,7 +555,7 @@ const
INVERTED_NAME: array [Boolean] of String = ('', ' Inverted');
begin
Result :=
SIDE_NAME[Alignment] + VISIBLE_NAME[Visible] + INVERTED_NAME[Inverted] +
SIDE_NAME[Alignment] + VISIBLE_NAME[Visible] + INVERTED_NAME[IsFlipped] +
FormatIfNotEmpty(' (%s)', Title.Caption);
end;
@ -564,9 +568,9 @@ procedure TChartAxis.GetMarkValues;
var
i: Integer;
d: TValuesInRangeParams;
vis: TChartOnVisitSources;
t: TChartValueText;
// vis: TChartOnVisitSources;
axisMin, axisMax: Double;
rng: TDoubleInterval;
begin
with FHelper do begin
axisMin := GetTransform.GraphToAxis(FValueMin);
@ -576,25 +580,27 @@ begin
Marks.Range.Intersect(axisMin, axisMax);
d := MakeValuesInRangeParams(axisMin, axisMax);
SetLength(FMarkValues, 0);
vis := TChartAxisList(Collection).OnVisitSources;
if Marks.AtDataOnly and Assigned(vis) then begin
vis(@VisitSource, Self, d);
// vis := TChartAxisList(Collection).OnVisitSources;
if Marks.AtDataOnly {and Assigned(vis)} then begin
// vis(@VisitSource, Self, d);
// FIXME: Intersect axisMin/Max with the union of series extents.
end
else
Marks.SourceDef.ValuesInRange(d, FMarkValues);
// wp: - I think this is fixed in what follows...
GetChart.Notify(CMD_QUERY_SERIESEXTENT, self, nil, rng{%H-});
UpdateBounds(rng.FStart, rng.FEnd);
d.FMin := rng.FStart;
d.FMax := rng.FEnd;
if IsNaN(d.FMin) or IsNaN(d.FMax) then begin
d.FMax := 1.0; d.FMin := 0.0;
end else
if (d.FMin = d.FMax) then d.FMax := d.FMin + 1.0;
end;
Marks.SourceDef.ValuesInRange(d, FMarkValues);
with FHelper do begin
FValueMin := GetTransform.AxisToGraph(axisMin);
FValueMax := GetTransform.AxisToGraph(axisMax);
FMinForMarks := GetTransform.AxisToGraph(d.FMin);
FMaxForMarks := GetTransform.AxisToGraph(d.FMax);
FMinForMarks := Min(FMinForMarks, GetTransform.AxisToGraph(d.FMin));
FMaxForMarks := Max(FMaxForMarks, GetTransform.AxisToGraph(d.FMax));
end;
if Inverted and (Length(FMarkValues) > 0) then
for i := 0 to High(FMarkValues) div 2 do begin
t := FMarkValues[i];
FMarkValues[i] := FMarkValues[High(FMarkValues) - i];
FMarkValues[High(FMarkValues) - i] := t;
end;
if Assigned(FOnMarkToText) then
for i := 0 to High(FMarkValues) do
@ -623,6 +629,18 @@ begin
Result := (PositionUnits = cuPercent) and (Position = 0);
end;
function TChartAxis.IsFlipped: Boolean;
{ Returns drawing direction of the axis:
FALSE - left to right, or bottom to tip
TRUE - right to left, or top to bottom }
begin
Result := FInverted;
if (FAlignment in [calBottom, calTop]) and
(GetChart.BiDiMode <> bdLeftToRight)
then
Result := not Result;
end;
function TChartAxis.IsPointInside(const APoint: TPoint): Boolean;
begin
Result := PtInRect(FTitleRect, APoint) and not PtInRect(FAxisRect, APoint);
@ -737,15 +755,19 @@ begin
end;
if not Title.PositionOnMarks then
FTitlePos := (rmin + rmax) div 2
else if minc < MaxInt then
else if minc < MaxInt then begin
c := FHelper.GraphToImage(FHelper.FMaxForMarks);
if c < maxc then maxc := c;
c := FHelper.GraphToImage(FHelper.FMinForMarks);
if c > minc then minc := c;
FTitlePos := (maxc + minc) div 2
else
end else
FTitlePos := MaxInt;
if Arrow.Visible then
with AMeasureData do begin
FSize := Max(d.Scale(Arrow.Width), FSize);
if Arrow.Inverted then
if IsFlipped then
FFirstMark := Max(d.Scale(Arrow.Length), FFirstMark)
else
FLastMark := Max(d.Scale(Arrow.Length), FLastMark);
@ -797,6 +819,9 @@ begin
FHelper.FTransf := ATransf;
FHelper.FZOffset.Y := Min(ZPosition, AMaxZPosition);
FHelper.FZOffset.X := -FHelper.FZOffset.Y;
FHelper.FAtDataOnly := AtDataOnly;
FHelper.FMaxForMarks := -infinity;
FHelper.FMinForMarks := infinity;
end;
procedure TChartAxis.SetAlignment(AValue: TChartAxisAlignment);
@ -806,6 +831,13 @@ begin
StyleChanged(Self);
end;
procedure TChartAxis.SetAtDataOnly(AValue: Boolean);
begin
if FAtDataOnly = AValue then exit;
FAtDataOnly := AValue;
StyleChanged(self);
end;
procedure TChartAxis.SetAxisPen(AValue: TChartAxisPen);
begin
FAxisPen.Assign(AValue);
@ -823,6 +855,7 @@ procedure TChartAxis.SetInverted(AValue: Boolean);
begin
if FInverted = AValue then exit;
FInverted := AValue;
if Arrow <> nil then Arrow.Inverted := IsFlipped;
StyleChanged(Self);
end;
@ -936,12 +969,8 @@ begin
Alignment := calLeft;
Title.LabelFont.Orientation := -Title.LabelFont.Orientation;
end;
calBottom,
calTop:
begin
Inverted := not Inverted;
if Arrow <> nil then Arrow.Inverted := not Arrow.Inverted;
end;
calBottom, calTop:
if Arrow <> nil then Arrow.Inverted := IsFlipped;
end;
end;
@ -955,6 +984,7 @@ begin
end;
end;
{
procedure TChartAxis.VisitSource(ASource: TCustomChartSource; var AData);
var
ext: TDoubleRect;
@ -966,6 +996,7 @@ begin
p.FMax := Min(TDoublePointBoolArr(ext.b)[IsVertical], p.FMax);
Marks.SourceDef.ValuesInRange(p, FMarkValues);
end;
}
{ TChartAxisList }
@ -1183,7 +1214,7 @@ end;
function TAxisCoeffHelper.CalcScale(ASign: Integer): Double;
begin
if (FMax^ = FMin^) or (Sign(FHi - FLo) <> ASign) then exit(1.0);
if (FAxis <> nil) and FAxis.Inverted then
if (FAxis <> nil) and FAxis.IsFlipped then
Exchange(FLo, FHi);
Result := (FHi - FLo) / (FMax^ - FMin^);
end;
@ -1197,7 +1228,7 @@ procedure TAxisCoeffHelper.UpdateMinMax(AConv: TAxisConvFunc);
begin
FMin^ := AConv(FImageLo);
FMax^ := AConv(FImageHi);
if (FAxis <> nil) and FAxis.Inverted then
if (FAxis <> nil) and FAxis.IsFlipped then
Exchange(FMin^, FMax^);
end;

View File

@ -172,6 +172,7 @@ type
destructor Destroy; override;
public
procedure Assign(ASource: TPersistent); override;
function IsFlipped: Boolean; virtual;
function TryApplyStripes(
ADrawer: IChartDrawer; var AIndex: Cardinal): Boolean;
@ -207,6 +208,7 @@ type
procedure LineZ(AP1, AP2: TPoint); inline;
function TryApplyStripes: Boolean; inline;
public
FAtDataOnly: Boolean;
FAxis: TChartBasicAxis;
FAxisTransf: TTransformFunc;
FClipRangeDelta: Integer;
@ -349,16 +351,28 @@ end;
procedure TAxisDrawHelper.InternalAxisLine(
APen: TChartPen; const AStart, AEnd: TPoint; AAngle: Double);
var
arrowBase: TPoint;
arrowFlipped: boolean;
begin
if not APen.Visible and not FAxis.Arrow.Visible then exit;
FDrawer.Pen := APen;
if APen.Visible then
LineZ(AStart, AEnd);
if FAxis.Arrow.Visible then
if FAxis.Arrow.Inverted then
FAxis.Arrow.Draw(FDrawer, AStart - FZOffset, AAngle, APen)
else
FAxis.Arrow.Draw(FDrawer, AEnd + FZOffset, AAngle, APen);
if FAxis.Arrow.Visible then begin
arrowFlipped := FAxis.IsFlipped;
if arrowFlipped <> FAxis.Arrow.Inverted then arrowFlipped := not arrowFlipped;
if FAxis.IsFlipped then begin
arrowBase := AStart - FZOffset;
if not arrowFlipped then
arrowBase -= RotatePointX(-FDrawer.Scale(FAxis.Arrow.Length), AAngle);
end else begin
arrowBase := AEnd + FZOffset;
if arrowFlipped then
arrowBase += RotatePointX(-FDrawer.Scale(FAxis.Arrow.Length), AAngle);
end;
FAxis.Arrow.Draw(FDrawer, arrowBase, AAngle, APen)
end;
end;
function TAxisDrawHelper.IsInClipRange(ACoord: Integer): Boolean;
@ -389,19 +403,20 @@ end;
procedure TAxisDrawHelperX.DrawAxisLine(APen: TChartPen; AFixedCoord: Integer);
var
p: TPoint;
p1, p2: TPoint;
begin
if FAxis.Arrow.Inverted then begin
p := Point(FClipRect^.Left, AFixedCoord);
if FAxis.IsFlipped then begin
p1 := Point(IfThen(FAtDataOnly, GraphToImage(FMaxForMarks), FClipRect^.Left), AFixedCoord);
p2 := Point(IfThen(FAtDataOnly, GraphToImage(FMinForMarks), FClipRect^.Right), AFixedCoord);
if FAxis.Arrow.Visible then
p.X -= FDrawer.Scale(FAxis.Arrow.Length);
InternalAxisLine(APen, p, Point(FClipRect^.Right, AFixedCoord), 0);
p1.X -= FDrawer.Scale(FAxis.Arrow.Length);
end else begin
p := Point(FClipRect^.Right, AFixedCoord);
p1 := Point(IfThen(FAtDataOnly, GraphToImage(FMinForMarks), FClipRect^.Left), AFixedCoord);
p2 := Point(IfThen(FAtDataOnly, GraphToImage(FMaxForMarks), FClipRect^.Right), AFixedCoord);
if FAxis.Arrow.Visible then
p.X += FDrawer.Scale(FAxis.Arrow.Length);
InternalAxisLine(APen, Point(FClipRect^.Left, AFixedCoord), p, 0);
p2.X += FDrawer.Scale(FAxis.Arrow.Length);
end;
InternalAxisLine(APen, p1, p2, 0);
end;
procedure TAxisDrawHelperX.DrawLabelAndTick(
@ -454,19 +469,20 @@ end;
procedure TAxisDrawHelperY.DrawAxisLine(APen: TChartPen; AFixedCoord: Integer);
var
p: TPoint;
p1, p2: TPoint;
begin
if FAxis.Arrow.Inverted then begin
p := Point(AFixedCoord, FClipRect^.Bottom);
if FAxis.IsFlipped then begin
p1 := Point(AFixedCoord, IfThen(FAtDataOnly, GraphToImage(FMaxForMarks), FClipRect^.Bottom));
p2 := Point(AFixedCoord, IfThen(FAtDataOnly, GraphToImage(FMinForMarks), FClipRect^.Top));
if FAxis.Arrow.Visible then
p.Y += FDrawer.Scale(FAxis.Arrow.Length);
InternalAxisLine(APen, p, Point(AFixedCoord, FClipRect^.Top), -Pi / 2);
p1.Y += FDrawer.Scale(FAxis.Arrow.Length);
end else begin
p := Point(AFixedCoord, FClipRect^.Top);
p1 := Point(AFixedCoord, IfThen(FAtDataOnly, GraphToImage(FMinForMarks), FClipRect^.Bottom));
p2 := Point(AFixedCoord, IfThen(FAtDataOnly, GraphToImage(FMaxForMarks), FClipRect^.Top));
if FAxis.Arrow.Visible then
p.Y -= FDrawer.Scale(FAxis.Arrow.Length);
InternalAxisLine(APen, Point(AFixedCoord, FClipRect^.Bottom), p, -Pi / 2);
p2.Y -= FDrawer.Scale(FAxis.Arrow.Length);
end;
InternalAxisLine(APen, p1, p2, -Pi / 2);
end;
procedure TAxisDrawHelperY.DrawLabelAndTick(
@ -696,6 +712,11 @@ begin
Result := Marks.DefaultSource.Params;
end;
function TChartBasicAxis.IsFlipped: Boolean;
begin
Result := false;
end;
procedure TChartBasicAxis.SetArrow(AValue: TChartArrow);
begin
FArrow.Assign(AValue);

View File

@ -171,7 +171,7 @@ procedure TDrawFuncHelper.ForEachPoint(
AXg, AXMax: Double; AOnMoveTo, AOnLineTo: TOnPoint);
var
hint: Integer;
xa, xg1, xa1: Double;
xa, xg1, xa1, dx: Double;
begin
if FGraphStep = 0 then exit;
@ -183,8 +183,9 @@ begin
if AXg < AXMax then
AOnMoveTo(AXg, xa);
dx := abs(FGraphStep);
while AXg < AXMax do begin
xg1 := AXg + FGraphStep;
xg1 := AXg + dx;
xa1 := FGraphToAxisXr(xg1);
if FDomainExclusions.Intersect(xa, xa1, hint) then begin
AOnLineTo(FAxisToGraphXr(xa), xa);

View File

@ -87,6 +87,7 @@ type
function AxisToGraphY(AY: Double): Double; override;
function GetAxisX: TChartAxis;
function GetAxisY: TChartAxis;
function GetAxisBounds(AAxis: TChartAxis; out AMin, AMax: Double): Boolean; override;
function GetGraphBounds: TDoubleRect; override;
function GraphToAxis(APoint: TDoublePoint): TDoublePoint;
function GraphToAxisX(AX: Double): Double; override;
@ -355,6 +356,29 @@ begin
inherited;
end;
function TCustomChartSeries.GetAxisBounds(AAxis: TChartAxis;
out AMin, AMax: Double): Boolean;
var
ex: TDoubleRect;
begin
if (AAxis.Index = AxisIndexX) or (AAxis.Index = AxisIndexY) then begin
ex := EmptyExtent;
GetBounds(ex);
with ex do begin
UpdateBoundsByAxisRange(FChart.AxisList, AxisIndexX, a.X, b.X);
UpdateBoundsByAxisRange(FChart.AxisList, AxisIndexY, a.Y, b.Y);
if IsRotated then begin
Exchange(a.X, a.Y);
Exchange(b.X, b.Y);
end;
end;
AMin := TDoublePointBoolArr(ex.a)[AAxis.IsVertical];
AMax := TDoublePointBoolArr(ex.b)[AAxis.IsVertical];
Result := true;
end else
Result := false;
end;
function TCustomChartSeries.GetAxisX: TChartAxis;
begin
if InRange(AxisIndexX, 0, FChart.AxisList.Count - 1) then

View File

@ -1708,8 +1708,8 @@ begin
ADrawer.SetPenParams(psClear, clTAColor);
end;
if StepX > 1 then scaled_stepX := Max(1, ADrawer.Scale(StepX));
if StepY > 1 then scaled_stepY := Max(1, ADrawer.Scale(StepY));
scaled_stepX := IfThen(StepX > 1, Max(1, ADrawer.Scale(StepX)), 1);
scaled_stepY := IfThen(StepY > 1, Max(1, ADrawer.Scale(StepY)), 1);
try
pt.Y := (r.Top div scaled_stepY - 1) * scaled_stepY + offset.Y mod scaled_stepY;

View File

@ -78,10 +78,12 @@ type
public
procedure Draw(ADrawer: IChartDrawer); virtual; abstract;
function GetAxisBounds(AAxis: TChartAxis; out AMin, AMax: Double): boolean; virtual; abstract;
function GetGraphBounds: TDoubleRect; virtual; abstract;
function IsEmpty: Boolean; virtual; abstract;
procedure MovePoint(var AIndex: Integer; const ANewPos: TPoint); overload; inline;
procedure MovePoint(var AIndex: Integer; const ANewPos: TDoublePoint); overload; virtual;
procedure UpdateBiDiMode; virtual;
property Active: Boolean read FActive write SetActive default true;
property Depth: TChartDistance read FDepth write SetDepth default 0;
@ -139,6 +141,7 @@ type
procedure Clear;
function Count: Integer;
function GetEnumerator: TBasicChartSeriesEnumerator;
procedure UpdateBiDiMode;
public
property Items[AIndex: Integer]: TBasicChartSeries read GetItem; default;
property List: TIndexedComponentList read FList;
@ -274,6 +277,7 @@ type
procedure MouseUp(
AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer); override;
protected
function GetAxisBounds(AAxis: TChartAxis): TDoubleInterval;
function GetAxisByAlign(AAlign: TChartAxisAlignment): TChartAxis;
procedure SetAxisByAlign(AAlign: TChartAxisAlignment; AValue: TChartAxis); inline;
protected
@ -318,6 +322,7 @@ type
procedure EnableRedrawing;
function GetFullExtent: TDoubleRect;
function GetLegendItems(AIncludeHidden: Boolean = false): TChartLegendItems;
procedure Notify(ACommand: Integer; AParam1, AParam2: Pointer; var AData); override;
procedure PaintOnAuxCanvas(ACanvas: TCanvas; ARect: TRect);
procedure PaintOnCanvas(ACanvas: TCanvas; ARect: TRect);
procedure Prepare;
@ -984,8 +989,27 @@ begin
AClass := nil;
end;
function TChart.GetAxisBounds(AAxis: TChartAxis): TDoubleInterval;
var
s: TBasicChartSeries;
mn, mx: Double;
begin
Result.FStart := Infinity;
Result.FEnd := NegInfinity;
for s in Series do
if s.Active and s.GetAxisBounds(AAxis, mn, mx) then begin
Result.FStart := Min(Result.FStart, mn);
Result.FEnd := Max(Result.FEnd, mx);
end;
end;
function TChart.GetAxisByAlign(AAlign: TChartAxisAlignment): TChartAxis;
begin
if (BidiMode <> bdLeftToRight) then
case AAlign of
calLeft: AAlign := calRight;
calRight: AAlign := calLeft;
end;
Result := FAxisList.GetAxisByAlign(AAlign);
end;
@ -1231,6 +1255,20 @@ begin
inherited Notification(AComponent, AOperation);
end;
{ Notifies the chart of something which is specified by ACommand and both
parameters. Needed for example by the axis to query the extent covered by
all series using this axis (cannot be called directly because TAChartAxis
does not "use" TACustomSeries. }
procedure TChart.Notify(ACommand: Integer; AParam1, AParam2: Pointer; var AData);
begin
UnUsed(AParam2);
case ACommand of
CMD_QUERY_SERIESEXTENT:
TDoubleInterval(AData) := GetAxisBounds(TChartAxis(AParam1));
end;
end;
procedure TChart.Paint;
var
defaultDrawing: Boolean = true;
@ -1418,6 +1456,7 @@ begin
Legend.UpdateBidiMode;
Title.UpdateBidiMode;
Foot.UpdateBidiMode;
Series.UpdateBiDiMode;
end;
end;
@ -1749,6 +1788,11 @@ begin
MovePoint(AIndex, FChart.ImageToGraph(ANewPos));
end;
procedure TBasicChartSeries.UpdateBiDiMode;
begin
// normally nothing to do. Override, e.g., to flip arrows
end;
procedure TBasicChartSeries.UpdateMargins(
ADrawer: IChartDrawer; var AMargins: TRect);
begin
@ -1804,6 +1848,14 @@ begin
Result := TBasicChartSeries(FList.Items[AIndex]);
end;
procedure TChartSeriesList.UpdateBiDiMode;
var
s: TBasicChartseries;
begin
for s in self do
s.UpdateBiDiMode;
end;
{ TBasicChartTool }
procedure TBasicChartTool.Activate;

View File

@ -289,6 +289,7 @@ type
out AResults: TNearestPointResults): Boolean; override;
function IsEmpty: Boolean; override;
procedure MovePoint(var AIndex: Integer; const ANewPos: TDoublePoint); override;
procedure UpdateBiDiMode; override;
published
property Active default true;
@ -894,6 +895,12 @@ begin
UpdateParentChart;
end;
procedure TConstantLine.UpdateBiDiMode;
begin
if LineStyle = lsHorizontal then
Arrow.Inverted := not Arrow.Inverted;
end;
{ TBarSeries }
procedure TBarSeries.Assign(ASource: TPersistent);

View File

@ -35,9 +35,14 @@ const
DEF_SHADOW_OFFSET = 8;
DEF_SHADOW_TRANSPARENCY = 128;
// Constants for Chart.Notify commands
CMD_QUERY_SERIESEXTENT = 0;
type
TCustomChart = class(TCustomControl)
public
procedure Notify(ACommand: Integer; AParam1, AParam2: Pointer; var Data); virtual; abstract;
procedure StyleChanged(Sender: TObject); virtual; abstract;
procedure ZoomFull(AImmediateRecalc: Boolean = false); virtual; abstract;
end;