XIII. Code complet du composant TCircleChart▲
CircChart.pas
Sélectionnez
unit
CircChart;
interface
uses
Windows, Messages, Forms, Classes, SysUtils, Graphics, Controls, Math,
ActnList;
type
TChartQuarter = class
;
TCircleChart = class
;
TChartQuarterActionLink = class
(TActionLink)
protected
FClient : TChartQuarter;
procedure
AssignClient(AClient : TObject); override
;
function
IsAutoCheckLinked : boolean
; virtual
;
function
IsCaptionLinked : boolean
; override
;
function
IsPercentLinked : boolean
; virtual
;
function
IsCheckedLinked : boolean
; override
;
function
IsEnabledLinked : boolean
; override
;
function
IsHelpContextLinked : boolean
; override
;
function
IsHintLinked: boolean
; override
;
function
IsGroupIndexLinked : boolean
; override
;
function
IsImageIndexLinked : boolean
; override
;
function
IsShortCutLinked : boolean
; override
;
function
IsVisibleLinked : boolean
; override
;
function
IsShowTextLinked : boolean
; virtual
;
function
IsOnExecuteLinked : boolean
; override
;
procedure
SetAutoCheck(Value : boolean
); override
;
procedure
SetCaption(const
value : string
); override
;
procedure
SetPercent(Value : Single
); virtual
;
procedure
SetChecked(Value : boolean
); override
;
procedure
SetEnabled(Value : boolean
); override
;
procedure
SetHint(const
Value : string
); override
;
procedure
SetShowText(Value : boolean
); virtual
;
procedure
SetOnExecute(Value : TNotifyEvent); override
;
end
;
TChartQuarterActionLinkClass = class
of
TChartQuarterActionLink;
TCustomChartQuarterAction = class
(TCustomAction)
private
FPercent : Single
;
FShowText : boolean
;
procedure
SetPercent(New : Single
);
procedure
SetShowText(New : boolean
);
protected
procedure
AssignTo(Dest : TPersistent); override
;
public
constructor
Create(AOwner : TComponent); override
;
property
Percent : Single
read
FPercent write
SetPercent;
property
ShowText : boolean
read
FShowText write
SetShowText default
True
;
end
;
TChartQuarterAction = class
(TCustomChartQuarterAction)
published
property
AutoCheck;
property
Caption;
property
Percent;
property
Checked;
property
Enabled;
property
GroupIndex;
property
HelpContext;
property
HelpKeyword;
property
HelpType;
property
Hint;
property
ImageIndex;
property
ShortCut;
property
SecondaryShortCuts;
property
Visible;
property
ShowText;
property
OnExecute;
property
OnHint;
property
OnUpdate;
end
;
TChartQuarterGraphics = class
(TPersistent)
private
FBackgroundBrush : TBrush;
FTextBrush : TBrush;
FFont : TFont;
procedure
SetBackgroundBrush(New : TBrush);
procedure
SetTextBrush(New : TBrush);
procedure
SetFont(New : TFont);
public
constructor
Create(AOnChange : TNotifyEvent = nil
);
destructor
Destroy; override
;
procedure
Assign(Source : TPersistent); override
;
published
property
BackgroundBrush : TBrush read
FBackgroundBrush write
SetBackgroundBrush;
property
TextBrush : TBrush read
FTextBrush write
SetTextBrush;
property
Font : TFont read
FFont write
SetFont;
end
;
TChartQuarter = class
(TCollectionItem)
private
FCircleChart : TCircleChart;
FActionLink : TChartQuarterActionLink;
FAutoCheck : boolean
;
FText : string
;
FPercent : Single
;
FDown : boolean
;
FEnabled : boolean
;
FGroupIndex : integer
;
FHint : string
;
FShowText : boolean
;
FGraphics : TChartQuarterGraphics;
FDownGraphics : TChartQuarterGraphics;
FDisabledGraphics : TChartQuarterGraphics;
FOnClick : TNotifyEvent;
function
GetAction : TBasicAction;
procedure
SetAction(New : TBasicAction);
procedure
SetText(const
New : string
);
procedure
SetPercent(New : Single
);
procedure
SetDown(New : boolean
);
procedure
SetEnabled(New : boolean
);
procedure
SetGroupIndex(New : integer
);
procedure
SetGraphics(New : TChartQuarterGraphics);
procedure
SetDownGraphics(New : TChartQuarterGraphics);
procedure
SetDisabledGraphics(New : TChartQuarterGraphics);
procedure
SetShowText(New : boolean
);
procedure
GraphicsChange(Sender : TObject);
procedure
DoActionChange(Sender : TObject);
function
IsAutoCheckStored : boolean
;
function
IsTextStored : boolean
;
function
IsPercentStored : boolean
;
function
IsDownStored : boolean
;
function
IsEnabledStored : boolean
;
function
IsGroupIndexStored : boolean
;
function
IsHintStored : boolean
;
function
IsShowTextStored : boolean
;
protected
function
GetDisplayName : string
; override
;
procedure
ActionChange(Sender : TObject; CheckDefaults : boolean
); dynamic
;
function
GetActionLinkClass : TChartQuarterActionLinkClass; dynamic
;
property
ActionLink : TChartQuarterActionLink read
FActionLink write
FActionLink;
public
constructor
Create(Collection : TCollection); override
;
destructor
Destroy; override
;
procedure
Assign(Source : TPersistent); override
;
procedure
Click;
published
property
Action : TBasicAction read
GetAction write
SetAction;
property
AutoCheck : boolean
read
FAutoCheck write
FAutoCheck stored
IsAutoCheckStored;
property
Text : string
read
FText write
SetText stored
IsTextStored;
property
Percent : Single
read
FPercent write
SetPercent stored
IsPercentStored;
property
Down : boolean
read
FDown write
SetDown stored
IsDownStored;
property
Enabled : boolean
read
FEnabled write
SetEnabled stored
IsEnabledStored;
property
GroupIndex : integer
read
FGroupIndex write
SetGroupIndex stored
IsGroupIndexStored;
property
Hint : string
read
FHint write
FHint stored
IsHintStored;
property
ShowText : boolean
read
FShowText write
SetShowText stored
IsShowTextStored;
property
Graphics : TChartQuarterGraphics read
FGraphics write
SetGraphics;
property
DownGraphics : TChartQuarterGraphics read
FDownGraphics write
SetDownGraphics;
property
DisabledGraphics : TChartQuarterGraphics read
FDisabledGraphics write
SetDisabledGraphics;
property
OnClick : TNotifyEvent read
FOnClick write
FOnClick;
end
;
TChartQuarters = class
(TCollection)
private
FCircleChart : TCircleChart;
function
GetItem(Index
: integer
) : TChartQuarter;
procedure
SetItem(Index
: integer
; Value : TChartQuarter);
protected
function
GetOwner : TPersistent; override
;
procedure
Update(Item : TCollectionItem); override
;
public
constructor
Create(ACircleChart : TCircleChart);
function
Add : TChartQuarter;
function
AddItem(Item : TChartQuarter; Index
: integer
) : TChartQuarter;
function
Insert(Index
: integer
) : TChartQuarter;
property
Items[index
: integer
] : TChartQuarter read
GetItem write
SetItem; default
;
end
;
TQuarterClickEvent = procedure
(Sender : TObject; Index
: integer
; Quarter : TChartQuarter) of
object
;
TCircleChart = class
(TGraphicControl)
private
FClickedQuarter : integer
;
FPopupQuarter : TChartQuarter;
FSpoke : integer
;
FBrush : TBrush;
FPen : TPen;
FQuarters : TChartQuarters;
FBaseAngle : integer
;
FOnClickQuarter : TQuarterClickEvent;
procedure
SetSpoke(New : integer
);
procedure
SetBrush(New : TBrush);
procedure
SetPen(New : TPen);
procedure
SetQuarters(New : TChartQuarters);
procedure
SetBaseAngle(New : integer
);
procedure
GraphicsChange(Sender : TObject);
procedure
CMHintShow(var
Message
: TCMHintShow); message
CM_HINTSHOW;
protected
procedure
Notification(AComponent : TComponent; Operation : TOperation); override
;
procedure
AdjustSize; override
;
procedure
Paint; override
;
procedure
DoContextPopup(MousePos : TPoint; var
Handled : boolean
); override
;
procedure
MouseDown(Button : TMouseButton; Shift : TShiftState;
X, Y : integer
); override
;
procedure
MouseUp(Button : TMouseButton; Shift : TShiftState;
X, Y : integer
); override
;
procedure
DoClickQuarter(Index
: integer
; Quarter : TChartQuarter); virtual
;
procedure
ClickQuarter(Index
: integer
);
public
constructor
Create(AOwner : TComponent); override
;
destructor
Destroy; override
;
function
PointToQuarterIndex(Point : TPoint) : integer
;
function
PointToQuarter(Point : TPoint) : TChartQuarter;
property
PopupQuarter : TChartQuarter read
FPopupQuarter;
published
property
AutoSize default
True
;
property
Color default
clNone;
property
DragKind;
property
DragCursor;
property
DragMode;
property
ParentBiDiMode;
property
ParentColor default
False
;
property
ParentShowHint;
property
PopupMenu;
property
Align;
property
Anchors;
property
BiDiMode;
property
Constraints;
property
DockOrientation;
property
ShowHint;
property
Visible;
property
Spoke : integer
read
FSpoke write
SetSpoke default
100
;
property
Brush : TBrush read
FBrush write
SetBrush;
property
Pen : TPen read
FPen write
SetPen;
property
Quarters : TChartQuarters read
FQuarters write
SetQuarters;
property
BaseAngle : integer
read
FBaseAngle write
SetBaseAngle default
90
;
property
OnClick;
property
OnConstrainedResize;
property
OnContextPopup;
property
OnDblClick;
property
OnDragDrop;
property
OnDragOver;
property
OnEndDock;
property
OnEndDrag;
property
OnMouseActivate;
property
OnMouseDown;
property
OnMouseMove;
property
OnMouseUp;
property
OnMouseWheel;
property
OnMouseWheelDown;
property
OnMouseWheelUp;
property
OnResize;
property
OnStartDock;
property
OnStartDrag;
property
OnClickQuarter : TQuarterClickEvent read
FOnClickQuarter write
FOnClickQuarter;
end
;
implementation
//////////////////////////////////////
/// Classe TChartQuarterActionLink ///
//////////////////////////////////////
procedure
TChartQuarterActionLink.AssignClient(AClient : TObject);
begin
FClient := AClient as
TChartQuarter;
end
;
function
TChartQuarterActionLink.IsAutoCheckLinked : boolean
;
begin
Result := (Action is
TCustomAction) and
(FClient.AutoCheck = (Action as
TCustomAction).AutoCheck);
end
;
function
TChartQuarterActionLink.IsCaptionLinked : boolean
;
begin
Result := inherited
IsCaptionLinked and
(FClient.Text = (Action as
TCustomAction).Caption);
end
;
function
TChartQuarterActionLink.IsPercentLinked : boolean
;
begin
Result := (Action is
TCustomChartQuarterAction) and
(FClient.Percent = (Action as
TCustomChartQuarterAction).Percent);
end
;
function
TChartQuarterActionLink.IsCheckedLinked : boolean
;
begin
Result := inherited
IsCheckedLinked and
(FClient.Down = (Action as
TCustomAction).Checked);
end
;
function
TChartQuarterActionLink.IsEnabledLinked : boolean
;
begin
Result := inherited
IsEnabledLinked and
(FClient.Enabled = (Action as
TCustomAction).Enabled);
end
;
function
TChartQuarterActionLink.IsHelpContextLinked : boolean
;
begin
Result := False
;
end
;
function
TChartQuarterActionLink.IsHintLinked : boolean
;
begin
Result := inherited
IsHintLinked and
(FClient.Hint = (Action as
TCustomAction).Hint);
end
;
function
TChartQuarterActionLink.IsGroupIndexLinked : boolean
;
begin
Result := inherited
IsGroupIndexLinked and
(FClient.GroupIndex = (Action as
TCustomAction).GroupIndex);
end
;
function
TChartQuarterActionLink.IsImageIndexLinked : boolean
;
begin
Result := False
;
end
;
function
TChartQuarterActionLink.IsShortCutLinked : boolean
;
begin
Result := False
;
end
;
function
TChartQuarterActionLink.IsVisibleLinked : boolean
;
begin
Result := False
;
end
;
function
TChartQuarterActionLink.IsShowTextLinked : boolean
;
begin
Result := (Action is
TCustomChartQuarterAction) and
(FClient.ShowText = (Action as
TCustomChartQuarterAction).ShowText);
end
;
function
TChartQuarterActionLink.IsOnExecuteLinked : boolean
;
begin
Result := inherited
IsOnExecuteLinked and
(@FClient.OnClick = @Action.OnExecute);
end
;
procedure
TChartQuarterActionLink.SetAutoCheck(Value : boolean
);
begin
if
IsAutoCheckLinked then
FClient.AutoCheck := Value;
end
;
procedure
TChartQuarterActionLink.SetCaption(const
Value : string
);
begin
if
IsCaptionLinked then
FClient.Text := Value;
end
;
procedure
TChartQuarterActionLink.SetPercent(Value : Single
);
begin
if
IsPercentLinked then
FClient.Percent := Value;
end
;
procedure
TChartQuarterActionLink.SetChecked(Value : boolean
);
begin
if
IsCheckedLinked then
FClient.Down := Value;
end
;
procedure
TChartQuarterActionLink.SetEnabled(Value : boolean
);
begin
if
IsEnabledLinked then
FClient.Enabled := Value;
end
;
procedure
TChartQuarterActionLink.SetHint(const
Value : string
);
begin
if
IsHintLinked then
FClient.Hint := Value;
end
;
procedure
TChartQuarterActionLink.SetShowText(Value : boolean
);
begin
if
IsShowTextLinked then
FClient.ShowText := Value;
end
;
procedure
TChartQuarterActionLink.SetOnExecute(Value : TNotifyEvent);
begin
if
IsOnExecuteLinked then
FClient.OnClick := Value;
end
;
////////////////////////////////////////
/// Classe TCustomChartQuarterAction ///
////////////////////////////////////////
constructor
TCustomChartQuarterAction.Create(AOwner : TComponent);
begin
inherited
;
FPercent := 0
.0
;
FShowText := True
;
end
;
procedure
TCustomChartQuarterAction.SetPercent(New : Single
);
var
I : integer
;
Link : TActionLink;
begin
if
(New <> FPercent) and
(New >= 0
.0
) then
begin
for
I := 0
to
FClients.Count-1
do
begin
Link := TObject(FClients.List[I]) as
TActionLink;
if
Assigned(Link) and
(Link is
TChartQuarterActionLink) then
TChartQuarterActionLink(Link).SetPercent(New);
end
;
FPercent := New;
Change;
end
;
end
;
procedure
TCustomChartQuarterAction.SetShowText(New : boolean
);
var
I : integer
;
Link : TActionLink;
begin
if
New <> FShowText then
begin
for
I := 0
to
FClients.Count-1
do
begin
Link := TObject(FClients.List[I]) as
TActionLink;
if
Assigned(Link) and
(Link is
TChartQuarterActionLink) then
TChartQuarterActionLink(Link).SetShowText(New);
end
;
FShowText := New;
Change;
end
;
end
;
procedure
TCustomChartQuarterAction.AssignTo(Dest : TPersistent);
begin
if
Dest is
TCustomChartQuarterAction then
with
TCustomChartQuarterAction(Dest) do
begin
Percent := Self
.Percent;
ShowText := Self
.ShowText;
end
;
inherited
;
end
;
////////////////////////////////////
/// Classe TChartQuarterGraphics ///
////////////////////////////////////
constructor
TChartQuarterGraphics.Create(AOnChange : TNotifyEvent = nil
);
begin
inherited
Create;
FBackgroundBrush := TBrush.Create;
FBackgroundBrush.OnChange := AOnChange;
FTextBrush := TBrush.Create;
FTextBrush.OnChange := AOnChange;
FFont := TFont.Create;
FFont.OnChange := AOnChange;
end
;
destructor
TChartQuarterGraphics.Destroy;
begin
FFont.Free;
FTextBrush.Free;
FBackgroundBrush.Free;
inherited
Destroy;
end
;
procedure
TChartQuarterGraphics.SetBackgroundBrush(New : TBrush);
begin
FBackgroundBrush.Assign(New);
end
;
procedure
TChartQuarterGraphics.SetTextBrush(New : TBrush);
begin
FTextBrush.Assign(New);
end
;
procedure
TChartQuarterGraphics.SetFont(New : TFont);
begin
FFont.Assign(New);
end
;
procedure
TChartQuarterGraphics.Assign(Source : TPersistent);
begin
if
Source is
TChartQuarterGraphics then
begin
with
TChartQuarterGraphics(Source) do
begin
Self
.FBackgroundBrush.Assign(FBackgroundBrush);
Self
.FTextBrush.Assign(FTextBrush);
Self
.FFont.Assign(FFont);
end
;
end
else
inherited
;
end
;
////////////////////////////
/// Classe TChartQuarter ///
////////////////////////////
constructor
TChartQuarter.Create(Collection : TCollection);
begin
inherited
;
FCircleChart := TChartQuarters(Collection).FCircleChart;
FActionLink := nil
;
FText := ''
;
FPercent := 0
.0
;
FDown := False
;
FEnabled := True
;
FGroupIndex := 0
;
FHint := ''
;
FShowText := True
;
FGraphics := TChartQuarterGraphics.Create(GraphicsChange);
FDownGraphics := TChartQuarterGraphics.Create(GraphicsChange);
FDisabledGraphics := TChartQuarterGraphics.Create(GraphicsChange);
end
;
destructor
TChartQuarter.Destroy;
begin
FDisabledGraphics.Free;
FDownGraphics.Free;
FGraphics.Free;
if
Assigned(FActionLink) then
FActionLink.Free;
inherited
;
end
;
function
TChartQuarter.GetAction : TBasicAction;
begin
if
Assigned(FActionLink) then
Result := FActionLink.Action
else
Result := nil
;
end
;
procedure
TChartQuarter.SetAction(New : TBasicAction);
begin
if
New = nil
then
FreeAndNil(FActionLink) else
begin
if
not
Assigned(FActionLink) then
FActionLink := GetActionLinkClass.Create(Self
);
FActionLink.Action := New;
FActionLink.OnChange := DoActionChange;
ActionChange(New, csLoading in
New.ComponentState);
New.FreeNotification(FCircleChart);
end
;
end
;
procedure
TChartQuarter.SetText(const
New : string
);
begin
FText := New;
Changed(False
);
end
;
procedure
TChartQuarter.SetPercent(New : Single
);
begin
if
New < 0
.0
then
exit;
FPercent := New;
Changed(True
);
end
;
procedure
TChartQuarter.SetDown(New : boolean
);
var
I : integer
;
Quarter : TChartQuarter;
begin
if
New = FDown then
exit;
FDown := New;
if
((FActionLink = nil
) or
(not
FActionLink.IsCheckedLinked)) and
(FGroupIndex > 0
) and
FDown then
for
I := 0
to
Collection.Count-1
do
begin
Quarter := TChartQuarters(Collection)[I];
if
(Quarter <> Self
) and
(Quarter.FGroupIndex = FGroupIndex) then
Quarter.Down := False
;
end
;
Changed(False
);
end
;
procedure
TChartQuarter.SetEnabled(New : boolean
);
begin
FEnabled := New;
Changed(False
);
end
;
procedure
TChartQuarter.SetGroupIndex(New : integer
);
begin
FGroupIndex := New;
end
;
procedure
TChartQuarter.SetGraphics(New : TChartQuarterGraphics);
begin
FGraphics.Assign(New);
end
;
procedure
TChartQuarter.SetDownGraphics(New : TChartQuarterGraphics);
begin
FDownGraphics.Assign(New);
end
;
procedure
TChartQuarter.SetDisabledGraphics(New : TChartQuarterGraphics);
begin
FDisabledGraphics.Assign(New);
end
;
procedure
TChartQuarter.SetShowText(New : boolean
);
begin
FShowText := New;
Changed(False
);
end
;
procedure
TChartQuarter.GraphicsChange(Sender : TObject);
begin
Changed(False
);
end
;
procedure
TChartQuarter.DoActionChange(Sender : TObject);
begin
if
Sender = FActionLink then
ActionChange(FActionLink.Action, False
);
end
;
function
TChartQuarter.IsAutoCheckStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsAutoCheckLinked) and
FAutoCheck <> False
;
end
;
function
TChartQuarter.IsTextStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsCaptionLinked) and
(FText <> ''
);
end
;
function
TChartQuarter.IsPercentStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsPercentLinked) and
(FPercent <> 0
.0
);
end
;
function
TChartQuarter.IsDownStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsCheckedLinked) and
(FDown <> False
);
end
;
function
TChartQuarter.IsEnabledStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsEnabledLinked) and
(FEnabled <> True
);
end
;
function
TChartQuarter.IsGroupIndexStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsGroupIndexLinked) and
(FGroupIndex <> 0
);
end
;
function
TChartQuarter.IsHintStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsHintLinked) and
(FHint <> ''
);
end
;
function
TChartQuarter.IsShowTextStored : boolean
;
begin
Result := (not
Assigned(FActionLink) or
not
FActionLink.IsShowTextLinked) and
(FShowText <> True
);
end
;
function
TChartQuarter.GetDisplayName : string
;
begin
if
Text <> ''
then
Result := Format('%s (%f%%)'
, [FText, FPercent])
else
Result := Format('%f%%'
, [FPercent]);
end
;
procedure
TChartQuarter.ActionChange(Sender : TObject; CheckDefaults : boolean
);
begin
if
Sender is
TCustomAction then
with
TCustomAction(Sender) do
begin
if
not
CheckDefaults or
(Self
.AutoCheck = False
) then
Self
.AutoCheck := AutoCheck;
if
not
CheckDefaults or
(Self
.Text = ''
) then
Self
.Text := Caption;
if
not
CheckDefaults or
(Self
.Down = False
) then
Self
.Down := Checked;
if
not
CheckDefaults or
(Self
.Enabled = True
) then
Self
.Enabled := Enabled;
if
not
CheckDefaults or
(Self
.Hint = ''
) then
Self
.Hint := Hint;
if
not
CheckDefaults or
(Self
.GroupIndex = 0
) then
Self
.GroupIndex := GroupIndex;
if
not
CheckDefaults or
not
Assigned(Self
.OnClick) then
Self
.OnClick := OnExecute;
end
;
if
Sender is
TCustomChartQuarterAction then
with
TCustomChartQuarterAction(Sender) do
begin
if
not
CheckDefaults or
(Self
.Percent = 0
.0
) then
Self
.Percent := Percent;
if
not
CheckDefaults or
(Self
.ShowText = True
) then
Self
.ShowText := ShowText;
end
;
end
;
function
TChartQuarter.GetActionLinkClass : TChartQuarterActionLinkClass;
begin
Result := TChartQuarterActionLink;
end
;
procedure
TChartQuarter.Assign(Source : TPersistent);
var
ChartQuarterSource : TChartQuarter;
begin
if
Source is
TChartQuarter then
begin
ChartQuarterSource := TChartQuarter(Source);
Action := ChartQuarterSource.Action;
FText := ChartQuarterSource.FText;
FPercent := ChartQuarterSource.FPercent;
FDown := ChartQuarterSource.FDown;
FEnabled := ChartQuarterSource.FEnabled;
FGroupIndex := ChartQuarterSource.FGroupIndex;
FHint := ChartQuarterSource.FHint;
FShowText := ChartQuarterSource.FShowText;
FGraphics.Assign(ChartQuarterSource.FGraphics);
FDownGraphics.Assign(ChartQuarterSource.FDownGraphics);
FDisabledGraphics.Assign(ChartQuarterSource.FDisabledGraphics);
Changed(True
);
end
else
inherited
;
end
;
procedure
TChartQuarter.Clic;
begin
if
Enabled then
begin
if
AutoCheck and
((not
Down) or
(GroupIndex = 0
)) and
(not
Assigned(ActionLink) or
not
ActionLink.IsAutoCheckLinked) then
Down := not
Down;
{ Appeler OnClick s'il est assigné et différent du OnExecute de l'action
associée. Si une action est associée, alors invoquer sa méthode Execute,
sinon, appeler OnClick }
if
Assigned(FOnClick) and
(Action <> nil
) and
(@FOnClick <> @Action.OnExecute) then
FOnClick(Self
)
else
if
not
(csDesigning in
FCircleChart.ComponentState) and
(FActionLink <> nil
) then
FActionLink.Action.Execute
else
if
Assigned(FOnClick) then
FOnClick(Self
);
FCircleChart.ClickQuarter(Index
);
end
;
end
;
/////////////////////////////
/// Classe TChartQuarters ///
/////////////////////////////
constructor
TChartQuarters.Create(ACircleChart : TCircleChart);
begin
inherited
Create(TChartQuarter);
FCircleChart := ACircleChart;
end
;
function
TChartQuarters.GetItem(Index
: integer
) : TChartQuarter;
begin
Result := TChartQuarter(inherited
GetItem(Index
));
end
;
procedure
TChartQuarters.SetItem(Index
: integer
; Value : TChartQuarter);
begin
inherited
SetItem(Index
, Value);
end
;
function
TChartQuarters.GetOwner : TPersistent;
begin
Result := FCircleChart;
end
;
procedure
TChartQuarters.Update(Item : TCollectionItem);
begin
FCircleChart.Invalidate;
end
;
function
TChartQuarters.Add : TChartQuarter;
begin
Result := TChartQuarter(inherited
Add);
end
;
function
TChartQuarters.AddItem(Item : TChartQuarter; Index
: integer
) : TChartQuarter;
begin
if
Item = nil
then
Result := Add
else
Result := Item;
if
Assigned(Result) then
begin
Result.Collection := Self
;
if
Index
< 0
then
Index
:= Count - 1
;
Result.Index
:= Index
;
end
;
end
;
function
TChartQuarters.Insert(Index
: integer
) : TChartQuarter;
begin
Result := AddItem(nil
, Index
);
end
;
///////////////////////////
/// Classe TCircleChart ///
///////////////////////////
constructor
TCircleChart.Create(AOwner : TComponent);
begin
inherited
;
FClickedQuarter := -1
;
FPopupQuarter := nil
;
Color := clNone;
FSpoke := 100
;
FBrush := TBrush.Create;
FBrush.OnChange := GraphicsChange;
FPen := TPen.Create;
FPen.OnChange := GraphicsChange;
FQuarters := TChartQuarters.Create(Self
);
FBaseAngle := 90
;
AutoSize := True
;
end
;
destructor
TCircleChart.Destroy;
begin
FQuarters.Free;
FPen.Free;
FBrush.Free;
inherited
;
end
;
procedure
TCircleChart.SetSpoke(New : integer
);
begin
if
New <= 0
then
exit;
FSpoke := New;
if
AutoSize then
AdjustSize;
Invalidate;
end
;
procedure
TCircleChart.SetBrush(New : TBrush);
begin
FBrush.Assign(New);
end
;
procedure
TCircleChart.SetPen(New : TPen);
begin
FPen.Assign(New);
end
;
procedure
TCircleChart.SetQuarters(New : TChartQuarters);
begin
FQuarters.Assign(New);
end
;
procedure
TCircleChart.SetBaseAngle(New : integer
);
begin
FBaseAngle := New mod
360
;
if
FBaseAngle < 0
then
inc(FBaseAngle, 360
);
Invalidate;
end
;
procedure
TCircleChart.GraphicsChange(Sender : TObject);
begin
Invalidate;
end
;
procedure
TCircleChart.CMHintShow(var
Message
: TCMHintShow);
var
Quarter : TChartQuarter;
begin
inherited
;
if
Message
.Result <> 0
then
exit;
Quarter := PointToQuarter(Message
.HintInfo.CursorPos);
if
Assigned(Quarter) and
(Quarter.Hint <> ''
) then
Message
.HintInfo.HintStr := Quarter.Hint;
end
;
procedure
TCircleChart.Notification(AComponent : TComponent; Operation : TOperation);
var
I : integer
;
begin
inherited
;
if
Operation = opRemove then
for
I := 0
to
Quarters.Count-1
do
if
AComponent = Quarters[I].Action then
Quarters[I].Action := nil
;
end
;
procedure
TCircleChart.AdjustSize;
begin
if
not
(csLoading in
ComponentState) then
begin
Width := Spoke*2
;
Height := Spoke*2
;
end
;
end
;
procedure
TCircleChart.Paint;
var
Center : TPoint; // Centre du cercle
CircRect : TRect; // Carré circonscrit au cercle
I : integer
;
Quarter : TChartQuarter;
Graphics : TChartQuarterGraphics;
MinAngle, MidAngle, MaxAngle : Single
;
MinPt, MidPt, MaxPt, TextPos : TPoint;
Text : string
;
DrawTextRect : TRect;
begin
// Calcul des données concernant le disque
Center := Point(Width div
2
, Height div
2
);
CircRect := Rect(Center.X-Spoke, Center.Y-Spoke, Center.X+Spoke, Center.Y+Spoke);
with
Canvas do
begin
// Dessin de la couleur de fond
if
Color <> clNone then
begin
Brush.Color := Color;
Brush.Style := bsSolid;
Pen.Style := psClear;
Ellipse(CircRect);
end
;
// Dessin du disque
Brush.Assign(Self
.Brush);
Pen.Assign(Self
.Pen);
Ellipse(CircRect);
// Dessin des différents quartiers
MaxAngle := FBaseAngle * Pi / 180
;
for
I := 0
to
Quarters.Count-1
do
begin
Quarter := Quarters[I];
if
Quarter.Percent = 0
.0
then
Continue;
if
not
Quarter.Enabled then
Graphics := Quarter.DisabledGraphics
else
if
Quarter.Down then
Graphics := Quarter.DownGraphics
else
Graphics := Quarter.Graphics;
// Avancement des angles
MinAngle := MaxAngle;
MaxAngle := MinAngle + (Quarter.Percent * 2
*Pi / 100
);
MidAngle := (MinAngle + MaxAngle) / 2
;
// Calcul des points
MinPt := Point(Round(Spoke * Cos(MinAngle)) + Center.X, Height - Round(Spoke * Sin(MinAngle)) - Center.Y);
MidPt := Point(Round(Spoke * Cos(MidAngle)) + Center.X, Height - Round(Spoke * Sin(MidAngle)) - Center.Y);
MaxPt := Point(Round(Spoke * Cos(MaxAngle)) + Center.X, Height - Round(Spoke * Sin(MaxAngle)) - Center.Y);
// Dessin du quartier
Brush.Assign(Graphics.BackgroundBrush);
with
CircRect do
Pie(Left, Top, Right, Bottom, MinPt.X, MinPt.Y, MaxPt.X, MaxPt.Y);
// Calcul de la position du texte et affichage du texte
if
Quarter.ShowText then
begin
Brush.Assign(Graphics.TextBrush);
Font.Assign(Graphics.Font);
TextPos := Point((Center.X+MidPt.X) div
2
, (Center.Y+MidPt.Y) div
2
);
if
Quarter.Text <> ''
then
Text := Format('%s'#13#10'(%f%%)'
, [Quarter.Text, Quarter.Percent])
else
Text := Format('%f%%'
, [Quarter.Percent]);
DrawTextRect := Rect(0
, 0
, Width, 0
);
DrawText(Handle, PChar(Text), -1
, DrawTextRect, DT_CALCRECT or
DT_CENTER or
DT_NOPREFIX);
with
TextPos, DrawTextRect do
DrawTextRect := Rect(X - Right div
2
, Y - Bottom div
2
, X + Right div
2
, Y + Bottom div
2
);
DrawText(Handle, PChar(Text), -1
, DrawTextRect, DT_CENTER or
DT_NOPREFIX);
end
;
end
;
end
;
end
;
procedure
TCircleChart.DoContextPopup(MousePos : TPoint; var
Handled : boolean
);
begin
FPopupQuarter := PointToQuarter(MousePos);
inherited
;
end
;
procedure
TCircleChart.MouseDown(Button : TMouseButton; Shift : TShiftState;
X, Y : integer
);
begin
if
Button = mbLeft then
begin
FClickedQuarter := PointToQuarterIndex(Point(X, Y));
if
(FClickedQuarter <> -1
) and
(not
Quarters[FClickedQuarter].Enabled) then
FClickedQuarter := -1
;
end
;
end
;
procedure
TCircleChart.MouseUp(Button : TMouseButton; Shift : TShiftState;
X, Y : integer
);
begin
if
(Button = mbLeft) and
(FClickedQuarter <> -1
) then
begin
if
PointToQuarterIndex(Point(X, Y)) = FClickedQuarter then
Quarters[FClickedQuarter].Clic;
FClickedQuarter := -1
;
end
;
end
;
procedure
TCircleChart.DoClickQuarter(Index
: integer
; Quarter : TChartQuarter);
begin
if
Assigned(FOnClickQuarter) then
FOnClickQuarter(Self
, Index
, Quarter);
end
;
procedure
TCircleChart.ClickQuarter(Index
: integer
);
begin
if
Index
<> -1
then
DoClickQuarter(Index
, Quarters[Index
]);
end
;
function
TCircleChart.PointToQuarterIndex(Point : TPoint) : integer
;
const
TwoPi = 2
*Pi;
var
CenterToPoint, PtCos : Single
;
PtAngle, MinAngle, MaxAngle : Single
;
Quarter : TChartQuarter;
begin
dec(Point.X, Width div
2
);
dec(Point.Y, Height div
2
);
Point.Y := -Point.Y;
CenterToPoint := Sqrt(Point.X*Point.X + Point.Y*Point.Y);
if
CenterToPoint > Spoke then
begin
Result := -1
;
exit;
end
;
PtCos := Point.X / CenterToPoint;
PtAngle := ArcCos(PtCos);
if
Point.Y < 0
then
PtAngle := -PtAngle;
PtAngle := PtAngle - FBaseAngle * Pi / 180
;
PtAngle := PtAngle - TwoPi * Floor(PtAngle/TwoPi);
MaxAngle := 0
;
Result := 0
;
while
Result < FQuarters.Count do
begin
Quarter := Quarters[Result];
MinAngle := MaxAngle;
MaxAngle := MinAngle + (Quarter.Percent * TwoPi / 100
);
if
(MinAngle < PtAngle) and
(PtAngle < MaxAngle) then
exit;
inc(Result);
end
;
Result := -1
;
end
;
function
TCircleChart.PointToQuarter(Point : TPoint) : TChartQuarter;
var
Index
: integer
;
begin
Index
:= PointToQuarterIndex(Point);
if
Index
= -1
then
Result := nil
else
Result := FQuarters[Index
];
end
;
end
.