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

📄 teeselectortool.pas

📁 BCB第三方组件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{**********************************************}
{   TeeChart Selector Tool                     }
{   Copyright (c) 2001-2007 by David Berneda   }
{        All Rights Reserved                   }
{**********************************************}
unit TeeSelectorTool;
{$I TeeDefs.inc}

interface

uses
  {$IFNDEF LINUX}
  Windows, Messages,
  {$ENDIF}
  SysUtils, Classes,
  {$IFDEF CLX}
  QGraphics, QControls, QForms, QDialogs, QComCtrls, QStdCtrls, Types,
  {$ELSE}
  Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls,
  {$IFDEF D9}
  Types,
  {$ENDIF}
  {$ENDIF}
  TeeProcs, TeEngine, Chart, TeeTools, TeCanvas, TeePenDlg;

type
  TSelectorTool=class(TTeeCustomTool, ITeeEventListener)
  private
    FAllowDrag  : Boolean;
    FAllowResizeChart: Boolean;
    FCursor     : TCursor;
    FHandleSize : Integer;
    FOnDragged  : TNotifyEvent;
    FOnDragging : TNotifyEvent;
    FOnResized  : TNotifyEvent;
    FOnResizing : TNotifyEvent;
    FOnSelected : TNotifyEvent;

    { internal }
    FAnnotation : TAnnotationTool;
    FDrawHandles: Boolean;
    FShape      : TTeeCustomShapePosition;
    FWall       : TChartWall;

    IDragging      : Boolean;
    IDragged       : Boolean;
    IDif           : TPoint;
    IResizingChart : Boolean;
    IResized       : Boolean;

    Procedure EmptySelection;
    function GetSelection:TPersistent;
    function GetSeries: TChartSeries;
    procedure SetHandleSize(const Value: Integer);
    procedure SetAnnotation(const Value: TAnnotationTool);
    procedure SetWall(const Value: TChartWall);
    procedure SetSeries(const Value: TChartSeries);
  protected
    Procedure ChartEvent(AEvent:TChartToolEvent); override;
    Procedure ChartMouseEvent( AEvent: TChartMouseEvent;
                               Button:TMouseButton;
                               Shift: TShiftState; X, Y: Integer); override;
    Procedure DoSelected; virtual;
    class Function GetEditorClass:String; override;
    procedure Notification( AComponent: TComponent;
                            Operation: TOperation); override;
    Procedure SetParentChart(Const Value:TCustomAxisPanel); override;
    procedure TeeEvent(Event: TTeeEvent);
  public
    Part: TChartClickedPart;

    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;

    Procedure ClearSelection;
    Procedure StopDragging;
    Function ClickedCorner(X,Y:Integer):Boolean;
    class Function Description:String; override;
    class Function LongDescription:String; override;
    Function SelectedTitle:TChartTitle;

    property Annotation : TAnnotationTool read FAnnotation write SetAnnotation;
    property DraggingShape: TTeeCustomShapePosition read FShape;
    property DrawHandles:Boolean read FDrawHandles write FDrawHandles;
    property Selection:TPersistent read GetSelection;
    property Series:TChartSeries read GetSeries write SetSeries;
    property Wall: TChartWall read FWall write SetWall;
  published
    property Active;
    property AllowDrag:Boolean read FAllowDrag write FAllowDrag default True;
    property AllowResizeChart:Boolean read FAllowResizeChart write FAllowResizeChart default False;
    property Brush;
    property Cursor:TCursor read FCursor write FCursor default crHandPoint;
    property HandleSize:Integer read FHandleSize write SetHandleSize default 3;
    property Pen;

    property OnDragged:TNotifyEvent read FOnDragged write FOnDragged;
    property OnDragging:TNotifyEvent read FOnDragging write FOnDragging;
    property OnResized:TNotifyEvent read FOnResized write FOnResized;
    property OnResizing:TNotifyEvent read FOnResizing write FOnResizing;
    property OnSelected:TNotifyEvent read FOnSelected write FOnSelected;
  end;

  { Form Editor }
  TSelectorToolEditor = class(TForm)
    ButtonPen1: TButtonPen;
    Label1: TLabel;
    Edit1: TEdit;
    UDSize: TUpDown;
    ButtonColor1: TButtonColor;
    CBAllowDrag: TCheckBox;
    CBResizeChart: TCheckBox;
    Label2: TLabel;
    CBCursor: TComboFlat;
    procedure FormShow(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure CBAllowDragClick(Sender: TObject);
    procedure CBResizeChartClick(Sender: TObject);
    procedure CBCursorChange(Sender: TObject);
  private
    { Private declarations }
    Selector : TSelectorTool;
  public
    { Public declarations }
  end;

implementation

{$IFNDEF CLX}
{$IFNDEF LCL}
{$R *.DFM}
{$ENDIF}
{$ELSE}
{$R *.xfm}
{$ENDIF}

uses
  TeeProCo;

{ TSelectorTool }
Constructor TSelectorTool.Create(AOwner: TComponent);
begin
  inherited;
  FHandleSize:=3;
  FDrawHandles:=True;
  FAllowDrag:=True;
  FCursor:=crHandPoint;
end;

type
  TAxisAccess=class(TChartAxis);
  TSeriesAccess=class(TChartSeries);

procedure TSelectorTool.ChartEvent(AEvent: TChartToolEvent);

  Function RectFromPoint(X,Y:Integer):TRect;
  begin { return a rectangle few pixels around XY point }
    result:=TeeRect(X-HandleSize,Y-HandleSize,X+HandleSize,Y+HandleSize);
  end;

  Procedure DrawHandle(Const R:TRect);
  begin { draw four handles, one at each R rectangle corner }
    with ParentChart.Canvas, R do
    begin
      Rectangle(RectFromPoint(Left,Top));
      Rectangle(RectFromPoint(Left,Bottom));
      Rectangle(RectFromPoint(Right,Top));
      Rectangle(RectFromPoint(Right,Bottom));
    end;
  end;

  Procedure DrawHandleZ(Const R:TRect; Z:Integer);
  begin { draw the four handles of R corners at Z depth position }
    with ParentChart.Canvas, R do
    begin
      RectangleWithZ(RectFromPoint(Left,Top),Z);
      RectangleWithZ(RectFromPoint(Left,Bottom),Z);
      RectangleWithZ(RectFromPoint(Right,Top),Z);
      RectangleWithZ(RectFromPoint(Right,Bottom),Z);
    end;
  end;

  Procedure DoDrawHandles;

    Procedure DrawSeriesHandles(AtMarks:Boolean);
    var t: Integer;
        X: Integer;
        Y: Integer;
        tmpStep  : Integer;
        tmpLast  : Integer;
        tmpCount : Integer;
    begin
      if Assigned(Part.ASeries) then
      With Part.ASeries do
      begin
        { number of visible points }
        tmpCount:=LastValueIndex-FirstValueIndex;

        { if zero, then number of points }
        if tmpCount=0 then tmpCount:=Count;

        { calculate "step" (how many points? maximum=20) }
        if tmpCount>20 then tmpStep:=tmpCount div 20
                       else tmpStep:=1;

        { start loop to draw handles }
        t:=FirstValueIndex;
        if t=-1 then t:=0;

        { last loop value }
        tmpLast:=LastValueIndex;
        if tmpLast=-1 then tmpLast:=Count-1;

        { loop... }
        While t<=tmpLast do
        begin
          if AtMarks then
             DrawHandleZ(Marks.Positions[t].Bounds,Marks.ZPosition)
          else
          begin
            TSeriesAccess(Part.ASeries).CalcSelectionPos(t,X,Y);
            ParentChart.Canvas.RectangleWithZ(RectFromPoint(X,Y),MiddleZ);
          end;

          Inc(t,tmpStep);
        end;
      end;
    end;

    Procedure DrawBackWallHandles;

      Procedure DrawHandlePoint(AX,AY:Integer);
      var P: TPoint;
      begin
        with ParentChart,Canvas do
        begin
          P:=Calculate3DPosition(AX,AY,Width3D);
          Rectangle(RectFromPoint(P.X,P.Y));
        end;
      end;

    begin
      with ParentChart.ChartRect do
      begin
        DrawHandlePoint(Left,Top);
        DrawHandlePoint(Right,Top);
        DrawHandlePoint(Left,Bottom);
        DrawHandlePoint(Right,Bottom);
      end;
    end;

  var R    : TRect;
      tmpP : TFourPoints;
  begin
    R:=TeeRect(0,0,0,0);

    { calculate R corners of selected part }
    With TCustomChart(ParentChart) do
    Case Part.Part of
      cpNone     : begin
                     R:=ClientRect;
                     InflateRect(R,-HandleSize,-HandleSize);
                   end;

      cpLegend   : if Legend.Visible then
                      R:=Legend.ShapeBounds;

      cpAxis     : R:=TAxisAccess(Part.AAxis).AxisRect;
      cpSeries   : DrawSeriesHandles(False);
      cpTitle    : R:=Title.TitleRect;
      cpFoot     : R:=Foot.TitleRect;
      cpSubTitle : R:=SubTitle.TitleRect;
      cpSubFoot  : R:=SubFoot.TitleRect;
     cpChartRect : DrawBackWallHandles;
   cpSeriesMarks : DrawSeriesHandles(True);
     cpAxisTitle : begin
                     R:=Part.AAxis.Title.ShapeBounds;
                     if Part.AAxis.Title.Angle<>0 then
                     begin
                       RectToFourPoints(R,Part.AAxis.Title.Angle,tmpP);
                       R:=RectFromPolygon(tmpP,4);
                     end;
                   end;
    end;

    { draw four handles at rectangle R corners }
    if R.Right-R.Left>0 then
       DrawHandle(R);
  end;

begin { after drawing Chart, draw handles on selected part }
  inherited;

  if (AEvent=cteAfterDraw) and (not ParentChart.Printing) and FDrawHandles then
  begin
    { prepare Handle pen and color }
    With ParentChart.Canvas do
    begin
      AssignVisiblePen(Self.Pen);
      AssignBrush(Self.Brush);
    end;

    { draw handles on selected Shape rectangle corners }
    if Assigned(FAnnotation) then
       DrawHandle(FAnnotation.Bounds)
    else
    if Assigned(FShape) then
       DrawHandle(FShape.ShapeBounds)
    else
       DoDrawHandles;
  end;
end;

Function TSelectorTool.ClickedCorner(X,Y:Integer):Boolean;
begin { return True if XY is over the chart right-bottom corner }
  result:=(Abs(X-ParentChart.Width)<=8) and
          (Abs(Y-ParentChart.Height)<=8)
          // and (ParentChart.Align=alNone);
end;

procedure TSelectorTool.ChartMouseEvent(AEvent: TChartMouseEvent;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

  function CalcClickedAnnotation:TAnnotationTool;
  var t : Integer;
  begin { return which Annotation is under the mouse cursor }
    result:=nil;

    With ParentChart do
    for t:=0 to Tools.Count-1 do
    if Tools[t] is TAnnotationTool then
       if TAnnotationTool(Tools[t]).Clicked(X,Y) then
       begin
         result:=TAnnotationTool(Tools[t]);
         break;
       end;
  end;

  procedure GuessCursor;
  var Part : TChartClickedPart;
  begin
    if CalcClickedAnnotation<>nil then
    begin
      ParentChart.Cursor:=Cursor;
      ParentChart.CancelMouse:=True;
    end
    else
    begin
      TCustomChart(ParentChart).CalcClickedPart(TeePoint(X,Y),Part);

      if (Part.Part<>cpNone) and (Part.Part<>cpChartRect) then
      begin
        ParentChart.Cursor:=Cursor;
        ParentChart.CancelMouse:=True;
      end;
    end;
  end;

  procedure DoDragShape;
  var Old : Integer;
  begin
    ParentChart.CancelMouse:=True;

    { check X position change }
    if FShape.Left<>(X+IDif.X) then
    begin
      if IDragged or (Abs(FShape.Left-(X+IDif.X))>2) then
      begin
        Old:=FShape.Width;
        FShape.Left:=X+IDif.X;
        FShape.Width:=Old;

        IDragged:=True;
      end;
    end;

    { check Y position change }
    if FShape.Top<>(Y+IDif.Y) then
    begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -