~ubuntu-branches/ubuntu/saucy/lazarus/saucy

« back to all changes in this revision

Viewing changes to components/tachart/tatypes.pas

  • Committer: Package Import Robot
  • Author(s): Paul Gevers, Abou Al Montacir, Bart Martens, Paul Gevers
  • Date: 2013-06-08 14:12:17 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20130608141217-7k0cy9id8ifcnutc
Tags: 1.0.8+dfsg-1
[ Abou Al Montacir ]
* New upstream major release and multiple maintenace release offering many
  fixes and new features marking a new milestone for the Lazarus development
  and its stability level.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_fixes_branch
* LCL changes:
  - LCL is now a normal package.
      + Platform independent parts of the LCL are now in the package LCLBase
      + LCL is automatically recompiled when switching the target platform,
        unless pre-compiled binaries for this target are already installed.
      + No impact on existing projects.
      + Linker options needed by LCL are no more added to projects that do
        not use the LCL package.
  - Minor changes in LCL basic classes behaviour
      + TCustomForm.Create raises an exception if a form resource is not
        found.
      + TNotebook and TPage: a new implementation of these classes was added.
      + TDBNavigator: It is now possible to have focusable buttons by setting
        Options = [navFocusableButtons] and TabStop = True, useful for
        accessibility and for devices with neither mouse nor touch screen.
      + Names of TControlBorderSpacing.GetSideSpace and GetSpace were swapped
        and are now consistent. GetSideSpace = Around + GetSpace.
      + TForm.WindowState=wsFullscreen was added
      + TCanvas.TextFitInfo was added to calculate how many characters will
        fit into a specified Width. Useful for word-wrapping calculations.
      + TControl.GetColorResolvingParent and
        TControl.GetRGBColorResolvingParent were added, simplifying the work
        to obtain the final color of the control while resolving clDefault
        and the ParentColor.
      + LCLIntf.GetTextExtentExPoint now has a good default implementation
        which works in any platform not providing a specific implementation.
        However, Widgetset specific implementation is better, when available.
      + TTabControl was reorganized. Now it has the correct class hierarchy
        and inherits from TCustomTabControl as it should.
  - New unit in the LCL:
      + lazdialogs.pas: adds non-native versions of various native dialogs,
        for example TLazOpenDialog, TLazSaveDialog, TLazSelectDirectoryDialog.
        It is used by widgetsets which either do not have a native dialog, or
        do not wish to use it because it is limited. These dialogs can also be
        used by user applications directly.
      + lazdeviceapis.pas: offers an interface to more hardware devices such
        as the accelerometer, GPS, etc. See LazDeviceAPIs
      + lazcanvas.pas: provides a TFPImageCanvas descendent implementing
        drawing in a LCL-compatible way, but 100% in Pascal.
      + lazregions.pas. LazRegions is a wholly Pascal implementation of
        regions for canvas clipping, event clipping, finding in which control
        of a region tree one an event should reach, for drawing polygons, etc.
      + customdrawncontrols.pas, customdrawndrawers.pas,
        customdrawn_common.pas, customdrawn_android.pas and
        customdrawn_winxp.pas: are the Lazarus Custom Drawn Controls -controls
        which imitate the standard LCL ones, but with the difference that they
        are non-native and support skinning.
  - New APIs added to the LCL to improve support of accessibility software
    such as screen readers.
* IDE changes:
  - Many improvments.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/New_IDE_features_since#v1.0_.282012-08-29.29
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes#IDE_Changes
* Debugger / Editor changes:
  - Added pascal sources and breakpoints to the disassembler
  - Added threads dialog.
* Components changes:
  - TAChart: many fixes and new features
  - CodeTool: support Delphi style generics and new syntax extensions.
  - AggPas: removed to honor free licencing. (Closes: Bug#708695)
[Bart Martens]
* New debian/watch file fixing issues with upstream RC release.
[Abou Al Montacir]
* Avoid changing files in .pc hidden directory, these are used by quilt for
  internal purpose and could lead to surprises during build.
[Paul Gevers]
* Updated get-orig-source target and it compinion script orig-tar.sh so that they
  repack the source file, allowing bug 708695 to be fixed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
}
24
24
unit TATypes;
25
25
 
26
 
{$mode objfpc}{$H+}
 
26
{$H+}
27
27
 
28
28
interface
29
29
 
30
30
uses
31
31
  Classes, SysUtils, Graphics, Controls, FPCanvas, Types,
32
 
  TAChartUtils;
 
32
  TAChartUtils, TADrawUtils,
 
33
 
 
34
  // Workaround for issue #22850.
 
35
  GraphMath, Math,
 
36
  TACustomSource, TAGeometry;
33
37
 
34
38
const
35
39
  MARKS_MARGIN_X = 4;
37
41
  DEF_MARGIN = 4;
38
42
  DEF_MARKS_DISTANCE = 20;
39
43
  DEF_POINTER_SIZE = 4;
 
44
  MARKS_YINDEX_ALL = -1;
 
45
  DEF_ARROW_LENGTH = 10;
 
46
  DEF_ARROW_WIDTH = 5;
40
47
 
41
48
type
42
49
  TCustomChart = class(TCustomControl)
48
55
  { TChartPen }
49
56
 
50
57
  TChartPen = class(TPen)
51
 
  private
 
58
  strict private
52
59
    FVisible: Boolean;
53
60
    procedure SetVisible(AValue: Boolean);
54
61
  public
55
62
    constructor Create; override;
56
63
  public
57
 
    procedure Assign(Source: TPersistent); override;
 
64
    procedure Assign(ASource: TPersistent); override;
58
65
  published
59
66
    property Visible: Boolean read FVisible write SetVisible default true;
60
67
  end;
64
71
  { TChartElement }
65
72
 
66
73
  TChartElement = class(TPersistent)
67
 
  protected
68
 
    FVisible: Boolean;
69
 
    procedure SetVisible(const AValue: Boolean);
70
 
  protected
 
74
  strict protected
71
75
    FOwner: TCustomChart;
 
76
    FVisible: Boolean;
 
77
    procedure InitHelper(var AResult; AClass: TFPCanvasHelperClass);
 
78
    procedure SetVisible(AValue: Boolean);
 
79
    procedure StyleChanged(Sender: TObject); virtual;
 
80
  protected
72
81
    function GetOwner: TPersistent; override;
73
 
    procedure InitHelper(var AResult; AClass: TFPCanvasHelperClass);
74
 
    procedure StyleChanged(Sender: TObject);
75
82
  public
76
83
    constructor Create(AOwner: TCustomChart);
77
84
  public
78
 
    procedure Assign(Source: TPersistent); override;
 
85
    procedure Assign(ASource: TPersistent); override;
79
86
 
80
87
    procedure SetOwner(AOwner: TCustomChart);
81
88
 
82
89
    property Visible: Boolean read FVisible write SetVisible;
83
90
  end;
84
91
 
 
92
  TChartMarksOverlapPolicy = (opIgnore, opHideNeighbour);
 
93
 
 
94
  TChartTextElement = class(TChartElement)
 
95
  strict private
 
96
    FClipped: Boolean;
 
97
    FOverlapPolicy: TChartMarksOverlapPolicy;
 
98
    procedure SetAlignment(AValue: TAlignment);
 
99
    procedure SetClipped(AValue: Boolean);
 
100
    procedure SetOverlapPolicy(AValue: TChartMarksOverlapPolicy);
 
101
  strict protected
 
102
    FAlignment: TAlignment;
 
103
    procedure AddMargins(ADrawer: IChartDrawer; var ASize: TPoint);
 
104
    procedure ApplyLabelFont(ADrawer: IChartDrawer); virtual;
 
105
    function IsMarginRequired: Boolean;
 
106
  strict protected
 
107
    function GetFrame: TChartPen; virtual; abstract;
 
108
    function GetLabelAngle: Double; virtual;
 
109
    function GetLabelBrush: TBrush; virtual; abstract;
 
110
    function GetLabelFont: TFont; virtual; abstract;
 
111
    function GetLinkPen: TChartPen; virtual;
 
112
  public
 
113
    constructor Create(AOwner: TCustomChart);
 
114
  public
 
115
    procedure Assign(ASource: TPersistent); override;
 
116
    procedure DrawLabel(
 
117
      ADrawer: IChartDrawer; const ADataPoint, ALabelCenter: TPoint;
 
118
      const AText: String; var APrevLabelPoly: TPointArray);
 
119
    function GetLabelPolygon(ADrawer: IChartDrawer; ASize: TPoint): TPointArray;
 
120
    function MeasureLabel(ADrawer: IChartDrawer; const AText: String): TSize;
 
121
  public
 
122
    // If false, labels may overlap axises and legend.
 
123
    property Clipped: Boolean read FClipped write SetClipped default true;
 
124
    property OverlapPolicy: TChartMarksOverlapPolicy
 
125
      read FOverlapPolicy write SetOverlapPolicy default opIgnore;
 
126
  published
 
127
    property Alignment: TAlignment
 
128
      read FAlignment write SetAlignment;
 
129
  end;
 
130
 
 
131
  TChartTitleFramePen = class(TChartPen)
 
132
  published
 
133
    property Visible default false;
 
134
  end;
 
135
 
85
136
  { TChartTitle }
86
137
 
87
 
  TChartTitle = class(TChartElement)
88
 
  private
89
 
    FAlignment: TAlignment;
 
138
  TChartTitle = class(TChartTextElement)
 
139
  strict private
90
140
    FBrush: TBrush;
91
141
    FFont: TFont;
92
 
    FFrame: TChartPen;
 
142
    FFrame: TChartTitleFramePen;
93
143
    FMargin: TChartDistance;
94
144
    FText: TStrings;
95
145
 
96
 
    procedure SetAlignment(AValue: TAlignment);
97
146
    procedure SetBrush(AValue: TBrush);
98
147
    procedure SetFont(AValue: TFont);
99
 
    procedure SetFrame(AValue: TChartPen);
 
148
    procedure SetFrame(AValue: TChartTitleFramePen);
100
149
    procedure SetMargin(AValue: TChartDistance);
101
150
    procedure SetText(AValue: TStrings);
 
151
  strict protected
 
152
    function GetFrame: TChartPen; override;
 
153
    function GetLabelBrush: TBrush; override;
 
154
    function GetLabelFont: TFont; override;
102
155
  public
103
156
    constructor Create(AOwner: TCustomChart);
104
157
    destructor Destroy; override;
105
158
  public
106
 
    procedure Assign(Source: TPersistent); override;
 
159
    procedure Assign(ASource: TPersistent); override;
 
160
    procedure Draw(
 
161
      ADrawer: IChartDrawer; ADir, ALeft, ARight: Integer; var AY: Integer);
107
162
  published
108
 
    property Alignment: TAlignment
109
 
      read FAlignment write SetAlignment default taCenter;
 
163
    property Alignment default taCenter;
110
164
    property Brush: TBrush read FBrush write SetBrush;
111
165
    property Font: TFont read FFont write SetFont;
112
 
    property Frame: TChartPen read FFrame write SetFrame;
 
166
    property Frame: TChartTitleFramePen read FFrame write SetFrame;
113
167
    property Margin: TChartDistance
114
168
      read FMargin write SetMargin default DEF_MARGIN;
115
169
    property Text: TStrings read FText write SetText;
116
170
    property Visible default false;
117
171
  end;
118
172
 
119
 
  TChartMarksOverlapPolicy = (opIgnore, opHideNeighbour);
120
 
 
121
173
  TChartMarkAttachment = (maDefault, maEdge, maCenter);
122
174
 
123
175
  { TGenericChartMarks }
124
176
 
125
177
  {$IFNDEF fpdoc}  // Workaround for issue #18549.
126
178
  generic TGenericChartMarks<_TLabelBrush, _TLinkPen, _TFramePen> =
127
 
    class(TChartElement)
 
179
    class(TChartTextElement)
128
180
  {$ELSE}
129
 
  TGenericChartMarks = class(TChartElement)
 
181
  TGenericChartMarks = class(TChartTextElement)
130
182
  {$ENDIF}
131
 
  private
 
183
  strict private
 
184
    FAdditionalAngle: Double;
 
185
    FAttachment: TChartMarkAttachment;
 
186
    FFrame: _TFramePen;
 
187
    FYIndex: Integer;
132
188
    function GetDistanceToCenter: Boolean;
133
 
    function LabelAngle: Double; inline;
134
 
    procedure PutLabelFontTo(ACanvas: TCanvas);
135
189
    procedure SetAttachment(AValue: TChartMarkAttachment);
 
190
    procedure SetDistance(AValue: TChartDistance);
136
191
    procedure SetDistanceToCenter(AValue: Boolean);
137
 
  protected
138
 
    FAdditionalAngle: Double;
139
 
    FAttachment: TChartMarkAttachment;
140
 
    FClipped: Boolean;
 
192
    procedure SetFormat(AValue: String);
 
193
    procedure SetFrame(AValue: _TFramePen);
 
194
    procedure SetLabelBrush(AValue: _TLabelBrush);
 
195
    procedure SetLabelFont(AValue: TFont);
 
196
    procedure SetLinkPen(AValue: _TLinkPen);
 
197
    procedure SetStyle(AValue: TSeriesMarksStyle);
 
198
    procedure SetYIndex(AValue: Integer);
 
199
  strict protected
141
200
    FDistance: TChartDistance;
142
201
    FFormat: String;
143
 
    FFrame: _TFramePen;
144
202
    FLabelBrush: _TLabelBrush;
145
203
    FLabelFont: TFont;
146
204
    FLinkPen: _TLinkPen;
147
 
    FOverlapPolicy: TChartMarksOverlapPolicy;
148
205
    FStyle: TSeriesMarksStyle;
149
 
 
150
 
    procedure SetClipped(AValue: Boolean);
151
 
    procedure SetDistance(AValue: TChartDistance);
152
 
    procedure SetFormat(const AValue: String);
153
 
    procedure SetFrame(const AValue: _TFramePen);
154
 
    procedure SetLabelBrush(const AValue: _TLabelBrush);
155
 
    procedure SetLabelFont(const AValue: TFont);
156
 
    procedure SetLinkPen(const AValue: _TLinkPen);
157
 
    procedure SetOverlapPolicy(AValue: TChartMarksOverlapPolicy);
158
 
    procedure SetStyle(const AValue: TSeriesMarksStyle);
159
 
  protected
160
 
    function IsMarginRequired: Boolean;
 
206
  strict protected
 
207
    procedure ApplyLabelFont(ADrawer: IChartDrawer); override;
 
208
    function GetFrame: TChartPen; override;
 
209
    function GetLabelAngle: Double; override;
 
210
    function GetLabelBrush: TBrush; override;
 
211
    function GetLabelFont: TFont; override;
 
212
    function GetLinkPen: TChartPen; override;
161
213
  public
162
214
    constructor Create(AOwner: TCustomChart);
163
215
    destructor Destroy; override;
164
 
 
165
216
  public
166
 
    procedure Assign(Source: TPersistent); override;
167
 
    function CenterOffset(ACanvas: TCanvas; const AText: String): TSize;
168
 
    procedure DrawLabel(
169
 
      ACanvas: TCanvas; const ADataPoint, ALabelCenter: TPoint;
170
 
      const AText: String; var APrevLabelPoly: TPointArray);
171
 
    function GetLabelPolygon(ASize: TPoint): TPointArray;
 
217
    procedure Assign(ASource: TPersistent); override;
 
218
    function CenterOffset(ADrawer: IChartDrawer; const AText: String): TSize;
172
219
    function IsMarkLabelsVisible: Boolean;
173
 
    function MeasureLabel(ACanvas: TCanvas; const AText: String): TSize;
174
220
    procedure SetAdditionalAngle(AAngle: Double);
175
221
  public
176
222
    property DistanceToCenter: Boolean
180
226
    property Frame: _TFramePen read FFrame write SetFrame;
181
227
    property LabelBrush: _TLabelBrush read FLabelBrush write SetLabelBrush;
182
228
    property LinkPen: _TLinkPen read FLinkPen write SetLinkPen;
183
 
    property OverlapPolicy: TChartMarksOverlapPolicy
184
 
      read FOverlapPolicy write SetOverlapPolicy default opIgnore;
185
229
    property Style: TSeriesMarksStyle read FStyle write SetStyle;
 
230
    property YIndex: Integer read FYIndex write SetYIndex default 0;
186
231
  published
 
232
    property Alignment default taLeftJustify;
187
233
    property Attachment: TChartMarkAttachment
188
234
      read FAttachment write SetAttachment default maDefault;
189
 
    // If false, labels may overlap axises and legend.
190
 
    property Clipped: Boolean read FClipped write SetClipped default true;
191
235
    // Distance between labelled object and label.
 
236
    property Clipped;
192
237
    property Distance: TChartDistance read FDistance write SetDistance;
193
238
    property LabelFont: TFont read FLabelFont write SetLabelFont;
194
239
    property Visible default true;
213
258
 
214
259
  TChartMarks = class(TCustomChartMarks)
215
260
  public
 
261
    procedure Assign(Source: TPersistent); override;
216
262
    constructor Create(AOwner: TCustomChart);
217
263
  published
218
264
    property Distance default DEF_MARKS_DISTANCE;
222
268
    property LinkPen;
223
269
    property OverlapPolicy;
224
270
    property Style default smsNone;
 
271
    property YIndex;
225
272
  end;
226
273
 
227
274
  TSeriesPointerStyle = (
232
279
  { TSeriesPointer }
233
280
 
234
281
  TSeriesPointer = class(TChartElement)
235
 
  private
 
282
  strict private
236
283
    FBrush: TBrush;
237
284
    FHorizSize: Integer;
238
285
    FPen: TChartPen;
250
297
  public
251
298
    procedure Assign(Source: TPersistent); override;
252
299
 
253
 
    procedure Draw(ACanvas: TCanvas; ACenter: TPoint; AColor: TColor);
 
300
    procedure Draw(ADrawer: IChartDrawer; ACenter: TPoint; AColor: TColor);
254
301
    procedure DrawSize(
255
 
      ACanvas: TCanvas; ACenter, ASize: TPoint; AColor: TColor);
 
302
      ADrawer: IChartDrawer; ACenter, ASize: TPoint; AColor: TColor);
256
303
  published
257
304
    property Brush: TBrush read FBrush write SetBrush;
258
305
    property HorizSize: Integer read FHorizSize write SetHorizSize default DEF_POINTER_SIZE;
264
311
 
265
312
  EExtentError = class(EChartError);
266
313
 
 
314
  TChartRange = class(TChartElement)
 
315
  strict private
 
316
    FBounds: array [1..2] of Double;
 
317
    FUseBounds: array [1..2] of Boolean;
 
318
 
 
319
    function GetBounds(AIndex: Integer): Double;
 
320
    function GetUseBounds(AIndex: integer): Boolean;
 
321
    function IsBoundsStored(AIndex: Integer): Boolean;
 
322
    procedure SetBounds(AIndex: Integer; const AValue: Double);
 
323
    procedure SetUseBounds(AIndex: Integer; AValue: Boolean);
 
324
  public
 
325
    procedure Assign(ASource: TPersistent); override;
 
326
    procedure CheckBoundsOrder;
 
327
    procedure Intersect(var AMin, AMax: Double);
 
328
  published
 
329
    property Max: Double index 2 read GetBounds write SetBounds stored IsBoundsStored;
 
330
    property Min: Double index 1 read GetBounds write SetBounds stored IsBoundsStored;
 
331
    property UseMax: Boolean index 2 read GetUseBounds write SetUseBounds default false;
 
332
    property UseMin: Boolean index 1 read GetUseBounds write SetUseBounds default false;
 
333
  end;
 
334
 
267
335
  { TChartExtent }
268
336
 
269
 
  TChartExtent = class (TChartElement)
270
 
  private
 
337
  TChartExtent = class(TChartElement)
 
338
  strict private
271
339
    FExtent: TDoubleRect;
272
340
    FUseBounds: array [1..4] of Boolean;
273
341
 
274
342
    function GetBounds(AIndex: Integer): Double;
275
343
    function GetUseBounds(AIndex: integer): Boolean;
276
 
    function IsBoundsStored(AIndex: Integer): boolean;
 
344
    function IsBoundsStored(AIndex: Integer): Boolean;
277
345
    procedure SetBounds(AIndex: Integer; const AValue: Double);
278
346
    procedure SetUseBounds(AIndex: Integer; AValue: Boolean);
279
347
  public
 
348
    procedure Assign(ASource: TPersistent); override;
280
349
    procedure CheckBoundsOrder;
281
350
  published
 
351
    property UseXMax: Boolean index 3 read GetUseBounds write SetUseBounds default false;
 
352
    property UseXMin: Boolean index 1 read GetUseBounds write SetUseBounds default false;
 
353
    property UseYMax: Boolean index 4 read GetUseBounds write SetUseBounds default false;
 
354
    property UseYMin: Boolean index 2 read GetUseBounds write SetUseBounds default false;
 
355
    property XMax: Double index 3 read GetBounds write SetBounds stored IsBoundsStored;
282
356
    property XMin: Double index 1 read GetBounds write SetBounds stored IsBoundsStored;
 
357
    property YMax: Double index 4 read GetBounds write SetBounds stored IsBoundsStored;
283
358
    property YMin: Double index 2 read GetBounds write SetBounds stored IsBoundsStored;
284
 
    property XMax: Double index 3 read GetBounds write SetBounds stored IsBoundsStored;
285
 
    property YMax: Double index 4 read GetBounds write SetBounds stored IsBoundsStored;
286
 
    property UseXMin: Boolean index 1 read GetUseBounds write SetUseBounds default false;
287
 
    property UseYMin: Boolean index 2 read GetUseBounds write SetUseBounds default false;
288
 
    property UseXMax: Boolean index 3 read GetUseBounds write SetUseBounds default false;
289
 
    property UseYMax: Boolean index 4 read GetUseBounds write SetUseBounds default false;
290
359
  end;
291
360
 
 
361
  TRectArray = array [1..4] of Integer;
 
362
 
292
363
  { TChartMargins }
293
364
 
294
 
  TChartMargins = class (TChartElement)
295
 
  private
 
365
  TChartMargins = class(TChartElement)
 
366
  strict private
296
367
    FData: record
297
368
      case Integer of
298
369
        0: (FRect: TRect;);
299
 
        1: (FCoords: array [1..4] of Integer;);
 
370
        1: (FCoords: TRectArray;);
300
371
      end;
301
372
    function GetValue(AIndex: Integer): integer;
302
373
    procedure SetValue(AIndex: integer; AValue: TChartDistance);
312
383
    property Bottom: TChartDistance index 4 read GetValue write SetValue default DEF_MARGIN;
313
384
  end;
314
385
 
 
386
  TChartArrow = class(TChartElement)
 
387
  strict private
 
388
    FBaseLength: TChartDistance;
 
389
    FLength: TChartDistance;
 
390
    FWidth: TChartDistance;
 
391
    procedure SetBaseLength(AValue: TChartDistance);
 
392
    procedure SetLength(AValue: TChartDistance);
 
393
    procedure SetWidth(AValue: TChartDistance);
 
394
  public
 
395
    constructor Create(AOwner: TCustomChart);
 
396
  public
 
397
    procedure Assign(ASource: TPersistent); override;
 
398
    procedure Draw(
 
399
      ADrawer: IChartDrawer; const AEndPos: TPoint; AAngle: Double;
 
400
      APen: TFPCustomPen);
 
401
  published
 
402
    property BaseLength: TChartDistance
 
403
      read FBaseLength write SetBaseLength default 0;
 
404
    property Length: TChartDistance
 
405
      read FLength write SetLength default DEF_ARROW_LENGTH;
 
406
    property Visible default false;
 
407
    property Width: TChartDistance
 
408
      read FWidth write SetWidth default DEF_ARROW_WIDTH;
 
409
  end;
 
410
 
315
411
implementation
316
412
 
317
 
uses
318
 
  TACustomSource;
319
 
 
320
413
{ TChartPen }
321
414
 
322
 
procedure TChartPen.Assign(Source: TPersistent);
 
415
procedure TChartPen.Assign(ASource: TPersistent);
323
416
begin
324
 
  if Source is TChartPen then
325
 
    with TChartPen(Source) do
326
 
      FVisible := Visible;
327
 
  inherited Assign(Source);
 
417
  if ASource is TChartPen then
 
418
    FVisible := TChartPen(ASource).Visible;
 
419
  inherited Assign(ASource);
328
420
end;
329
421
 
330
422
constructor TChartPen.Create;
331
423
begin
332
424
  inherited Create;
333
 
  FVisible := true;
 
425
  SetPropDefaults(Self, ['Color', 'Style', 'Visible']);
334
426
end;
335
427
 
336
428
procedure TChartPen.SetVisible(AValue: Boolean);
341
433
 
342
434
{ TChartElement }
343
435
 
344
 
procedure TChartElement.Assign(Source: TPersistent);
 
436
procedure TChartElement.Assign(ASource: TPersistent);
345
437
begin
346
 
  if Source is TChartElement then
347
 
    with TChartElement(Source) do begin
 
438
  if ASource is TChartElement then
 
439
    with TChartElement(ASource) do begin
348
440
      Self.FVisible := FVisible;
349
441
      Self.FOwner := FOwner;
350
442
    end;
351
 
  inherited Assign(Source);
352
443
end;
353
444
 
354
445
constructor TChartElement.Create(AOwner: TCustomChart);
373
464
  FOwner := AOwner;
374
465
end;
375
466
 
376
 
procedure TChartElement.SetVisible(const AValue: Boolean);
 
467
procedure TChartElement.SetVisible(AValue: Boolean);
377
468
begin
378
469
  if FVisible = AValue then exit;
379
470
  FVisible := AValue;
386
477
    FOwner.StyleChanged(Sender);
387
478
end;
388
479
 
 
480
{ TChartTextElement }
 
481
 
 
482
procedure TChartTextElement.AddMargins(
 
483
  ADrawer: IChartDrawer; var ASize: TPoint);
 
484
begin
 
485
  if not IsMarginRequired then exit;
 
486
  with ADrawer do
 
487
    ASize += Point(Scale(MARKS_MARGIN_X), Scale(MARKS_MARGIN_Y)) * 2;
 
488
end;
 
489
 
 
490
procedure TChartTextElement.ApplyLabelFont(ADrawer: IChartDrawer);
 
491
begin
 
492
  ADrawer.Font := GetLabelFont;
 
493
end;
 
494
 
 
495
procedure TChartTextElement.Assign(ASource: TPersistent);
 
496
begin
 
497
  if ASource is TChartTextElement then
 
498
    with TChartTextElement(ASource) do begin
 
499
      Self.FAlignment := Alignment;
 
500
      Self.FClipped := FClipped;
 
501
      Self.FOverlapPolicy := FOverlapPolicy;
 
502
    end;
 
503
  inherited Assign(ASource);
 
504
end;
 
505
 
 
506
constructor TChartTextElement.Create(AOwner: TCustomChart);
 
507
begin
 
508
  inherited Create(AOwner);
 
509
  FClipped := true;
 
510
  FOverlapPolicy := opIgnore;
 
511
end;
 
512
 
 
513
procedure TChartTextElement.DrawLabel(
 
514
  ADrawer: IChartDrawer; const ADataPoint, ALabelCenter: TPoint;
 
515
  const AText: String; var APrevLabelPoly: TPointArray);
 
516
var
 
517
  labelPoly: TPointArray;
 
518
  ptText: TPoint;
 
519
  i, w: Integer;
 
520
begin
 
521
  ApplyLabelFont(ADrawer);
 
522
  ptText := ADrawer.TextExtent(AText);
 
523
  w := ptText.X;
 
524
  labelPoly := GetLabelPolygon(ADrawer, ptText);
 
525
  for i := 0 to High(labelPoly) do
 
526
    labelPoly[i] += ALabelCenter;
 
527
 
 
528
  if
 
529
    (OverlapPolicy = opHideNeighbour) and
 
530
    IsPolygonIntersectsPolygon(APrevLabelPoly, labelPoly)
 
531
  then
 
532
    exit;
 
533
  APrevLabelPoly := labelPoly;
 
534
 
 
535
  if not Clipped then
 
536
    ADrawer.ClippingStop;
 
537
 
 
538
  if (ADataPoint <> ALabelCenter) and GetLinkPen.Visible then begin
 
539
    ADrawer.Pen := GetLinkPen;
 
540
    ADrawer.Line(ADataPoint, ALabelCenter);
 
541
  end;
 
542
  ADrawer.Brush := GetLabelBrush;
 
543
  if IsMarginRequired then begin
 
544
    if GetFrame.Visible then
 
545
      ADrawer.Pen := GetFrame
 
546
    else
 
547
      ADrawer.SetPenParams(psClear, clTAColor);
 
548
    ADrawer.Polygon(labelPoly, 0, Length(labelPoly));
 
549
  end;
 
550
 
 
551
  ptText := RotatePoint(-ptText div 2, GetLabelAngle) + ALabelCenter;
 
552
  ADrawer.TextOut.Pos(ptText).Alignment(Alignment).Width(w).Text(AText).Done;
 
553
  if not Clipped then
 
554
    ADrawer.ClippingStart;
 
555
end;
 
556
 
 
557
function TChartTextElement.GetLabelAngle: Double;
 
558
begin
 
559
  // Negate to take into account top-down Y axis.
 
560
  Result := -OrientToRad(GetLabelFont.Orientation);
 
561
end;
 
562
 
 
563
function TChartTextElement.GetLabelPolygon(
 
564
  ADrawer: IChartDrawer; ASize: TPoint): TPointArray;
 
565
begin
 
566
  AddMargins(ADrawer, ASize);
 
567
  Result := RotateRect(ASize, GetLabelAngle);
 
568
end;
 
569
 
 
570
function TChartTextElement.GetLinkPen: TChartPen;
 
571
begin
 
572
  Result := nil;
 
573
end;
 
574
 
 
575
function TChartTextElement.IsMarginRequired: Boolean;
 
576
begin
 
577
  with GetFrame do
 
578
    Result := (GetLabelBrush.Style <> bsClear) or (Style <> psClear) and Visible;
 
579
end;
 
580
 
 
581
function TChartTextElement.MeasureLabel(
 
582
  ADrawer: IChartDrawer; const AText: String): TSize;
 
583
var
 
584
  sz: TPoint;
 
585
begin
 
586
  ApplyLabelFont(ADrawer);
 
587
  sz := ADrawer.TextExtent(AText);
 
588
  AddMargins(ADrawer, sz);
 
589
  Result := MeasureRotatedRect(sz, GetLabelAngle);
 
590
end;
 
591
 
 
592
procedure TChartTextElement.SetAlignment(AValue: TAlignment);
 
593
begin
 
594
  if FAlignment = AValue then exit;
 
595
  FAlignment := AValue;
 
596
  StyleChanged(Self);
 
597
end;
 
598
 
 
599
procedure TChartTextElement.SetClipped(AValue: Boolean);
 
600
begin
 
601
  if FClipped = AValue then exit;
 
602
  FClipped := AValue;
 
603
  StyleChanged(Self);
 
604
end;
 
605
 
 
606
procedure TChartTextElement.SetOverlapPolicy(AValue: TChartMarksOverlapPolicy);
 
607
begin
 
608
  if FOverlapPolicy = AValue then exit;
 
609
  FOverlapPolicy := AValue;
 
610
  StyleChanged(Self);
 
611
end;
 
612
 
389
613
{ TChartTitle }
390
614
 
391
 
procedure TChartTitle.Assign(Source: TPersistent);
 
615
procedure TChartTitle.Assign(ASource: TPersistent);
392
616
begin
393
 
  if Source is TChartTitle then
394
 
    with TChartTitle(Source) do begin
395
 
      Self.FAlignment := Alignment;
 
617
  if ASource is TChartTitle then
 
618
    with TChartTitle(ASource) do begin
396
619
      Self.FBrush.Assign(Brush);
397
620
      Self.FFont.Assign(Font);
398
621
      Self.FFrame.Assign(Frame);
399
622
      Self.FText.Assign(Text);
400
623
   end;
401
624
 
402
 
  inherited Assign(Source);
 
625
  inherited Assign(ASource);
403
626
end;
404
627
 
405
628
constructor TChartTitle.Create(AOwner: TCustomChart);
411
634
  FBrush.Color := FOwner.Color;
412
635
  InitHelper(FFont, TFont);
413
636
  FFont.Color := clBlue;
414
 
  InitHelper(FFrame, TChartPen);
 
637
  InitHelper(FFrame, TChartTitleFramePen);
415
638
  FMargin := DEF_MARGIN;
416
639
  FText := TStringList.Create;
417
640
  TStringList(FText).OnChange := @StyleChanged;
427
650
  inherited;
428
651
end;
429
652
 
430
 
procedure TChartTitle.SetAlignment(AValue: TAlignment);
431
 
begin
432
 
  if FAlignment = AValue then exit;
433
 
  FAlignment := AValue;
434
 
  StyleChanged(Self);
 
653
procedure TChartTitle.Draw(
 
654
  ADrawer: IChartDrawer; ADir, ALeft, ARight: Integer; var AY: Integer);
 
655
var
 
656
  p, ptSize: TPoint;
 
657
  dummy: TPointArray = nil;
 
658
begin
 
659
  if not Visible or (Text.Count = 0) then exit;
 
660
  ptSize := MeasureLabel(ADrawer, Text.Text);
 
661
  case Alignment of
 
662
    taLeftJustify: p.X := ALeft + ptSize.X div 2;
 
663
    taRightJustify: p.X := ARight - ptSize.X div 2;
 
664
    taCenter: p.X := (ALeft + ARight) div 2;
 
665
  end;
 
666
  p.Y := AY + ADir * ptSize.Y div 2;
 
667
  DrawLabel(ADrawer, p, p, Text.Text, dummy);
 
668
  AY += ADir * (ptSize.Y + Margin);
 
669
end;
 
670
 
 
671
function TChartTitle.GetFrame: TChartPen;
 
672
begin
 
673
  Result := Frame;
 
674
end;
 
675
 
 
676
function TChartTitle.GetLabelBrush: TBrush;
 
677
begin
 
678
  Result := Brush;
 
679
end;
 
680
 
 
681
function TChartTitle.GetLabelFont: TFont;
 
682
begin
 
683
  Result := Font;
435
684
end;
436
685
 
437
686
procedure TChartTitle.SetBrush(AValue: TBrush);
446
695
  StyleChanged(Self);
447
696
end;
448
697
 
449
 
procedure TChartTitle.SetFrame(AValue: TChartPen);
 
698
procedure TChartTitle.SetFrame(AValue: TChartTitleFramePen);
450
699
begin
451
700
  FFrame.Assign(AValue);
452
701
  StyleChanged(Self);
467
716
 
468
717
{ TGenericChartMarks }
469
718
 
470
 
procedure TGenericChartMarks.Assign(Source: TPersistent);
471
 
begin
472
 
  if Source is Self.ClassType then
473
 
    with TGenericChartMarks(Source) do begin
474
 
      Self.FClipped := FClipped;
 
719
procedure TGenericChartMarks.ApplyLabelFont(ADrawer: IChartDrawer);
 
720
begin
 
721
  inherited ApplyLabelFont(ADrawer);
 
722
  if FAdditionalAngle <> 0 then
 
723
    ADrawer.AddToFontOrientation(RadToOrient(FAdditionalAngle));
 
724
end;
 
725
 
 
726
procedure TGenericChartMarks.Assign(ASource: TPersistent);
 
727
begin
 
728
  if ASource is Self.ClassType then
 
729
    with TGenericChartMarks(ASource) do begin
 
730
      Self.FAttachment := FAttachment;
475
731
      Self.FDistance := FDistance;
476
732
      Self.FFormat := FFormat;
477
733
      Self.FFrame.Assign(FFrame);
478
 
      Self.FLabelBrush.Assign(FLabelBrush);
479
 
      Self.FLabelFont.Assign(FLabelFont);
480
 
      Self.FLinkPen.Assign(FLinkPen);
481
 
      Self.FOverlapPolicy := FOverlapPolicy;
 
734
      // FPC miscompiles virtual calls to generic type arguments,
 
735
      // so as a workaround these assignments are moved to the specializations.
 
736
      // Self.FLabelBrush.Assign(FLabelBrush);
 
737
      // Self.FLabelFont.Assign(FLabelFont);
 
738
      // Self.FLinkPen.Assign(FLinkPen);
482
739
      Self.FStyle := FStyle;
 
740
      Self.FYIndex := FYIndex;
483
741
    end;
484
 
  inherited Assign(Source);
 
742
  inherited Assign(ASource);
485
743
end;
486
744
 
487
745
function TGenericChartMarks.CenterOffset(
488
 
  ACanvas: TCanvas; const AText: String): TSize;
 
746
  ADrawer: IChartDrawer; const AText: String): TSize;
 
747
var
 
748
  d: Integer;
489
749
begin
490
 
  Result := Point(Distance, Distance);
 
750
  d := ADrawer.Scale(Distance);
 
751
  Result := Point(d, d);
491
752
  if not DistanceToCenter then
492
 
    Result += MeasureLabel(ACanvas, AText) div 2;
 
753
    Result += MeasureLabel(ADrawer, AText) div 2;
493
754
end;
494
755
 
495
756
constructor TGenericChartMarks.Create(AOwner: TCustomChart);
496
757
begin
497
758
  inherited Create(AOwner);
498
 
  FClipped := true;
499
759
  InitHelper(FFrame, _TFramePen);
500
760
  InitHelper(FLabelBrush, _TLabelBrush);
501
761
  InitHelper(FLabelFont, TFont);
502
762
  InitHelper(FLinkPen, _TLinkPen);
503
 
  FOverlapPolicy := opIgnore;
504
763
  FStyle := smsNone;
505
764
  FVisible := true;
506
765
end;
514
773
  inherited;
515
774
end;
516
775
 
517
 
procedure TGenericChartMarks.DrawLabel(
518
 
  ACanvas: TCanvas; const ADataPoint, ALabelCenter: TPoint;
519
 
  const AText: String; var APrevLabelPoly: TPointArray);
520
 
var
521
 
  wasClipping: Boolean = false;
522
 
  labelPoly: TPointArray;
523
 
  ptText: TPoint;
524
 
  i: Integer;
525
 
begin
526
 
  PutLabelFontTo(ACanvas);
527
 
  ptText := ACanvas.TextExtent(AText);
528
 
  labelPoly := GetLabelPolygon(ptText);
529
 
  for i := 0 to High(labelPoly) do
530
 
    labelPoly[i] += ALabelCenter;
531
 
 
532
 
  if
533
 
    (OverlapPolicy = opHideNeighbour) and
534
 
    IsPolygonIntersectsPolygon(APrevLabelPoly, labelPoly)
535
 
  then
536
 
    exit;
537
 
  APrevLabelPoly := labelPoly;
538
 
 
539
 
  if not Clipped and ACanvas.Clipping then begin
540
 
    ACanvas.Clipping := false;
541
 
    wasClipping := true;
542
 
  end;
543
 
 
544
 
  if LinkPen.Visible then begin
545
 
    ACanvas.Pen.Assign(LinkPen);
546
 
    ACanvas.Line(ADataPoint, ALabelCenter);
547
 
  end;
548
 
  ACanvas.Brush.Assign(LabelBrush);
549
 
  if IsMarginRequired then begin
550
 
    ACanvas.Pen.Assign(Frame);
551
 
    ACanvas.Polygon(labelPoly);
552
 
  end;
553
 
 
554
 
  ptText := RotatePoint(-ptText div 2, LabelAngle) + ALabelCenter;
555
 
  ACanvas.TextOut(ptText.X, ptText.Y, AText);
556
 
  if wasClipping then
557
 
    ACanvas.Clipping := true;
558
 
end;
559
 
 
560
776
function TGenericChartMarks.GetDistanceToCenter: Boolean;
561
777
begin
562
778
  Result := Attachment = maCenter;
563
779
end;
564
780
 
565
 
function TGenericChartMarks.GetLabelPolygon(ASize: TPoint): TPointArray;
566
 
var
567
 
  i: Integer;
568
 
  a: Double;
569
 
begin
570
 
  if IsMarginRequired then
571
 
    ASize += Point(MARKS_MARGIN_X, MARKS_MARGIN_Y) * 2;
572
 
  SetLength(Result, 4);
573
 
  Result[0] := -ASize div 2;
574
 
  Result[2] := Result[0] + ASize;
575
 
  Result[1] := Point(Result[2].X, Result[0].Y);
576
 
  Result[3] := Point(Result[0].X, Result[2].Y);
577
 
  a := LabelAngle;
578
 
  for i := 0 to High(Result) do
579
 
    Result[i] := RotatePoint(Result[i], a);
580
 
end;
581
 
 
582
 
function TGenericChartMarks.IsMarginRequired: Boolean;
583
 
begin
584
 
  Result :=
585
 
    (LabelBrush.Style <> bsClear) or
586
 
    (Frame.Style <> psClear) and Frame.Visible;
 
781
function TGenericChartMarks.GetFrame: TChartPen;
 
782
begin
 
783
  Result := Frame;
 
784
end;
 
785
 
 
786
function TGenericChartMarks.GetLabelAngle: Double;
 
787
begin
 
788
  Result := inherited GetLabelAngle - FAdditionalAngle;
 
789
end;
 
790
 
 
791
function TGenericChartMarks.GetLabelBrush: TBrush;
 
792
begin
 
793
  Result := LabelBrush;
 
794
end;
 
795
 
 
796
function TGenericChartMarks.GetLabelFont: TFont;
 
797
begin
 
798
  Result := LabelFont;
 
799
end;
 
800
 
 
801
function TGenericChartMarks.GetLinkPen: TChartPen;
 
802
begin
 
803
  Result := LinkPen;
587
804
end;
588
805
 
589
806
function TGenericChartMarks.IsMarkLabelsVisible: Boolean;
591
808
  Result := Visible and (Style <> smsNone) and (Format <> '');
592
809
end;
593
810
 
594
 
function TGenericChartMarks.LabelAngle: Double;
595
 
begin
596
 
  // Negate to take into account top-down Y axis.
597
 
  Result := -OrientToRad(LabelFont.Orientation) - FAdditionalAngle;
598
 
end;
599
 
 
600
 
function TGenericChartMarks.MeasureLabel(
601
 
  ACanvas: TCanvas; const AText: String): TSize;
602
 
var
603
 
  sz: TPoint;
604
 
begin
605
 
  PutLabelFontTo(ACanvas);
606
 
  sz := ACanvas.TextExtent(AText);
607
 
  if IsMarginRequired then
608
 
    sz += Point(MARKS_MARGIN_X, MARKS_MARGIN_Y) * 2;
609
 
  Result := MeasureRotatedRect(sz, LabelAngle);
610
 
end;
611
 
 
612
 
procedure TGenericChartMarks.PutLabelFontTo(ACanvas: TCanvas);
613
 
begin
614
 
  with ACanvas.Font do begin
615
 
    Assign(LabelFont);
616
 
    if FAdditionalAngle <> 0 then
617
 
      Orientation := Orientation + RadToOrient(FAdditionalAngle);
618
 
  end;
619
 
end;
620
 
 
621
811
procedure TGenericChartMarks.SetAdditionalAngle(AAngle: Double);
622
812
begin
623
813
  FAdditionalAngle := AAngle;
630
820
  StyleChanged(Self);
631
821
end;
632
822
 
633
 
procedure TGenericChartMarks.SetClipped(AValue: Boolean);
634
 
begin
635
 
  if FClipped = AValue then exit;
636
 
  FClipped := AValue;
637
 
  StyleChanged(Self);
638
 
end;
639
 
 
640
823
procedure TGenericChartMarks.SetDistance(AValue: TChartDistance);
641
824
begin
642
825
  if FDistance = AValue then exit;
652
835
    Attachment := maDefault;
653
836
end;
654
837
 
655
 
procedure TGenericChartMarks.SetFormat(const AValue: String);
 
838
procedure TGenericChartMarks.SetFormat(AValue: String);
656
839
begin
657
840
  if FFormat = AValue then exit;
658
841
  TCustomChartSource.CheckFormat(AValue);
663
846
  StyleChanged(Self);
664
847
end;
665
848
 
666
 
procedure TGenericChartMarks.SetFrame(const AValue: _TFramePen);
 
849
procedure TGenericChartMarks.SetFrame(AValue: _TFramePen);
667
850
begin
668
851
  if FFrame = AValue then exit;
669
852
  FFrame.Assign(AValue);
670
853
  StyleChanged(Self);
671
854
end;
672
855
 
673
 
procedure TGenericChartMarks.SetLabelBrush(const AValue: _TLabelBrush);
 
856
procedure TGenericChartMarks.SetLabelBrush(AValue: _TLabelBrush);
674
857
begin
675
858
  if FLabelBrush = AValue then exit;
676
859
  FLabelBrush.Assign(AValue);
677
860
  StyleChanged(Self);
678
861
end;
679
862
 
680
 
procedure TGenericChartMarks.SetLabelFont(const AValue: TFont);
 
863
procedure TGenericChartMarks.SetLabelFont(AValue: TFont);
681
864
begin
682
865
  if FLabelFont = AValue then exit;
683
 
  FLabelFont := AValue;
 
866
  FLabelFont.Assign(AValue);
684
867
  StyleChanged(Self);
685
868
end;
686
869
 
687
 
procedure TGenericChartMarks.SetLinkPen(const AValue: _TLinkPen);
 
870
procedure TGenericChartMarks.SetLinkPen(AValue: _TLinkPen);
688
871
begin
689
872
  if FLinkPen = AValue then exit;
690
 
  FLinkPen := AValue;
691
 
  StyleChanged(Self);
692
 
end;
693
 
 
694
 
procedure TGenericChartMarks.SetOverlapPolicy(AValue: TChartMarksOverlapPolicy);
695
 
begin
696
 
  if FOverlapPolicy = AValue then exit;
697
 
  FOverlapPolicy := AValue;
698
 
  StyleChanged(Self);
699
 
end;
700
 
 
701
 
procedure TGenericChartMarks.SetStyle(const AValue: TSeriesMarksStyle);
 
873
  FLinkPen.Assign(AValue);
 
874
  StyleChanged(Self);
 
875
end;
 
876
 
 
877
procedure TGenericChartMarks.SetStyle(AValue: TSeriesMarksStyle);
702
878
begin
703
879
  if FStyle = AValue then exit;
704
880
  FStyle := AValue;
707
883
  StyleChanged(Self);
708
884
end;
709
885
 
 
886
procedure TGenericChartMarks.SetYIndex(AValue: Integer);
 
887
begin
 
888
  if FYIndex = AValue then exit;
 
889
  FYIndex := AValue;
 
890
  StyleChanged(Self);
 
891
end;
 
892
 
710
893
{ TChartMarks }
711
894
 
 
895
procedure TChartMarks.Assign(Source: TPersistent);
 
896
begin
 
897
  if Source is TChartMarks then
 
898
    with TChartMarks(Source) do begin
 
899
      Self.FLabelBrush.Assign(FLabelBrush);
 
900
      Self.FLabelFont.Assign(FLabelFont);
 
901
      Self.FLinkPen.Assign(FLinkPen);
 
902
    end;
 
903
  inherited Assign(Source);
 
904
end;
 
905
 
712
906
constructor TChartMarks.Create(AOwner: TCustomChart);
713
907
begin
714
908
  inherited Create(AOwner);
715
909
  FDistance := DEF_MARKS_DISTANCE;
716
910
  FLabelBrush.Color := clYellow;
717
 
  FLinkPen.Color := clWhite;
718
911
end;
719
912
 
720
913
{ TSeriesPointer }
724
917
  if Source is TSeriesPointer then
725
918
    with TSeriesPointer(Source) do begin
726
919
      Self.FBrush.Assign(Brush);
 
920
      Self.FHorizSize := HorizSize;
727
921
      Self.FPen.Assign(Pen);
728
922
      Self.FStyle := Style;
 
923
      Self.FVertSize := VertSize;
729
924
    end;
730
925
  inherited Assign(Source);
731
926
end;
750
945
  inherited;
751
946
end;
752
947
 
753
 
procedure TSeriesPointer.Draw(ACanvas: TCanvas; ACenter: TPoint; AColor: TColor);
 
948
procedure TSeriesPointer.Draw(
 
949
  ADrawer: IChartDrawer; ACenter: TPoint; AColor: TColor);
754
950
begin
755
 
  DrawSize(ACanvas, ACenter, Point(HorizSize, VertSize), AColor);
 
951
  DrawSize(ADrawer, ACenter, Point(HorizSize, VertSize), AColor);
756
952
end;
757
953
 
758
954
procedure TSeriesPointer.DrawSize(
759
 
  ACanvas: TCanvas; ACenter, ASize: TPoint; AColor: TColor);
 
955
  ADrawer: IChartDrawer; ACenter, ASize: TPoint; AColor: TColor);
760
956
 
761
957
  function PointByIndex(AIndex: Char): TPoint;
762
958
  // 7--8--9
780
976
    SetLength(pts, Length(AStr));
781
977
    for i := 1 to Length(AStr) do begin
782
978
      if AStr[i] = ' ' then begin
783
 
        if Brush.Style = bsClear then begin
784
 
          ACanvas.Polyline(pts, 0, j);
785
 
          // Polyline does not draw the end point.
786
 
          ACanvas.Pixels[pts[j - 1].X, pts[j - 1].Y] := Pen.Color;
787
 
        end
 
979
        if Brush.Style = bsClear then
 
980
          ADrawer.Polyline(pts, 0, j)
788
981
        else
789
 
          ACanvas.Polygon(pts, true, 0, j);
 
982
          ADrawer.Polygon(pts, 0, j); // Winding?
790
983
        j := 0;
791
984
      end
792
985
      else begin
805
998
    '41236', '47896', '87412', '89632', '84268',
806
999
    '183', '842', '862');
807
1000
begin
808
 
  ACanvas.Brush.Assign(FBrush);
 
1001
  ADrawer.Brush := Brush;
809
1002
  if AColor <> clTAColor then
810
 
    ACanvas.Brush.Color := AColor;
811
 
  ACanvas.Pen.Assign(FPen);
 
1003
    ADrawer.BrushColor := AColor;
 
1004
  ADrawer.Pen := Pen;
812
1005
 
813
 
  if FStyle = psCircle then
814
 
    ACanvas.Ellipse(
 
1006
  if Style = psCircle then
 
1007
    ADrawer.Ellipse(
815
1008
      ACenter.X - ASize.X, ACenter.Y - ASize.Y,
816
 
      ACenter.X + ASize.X, ACenter.Y + ASize.Y)
 
1009
      ACenter.X + ASize.X + 1, ACenter.Y + ASize.Y + 1)
817
1010
  else
818
 
    DrawByString(DRAW_STRINGS[FStyle] + ' ');
 
1011
    DrawByString(DRAW_STRINGS[Style] + ' ');
819
1012
end;
820
1013
 
821
1014
procedure TSeriesPointer.SetBrush(AValue: TBrush);
851
1044
  StyleChanged(Self);
852
1045
end;
853
1046
 
 
1047
{ TChartRange }
 
