unit FMX.uecSwitchServerComponent;

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

type

  TSwitchServerComponent = class(TECCustomTool)
  private

   FPanelBar : TRectangle;
   FSwitchMap: TNativeMapControl;

   FXYRadius : single;

   FHint,
   FStyle  : String;

   FColor,FSecondaryColor : TAlphaColor;

   FName : string;

   FDeltaZoom : integer;

   FSwitch   : boolean;

   FObserver : TNativeMapObserver;

   FOnEnter,FOnLeave,FOnSwitch,FOnChange : TNotifyEvent;

   FCustomTileServer : TOnMapServerTilePath;

   procedure setCustomTileServer(const Value:TOnMapServerTilePath);

   procedure setXYRadius(const Value: single);

   procedure setColor(const Value:TAlphaColor);
   procedure setSecondaryColor(const Value:TAlphaColor);
   procedure UpdateColor;


   function   getHint : string;
   procedure  setHint(const Value : string);

   procedure setSwitch(const Value:boolean);
   procedure setBorderSize(const Value:integer);

   procedure setSize(const Value:integer);
   function  getSize : integer;

   procedure doOnChange(sender: TObject);

   procedure doMapBounds(Sender : TObject);
   procedure doMapZoom(Sender : TObject);

   procedure doOnEnter(Sender : TObject);
   procedure doOnLeave(Sender : TObject);

   procedure doOnMoveMouseMap(ender : TObject; const Lat, Lng: Double);
   procedure doMapClick(Sender : TObject; const Lat, Lng: Double);


   procedure setServer(const Value:TTileServer);
   function  getServer : TTileServer;

   procedure setStyle(const Value:string);
   procedure setApiKeys;


   procedure setDeltaZoom(const Value:integer);

   public
   constructor Create(Map : TNativeMapControl;const AName:string='');  override;
   destructor  Destroy; override;

   property Color          : TAlphaColor read FColor          write setColor;
   property SecondaryColor : TAlphaColor read FSecondaryColor write setSecondaryColor;

   property CustomTileServer : TOnMapServerTilePath read FCustomTileServer write setCustomTileServer;

   property DeltaZoom : integer read FDeltaZoom write setDeltaZoom;

   property TileServer : TTileServer read getServer write setServer;
   property MapStyle   : string      read FStyle  write setStyle;

   property Hint : string read getHint write setHint;

   property Size   : integer read getSize write setSize;
   property Switch : boolean read FSwitch write setSwitch;

   property XYRadius : single read FXYRadius write setXYRadius;

   property OnChange : TNotifyEvent read FOnChange write FOnChange;
   property OnEnter  : TNotifyEvent read FOnEnter  write FOnEnter;
   property OnLeave  : TNotifyEvent read FOnLeave  write FOnLeave;
   property OnSwitch : TNotifyEvent read FOnSwitch write FOnSwitch;


  end;

implementation

constructor TSwitchServerComponent.Create(Map : TNativeMapControl;const AName:string);
begin

  inherited ;

  FSwitch := false;

  FXYRadius := 4;


  FColor          := claWhite;
  FSecondaryColor := claBlack;

  // create bar

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

  FPanelBar  := TRectangle.Create(nil);

  {$IF CompilerVersion >= 27 }
 // FPanelBar.Stroke.Kind := TBrushKind.None;
  {$ELSE}
 //  FPanelBar.Stroke.Kind := TBrushKind.bkNone;
  {$ENDIF}

  FPanelBar.fill.Color := Color;
  FPanelBar.stroke.Color := Color;
  FPanelBar.showHint := true;

  FSwitchMap := TNativeMapControl.Create(FPanelBar);
  FSwitchMap.Parent := FPanelBar;


  FObserver := TNativeMapObserver.Create;

  FObserver.OnMapBounds  := doMapBounds;

  FObserver.OnMapzoom    := doMapZoom;

  FPanelBar.Width := 48;
  FPanelBar.Height:= 48;

   // Anchoring the panel on the map

  add('SwitchServer'+FName,FPanelBar,ecLeftBottom);

  Component.OnChange := doOnChange;


  Size := 48;

  Map.Attach(FObserver) ;

  TileServer := tsArcGisWorldImagery;

  FSwitchMap.Draggable := false;
  FSwitchMap.OnMapMouseMove := doOnMoveMouseMap;
  FSwitchMap.OnMapClick := doMapClick;
  FSwitchMap.OnMapEnter := doOnEnter;
  FSwitchMap.OnMapLeave := doOnLeave;
  FSwitchMap.PrechargingTilesDelay := 10;

  DeltaZoom := -4;


end;

procedure TSwitchServerComponent.setCustomTileServer(const Value:TOnMapServerTilePath);
begin
  if assigned(Value) then
  begin
    FCustomTileServer := Value;
    TileServer        := tsCustom;
    FSwitchMap.TileServerInfo.GetTileFilename := FCustomTileServer;
  end else TileServer := tsOSM;
end;

procedure TSwitchServerComponent.setDeltaZoom(const Value:integer);
begin
  if (Value>-8) and (Value<8) then
  begin
    FDeltaZoom := Value;
    FSwitchMap.Zoom := Map.Zoom + FDeltaZoom;
  end;
end;

procedure TSwitchServerComponent.setSwitch(const Value:boolean);
begin
  FSwitch := Value;

  UpdateColor;

  if assigned(OnSwitch) then
   OnSwitch(Self);

end;

// call when resize component
procedure TSwitchServerComponent.doOnChange(sender: TObject);
begin
 setBorderSize(2);

 if assigned(OnChange) then
  OnChange(Self);
end;


procedure TSwitchServerComponent.setSize(const Value:integer);
var FEvt : TNotifyEvent;
begin
 FEvt := FOnChange;
 // modifying With and Height leads to a call to OnChange, set to nil to avoid double calls
 FOnChange := nil;
 Component.Width := value;
 Component.Height:= value;
 FOnChange := FEvt;
 // only one OnChange
 if assigned(FOnChange) then
  FOnChange(Self);
end;

function  TSwitchServerComponent.getSize : integer;
begin
  result := Component.Width;
end;

procedure TSwitchServerComponent.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 TSwitchServerComponent.setBorderSize(const Value:integer);
begin

  FSwitchMap.position.y    := Value;
  FSwitchMap.position.x    := Value;
  FSwitchMap.Width  := FPanelBar.Width  - 2*Value;
  FSwitchMap.Height := FPanelBar.Height - 2*Value;

  FPanelBar.Stroke.Thickness := value;


   XYRadius := XYRadius;


end;

procedure TSwitchServerComponent.doOnEnter(Sender : TObject);
begin
 setBorderSize(4);
 if assigned(OnEnter) then
  OnEnter(Self);
end;

procedure TSwitchServerComponent.doOnLeave(Sender : TObject);
begin
 setBorderSize(2);

  if assigned(OnLeave) then
  OnLeave(Self);
end;


procedure TSwitchServerComponent.UpdateColor;
begin
if Switch then
   FPanelBar.stroke.Color := SecondaryColor
  else
   FPanelBar.stroke.Color := Color;

   FPanelBar.fill.Color := FPanelBar.stroke.Color;
end;

procedure TSwitchServerComponent.setColor(const Value:TAlphaColor);
begin
  FColor := Value;
  UpdateColor;

end;

procedure TSwitchServerComponent.setSecondaryColor(const Value:TAlphaColor);
begin
 FSecondaryColor := Value;
 UpdateColor;
end;

function TSwitchServerComponent.getHint : string;
begin
  result := FSwitchMap.Hint;
end;

procedure  TSwitchServerComponent.setHint(const Value : string);
begin
  FHint := Value;
  FSwitchMap.Hint := Value;
end;

procedure TSwitchServerComponent.setServer(const Value:TTileServer);
begin
  FSwitchMap.TileServer := Value;
  FSwitchMap.CopyrightTile := '';

  if FHint='' then
   FSwitchMap.Hint := tsToString(Value)
  else
   FSwitchMap.Hint := FHint;

  setApiKeys;
end;

function  TSwitchServerComponent.getServer : TTileServer;
begin
 result := FSwitchMap.TileServer;
end;

procedure TSwitchServerComponent.setStyle(const Value:string);
begin
 if FSwitchMap.TileServerInfo.MapStyle = Value then exit;

 FSwitchMap.TileServerInfo.MapStyle := Value;

 if FHint='' then
 begin
  FSwitchMap.Hint := tsToString(TileServer);

  if Value<>'' then
  FSwitchMap.Hint := FSwitchMap.Hint + ' '+Value;
 end
 else
  FSwitchMap.Hint := FHint;


 FSwitchMap.CopyrightTile := '';
 setApiKeys;
end;

procedure TSwitchServerComponent.setApiKeys;
begin
 FSwitchMap.BingKey           := Map.BingKey;
 FSwitchMap.MapQuestKey       := Map.MapQuestKey;
 FSwitchMap.VectorMapZenKey   := Map.VectorMapZenKey;
 FSwitchMap.Google.APiKey     := Map.Google.APiKey;
 FSwitchMap.TomTomKey         := Map.TomTomKey;
 FSwitchMap.MapBoxToken       := Map.MapBoxToken;
 FSwitchMap.IgnKey            := Map.IgnKey;
 FSwitchMap.ThunderforestKey  := Map.ThunderforestKey;
 FSwitchMap.DigitalGlobeToken := Map.DigitalGlobeToken;
 FSwitchMap.HereApiKey        := Map.HereApiKey;
end;


procedure TSwitchServerComponent.doOnMoveMouseMap(ender : TObject; const Lat, Lng: Double);
begin
  FSwitchMap.Cursor := crHandPoint;
end;

procedure TSwitchServerComponent.doMapBounds(Sender : TObject);
begin
  FSwitchMap.setCenter(Map.latitude,Map.longitude);
end;

procedure TSwitchServerComponent.doMapZoom(Sender : TObject);
begin
  FSwitchMap.Zoom := Map.Zoom + FDeltaZoom;
end;

procedure TSwitchServerComponent.doMapClick(Sender : TObject;const Lat, Lng: Double);
var ts1,ts2:TTileServer;
    st1,st2:string;
begin


 ts1 := map.TileServer;
 st1 := map.TileServerInfo.MapStyle;

 ts2 := FSwitchMap.TileServer;
 st2 := FSwitchMap.TileServerInfo.MapStyle;

 map.tileserver := ts2;
 map.TileServerInfo.MapStyle := st2;
 FSwitchMap.visible := false;
 Tileserver := ts1;
 MapStyle   := st1;
 FSwitchMap.visible := true;

 SWitch := not Switch;

end;





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



destructor  TSwitchServerComponent.Destroy;
begin
 Map.Detach(FObserver);
 FObserver.Free;


 FPanelBar.Free;
  inherited;
end;


end.
