⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 teedatatabletool.pas

📁 BCB第三方组件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{**********************************************}
{   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 + -