{$I Delphi_Versions.inc}
unit FMX.uecZoomBarComponent;

interface
 uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics,  FMX.Objects,
  FMX.Layouts,FMX.Controls.Presentation,FMX.StdCtrls,
  FMX.uecNativeMapControl,FMX.uecMapUtil;

type


TZoomBarComponent = class(TECCustomTool)
  private

   tmZoom : TTimer;

   FXYRadius : single;

   FPanelBar : TRectangle;
   FNextZoom ,
   FPrevZoom : Tbutton;

   FButtonSize : integer;

   FInProgressiveZoom,
   FProgressiveZoom : boolean;

   procedure setXYRadius(const Value: single);

   procedure setProgressiveZoom(const value:boolean);

   procedure setButtonSize(const value:integer);

   procedure doNextZoom(Sender:TObject);
   procedure doPrevZoom(Sender:TObject);

   procedure doNextMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Single);
   procedure doNextMouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Single);

   procedure tmZoomTimer(Sender: TObject);

   procedure ChangeZoom;

   protected
    procedure setLayout(const value:TECCustomToolLayout);  override;


  public
   constructor Create(Map : TNativeMapControl);  override;
   destructor  Destroy; override;


   property ButtonSize : integer read FButtonSize  write setButtonSize;
   property ProgressiveZoom : boolean read FProgressiveZoom write setProgressiveZoom;
   property XYRadius : single read FXYRadius write setXYRadius;

  end;

implementation

constructor TZoomBarComponent.Create(Map : TNativeMapControl);
begin

  inherited;

  // create zoom bar

  // FPanelBar will be the support that determines the total occupancy of our component
  // It will be connected to TECNativeMap



  FPanelBar  := TRectangle.Create(nil);
  FPanelBar.Fill.Color := $FFE0E0E0;
  FPanelBar.showHint := true;
  FPanelBar.Stroke.Color := FPanelBar.Fill.Color;


  // place buttons on the panel

  FNextZoom := TButton.Create(FPanelBar);
  FNextZoom.Parent := FPanelBar;
  {$IF CompilerVersion >= 34.0} // before ?
  FNextZoom.ControlType := TPresentedControl.TControlType.Platform;
  FNextZoom.StyleLookup := 'addtoolbuttonbordered';
  {$ELSE}
   FNextZoom.Text   := '+';
   FNextZoom.font.size := 11;
  {$ENDIF}

  FNextZoom.Hint   := doubleToStrDigit(map.NumericalZoom,1);


  FNextZoom.OnMouseDown := doNextMouseDown;
  FNextZoom.OnMouseUp   := doNextMouseUp;
  FNextZoom.onClick := doNextZoom;

  FPrevZoom := TButton.Create(FPanelBar);
  FPrevZoom.Parent := FPanelBar;
  {$IF CompilerVersion >= 34.0} // before ?
   FPrevZoom.ControlType := TPresentedControl.TControlType.Platform;
   FPrevZoom.StyleLookup := 'deleteitembutton';
  {$ELSE}
   FPrevZoom.Text   := '-';
   FPrevZoom.font.size := 11;
  {$ENDIF}
  FPrevZoom.Hint   := doubleToStrDigit(map.NumericalZoom,1);

  FPrevZoom.OnMouseDown := doNextMouseDown;
  FPrevZoom.OnMouseUp   := doNextMouseUp;

  FPrevZoom.onClick:= doPrevZoom;


   // Anchoring the panel on the map

  add('ZoomBar',FPanelBar,ecTopRight);

  {$IFDEF OS_MOBILE}
   ButtonSize := 48;
  {$ELSE}
   ButtonSize := 32;
  {$ENDIF}


 // A timer is used to manage the progressive zoom
 // triggered when a zoom button is pressed.

  tmZoom := TTimer.Create(nil);
  tmZoom.Enabled  := false;
  tmZoom.Interval := 80;
  tmZoom.OnTimer := tmZoomTimer;

  ProgressiveZoom := true;

  XYRadius := 4;

end;

procedure TZoomBarComponent.setXYRadius(const Value: single);
begin


  if Value <= 10 then
    FXYRadius := Value
  else
  if FXYRadius=10 then
   exit
  else
    FXYRadius := 10;



   FPanelBar.XRadius := FXYRadius;
   FPanelBar.YRadius := FXYRadius;


end;

procedure TZoomBarComponent.setProgressiveZoom(const value:boolean);
begin

  FProgressiveZoom := value;

  if value then
  begin
    FNextZoom.OnMouseDown := doNextMouseDown;
    FNextZoom.OnMouseUp   := doNextMouseUp;
    FPrevZoom.OnMouseDown := doNextMouseDown;
    FPrevZoom.OnMouseUp   := doNextMouseUp;
  end
  else
  begin
    FNextZoom.OnMouseDown := nil;
    FNextZoom.OnMouseUp   := nil;
    FPrevZoom.OnMouseDown := nil;
    FPrevZoom.OnMouseUp   := nil;
  end;
end;

procedure TZoomBarComponent.setButtonSize(const value:integer);
begin
 FButtonSize := value;

 FNextZoom.width  := FButtonSize;
 FNextZoom.Height := FButtonSize;

 FPrevZoom.width  := FButtonSize;
 FPrevZoom.Height := FButtonSize;

 // recalculate button layout
 Layout:=Layout;

end;

procedure TZoomBarComponent.setLayout(const value:TECCustomToolLayout);
begin
  inherited;

  FNextZoom.position.y    := 0;
  FNextZoom.position.X    := 0;

 if (Layout = ctlVertical) then
 begin
   Width := FButtonSize;
   Height := 2*FButtonSize+1;
   FPrevZoom.position.y    := FButtonSize+1;
   FPrevZoom.position.X    := 0;
 end
 else
 begin
   Width := 2*FButtonSize+1;
   Height:= FButtonSize;
   FPrevZoom.position.y  := 0;
   FPrevZoom.position.x  := FButtonSize+1;
 end;
end;


procedure TZoomBarComponent.ChangeZoom;
begin
   FNextZoom.Hint   := doubleToStrDigit(map.NumericalZoom,1);
   FPrevZoom.Hint   := doubleToStrDigit(map.NumericalZoom,1);
end;

procedure TZoomBarComponent.doNextZoom(Sender:TObject);
begin

  if not FInProgressiveZoom then
  begin
    Map.Zoom := Map.Zoom + 1;
    ChangeZoom;
  end;

   FInProgressiveZoom := false;
end;

procedure TZoomBarComponent.doPrevZoom(Sender:TObject);
begin

  if not FInProgressiveZoom then
  begin
    Map.Zoom := Map.Zoom - 1;
    ChangeZoom;
  end;

   FInProgressiveZoom := false;
end;


// ============= automatic Zoom ================================================

// activate the timer when the button is pressed
// a progressive zoom will then be automatically performed
procedure TZoomBarComponent.doNextMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
 // save the button pressed to react on it.
 tmZoom.TagObject := Sender;
 tmZoom.Enabled   := true;
end;


// cancel progressive zoom
procedure TZoomBarComponent.doNextMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
 tmZoom.Enabled   := false;
 ChangeZoom;
end;



// Progressive zoom in or out
// Allows to go beyond the maximum zoom managed by the tile server
procedure TZoomBarComponent.tmZoomTimer(Sender: TObject);
begin

  FInProgressiveZoom := true;

  if (tmZoom.TagObject = FNextZoom) then
  begin
    map.ZoomScaleFactor := map.ZoomScaleFactor + 10
  end
  else
   map.ZoomScaleFactor := map.ZoomScaleFactor - 10;


end;

//------------------------------------------------------------------------------



destructor  TZoomBarComponent.Destroy;
begin
 inherited;
 tmZoom.Free;
 FPanelBar.Free;
end;
end.