1048
 
 
1049
procedure TChartRange.Assign(ASource: TPersistent);
 
1050
begin
 
1051
  if ASource is TChartRange then
 
1052
    with TChartRange(ASource) do begin
 
1053
      Self.FBounds := FBounds;
 
1054
      Self.FUseBounds := FUseBounds;
 
1055
    end;
 
1056
  inherited Assign(ASource);
 
1057
end;
 
1058
 
 
1059
procedure TChartRange.CheckBoundsOrder;
 
1060
begin
 
1061
  if UseMin and UseMax and (Min >= Max) then begin
 
1062
    UseMin := false;
 
1063
    UseMax := false;
 
1064
    raise EExtentError.Create('ChartRange: Min >= Max');
 
1065
  end;
 
1066
end;
 
1067
 
 
1068
function TChartRange.GetBounds(AIndex: Integer): Double;
 
1069
begin
 
1070
  Result := FBounds[AIndex];
 
1071
end;
 
1072
 
 
1073
function TChartRange.GetUseBounds(AIndex: integer): Boolean;
 
1074
begin
 
1075
  Result := FUseBounds[AIndex];
 
1076
end;
 
1077
 
 
1078
procedure TChartRange.Intersect(var AMin, AMax: Double);
 
1079
begin
 
1080
  if UseMin and (Min > AMin) then
 
1081
    AMin := Min;
 
1082
  if UseMax and (Max < AMax)then
 
1083
    AMax := Max;
 
1084
end;
 
1085
 
 
1086
function TChartRange.IsBoundsStored(AIndex: Integer): Boolean;
 
1087
begin
 
1088
  Result := FBounds[AIndex] <> 0;
 
1089
end;
 
1090
 
 
1091
procedure TChartRange.SetBounds(AIndex: Integer; const AValue: Double);
 
1092
begin
 
1093
  FBounds[AIndex] := AValue;
 
1094
  StyleChanged(Self);
 
1095
end;
 
1096
 
 
1097
procedure TChartRange.SetUseBounds(AIndex: Integer; AValue: Boolean);
 
1098
begin
 
1099
  FUseBounds[AIndex] := AValue;
 
1100
  StyleChanged(Self);
 
1101
end;
 
1102
 
854
1103
{ TChartExtent }
855
1104
 
856
 
function TChartExtent.GetUseBounds(AIndex: Integer): Boolean;
857
 
begin
858
 
  Result := FUseBounds[AIndex];
859
 
end;
860
 
 
861
 
function TChartExtent.IsBoundsStored(AIndex: Integer): boolean;
862
 
begin
863
 
  Result := FExtent.coords[AIndex] <> 0;
 
1105
procedure TChartExtent.Assign(ASource: TPersistent);
 
1106
begin
 
1107
  if ASource is TChartExtent then
 
1108
    with TChartExtent(ASource) do begin
 
1109
      Self.FExtent := FExtent;
 
1110
      Self.FUseBounds := FUseBounds;
 
1111
    end;
 
1112
  inherited Assign(ASource);
864
1113
end;
865
1114
 
866
1115
procedure TChartExtent.CheckBoundsOrder;
882
1131
  Result := FExtent.coords[AIndex];
883
1132
end;
884
1133
 
885
 
procedure TChartExtent.SetUseBounds(AIndex: Integer; AValue: Boolean);
886
 
begin
887
 
  FUseBounds[AIndex] := AValue;
888
 
  StyleChanged(Self);
 
1134
function TChartExtent.GetUseBounds(AIndex: Integer): Boolean;
 
1135
begin
 
1136
  Result := FUseBounds[AIndex];
 
1137
end;
 
1138
 
 
1139
function TChartExtent.IsBoundsStored(AIndex: Integer): Boolean;
 
1140
begin
 
1141
  Result := FExtent.coords[AIndex] <> 0;
889
1142
end;
890
1143
 
891
1144
procedure TChartExtent.SetBounds(AIndex: Integer; const AValue: Double);
894
1147
  StyleChanged(Self);
895
1148
end;
896
1149
 
 
1150
procedure TChartExtent.SetUseBounds(AIndex: Integer; AValue: Boolean);
 
1151
begin
 
1152
  FUseBounds[AIndex] := AValue;
 
1153
  StyleChanged(Self);
 
1154
end;
 
1155
 
897
1156
{ TChartMargins }
898
1157
 
899
1158
procedure TChartMargins.Assign(Source: TPersistent);
921
1180
  StyleChanged(Self);
922
1181
end;
923
1182
 
 
1183
{ TChartArrow }
 
1184
 
 
1185
procedure TChartArrow.Assign(ASource: TPersistent);
 
1186
begin
 
1187
  if ASource is TChartArrow then
 
1188
    with TChartArrow(ASource) do begin
 
1189
      Self.FBaseLength := FBaseLength;
 
1190
      Self.FLength := FLength;
 
1191
      Self.FWidth := FWidth;
 
1192
    end;
 
1193
  inherited Assign(ASource);
 
1194
end;
 
1195
 
 
1196
constructor TChartArrow.Create(AOwner: TCustomChart);
 
1197
begin
 
1198
  inherited Create(AOwner);
 
1199
  FLength := DEF_ARROW_LENGTH;
 
1200
  FVisible := false;
 
1201
  FWidth := DEF_ARROW_WIDTH;
 
1202
end;
 
1203
 
 
1204
procedure TChartArrow.Draw(
 
1205
  ADrawer: IChartDrawer; const AEndPos: TPoint; AAngle: Double;
 
1206
  APen: TFPCustomPen);
 
1207
var
 
1208
  da: Double;
 
1209
  diag: Integer;
 
1210
  pt1, pt2, ptBase: TPoint;
 
1211
begin
 
1212
  if not Visible then exit;
 
1213
  da := ArcTan2(Width, Length);
 
1214
 
 
1215
  diag := -ADrawer.Scale(Round(Sqrt(Sqr(Length) + Sqr(Width))));
 
1216
  pt1 := AEndPos + RotatePointX(diag, AAngle - da);
 
1217
  pt2 := AEndPos + RotatePointX(diag, AAngle + da);
 
1218
  if BaseLength > 0 then begin
 
1219
    ptBase := AEndPos + RotatePointX(-ADrawer.Scale(BaseLength), AAngle);
 
1220
    ADrawer.SetBrushParams(bsSolid, FPColorToChartColor(APen.FPColor));
 
1221
    ADrawer.Polygon([pt1, AEndPos, pt2, ptBase], 0, 4);
 
1222
  end
 
1223
  else
 
1224
    ADrawer.Polyline([pt1, AEndPos, pt2], 0, 3);
 
1225
end;
 
1226
 
 
1227
procedure TChartArrow.SetBaseLength(AValue: TChartDistance);
 
1228
begin
 
1229
  if FBaseLength = AValue then exit;
 
1230
  FBaseLength := AValue;
 
1231
  StyleChanged(Self);
 
1232
end;
 
1233
 
 
1234
procedure TChartArrow.SetLength(AValue: TChartDistance);
 
1235
begin
 
1236
  if FLength = AValue then exit;
 
1237
  FLength := AValue;
 
1238
  StyleChanged(Self);
 
1239
end;
 
1240
 
 
1241
procedure TChartArrow.SetWidth(AValue: TChartDistance);
 
1242
begin
 
1243
  if FWidth = AValue then exit;
 
1244
  FWidth := AValue;
 
1245
  StyleChanged(Self);
 
1246
end;
 
1247
 
924
1248
end.
925
1249