📄 teedatatabletool.pas
字号:
{**********************************************}
{ TeeChart DataTable Tool }
{ Copyright (c) 2005 by David Berneda }
{ All Rights Reserved }
{**********************************************}
unit TeeDataTableTool;
{$I TeeDefs.inc}
interface
uses
Windows, Classes, SysUtils, TeCanvas, TeeProcs, TeEngine, Chart;
type
TTableLegend=class(TTeeCustomShape)
private
FFontColor : Boolean;
FSymbol : TLegendSymbol;
FOtherSide: Boolean;
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(TTeeCustomTool)
private
FAutoPos : Boolean;
FClipText : Boolean;
FColumnPen : TChartPen;
FFont : TTeeFont;
FInverted : Boolean;
FLeft : Integer;
FLegend : TTableLegend;
FTop : Integer;
function CalcMaxSeriesCount:Integer;
function CalcPosLabels(Axis:TChartAxis; Value:Integer):Integer;
function Chart:TCustomChart;
procedure Draw;
function GetRowPen: TChartPen;
function GuessAxis:TChartAxis;
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 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;
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;
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.GuessAxis:TChartAxis;
var t : Integer;
begin
// Guess Axis
for t:=0 to Chart.SeriesCount-1 do
with Chart[t] do
if (not HasZValues) and Visible then
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 (not Chart[t].HasZValues) and Chart[t].Visible then
result:=Math.Max(result,Chart[t].Count);
end;
function TDataTableTool.VisibleSeriesCount:Integer;
var t : Integer;
begin
result:=0;
for t:=0 to Chart.SeriesCount-1 do
if (not Chart[t].HasZValues) and Chart[t].Visible then
Inc(result);
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 (not Chart[t].HasZValues) and Chart[t].Visible 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
TAxis=class(TChartAxis);
procedure TDataTableTool.Draw;
var tmpItemSize,
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 (not Chart[t].HasZValues) and Chart[t].Visible then
Inc(tmp);
end
else
for t:=0 to SeriesIndex-1 do
if (not Chart[t].HasZValues) and Chart[t].Visible then
Inc(tmp);
tmp:=10+(tmpItemSize*(tmp+1));
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 TAxis(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;
tmpValue : TChartValue;
begin
with Chart[SeriesIndex] do
if Visible then
begin
tmp:=MaxSeriesCount-TextIndex;
if (tmp>=0) and (Count>tmp) and (not IsNull(tmp)) then
begin
tmpValue:=GetMarkValue(tmp);
if MandatoryValueList.DateTime then
DateTimeToString(s,DateTimeDefaultFormat(tmpValue),tmpValue)
else
s:=FormatFloat(ValueFormat,tmpValue);
tmp:=ColRowPos(SeriesToPos(SeriesIndex));
if TableHorizontal then
Chart.Canvas.TextOut(tmpOffset+Pos, tmp, s)
else
Chart.Canvas.TextOut(tmp+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 (not Chart[Index].HasZValues) and Chart[Index].Visible 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);
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);
Chart.Canvas.DoHorizLine(ColRowPos(-1),ColRowPos(Chart.SeriesCount),tmp);
end;
if Inverted then
for t:=Chart.SeriesCount-1 downto 0 do
DrawLegendItem(t)
else
for t:=0 to Chart.SeriesCount-1 do
DrawLegendItem(t);
end;
procedure CalcPositions;
begin
if AutoPosition then
begin
tmpPos:=Axis.PosAxis;
tmpOffset:=0;
if TableHorizontal then
begin
if Axis.OtherSide and Chart.View3D then
begin
tmpPos:=tmpPos-Chart.SeriesWidth3D;
tmpOffset:=Chart.SeriesWidth3D;
end;
Top:=tmpPos;
Left:=0;
end
else
begin
if Axis.OtherSide and Chart.View3D then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -