📄 teedatatabletool.pas
字号:
{**********************************************}
{ TeeChart DataTable Tool }
{ Copyright (c) 2006-2007 by David Berneda }
{ All Rights Reserved }
{**********************************************}
unit TeeDataTableTool;
{$I TeeDefs.inc}
interface
uses
{$IFNDEF LINUX}
Windows, Messages,
{$ENDIF}
Classes, SysUtils,
{$IFNDEF CLX}
{$IFDEF D9}
Types,
{$ENDIF}
{$ENDIF}
TeCanvas, TeeProcs, TeEngine, Chart;
type
TTableLegend=class(TTeeCustomShape)
private
FFontColor : Boolean;
FOtherSide : Boolean;
FSymbol : TLegendSymbol;
function CalcSymbolHeight:Integer;
procedure SetFontColor(const Value: Boolean);
procedure SetSymbol(const Value: TLegendSymbol);
procedure SetOtherSide(const Value: Boolean);
protected
Procedure SetParent(Value:TCustomTeePanel); override;
public
Constructor Create(AOwner: TCustomTeePanel); overload; override;
Destructor Destroy; override;
Procedure Assign(Source:TPersistent); override;
published
property Brush;
property Color;
property Font;
property FontSeriesColor:Boolean read FFontColor write SetFontColor default False;
property Gradient;
property OtherSide:Boolean read FOtherSide write SetOtherSide default False;
property Pen;
property Symbol:TLegendSymbol read FSymbol write SetSymbol;
property Transparency;
property Transparent default True;
property Visible;
end;
TDataTableTool=class;
TDataTableFilterSeries=procedure(Sender:TDataTableTool; Series:TChartSeries;
var Accept:Boolean) of object;
TDataTableTool=class(TTeeCustomTool)
private
FAutoPos : Boolean;
FClipText : Boolean;
FColumnPen : TChartPen;
FFont : TTeeFont;
FInverted : Boolean;
FLeft : Integer;
FLegend : TTableLegend;
FOnFilterSeries : TDataTableFilterSeries;
FTop : Integer;
function CalcMaxSeriesCount:Integer;
function CalcPosLabels(Axis:TChartAxis; Value:Integer):Integer;
function CalcTableSize(Axis:TChartAxis):Integer;
function Chart:TCustomChart;
procedure Draw;
function GetRowPen: TChartPen;
function GuessAxis:TChartAxis;
function ItemText(Series:TChartSeries; ValueIndex:Integer):String;
function LegendWidth(var SymbolWidth:Integer):Integer;
procedure SetAutoPos(const Value: Boolean);
procedure SetClipText(const Value: Boolean);
procedure SetColumnPen(const Value: TChartPen);
procedure SetFont(const Value: TTeeFont);
procedure SetInverted(const Value: Boolean);
procedure SetLeft(const Value: Integer);
procedure SetLegend(const Value: TTableLegend);
procedure SetRowPen(const Value: TChartPen);
procedure SetTop(const Value: Integer);
function TableSize:Integer;
function ValidSeries(Index:Integer):Boolean;
function VisibleSeriesCount:Integer;
protected
Procedure ChartEvent(AEvent:TChartToolEvent); override;
class function GetEditorClass: String; override;
Procedure SetParentChart(Const Value:TCustomAxisPanel); override;
public
Constructor Create(AOwner:TComponent); override;
Destructor Destroy; override;
class Function Description:String; override;
class Function LongDescription:String; override;
published
property Active;
property AutoPosition:Boolean read FAutoPos write SetAutoPos default True;
property Brush;
property ClipText:Boolean read FClipText write SetClipText default True;
property ColumnPen:TChartPen read FColumnPen write SetColumnPen;
property Font:TTeeFont read FFont write SetFont;
property Inverted:Boolean read FInverted write SetInverted default False;
property Left:Integer read FLeft write SetLeft default 0;
property Legend:TTableLegend read FLegend write SetLegend;
property RowPen:TChartPen read GetRowPen write SetRowPen;
property Top:Integer read FTop write SetTop default 0;
// events
property OnFilterSeries:TDataTableFilterSeries read FOnFilterSeries
write FOnFilterSeries; // 8.01
end;
implementation
uses
Math, TeeProCo;
Constructor TDataTableTool.Create(AOwner: TComponent);
begin
inherited;
FAutoPos:=True;
FClipText:=True;
FLegend:=TTableLegend.Create(nil);
FFont:=TTeeFont.Create(CanvasChanged);
FColumnPen:=TChartPen.Create(CanvasChanged);
end;
Destructor TDataTableTool.Destroy;
begin
FColumnPen.Free;
FFont.Free;
FLegend.Free;
inherited;
end;
function TDataTableTool.ValidSeries(Index:Integer):Boolean;
begin
with Chart[Index] do
result:=(not HasZValues) and Visible;
if Assigned(FOnFilterSeries) then
FOnFilterSeries(Self,Chart[Index],result);
end;
function TDataTableTool.GuessAxis:TChartAxis;
var t : Integer;
begin
// Guess Axis
for t:=0 to Chart.SeriesCount-1 do
if ValidSeries(t) then
with Chart[t] do
begin
if YMandatory then
result:=GetHorizAxis
else
result:=GetVertAxis;
Exit;
end;
result:=nil;
end;
function TDataTableTool.CalcMaxSeriesCount:Integer;
var t : Integer;
begin
result:=0;
for t:=0 to Chart.SeriesCount-1 do
if ValidSeries(t) then
result:=Math.Max(result,Chart[t].Count);
if Chart.Pages.MaxPointsPerPage<>0 then // 8.01 TV52012279
result:=Min(result,Chart.Pages.MaxPointsPerPage);
end;
function TDataTableTool.VisibleSeriesCount:Integer;
var t : Integer;
begin
result:=0;
for t:=0 to Chart.SeriesCount-1 do
if ValidSeries(t) then
Inc(result);
end;
function TDataTableTool.ItemText(Series:TChartSeries; ValueIndex:Integer):String;
var tmpValue : TChartValue;
begin
tmpValue:=Series.GetMarkValue(ValueIndex);
if Series.MandatoryValueList.DateTime then
DateTimeToString(result,DateTimeDefaultFormat(tmpValue),tmpValue)
else
result:=FormatFloat(Series.ValueFormat,tmpValue);
end;
function TDataTableTool.CalcTableSize(Axis:TChartAxis):Integer;
var t : Integer;
tt : Integer;
begin
if Legend.Visible then
begin
Chart.Canvas.AssignFont(Legend.Font);
result:=Chart.Canvas.FontHeight;
end
else
result:=0;
// Prepare Font
Chart.Canvas.AssignFont(Font);
if Axis.Horizontal then
result:=Max(result,Chart.Canvas.FontHeight)
else
begin
for t:=0 to Chart.SeriesCount-1 do
if ValidSeries(t) then
with Chart[t] do
for tt:=0 to Count-1 do
result:=Max(result, Chart.Canvas.TextWidth(ItemText(Chart[t],tt)));
// Margins
Inc(result,Chart.Canvas.FontHeight div 2);
end;
end;
type
TSymbolAccess=class(TLegendSymbol);
function TDataTableTool.LegendWidth(var SymbolWidth:Integer):Integer;
var t : Integer;
begin
result:=0;
Chart.Canvas.AssignFont(FLegend.Font);
for t:=0 to Chart.SeriesCount-1 do
if ValidSeries(t) then
result:=Math.Max(result,Chart.Canvas.TextWidth(SeriesTitleOrName(Chart[t])));
Inc(result,Chart.Canvas.FontHeight);
if Legend.Symbol.Visible then
SymbolWidth:=TSymbolAccess(Legend.Symbol).CalcWidth(result)
else
SymbolWidth:=0;
Inc(result,SymbolWidth);
end;
type
TAxisAccess=class(TChartAxis);
procedure TDataTableTool.Draw;
var tmpItemSize,
ISizeLabels,
MaxSeriesCount : Integer;
Axis : TChartAxis;
TableHorizontal : Boolean;
tmpOffset : Integer;
tmpPos : Integer;
function ColRowPos(SeriesIndex:Integer):Integer;
var tmp,t : Integer;
begin
tmp:=0;
if Inverted then
begin
for t:=Chart.SeriesCount-1 downto SeriesIndex+1 do
if ValidSeries(t) then
Inc(tmp);
end
else
for t:=0 to SeriesIndex-1 do
if ValidSeries(t) then
Inc(tmp);
if TableHorizontal then
tmp:=ISizeLabels+(tmpItemSize*(tmp+1))
else
tmp:=ISizeLabels+(tmpItemSize*(tmp));
if Axis.OtherSide then
tmp:=-tmp;
if TableHorizontal then
result:=tmpPos+tmp
else
result:=tmpPos-tmp;
end;
procedure ColDivider(Pos:Integer);
var tmpMax : Integer;
tmp : Integer;
begin
if Inverted then
tmpMax:=ColRowPos(-1)
else
tmpMax:=ColRowPos(Chart.SeriesCount);
if AutoPosition then
tmp:=tmpPos
else
begin
if Inverted then
tmp:=ColRowPos(Chart.SeriesCount)
else
tmp:=ColRowPos(-1);
end;
with {$IFNDEF CLR}TAxisAccess{$ENDIF}(Axis) do
if TableHorizontal then
if OtherSide then
Chart.Canvas.DoVertLine(tmpOffset+Pos, tmp, tmpMax-1)
else
Chart.Canvas.DoVertLine(tmpOffset+Pos, tmp, tmpMax+1)
else
Chart.Canvas.DoHorizLine(tmp, tmpMax, tmpOffset+Pos)
end;
function SeriesToPos(SeriesIndex:Integer):Integer;
begin
if TableHorizontal then
begin
if Axis.OtherSide then
if Inverted then
result:=SeriesIndex-1
else
result:=SeriesIndex+1
else
result:=SeriesIndex;
end
else
begin
if Inverted then
result:=SeriesIndex-1
else
result:=SeriesIndex+1;
if Axis.OtherSide then
if Inverted then
Inc(result)
else
Dec(result);
end;
end;
procedure DoText(Pos,TextIndex,SeriesIndex:Integer);
var s : String;
tmp : Integer;
begin
with Chart[SeriesIndex] do
begin
with Chart.Pages do
if MaxPointsPerPage>0 then
tmp:=LastValueIndex-TextIndex+1
else
tmp:=MaxSeriesCount-TextIndex;
if (tmp>=0) and (Count>tmp) and (not IsNull(tmp)) then
begin
s:=ItemText(Chart[SeriesIndex],tmp);
tmp:=ColRowPos(SeriesToPos(SeriesIndex));
if TableHorizontal then
Chart.Canvas.TextOut(tmpOffset+Pos, tmp, s)
else
Chart.Canvas.TextOut(tmp+1+(Chart.Canvas.FontHeight div 4),
tmpOffset+Pos-(Chart.Canvas.FontHeight div 2), s);
end;
end;
end;
procedure DrawLegend(x0,x1:Integer);
var w : Integer;
tmpSymbolWidth : Integer;
procedure DrawLegendItem(Index:Integer);
var s : String;
tmp : Integer;
p : Integer;
r : TRect;
begin
if ValidSeries(Index) then
begin
s:=SeriesTitleOrName(Chart[Index]);
tmp:=ColRowPos(SeriesToPos(Index));
Chart.Canvas.BackMode:=cbmTransparent;
p:=x0+4;
if Legend.Symbol.Visible then
if Legend.Symbol.Position=spLeft then
Inc(p,tmpSymbolWidth+4);
if Legend.FFontColor then
Chart.Canvas.Font.Color:=Chart[Index].Color;
if TableHorizontal then
Chart.Canvas.TextOut(p,tmp,s)
else
if Legend.Symbol.Visible and (Legend.Symbol.Position=spRight) then
Chart.Canvas.RotateLabel(tmp+4,x1+w-4,s,90)
else
Chart.Canvas.RotateLabel(tmp+4,x1+w-4-tmpSymbolWidth-4,s,90);
if Legend.Symbol.Visible then
begin
if TableHorizontal then
if Legend.Symbol.Position=spLeft then
r:=TeeRect(x0+4,tmp+4,x0+4+tmpSymbolWidth,tmp+12)
else
r:=TeeRect(x0+w-4-tmpSymbolWidth,tmp+4,x0+w-4,tmp+12)
else
if Legend.Symbol.Position=spLeft then
r:=TeeRect(tmp+6,x1+w-4,tmp+6+12,x1+w-4-tmpSymbolWidth)
else
r:=TeeRect(tmp+6,x1+4,tmp+6+tmpSymbolWidth,x1+4+tmpSymbolWidth);
r:=OrientRectangle(r);
if Legend.Symbol.Gradient.Visible then
TSymbolAccess(Legend.Symbol).Draw(Chart[Index].Color,r)
else
Chart[Index].DrawLegend(-1,r);
end;
end;
end;
var t : Integer;
tmp : Integer;
begin
Chart.Canvas.AssignFont(FLegend.Font);
Chart.Canvas.TextAlign:=TA_LEFT;
w:=LegendWidth(tmpSymbolWidth);
if TableHorizontal then
begin
if Legend.OtherSide then tmp:=x1
else tmp:=x0;
Chart.Canvas.DoVertLine(tmp,ColRowPos(-1),ColRowPos(Chart.SeriesCount));
end
else
begin
tmp:=x1;
if Legend.OtherSide then Inc(tmp,w);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -