{********************************************}
{ TTeeCommander Component                    }
{ Copyright (c) 1998-2020 by Steema Software }
{********************************************}
unit TeeComma;
{$I TeeDefs.inc}

{$IFDEF TEEOCX}
{$I TeeAXDefs.inc}
{$ENDIF}

interface

uses {$IFNDEF LINUX}
     {$IFNDEF FMX}
     Windows, Messages,
     {$ENDIF}
     {$ENDIF}
     SysUtils, Classes,

     {$IFDEF FMX}
     FMX.Types, System.UITypes, FMX.Controls,

     {$IFDEF D18}
     FMX.StdCtrls,
     {$ENDIF}

     {$IFDEF D17}
     System.UIConsts,
     {$ENDIF}

     {$IFDEF D19}
     FMX.Graphics,
     {$ENDIF}
     
     {$ELSE}
     Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, Buttons,
     {$ENDIF}

     {$IFDEF D9}
     Types,
     {$ENDIF}

     {$IFDEF FMX}
     FMXTee.Canvas, FMXTee.Procs, FMXTee.Chart, FMXTee.Series,
     FMXTee.Editor.EditorPanel, FMX.Dialogs
     {$ELSE}
     TeCanvas, TeeProcs, Series,
     {$IFNDEF TEEOCXSTD}
     TeeEdit,
     {$ENDIF}
     Chart
     {$ENDIF}
     ;

type
  TCustomTeeCommander=class(TCustomPanelNoCaption,ITeeEventListener)
  private
    FGradient    : TTeeGradient;
    FMouseButton : TMouseButton;
    FPanel       : TCustomTeePanel;
    FVertical    : Boolean;

    Procedure CanvasChanged(Sender:TObject);
    procedure CheckVerticalAlign;
    Function GetGradient:TTeeGradient;
    Procedure ReAlignTeeControls;
    Procedure SetGradient(const Value:TTeeGradient);
    Procedure SetVertical(Value:Boolean);
  protected
    FDragging : Boolean;

    function ChildCount:Integer;
    function GetChild(Index:Integer):{$IFDEF FMX}TFmxObject{$ELSE}TControl{$ENDIF};

    Procedure DoMouseDown(X,Y:Integer); virtual;
    Procedure DoMouseMove(X,Y:Integer; const Shift:TShiftState); virtual;
    Procedure DoMouseUp; virtual;
    Function DoPanelMouse:Boolean; virtual;
    Procedure FreeOwnedControls;
    procedure Loaded; override;
    procedure Notification( AComponent: TComponent;
                            Operation: TOperation); override;
    procedure Paint; override;
    Procedure RemovingControl(const AComponent:TComponent); dynamic;
    procedure SetPanel(Const Value: TCustomTeePanel); virtual;
    Procedure ShowHideControls(Value:Boolean); virtual;
    procedure TeeEvent(Event:TTeeEvent);
    Function TeePanelClass:String;
  public
    { Public declarations }
    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;

    Procedure CreateBevel( APos:Integer);

    Function CreateButton( APos:Integer; AProc:TNotifyEvent;
                           Const AHint:String;
                           Const AResName:String;
                           AGroupIndex:Integer {$IFNDEF BCB}=0{$ENDIF}):TSpeedButton; {$IFNDEF BCB4}overload;{$ENDIF}

    {$IFNDEF BCB4}
    Function CreateButton( APos:Integer;
                           AProc:TNotifyEvent;
                           Const AHint:String;
                           const ABitmap: TBitmap;
                           AGroupIndex:Integer {$IFNDEF BCB}=0{$ENDIF}):TSpeedButton; overload;
    {$ENDIF}

    Function CreateLabel(APos:Integer; AColor:TColor):TLabel;

    property Child[Index:Integer]:{$IFDEF FMX}TFmxObject{$ELSE}TControl{$ENDIF} read GetChild;
  published
    { Published declarations }
    property Gradient:TTeeGradient read GetGradient write SetGradient;
    property Panel:TCustomTeePanel read FPanel write SetPanel;
    property Vertical:Boolean read FVertical write SetVertical default False;

    { TPanel properties }
    property Align;

    {$IFNDEF FMX}
    property BevelInner;
    property BevelOuter;
    property BevelWidth;
    property BorderWidth;
    property BorderStyle;
    {$ENDIF}

    {$IFDEF FMX}
    {$IFDEF D17}
    property ClipChildren;
    {$ENDIF}
    {$ENDIF}

    property Color;
    property DragMode;

    {$IFNDEF FMX}
    property DragCursor;
    {$ENDIF}

    property Enabled;

    {$IFDEF FMX}
    {$IFDEF D23}
    property ParentShowHint;
    {$ENDIF}
    {$ELSE}
    property ParentColor;
    property ParentShowHint;
    {$ENDIF}

    property ShowHint{$IFNDEF TEEOCX} default True{$ENDIF};
    property PopupMenu;

    {$IFDEF FMX}
    {$IFDEF D21}
    property Size;
    {$ENDIF}
    {$ENDIF}

    property TabOrder;

    {$IFNDEF FMX}
    property TabStop;
    {$ENDIF}

    property Visible;

    {$IFDEF FMX}
    {$IFDEF D17}
    property Action;
    property Anchors;
    {$ENDIF}
    {$ELSE}
    property Anchors;
    {$ENDIF}

    {$IFNDEF FMX}
    property Constraints;
    {$ENDIF}

    {$IFNDEF FMX}
    property AutoSize;
    property DragKind;
    {$ENDIF}

    { TPanel events }
    property OnClick;

    {$IFNDEF FMX}
    property OnContextPopup;
    {$ENDIF}

    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;

    {$IFNDEF FMX}
    property OnEndDrag;
    property OnStartDrag;
    {$ENDIF}

    property OnEnter;
    property OnExit;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;

    {$IFNDEF FMX}
    property OnConstrainedResize;

    {$IFNDEF LCL}
    property OnCanResize;
    {$ENDIF}

    {$IFNDEF TEEOCX}
    property OnDockDrop;
    property OnDockOver;
    property OnEndDock;
    property OnStartDock;
    property OnUnDock;
    {$ENDIF}
    {$ENDIF}
  end;

  TCommanderControls=( tcbNormal,
                       tcbSeparator,
                       tcbRotate,
                       tcbMove,
                       tcbZoom,
                       tcbDepth,
                       tcbEdit,
                       tcbPrintPreview,
                       tcbCopy,
                       tcbSave,
                       tcbLabel,
                       tcb3D );

  TTeeCommander=class;
  TTeeEditedChartEvent=procedure(Sender:TTeeCommander; AChart:TCustomChart) of object;

  TTeeCommanderOnSetLabel=procedure(Sender:TTeeCommander; Var Text:String) of object;

  {$IFDEF D16}
  [ComponentPlatformsAttribute(TeeAllComponentPlatformIDs)]
  {$ENDIF}
  TTeeCommander=class(TCustomTeeCommander)
  private
    { Private declarations }
    FAllowFull     : Boolean;

    FButtonCopy    : TSpeedButton;
    FButtonDepth   : TSpeedButton;
    FButtonEdit    : TSpeedButton;
    FButtonMove    : TSpeedButton;
    FButtonNormal  : TSpeedButton;
    FButtonPrint   : TSpeedButton;
    FButtonRotate  : TSpeedButton;
    FButtonSave    : TSpeedButton;
    FButtonZoom    : TSpeedButton;
    FButton3D      : TSpeedButton;

    {$IFNDEF TEEOCXNOEDITOR}
    FEditor        : TChartEditor;
    FPreviewer     : TChartPreviewer;
    {$ENDIF}

    FEnablePieExp  : Boolean;
    FLabel         : TLabel;
    FLabelValues   : Boolean;

    FDraggingIndex : Integer;
    FInertia       : Integer;

    FOldX          : Integer;
    FOldY          : Integer;

    IDifX          : Double;
    IDifY          : Double;
    IShift         : TShiftState;
    
    ICircledSeries : TCircledSeries;
    IRotating      : Boolean;

    FOnEditedChart : TTeeEditedChartEvent;
    FOnSetLabel    : TTeeCommanderOnSetLabel;

    procedure Button3DClick(Sender: TObject);
    procedure ButtonCopyClick(Sender: TObject);
    procedure ButtonDepthClick(Sender: TObject);
    procedure ButtonEditClick(Sender: TObject);
    procedure ButtonMoveClick(Sender: TObject);
    procedure ButtonNormalClick(Sender: TObject);
    procedure ButtonPrintClick(Sender: TObject);
    procedure ButtonRotateClick(Sender: TObject);
    procedure ButtonSaveClick(Sender: TObject);
    procedure ButtonZoomClick(Sender: TObject);

    Function DoCustomButton:Boolean;
    Procedure DoRotation(const IDifX,IDifY:Double);

    {$IFDEF FMX}
    procedure InvalidatePanel;
    {$ENDIF}

    Function IsButtonDown(const AButton:TSpeedButton):Boolean;

    function GetDefault:TCommanderControls;
    procedure SetDefault(const AButton:TCommanderControls);

    procedure SetLabelCaption(Const ACaption:String);
    procedure SetLabelValues(Value:Boolean);

    Function CaptionPanel(Const ACaption:String):String;

    Function GetCircledSeries(x,y:Integer):TCircledSeries;

    {$IFNDEF TEEOCXNOEDITOR}
    procedure SetEditor(const Value: TChartEditor);
    procedure SetPreviewer(const Value: TChartPreviewer);
    {$ENDIF}

  protected
    { Protected declarations }

    FAllowRotationX : Boolean;
    FAllowRotationY : Boolean;

    procedure CheckPendingInertia;
    Procedure DoMouseDown(X,Y:Integer); override;
    Procedure DoMouseMove(X,Y:Integer; const Shift:TShiftState); override;
    Procedure DoMouseUp; override;
    Function DoPanelMouse:Boolean; override;
    Procedure RemovingControl(const AComponent:TComponent); override;
    Procedure ShowHideControls(Value:Boolean); override;

    {$IFNDEF TEEOCXNOEDITOR}
    procedure Notification( AComponent: TComponent;
                            Operation: TOperation); override;
    {$ENDIF}
  public
    { Public declarations }
    Constructor Create(AOwner:TComponent); override;

    Procedure CreateControls(const AControls:Array of TCommanderControls);
    Procedure RepositionControls;

    property Button3D      : TSpeedButton read FButton3D;
    property ButtonCopy    : TSpeedButton read FButtonCopy;
    property ButtonDepth   : TSpeedButton read FButtonDepth;
    property ButtonEdit    : TSpeedButton read FButtonEdit;
    property ButtonMove    : TSpeedButton read FButtonMove;
    property ButtonNormal  : TSpeedButton read FButtonNormal;
    property ButtonPrint   : TSpeedButton read FButtonPrint;
    property ButtonRotate  : TSpeedButton read FButtonRotate;
    property ButtonSave    : TSpeedButton read FButtonSave;
    property ButtonZoom    : TSpeedButton read FButtonZoom;

    property DefaultButton : TCommanderControls read GetDefault write SetDefault;

    property FullRotation  : Boolean read FAllowFull write FAllowFull default False;
    property LabelText     : TLabel read FLabel;

    Procedure ShowValues;
  published
    {$IFNDEF TEEOCXNOEDITOR}
    property ChartEditor   : TChartEditor read FEditor write SetEditor;
    property Previewer     : TChartPreviewer read FPreviewer write SetPreviewer;
    {$ENDIF}

    property EnablePieExploding:Boolean read FEnablePieExp
                                        write FEnablePieExp default True;
    property LabelValues:Boolean read FLabelValues write SetLabelValues default True;

    property RotateInertia:Integer read FInertia write FInertia default 3;

    property OnEditedChart:TTeeEditedChartEvent read FOnEditedChart
                                                write FOnEditedChart;
    property OnSetLabel:TTeeCommanderOnSetLabel read FOnSetLabel
                                                write FOnSetLabel;

    {$IFDEF D10}
    property OnMouseEnter;
    property OnMouseLeave;
    {$ENDIF}
  end;

implementation

{$R TeeComma.res}

Uses Math,
     {$IFDEF FMX}
     FMXTee.Engine, FMXTee.Tools, FMXTee.Editor.Pro, FMXTee.Print.Preview,
     FMXTee.ProConstants, FMX.Objects, FMXTee.Editor.Chart,
     FMXTee.Editor.Gradient, FMXTee.Constants, FMXTee.Store
     {$ELSE}
     {$IFNDEF TEEOCXNOEDITOR}
     {$IFDEF LCL}
     GraphType, Types,
     {$ENDIF}
     TeeEditPro, EditChar, TeePrevi, TeeEdiGene, TeeEdiGrad,
     {$ENDIF}
     TeeProCo, TeeTools, TeEngine
     {$ENDIF}
     ;

{$IFDEF FMX}
type
  TBevel=TPanel;

  TSpeedButtonHelper=class helper for TSpeedButton
  private
    function GetDown: Boolean;
    procedure SetDown(const Value: Boolean);
  public
    property Down:Boolean read GetDown write SetDown;
  end;
{$ENDIF}

{ TCustomTeeCommander }
Constructor TCustomTeeCommander.Create(AOwner:TComponent);
begin
  inherited;
  Panel:=nil;
  Height:=33;
  Width:=400;
  FMouseButton:={$IFDEF FMX}TMouseButton.{$ENDIF}mbLeft;

  {$IFNDEF TEEOCX}
  ShowHint:=True;
  {$ENDIF}

  if (csDesigning in ComponentState) and
     (not (csLoading in Owner.ComponentState)) then
     Align:={$IFDEF FMX}TAlignLayout.{$IFDEF D20}Top{$ELSE}alTop{$ENDIF}{$ELSE}alTop{$ENDIF};
end;

Destructor TCustomTeeCommander.Destroy;
begin
  FreeOwnedControls;
  FGradient.Free;
  Panel:=nil;
  inherited;
end;

procedure TCustomTeeCommander.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) and Assigned(FPanel) and (AComponent=FPanel) then
     Panel:=nil;
end;

Procedure TCustomTeeCommander.CanvasChanged(Sender:TObject);
begin
  {$IFDEF FMX}
  Repaint;
  {$ELSE}
  Invalidate;
  {$ENDIF}
end;

Function TCustomTeeCommander.GetGradient:TTeeGradient;
begin
  if not Assigned(FGradient) then
     FGradient:=TTeeGradient.Create(CanvasChanged);

  result:=FGradient;
end;

procedure TCustomTeeCommander.SetGradient(const Value:TTeeGradient);
begin
  if Assigned(Value) then Gradient.Assign(Value)
                     else FreeAndNil(FGradient);
end;

procedure TCustomTeeCommander.TeeEvent(Event:TTeeEvent);
begin
  if Event is TTeeMouseEvent then
  With TTeeMouseEvent(Event) do
  begin
    Case Event of
      meDown: begin
                FMouseButton:=Button;
                DoMouseDown({$IFDEF FMX}Round{$ENDIF}(X),
                            {$IFDEF FMX}Round{$ENDIF}(Y));
              end;

        meUp: DoMouseUp;

      meMove: DoMouseMove({$IFDEF FMX}Round{$ENDIF}(X),
                          {$IFDEF FMX}Round{$ENDIF}(Y),Shift);
    end;

    if not Sender.CancelMouse then
       Sender.CancelMouse:=not DoPanelMouse;

  end
  else
  if Event is TTeeView3DEvent then
     ShowHideControls(Assigned(Panel))
  {
  // No longer needed:
  else
  if Event is TMouseLeaveEvent then
     FDragging:=False;
  }
end;

Procedure TCustomTeeCommander.DoMouseDown(X,Y:Integer);
begin
end;

Procedure TCustomTeeCommander.DoMouseMove(X,Y:Integer; const Shift:TShiftState);
begin
end;

Procedure TCustomTeeCommander.DoMouseUp;
begin
end;

function TCustomTeeCommander.ChildCount:Integer;
begin
  result:={$IFDEF FMX}ChildrenCount{$ELSE}ControlCount{$ENDIF};
end;

function TCustomTeeCommander.GetChild(Index:Integer):{$IFDEF FMX}TFmxObject{$ELSE}TControl{$ENDIF};
begin
  result:={$IFDEF FMX}Children{$ELSE}Controls{$ENDIF}[Index];
end;

Procedure TCustomTeeCommander.ShowHideControls(Value:Boolean);
Var t : Integer;
begin
  if not( csDestroying in ComponentState) then
     for t:=0 to ChildCount-1 do
         if Child[t].Owner=Self then
            if Child[t] is TControl then
               {$IFDEF FMX}TControl{$ENDIF}(Child[t]).Enabled:=Value;
end;

{$IFDEF FMX}
{$IFNDEF D21}
type
  TControlAccess=class(TControl);
{$ENDIF}
{$ENDIF}

Procedure TCustomTeeCommander.ReAlignTeeControls;

  procedure SetLeftTop(const AControl:TControl; const ALeft,ATop:Integer);
  begin
    AControl.{$IFDEF FMX}Position.X{$ELSE}Left{$ENDIF}:=ALeft;
    AControl.{$IFDEF FMX}Position.Y{$ELSE}Top{$ENDIF}:=ATop;
  end;

  procedure SetSize(const AControl:TControl; const AWidth,AHeight:{$IFDEF FMX}Single{$ELSE}Integer{$ENDIF});
  begin
    {$IFDEF FMX}

    {$IFDEF D21}
    AControl.Size.Width:=AWidth;
    AControl.Size.Height:=AHeight;
    {$ELSE}
    TControlAccess(AControl).Width:=AWidth;
    TControlAccess(AControl).Height:=AHeight;
    {$ENDIF}

    {$ELSE}
    AControl.Width:=AWidth;
    AControl.Height:=AHeight;
    {$ENDIF}
  end;

var
  tmpPos : Integer;

  procedure Reposition(const AControl:TControl);
  begin
    if FVertical then
       SetLeftTop(AControl,4,tmpPos)
    else
       SetLeftTop(AControl,tmpPos,4);

    if AControl is TBevel then
    begin
      Inc(tmpPos,4+2);

      if FVertical then
      begin
        {$IFNDEF FMX}
        TBevel(AControl).Shape:=bsTopLine;
        {$ENDIF}

        SetSize(AControl,Width-2*4,2);
      end
      else
      begin
        {$IFNDEF FMX}
        TBevel(AControl).Shape:=bsLeftLine;
        {$ENDIF}

        SetSize(AControl,2,Height-2*4);
      end;
    end
    else
      Inc(tmpPos,25+4);
  end;

var t   : Integer;
    tmp : {$IFDEF FMX}TFmxObject{$ELSE}TControl{$ENDIF};
begin
  tmpPos:=4;

  for t:=0 to ChildCount-1 do
  begin
    tmp:=Child[t];

    if tmp.Owner=Self then
       Reposition(tmp as TControl);
  end;
end;

procedure TCustomTeeCommander.SetVertical(Value:Boolean);
begin
  if FVertical<>Value then
  begin
    FVertical:=Value;
    CheckVerticalAlign;
  end;
end;

type
  TTeePanelAccess=class(TCustomTeePanel);

procedure TCustomTeeCommander.SetPanel(const Value: TCustomTeePanel);
begin
  if Assigned(FPanel) then
  begin
    FPanel.RemoveFreeNotification(Self);
    TTeePanelAccess(FPanel).RemoveListener(Self);
  end;

  FPanel:=Value;

  if Assigned(FPanel) then
  begin
    FPanel.FreeNotification(Self);
    TTeePanelAccess(FPanel).AddListener(Self);
  end;

  if not (csDestroying in ComponentState) then
    ShowHideControls(Assigned(FPanel));
end;

procedure TCustomTeeCommander.CheckVerticalAlign;
begin
  if Align<>{$IFDEF FMX}TAlignLayout.{$IFDEF D20}None{$ELSE}alNone{$ENDIF}{$ELSE}alNone{$ENDIF} then
     if FVertical then Align:={$IFDEF FMX}TAlignLayout.{$IFDEF D20}Left{$ELSE}alLeft{$ENDIF}{$ELSE}alLeft{$ENDIF}
                  else Align:={$IFDEF FMX}TAlignLayout.{$IFDEF D20}Top{$ELSE}alTop{$ENDIF}{$ELSE}alTop{$ENDIF};

  ReAlignTeeControls;
end;

procedure TCustomTeeCommander.Loaded;
var t : Integer;
begin
  inherited;

  if Vertical then
     CheckVerticalAlign;

  if not Assigned(FPanel) then
  if Assigned(Parent) then
  begin
    if Parent is TCustomTeePanel then
       Panel:=TCustomTeePanel(Parent)
    else
    With Parent do
    for t:=0 to ComponentCount-1 do
      if Components[t] is TCustomTeePanel then
      begin
        Self.Panel:=TCustomTeePanel(Components[t]);
        break;
      end;
  end;

  ShowHideControls(Assigned(FPanel));
end;

{$IFDEF FMX}
procedure SetBitmapTransparent(const ABitmap:TBitmap);
var tmpBack : TColor;
    x,y: Integer;
    {$IFDEF D17}
    tmpData : TBitmapData;
    {$ENDIF}
begin
  if (ABitmap.Width>0) and (ABitmap.Height>0) then
  begin
    {$IFDEF D17}
    if ABitmap.Map(TMapAccess.{$IFDEF D20}ReadWrite{$ELSE}maReadWrite{$ENDIF},tmpData) then
    begin
      tmpBack:=tmpData.GetPixel(0,0);

      for x := 0 to ABitmap.Width-1 do
        for y := 0 to ABitmap.Height-1 do
            if tmpData.GetPixel(x,y)=tmpBack then
               tmpData.SetPixel(x,y,TAlphaColorRec.Null);

      ABitmap.Unmap(tmpData);
    end;
    {$ELSE}
    tmpBack:=ABitmap.Pixels[0,0];

    for x := 0 to ABitmap.Width-1 do
        for y := 0 to ABitmap.Height-1 do
            if ABitmap.Pixels[x,y]=tmpBack then
               ABitmap.Pixels[x,y]:=TAlphaColorRec.Null;
    {$ENDIF}
  end;
end;
{$ENDIF}

Function TCustomTeeCommander.CreateButton( APos:Integer;
                                           AProc:TNotifyEvent;
                                           Const AHint:String;
                                           Const AResName:String;
                                           AGroupIndex:Integer):TSpeedButton;
{$IFDEF FMX}
var tmpImage : TImage;
    tmpBitmap : TBitmap;
    tmpW : Integer;
{$ENDIF}
begin
  result:=TSpeedButton.Create(Self);

  With result do
  begin
    OnClick:=AProc;
    if FVertical then SetBounds(4,APos,25,25)
                 else SetBounds(APos,4,25,25);

    {$IFDEF FMX}

    {$IFDEF D23}
    ParentShowHint:=True;
    {$ENDIF}

    {$ELSE}
    Flat:= True;

    {$IFDEF TEEOCX}
    ShowHint:=True;
    {$ELSE}
    ParentShowHint:=True;
    {$ENDIF}

    {$ENDIF}

    {$IFDEF FMX}
    Stored:=False;

    tmpImage:=TImage.Create(Self);
    tmpImage.Align:=TAlignLayout.{$IFDEF D20}Client{$ELSE}alClient{$ENDIF};
    tmpImage.WrapMode:=TImageWrapMode.{$IFDEF D20}Stretch{$ELSE}iwStretch{$ENDIF};
    tmpImage.DisableInterpolation:=True;
    tmpImage.HitTest:=False;
    tmpImage.Stored:=False;
    result.AddObject(tmpImage);
    {$ENDIF}

    Hint:=AHint;
    Parent:=Self;

    {$IFDEF FMX}
    StaysPressed:=AGroupIndex<>0;
    Tag:=AGroupIndex;
    {$ELSE}
    GroupIndex:=AGroupIndex;
    AllowAllUp:=True;
    {$ENDIF}

    Down:= True;

    if AResName<>'' then
    begin
      {$IFDEF FMX}
      tmpBitmap:=TBitmap.Create{$IFNDEF D19}(0,0){$ENDIF};
      try
        TeeLoadBitmap(tmpBitmap,AResName);
        SetBitmapTransparent(tmpBitmap);

        tmpW:=tmpBitmap.Width div 2;

        {$IFDEF D18}
        tmpImage.Bitmap.Width:=tmpW;
        tmpImage.Bitmap.Height:=tmpBitmap.Height;
        {$ELSE}
        tmpImage.Bitmap:=TBitmap.Create(tmpW, tmpBitmap.Height);
        {$ENDIF}

        tmpImage.Bitmap.Canvas.BeginScene;
        try
          tmpImage.Bitmap.Canvas.DrawBitmap(tmpBitmap,
               TeeRect(tmpW,tmpImage.Bitmap.Height),
               TeeRect(tmpW,tmpImage.Bitmap.Height),AbsoluteOpacity);
        finally
          tmpImage.Bitmap.Canvas.EndScene;
        end;
      finally
        tmpBitmap.Free;
      end;
      {$ELSE}
      Glyph.LoadFromResourceName(HInstance,AResName);
      Glyph.Transparent:=True;
      {$ENDIF}

      {$IFNDEF FMX}
      NumGlyphs:=2; // 1=Up, 2=Disabled
      {$ENDIF}
    end;
  end;
end;

{$IFNDEF BCB4}
Function TCustomTeeCommander.CreateButton( APos:Integer;
                           AProc:TNotifyEvent;
                           Const AHint:String;
                           const ABitmap: TBitmap;
                           AGroupIndex:Integer {$IFNDEF BCB}=0{$ENDIF}):TSpeedButton;
begin
  result:=CreateButton(APos,AProc,AHint,'',AGroupIndex);

  {$IFDEF FMX}
  TImage(result.Children[0]).Bitmap:=ABitmap;
  {$ELSE}
  result.Glyph.Assign(ABitmap);
  {$ENDIF}
end;
{$ENDIF}

Function TCustomTeeCommander.DoPanelMouse:Boolean;
begin
  result:=True;
end;

Procedure TCustomTeeCommander.CreateBevel(APos:Integer);
begin
  With TBevel.Create(Self) do
  begin
    {$IFDEF FMX}
    Position.X:=APos;
    Position.Y:=2;
    Stored:=False;
    {$ELSE}
    Shape:=bsLeftLine;
    Top:=2;
    Left:=APos;
    {$ENDIF}
    Width:=2;
    Height:=Self.Height-4;
    Parent:=Self;
  end;
end;

Function TCustomTeeCommander.CreateLabel(APos:Integer; AColor:TColor):TLabel;
begin
  result:=TLabel.Create(Self);

  With result do
  begin
    Font.{$IFDEF FMX}Family{$ELSE}Name{$ENDIF}:=GetDefaultFontName;

    {$IFDEF FMX}
    Position.X:=APos;
    Position.Y:=12;

    {$IFDEF D17}
    FontColor:=AColor;
    {$ELSE}
    FontFill.Color:=AColor;
    {$ENDIF}
    
    TextAlign:=TTextAlign.{$IFDEF D20}Leading{$ELSE}taLeading{$ENDIF};
    WordWrap:=False;
    AutoSize:=True;
    Stored:=False;

    {$ELSE}
    Left:=APos;
    Top:=12;
    Font.Color:=AColor;
    {$ENDIF}

    Font.Size:=GetDefaultFontSize;
    {$IFDEF FMX}Text{$ELSE}Caption{$ENDIF}:='';
    Parent:=Self;

    {$IFNDEF LCL}
    {$IFNDEF FMX}
    Transparent:=True;
    {$ENDIF}
    {$ENDIF}
  end;
end;

Function TCustomTeeCommander.TeePanelClass:String;
begin
  if FPanel is TCustomAxisPanel then result:=TeeCommanMsg_Chart
                                else result:=TeeCommanMsg_Panel;
end;

Procedure TCustomTeeCommander.FreeOwnedControls;
var Num : Integer;
    tmp : Integer;
    t   : Integer;
begin
  Repeat
    Num:=0;
    tmp:=-1;

    for t:=0 to ChildCount-1 do
    if Child[t].Owner=Self then
    begin
      Inc(Num);
      tmp:=t;
      Break;
    end;

    if tmp<>-1 then
    begin
      RemovingControl(Child[tmp]);
      {$IFDEF AUTOREFCOUNT}
      Child[tmp].Parent:=nil;
      {$ELSE}
      Child[tmp].Free;
      {$ENDIF}
    end;

  Until Num=0;
end;

procedure TCustomTeeCommander.RemovingControl(const AComponent: TComponent);
begin
end;

procedure TCustomTeeCommander.Paint;
var
  tmpRect : TRect;

  {$IFNDEF FMX}
  procedure Adjust(const Bevel:TBevelCut);
  begin
    if Bevel<>bvNone then
        InflateRect(tmpRect,-BevelWidth,-BevelWidth);
  end;
  {$ENDIF}

var
  tmpCanvas : TTeeCanvas;
begin
  inherited;

  // Draw gradient under commander controls
  if Assigned(FGradient) and FGradient.Visible then
  begin
    tmpRect:={$IFDEF FMX}LocalRect{$ELSE}GetClientRect{$ENDIF};

    {$IFNDEF FMX}
    Adjust(BevelInner);
    Adjust(BevelOuter);
    {$ENDIF}

    tmpCanvas:=TTeeCanvas3D.Create;
    try
      tmpCanvas.ReferenceCanvas:=Canvas;
      FGradient.Draw(tmpCanvas,tmpRect);
    finally
      tmpCanvas.Free;
    end;
  end;
end;

{ TTeeCommander }
Constructor TTeeCommander.Create(AOwner:TComponent);
begin
  inherited;

  {$IFNDEF TEEOCXNOEDITOR}
  FEditor:=nil;
  FPreviewer:=nil;
  {$ENDIF}

  FDragging:=False;
  FLabelValues:=True;
  FVertical:=False;
  FEnablePieExp:=True;
  FInertia:=3;

  FAllowRotationX:=True;
  FAllowRotationY:=True;

  CreateControls([ tcbNormal,
                   tcbSeparator,
                   tcbRotate,
                   tcbMove,
                   tcbZoom,
                   tcbDepth,
                   tcb3D,
                   tcbSeparator,
                   tcbEdit,
                   tcbPrintPreview,
                   tcbCopy,
                   tcbSave,
                   tcbLabel ]);

  {$IFDEF TEEOCXNOEDITOR}
  FButtonEdit.Hide;
  FButtonPrint.Hide;
  RepositionControls;
  {$ENDIF}
end;

Procedure TTeeCommander.RemovingControl(const AComponent:TComponent);
begin
  inherited;

  if AComponent=FButtonNormal then FButtonNormal:=nil else
  if AComponent=FButtonRotate then FButtonRotate:=nil else
  if AComponent=FButtonMove then FButtonMove:=nil else
  if AComponent=FButtonZoom then FButtonZoom:=nil else
  if AComponent=FButtonDepth then FButtonDepth:=nil else
  if AComponent=FButtonEdit then FButtonEdit:=nil else
  if AComponent=FButtonPrint then FButtonPrint:=nil else
  if AComponent=FButtonCopy then FButtonCopy:=nil else
  if AComponent=FButtonSave then FButtonSave:=nil else
  if AComponent=FButton3D then FButton3D:=nil else
  if AComponent=FLabel then FLabel:=nil;
end;

Procedure TTeeCommander.CreateControls(const AControls:Array of TCommanderControls);
var t,
    tmpPos:Integer;
begin
  FreeOwnedControls;
  tmpPos:=4;

  for t:=Low(AControls) to High(AControls) do
  begin
    Case AControls[t] of
      tcbNormal : FButtonNormal := CreateButton(tmpPos,ButtonNormalClick,TeeCommanMsg_Normal,'TeeNormal',1); // Do not localize
      tcbRotate:  FButtonRotate := CreateButton(tmpPos,ButtonRotateClick,TeeCommanMsg_Rotate,'TeeRotate',1); // Do not localize
      tcbMove:    FButtonMove   := CreateButton(tmpPos,ButtonMoveClick,TeeCommanMsg_Move,'TeeMove',1); // Do not localize
      tcbZoom:    FButtonZoom   := CreateButton(tmpPos,ButtonZoomClick,TeeCommanMsg_Zoom,'TeeZoom',1); // Do not localize
      tcbDepth:   FButtonDepth  := CreateButton(tmpPos,ButtonDepthClick,TeeCommanMsg_Depth,'TeeDepth',1); // Do not localize
      tcbEdit:    FButtonEdit   := CreateButton(tmpPos,ButtonEditClick,TeeCommanMsg_Edit,'TeeEdit',0); // Do not localize
 tcbPrintPreview: FButtonPrint  := CreateButton(tmpPos,ButtonPrintClick,TeeCommanMsg_Print,'TeePrint',0); // Do not localize
      tcbCopy:    FButtonCopy   := CreateButton(tmpPos,ButtonCopyClick,TeeCommanMsg_Copy,'TeeCopy',0); // Do not localize
      tcbSave:    FButtonSave   := CreateButton(tmpPos,ButtonSaveClick,TeeCommanMsg_Save,'TeeSave',0); // Do not localize

      tcb3D:      begin
                    FButton3D:= CreateButton(tmpPos,Button3DClick,TeeCommanMsg_3D,'TeeView3D',2); // Do not localize
                    {$IFNDEF FMX}
                    FButton3D.AllowAllUp:=True;
                    {$ENDIF}
                  end;

    tcbSeparator: CreateBevel(tmpPos);
      tcbLabel:   FLabel        := CreateLabel(tmpPos,{$IFDEF FMX}claNavy{$ELSE}clNavy{$ENDIF});
    end;

    if AControls[t]=tcbSeparator then Inc(tmpPos,4+2)
                                 else Inc(tmpPos,25+4);
  end;

  ShowHideControls(Assigned(Panel));

  if Assigned(FButtonNormal) then
     FButtonNormal.Down:=True;
end;

Procedure TTeeCommander.RepositionControls;
var t      : Integer;
    tmpPos : Integer;
begin
  tmpPos:=4;

  for t:=0 to ChildCount-1 do
  begin
    if (Child[t].Owner=Self) and
       {$IFDEF FMX}(Child[t] is TControl) and TControl{$ENDIF}(Child[t]).Visible then
    begin
      {$IFDEF FMX}
      TControl(Child[t]).Position.X
      {$ELSE}
      Child[t].Left
      {$ENDIF}:=tmpPos;

      if Child[t] is TBevel then Inc(tmpPos,4+2)
                            else Inc(tmpPos,25+4);
    end;
  end;
end;

// TV52016247
Function TTeeCommander.DoCustomButton:Boolean;
begin
  // {$IFNDEF TEEOCX}(not Assigned(FButtonNormal)) or{$ENDIF} IsButtonDown(FButtonNormal) then

  result:=not DoPanelMouse;
end;

Procedure TTeeCommander.DoMouseDown(X,Y:Integer);
var tmpCancel : Boolean;
begin
  if (not DoCustomButton) or (not FPanel.Canvas.SupportsFullRotation) then
     ICircledSeries:=GetCircledSeries(x,y)
  else
     ICircledSeries:=nil;

  if (ICircledSeries is TPieSeries) or DoCustomButton then
  begin
    FDragging:=True;

    FOldX:=X;
    FOldY:=Y;

    if Assigned(ICircledSeries) then
    begin
      FDraggingIndex:=ICircledSeries.Clicked(X,Y);
    end
    else
       FDraggingIndex:=-1;

    if FPanel is TCustomTeePanel then
    begin
      tmpCancel:=(FDraggingIndex<>-1) or DoCustomButton;

      TCustomTeePanel(FPanel).CancelMouse:=tmpCancel;

      {$IFDEF FMX}
      // if tmpCancel then
      //    FPanel.Capture
      {$ELSE}
      if tmpCancel then
         SetCaptureControl(FPanel)
      {$ENDIF};
    end;
  end;
end;

Function TTeeCommander.DoPanelMouse:Boolean;

  Function IsButtonUp(const AButton:TSpeedButton):Boolean;
  begin
    result:=((not Assigned(AButton)) or (not AButton.Down));
  end;

begin
  result:=IsButtonUp(FButtonRotate) and
          IsButtonUp(FButtonDepth) and
          IsButtonUp(FButtonMove) and
          IsButtonUp(FButtonZoom);
end;

procedure TTeeCommander.CheckPendingInertia;

  function ChangeInertia:Boolean;
  const
    Level = 0.01;

  var tmp : Double;
  begin
    result:=False;

    if FInertia>0 then
    begin
      if (Abs(IDifX)>Level) or (Abs(IDifY)>Level) then
      begin
        tmp:=(100-FInertia)*0.001;

        if Abs(IDifX)>Level then
           IDifX:=IDifX-(IDifX*tmp)
        else
           IDifX:=0;

        if Abs(IDifY)>Level then
           IDifY:=IDifY-(IDifY*tmp)
        else
           IDifY:=0;

        result:=True;
      end;
    end;
  end;

var Old : Boolean;
begin
  if not FDragging then
     if ChangeInertia then
     begin
       DoRotation(IDifX,IDifY);

       if not FPanel.AutoRepaint then
       begin
         Old:=FPanel.AutoRepaint;
         FPanel.AutoRepaint:=True;
         FPanel.Invalidate;
         FPanel.AutoRepaint:=Old;
       end;
     end;
end;

Procedure TTeeCommander.DoMouseUp;
begin
  {$IFDEF FMX}
  // if FDragging or IRotating then
  //    FPanel.ReleaseCapture
  {$ELSE}
  if FDragging or IRotating then
     SetCaptureControl(nil)
  {$ENDIF}
  ;

  if FDragging and (FInertia>0) then
     FPanel.Invalidate;

  ICircledSeries:=nil;
  IRotating:=False;
  FDragging:=False;
  FDraggingIndex:=-1;
end;

Function TTeeCommander.GetCircledSeries(x,y:Integer):TCircledSeries;
var t : Integer;
    tmp : TChartSeries;
    tmpPart : TChartClickedPart;
begin
  result:=nil;

  if EnablePieExploding and (FPanel is TCustomChart) then
  With TCustomChart(FPanel) do
  begin
    CalcClickedPart(TeePoint(x,y),tmpPart);

    if (tmpPart.Part=cpSeries) and (tmpPart.ASeries is TCircledSeries) then
       result:=tmpPart.ASeries as TCircledSeries
    else
    for t:=0 to SeriesCount-1 do
    begin
      tmp:=Series[t];

      if (tmp is TCircledSeries) and tmp.Active then
      begin
        result:=tmp as TCircledSeries;
        exit;
      end;
    end;
  end;
end;

Function TTeeCommander.IsButtonDown(const AButton:TSpeedButton):Boolean;
begin
  result:=Assigned(AButton) and AButton.Down;
end;

{$IFDEF FMX}
// When BufferedDisplay=True this is necessary because View3DOptions does not call
// FPanel.Invalidate
Procedure TTeeCommander.InvalidatePanel;
begin
  FPanel.Invalidate;
end;
{$ENDIF}

Procedure TTeeCommander.DoRotation(const IDifX,IDifY:Double);

  function AllowFullRotation:Boolean;
  begin
    result:=FAllowFull or FPanel.Canvas.SupportsFullRotation;
  end;

  Function CorrectAngle(Const AAngle:Double):Double;
  begin
    result:=AAngle;

    if result>360 then result:=result-360
    else
    if result<0 then result:=360+result;
  end;

begin
  with FPanel.View3DOptions do
  if AllowFullRotation then
  begin
    if ssShift in IShift then
       Tilt:=Round(CorrectAngle(Tilt+IDifY))
    else
    begin
      RotationFloat:=CorrectAngle(RotationFloat+IDifX);
      ElevationFloat:=CorrectAngle(ElevationFloat+IDifY);
    end;
  end
  else
  begin
    if Assigned(ICircledSeries) then
    begin
      Rotation:=360;

      if not AllowFullRotation then
         Perspective:=0;

      if IDifX<>0 then
         with ICircledSeries do
              RotationAngle:=Round(CorrectAngle(RotationAngle+IDifX));
    end
    else
      RotationFloat:=TRotateTool.RotationChange(AllowFullRotation,RotationFloat,IDifX);

    ElevationFloat:=TRotateTool.ElevationChange(AllowFullRotation,ElevationFloat,IDifY);
  end;

  {$IFDEF FMX}
  InvalidatePanel;
  {$ENDIF}
end;

Procedure TTeeCommander.DoMouseMove(X,Y:Integer; const Shift:TShiftState);

  Procedure Set3D;
  begin
    FPanel.View3D:=True;

    if Assigned(FButton3D) then
       FButton3D.Down:=True;
  end;

  Procedure DoRotate;
  begin
    // 2D with circled series (Pie, Gauge, Polar, Smith, etc):
    if (not FPanel.View3D) and Assigned(ICircledSeries) then
       ICircledSeries.RotationAngle:=Round(HalfDivPi*ICircledSeries.PointToAngle(X,Y))+ICircledSeries.RotationAngle
    else
    begin
      Set3D;

      with FPanel,View3DOptions do
      begin
        Orthogonal:=False;

        if FAllowRotationX then
           IDifX:=90.0*(X-FOldX)/Width
        else
           IDifX:=0;

        if FAllowRotationY then
           IDifY:=90.0*(FOldY-Y)/Height
        else
           IDifY:=0;
      end;

      IShift:=Shift;

      DoRotation(IDifX,IDifY);
    end;

    FOldX:=X;
    FOldY:=Y;

    IRotating:=True;
  end;

  Procedure DoMove;
  var tmpZ : Double;
  begin
    if not FPanel.Canvas.SupportsFullRotation then // SupportsZoom2D
       Set3D;

    With FPanel.View3DOptions do
    begin
      tmpZ:=1;

      HorizOffsetFloat:=HorizOffsetFloat+((X-FOldX)*tmpZ);
      VertOffsetFloat:=VertOffsetFloat+((Y-FOldY)*tmpZ);
    end;

    {$IFDEF FMX}
    InvalidatePanel;
    {$ENDIF}

    FOldX:=X;
    FOldY:=Y;
  end;

  Procedure DoZoom;
  var tmp  : Double;
      tmp2 : Double;
  begin
    if not FPanel.Canvas.SupportsFullRotation then // SupportsZoom2D
       Set3D;

    With FPanel,View3DOptions do
    begin
      tmp:=(10.0*(FOldY-Y)/TeeDistance(ChartWidth,ChartHeight));

      tmp2:=(10.0*tmp*ZoomFloat/100.0);
      if tmp>0 then
         ZoomFloat:=ZoomFloat+Math.Max(1,tmp2)
      else
      if tmp<0 then
         ZoomFloat:=Math.Max(1,{$IFDEF CPUX64}Double{$ENDIF}(ZoomFloat+Math.Min(-1,tmp2)));
    end;

    {$IFDEF FMX}
    InvalidatePanel;
    {$ENDIF}
    
    FOldY:=Y;
  end;

  Function CalcDistPercent(APercent,AWidth,AHeight:Integer):Integer;
  begin
    result:=Round(1.0*APercent*TeeDistance(FOldX-X,FOldY-Y)/TeeDistance(AWidth,AHeight));
  end;

  Procedure DoDepth;
  var tmp : Integer;
  begin
    if FPanel is TCustomAxisPanel then
    With TCustomAxisPanel(FPanel) do
    begin
      Set3D;

      tmp:=CalcDistPercent(200,ChartWidth,ChartHeight);

      if (tmp>=1) then
         Chart3DPercent:=Math.Min(100,tmp);
    end;
  end;

  Procedure DoNormal;
  Var tmp : Integer;
  begin
    if FDraggingIndex<>-1 then
    begin
      if Assigned(ICircledSeries) and (ICircledSeries is TPieSeries) then
      With ICircledSeries as TPieSeries do
      begin
        tmp:=Math.Min(100,CalcDistPercent(100,CircleWidth,CircleHeight));
        ExplodedSlice[FDraggingIndex]:=tmp;
      end;
    end;
  end;

begin
  if FDragging then
  begin
    FDragging:=False;
    IRotating:=False;

    if not DoCustomButton then
       DoNormal  { first do this !!! }
    else
    if FMouseButton={$IFDEF FMX}TMouseButton.{$ENDIF}mbRight then DoMove
    else
    if IsButtonDown(FButtonRotate) then
       if ssCtrl in Shift then DoZoom
       else
       if ssShift in Shift then DoMove
       else
          DoRotate
    else
    if IsButtonDown(FButtonMove) then
       if ssCtrl in Shift then DoZoom
       else
       if ssShift in Shift then DoRotate
       else
          DoMove
    else
    if IsButtonDown(FButtonZoom) then
       if ssCtrl in Shift then DoRotate
       else
       if ssShift in Shift then DoMove
       else
          DoZoom
    else
    if IsButtonDown(FButtonDepth) then
       DoDepth;

    if FLabelValues and (not FVertical) then
       ShowValues;

    FDragging:=True;
  end;
end;

Function TTeeCommander.CaptionPanel(Const ACaption:String):String;
begin
  result:=Format(ACaption,[TeePanelClass]);
end;

procedure TTeeCommander.SetLabelCaption(Const ACaption:String);
var tmp: String;
begin
  tmp:=ACaption;

  if Assigned(FOnSetLabel) then
     FOnSetLabel(Self,tmp);

  if Assigned(FLabel) then
     if FLabelValues and (not FVertical) then
        FLabel.{$IFDEF FMX}Text{$ELSE}Caption{$ENDIF}:=tmp
     else
        FLabel.Visible:=False;
end;

procedure TTeeCommander.ButtonRotateClick(Sender: TObject);
begin
  SetLabelCaption(CaptionPanel(TeeCommanMsg_RotateLabel));

  {$IFDEF FMX}
  if Assigned(ButtonRotate) then
     ButtonRotate.Down:=True;
  {$ENDIF}
end;

procedure TTeeCommander.ButtonMoveClick(Sender: TObject);
begin
  SetLabelCaption(CaptionPanel(TeeCommanMsg_MoveLabel));

  {$IFDEF FMX}
  if Assigned(ButtonMove) then
     ButtonMove.Down:=True;
  {$ENDIF}
end;

procedure TTeeCommander.ButtonZoomClick(Sender: TObject);
begin
  SetLabelCaption(CaptionPanel(TeeCommanMsg_ZoomLabel));

  {$IFDEF FMX}
  if Assigned(ButtonZoom) then
     ButtonZoom.Down:=True;
  {$ENDIF}
end;

procedure TTeeCommander.ButtonDepthClick(Sender: TObject);
begin
  SetLabelCaption(CaptionPanel(TeeCommanMsg_DepthLabel));

  {$IFDEF FMX}
  if Assigned(ButtonDepth) then
     ButtonDepth.Down:=True;
  {$ENDIF}
end;

procedure TTeeCommander.ButtonEditClick(Sender: TObject);
{$IFNDEF TEEOCXNOEDITOR}
var tmp : TCustomTeePanel;
{$ENDIF}
begin
  {$IFNDEF TEEOCXNOEDITOR}
  tmp:=nil;

  if Assigned(FEditor) then
     FEditor.Execute
  else
  if Assigned(FPanel) then
  begin
    tmp:=TTeePanelAccess(FPanel).GetEditablePanel;

    if tmp is TCustomChart then
       {$IFDEF FMX}
       TChartEditForm.Edit(nil,TCustomChart(tmp))
       {$ELSE}
       {$IFDEF TEEOCX}
       EditChart(self,TCustomChart(tmp)) //TA05015162
       {$ELSE}
       EditChart(nil,TCustomChart(tmp))
       {$ENDIF}
       {$ENDIF}
    else
    if tmp is TCustomTeePanelExtended then
       {$IFDEF FMX}
       TGradientEditor.Edit(nil,TCustomTeePanelExtended(tmp).Gradient);
       {$ELSE}
       EditTeeGradient(nil,TCustomTeePanelExtended(tmp).Gradient);
       {$ENDIF}
  end;

  if Assigned(FOnEditedChart) then
     if Assigned(tmp) and (tmp is TCustomChart) then
        FOnEditedChart(Self,TCustomChart(tmp));

  if Assigned(FButton3D) then
     FButton3D.Down:=FPanel.View3D;
  {$ENDIF}
end;

procedure TTeeCommander.ButtonPrintClick(Sender: TObject);
begin
  {$IFNDEF TEEOCXNOEDITOR}
  if Assigned(FPreviewer) then FPreviewer.Execute
  else
  if Assigned(FPanel) then
     {$IFDEF FMX}
     TChartPreview.Preview(nil, FPanel);
     {$ELSE}
     {$IFDEF TEEOCX}
     ChartPreview(self,FPanel); //TA05015162
     {$ELSE}
     ChartPreview(nil,FPanel);
     {$ENDIF}
     {$ENDIF}
  {$ENDIF}
end;

procedure TTeeCommander.Button3DClick(Sender: TObject);
begin
  if Assigned(FPanel) then
     FPanel.View3D:=FButton3D.Down;
end;

procedure TTeeCommander.ButtonCopyClick(Sender: TObject);
begin
  if Assigned(FPanel) then FPanel.CopyToClipboardBitmap;
end;

procedure TTeeCommander.ButtonNormalClick(Sender: TObject);
var tmp : TCircledSeries;
begin
  tmp:=GetCircledSeries(0,0);

  if Assigned(tmp) and tmp.Visible then
     SetLabelCaption(CaptionPanel(TeeCommanMsg_NormalPieLabel))
  else
     SetLabelCaption(CaptionPanel(TeeCommanMsg_NormalLabel));

  {$IFDEF FMX}
  if Assigned(ButtonNormal) then
     ButtonNormal.Down:=True;
  {$ENDIF}
end;

Procedure TTeeCommander.ShowHideControls(Value:Boolean);
begin
  EnableControls(Value,[FButtonRotate,FButtonMove,FButtonZoom,FButtonNormal,
                        FButtonCopy,FButtonSave,FButtonPrint,FButton3D]);

  if Assigned(FButtonEdit) then
     FButtonEdit.Enabled:=Value and (FPanel is TCustomTeePanel);

  if Value then
     Value:=FPanel is TCustomAxisPanel;

  if Assigned(FButtonDepth) then
     FButtonDepth.Enabled:=Value;

  if Assigned(FButtonSave) then
     FButtonSave.Enabled:=Value;

  if Assigned(FButton3D) and Assigned(FPanel) then
     FButton3D.Down:=FPanel.View3D;
end;

procedure TTeeCommander.SetLabelValues(Value:Boolean);
begin
  if FLabelValues<>Value then
  begin
    FLabelValues:=Value;
    if Assigned(FLabel) then FLabel.Visible:=FLabelValues;
  end;
end;

// Gets current "default" button
function TTeeCommander.GetDefault:TCommanderControls;
begin
  if Assigned(FButtonNormal) and FButtonNormal.Down then result:=tcbNormal else
  if Assigned(FButtonRotate) and FButtonRotate.Down then result:=tcbRotate else
  if Assigned(FButtonMove) and FButtonMove.Down then result:=tcbMove else
  if Assigned(FButtonZoom) and FButtonZoom.Down then result:=tcbZoom else
  if Assigned(FButtonDepth) and FButtonDepth.Down then result:=tcbDepth else
     result:=tcbNormal; // default
end;

// Sets default button down
procedure TTeeCommander.SetDefault(const AButton:TCommanderControls);
begin
  case AButton of
    tcbNormal: if Assigned(FButtonNormal) then FButtonNormal.Down:=True;
    tcbRotate: if Assigned(FButtonRotate) then FButtonRotate.Down:=True;
      tcbMove: if Assigned(FButtonMove) then FButtonMove.Down:=True;
      tcbZoom: if Assigned(FButtonZoom) then FButtonZoom.Down:=True;
     tcbDepth: if Assigned(FButtonDepth) then FButtonDepth.Down:=True;
  end;
end;

Procedure TTeeCommander.ShowValues;
var tmp : String;
begin
  with FPanel.View3DOptions do
  if IsButtonDown(FButtonRotate) then
     tmp:=Format(TeeCommanMsg_Rotating,[Rotation,Elevation])
  else
  if IsButtonDown(FButtonMove) then
     tmp:=Format(TeeCommanMsg_Moving,[HorizOffset,VertOffset])
  else
  if IsButtonDown(FButtonZoom) then
     tmp:=Format(TeeCommanMsg_Zooming,[Zoom])
  else
  if IsButtonDown(FButtonDepth) then
  begin
    if FPanel is TCustomAxisPanel then
    with TCustomAxisPanel(FPanel) do
         tmp:=Format(TeeCommanMsg_Depthing,[Chart3DPercent])
  end
  else
  if IsButtonDown(FButtonNormal) and (FDraggingIndex<>-1) then
  begin
    if Assigned(ICircledSeries) and (ICircledSeries is TPieSeries) then
       tmp:=Format( TeeCommanMsg_PieExploding,
                    [FDraggingIndex,TPieSeries(ICircledSeries).ExplodedSlice[FDraggingIndex]])
    else
       tmp:='';
  end
  else
  if Assigned(FLabel) then
     tmp:='';

  SetLabelCaption(tmp);

  if Assigned(FLabel) and FLabel.Visible then
     FLabel.{$IFDEF FMX}Repaint{$ELSE}Update{$ENDIF};
end;

{$IFDEF FMX}
function SaveChartDialog(AChart:TCustomChart):Boolean;
var tmp : String;
begin
  With TSaveDialog.Create(nil) do
  try
    FileName:='';
    DefaultExt:=TeeMsg_TeeExtension;
    Filter:=TeeMsg_NativeFilter;

    result:=Execute;

    if result then
    begin
      tmp:=ChangeFileExt(FileName,'.'+TeeMsg_TeeExtension);
      SaveChartToFile(AChart,tmp,True,False);
    end;
  finally
    Free;
  end;
end;
{$ENDIF}

procedure TTeeCommander.ButtonSaveClick(Sender: TObject);
begin
  {$IFNDEF TEEOCXNOEDITOR}
  if Assigned(FPanel) then
     if FPanel is TCustomChart then
        SaveChartDialog(FPanel as TCustomChart);
  {$ENDIF}
end;

{$IFNDEF TEEOCXNOEDITOR}
procedure TTeeCommander.SetEditor(const Value: TChartEditor);
begin
  if FEditor<>Value then
  begin
    if Assigned(FEditor) then
       FEditor.RemoveFreeNotification(Self);

    FEditor:=Value;

    if Assigned(FEditor) then
       FEditor.FreeNotification(Self);
  end;
end;

procedure TTeeCommander.SetPreviewer(const Value: TChartPreviewer);
begin
  if FPreviewer<>Value then
  begin
    if Assigned(FPreviewer) then
       FPreviewer.RemoveFreeNotification(Self);

    FPreviewer:=Value;

    if Assigned(FPreviewer) then
       FPreviewer.FreeNotification(Self);
  end;
end;

procedure TTeeCommander.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;

  if Operation=opRemove then
  begin
    if Assigned(FEditor) and (AComponent=FEditor) then
       FEditor:=nil;

    if Assigned(FPreviewer) and (AComponent=FPreviewer) then
       FPreviewer:=nil;
  end;
end;
{$ENDIF}

{$IFDEF FMX}
{ TSpeedButtonHelper }

function TSpeedButtonHelper.GetDown: Boolean;
begin
  result:=IsPressed;
end;

procedure TSpeedButtonHelper.SetDown(const Value: Boolean);
var t : Integer;
begin
  //if IsPressed<>Value then  <-- (in XE4 this is never True)
  begin
    IsPressed:=Value;

    if IsPressed then
    for t := 0 to Parent.ChildrenCount-1 do
    if Parent.Children[t]<>Self then
       if Parent.Children[t] is TCustomButton then
          if TCustomButton(Parent.Children[t]).StaysPressed then
             if TCustomButton(Parent.Children[t]).Tag=Tag then
                TCustomButton(Parent.Children[t]).IsPressed:=False;
  end;
end;
{$ENDIF}

end.
