lazarus-ccr/components/lazmapviewer/examples/fulldemo/main.pas
2024-04-05 14:51:09 +00:00

896 lines
25 KiB
ObjectPascal

{ This file is used by the "MapViewer_Demo" and the "MapViewer_Demo_with_Addons"
projects.
Active define WITH_ADDONS in the project options for "MapViewer_Demo_with_Addons"
and make sure that the addon packages are listed as requirements.
}
unit Main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, ComCtrls, Buttons, IntfGraphics, PrintersDlgs,
Grids, ExtDlgs,
mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine,
{$IFDEF WITH_ADDONS}ConfigFrame_with_Addons{$ELSE}ConfigFrame{$ENDIF};
type
{ TMainForm }
TMainForm = class(TForm)
Bevel2: TBevel;
BtnSearch: TButton;
BtnGoTo: TButton;
BtnGPSPoints: TButton;
BtnSaveToFile: TButton;
BtnLoadGPXFile: TButton;
BtnPrintMap: TButton;
CbFoundLocations: TComboBox;
CbLocations: TComboBox;
OpenPictureDialog: TOpenPictureDialog;
PgLayers: TTabSheet;
CbMouseCoords: TGroupBox;
CbDistanceUnits: TComboBox;
FontDialog: TFontDialog;
GbCenterCoords: TGroupBox;
GbScreenSize: TGroupBox;
GbSearch: TGroupBox;
GbGPS: TGroupBox;
InfoCenterLatitude: TLabel;
InfoViewportHeight: TLabel;
InfoCenterLongitude: TLabel;
InfoBtnGPSPoints: TLabel;
GPSPointInfo: TLabel;
InfoViewportWidth: TLabel;
LblSelectLocation: TLabel;
LblCenterLatitude: TLabel;
LblViewportHeight: TLabel;
LblViewportWidth: TLabel;
LblPositionLongitude: TLabel;
LblPositionLatitude: TLabel;
InfoPositionLongitude: TLabel;
InfoPositionLatitude: TLabel;
LblCenterLongitude: TLabel;
LblZoom: TLabel;
MapView: TMapView;
GeoNames: TMVGeoNames;
OpenDialog: TOpenDialog;
PageControl: TPageControl;
PgData: TTabSheet;
PgConfig: TTabSheet;
POIImages: TImageList;
PrintDialog: TPrintDialog;
sgLayers: TStringGrid;
rgDrawMode: TRadioGroup;
lblOpacity: TLabel;
tbOpacity: TTrackBar;
ZoomTrackBar: TTrackBar;
procedure BtnGoToClick(Sender: TObject);
procedure BtnLoadGPXFileClick(Sender: TObject);
procedure BtnPrintMapClick(Sender: TObject);
procedure BtnSearchClick(Sender: TObject);
procedure BtnGPSPointsClick(Sender: TObject);
procedure BtnSaveToFileClick(Sender: TObject);
procedure BtnPOITextFontClick(Sender: TObject);
procedure CbFoundLocationsDrawItem(Control: TWinControl; Index: Integer;
ARect: TRect; State: TOwnerDrawState);
procedure CbDistanceUnitsChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure GeoNamesNameFound(const AName: string; const ADescr: String;
const ALoc: TRealPoint);
procedure MapViewChange(Sender: TObject);
procedure MapViewDrawGpsPoint(Sender: TObject;
ADrawer: TMvCustomDrawingEngine; APoint: TGpsPoint);
procedure MapViewMouseLeave(Sender: TObject);
procedure MapViewMouseMove(Sender: TObject; {%H-}Shift: TShiftState; X, Y: Integer);
procedure MapViewMouseUp(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; X, Y: Integer);
procedure MapViewZoomChange(Sender: TObject);
procedure rgDrawModeSelectionChanged(Sender: TObject);
procedure sgLayersCheckboxToggled({%H-}Sender: TObject; {%H-}aCol, {%H-}aRow: Integer; aState: TCheckboxState);
procedure sgLayersEditingDone(Sender: TObject);
procedure sgLayersSelection(Sender: TObject; {%H-}aCol, aRow: Integer);
procedure tbOpacityChange(Sender: TObject);
procedure UpdateLayers(Sender: TObject);
procedure ZoomTrackBarChange(Sender: TObject);
private
CfgFrame: {$IFDEF WITH_ADDONS}TCfgFrame_with_Addons{$ELSE}TCfgFrame{$ENDIF};
procedure ClearFoundLocations;
procedure UpdateCoords(X, Y: Integer);
procedure UpdateDropdownWidth(ACombobox: TCombobox);
procedure UpdateLocationHistory(ALocation: String);
procedure UpdateViewportSize;
public
procedure ReadFromIni;
procedure WriteToIni;
end;
var
MainForm: TMainForm;
implementation
{$R *.lfm}
uses
LCLType, IniFiles, Math, FPCanvas, FPImage, GraphType,
Printers, OSPrinters,
mvEngine, mvGPX,
globals, gpsPtForm, gpslistform;
type
TLocationParam = class
Descr: String;
Loc: TRealPoint;
end;
const
MAX_LOCATIONS_HISTORY = 50;
USE_DMS = true;
_TILELAYERS_ID_ = 42;
var
PointFormatSettings: TFormatsettings;
TileLayer: array[0..9] of TGPSTileLayer;
function CalcIniName: String;
begin
Result := ChangeFileExt(Application.ExeName, '.ini');
end;
{ TMainForm }
procedure TMainForm.rgDrawModeSelectionChanged(Sender: TObject);
begin
TileLayer[Pred(sgLayers.Row)].DrawMode := TItemDrawMode(rgDrawMode.ItemIndex);
MapView.Redraw;
end;
procedure TMainForm.BtnSearchClick(Sender: TObject);
begin
ClearFoundLocations;
GeoNames.Search(CbLocations.Text, MapView.DownloadEngine);
UpdateDropdownWidth(CbFoundLocations);
UpdateLocationHistory(CbLocations.Text);
if CbFoundLocations.Items.Count > 0 then CbFoundLocations.ItemIndex := 0;
end;
procedure TMainForm.BtnGPSPointsClick(Sender: TObject);
var
F: TGpsListViewer;
begin
F := TGpsListViewer.Create(nil);
try
F.MapViewer := MapView;
F.ShowModal;
finally
F.Free;
end;
end;
procedure TMainForm.BtnGoToClick(Sender: TObject);
var
s: String;
P: TLocationParam;
begin
if CbFoundLocations.ItemIndex = -1 then
exit;
// Extract parameters of found locations. We need that to get the coordinates.
s := CbFoundLocations.Items.Strings[CbFoundLocations.ItemIndex];
P := TLocationParam(CbFoundLocations.Items.Objects[CbFoundLocations.ItemIndex]);
if P = nil then
exit;
CbFoundLocations.Text := s;
// Show location in center of mapview
MapView.Zoom := 12;
MapView.Center := P.Loc;
MapView.Invalidate;
end;
procedure TMainForm.BtnLoadGPXFileClick(Sender: TObject);
var
reader: TGpxReader;
b: TRealArea;
begin
if OpenDialog.FileName <> '' then
OpenDialog.InitialDir := ExtractFileDir(OpenDialog.Filename);
if OpenDialog.Execute then begin
reader := TGpxReader.Create;
try
reader.LoadFromFile(OpenDialog.FileName, MapView.GPSItems, b);
MapView.Engine.ZoomOnArea(b);
MapViewZoomChange(nil);
finally
reader.Free;
end;
end;
end;
procedure TMainForm.BtnPrintMapClick(Sender: TObject);
const
INCH = 25.4; // 1" = 25.4 mm
HOR_MARGIN = 10.0; // mm
VERT_MARGIN = 10.0; // mm
function px2mm(px, ppi: Integer): Double;
begin
Result := px / ppi * INCH;
end;
function mm2px(mm: Double; ppi: Integer): Integer;
begin
Result := round(mm / INCH * ppi);
end;
var
bmp: TBitmap;
PrintedRect: TRect;
aspectRatio_map: Double;
aspectRatio_page: Double;
mapWidth_mm: Double;
mapHeight_mm: Double;
pageWidth_mm: Double;
pageHeight_mm: Double;
printedWidth_mm: Double;
printedHeight_mm: Double;
factor: Double;
begin
if PrintDialog.Execute then
begin
Printer.Orientation := poPortrait;
// Scale map such that it fits into the width of the printer paper with
// a margin at all sides
mapWidth_mm := px2mm(MapView.Width, ScreenInfo.PixelsPerInchX);
mapHeight_mm := px2mm(MapView.Height, ScreenInfo.PixelsPerInchY);
pageWidth_mm := px2mm(Printer.PageWidth, Printer.XDPI) - 2*HOR_MARGIN;
pageHeight_mm := px2mm(Printer.PageHeight, Printer.YDPI) - 2*VERT_MARGIN;
aspectRatio_map := mapHeight_mm / mapWidth_mm;
aspectRatio_page := pageHeight_mm / pageWidth_mm;
if aspectRatio_Map > aspectRatio_page then
begin
factor := pageHeight_mm / mapHeight_mm;
printedWidth_mm := mapWidth_mm * factor;
printedHeight_mm := pageHeight_mm;
end else
begin
factor := pageWidth_mm / mapWidth_mm;
printedWidth_mm := pageWidth_mm;
printedHeight_mm := mapHeight_mm * factor;
end;
// Calculate size of the output rectangle (on paper).
PrintedRect := Rect(0, 0, mm2px(printedWidth_mm, Printer.XDPI), mm2px(printedHeight_mm, Printer.YDPI));
// Center output rectangle horizontally on page
OffsetRect(PrintedRect, mm2px(HOR_MARGIN + (pageWidth_mm-printedWidth_mm) / 2 , Printer.XDPI), mm2px(VERT_MARGIN, Printer.YDPI));
// Begin printing
Printer.BeginDoc;
try
// Catch the displayed images as a bitmap.
bmp := TBitmap.Create;
try
bmp.SetSize(MapView.Width, MapView.Height);
MapView.DrawingEngine.PaintToCanvas(bmp.Canvas);
// Stretch-draw the map image to the output rectangle on the printer.
Printer.Canvas.StretchDraw(PrintedRect, bmp);
finally
bmp.Free;
end;
finally
Printer.EndDoc;
end;
end;
end;
procedure TMainForm.BtnSaveToFileClick(Sender: TObject);
begin
MapView.SaveToFile(TPortableNetworkGraphic, 'mapview.png');
ShowMessage('Map saved to "mapview.png".');
end;
procedure TMainForm.BtnPOITextFontClick(Sender: TObject);
begin
FontDialog.Font.Assign(MapView.Font);
if FontDialog.Execute then
MapView.Font.Assign(FontDialog.Font);
end;
procedure TMainForm.CbFoundLocationsDrawItem(Control: TWinControl;
Index: Integer; ARect: TRect; State: TOwnerDrawState);
var
s: String;
P: TLocationParam;
combo: TCombobox;
x, y: Integer;
begin
combo := TCombobox(Control);
if (State * [odSelected, odFocused] <> []) then begin
combo.Canvas.Brush.Color := clHighlight;
combo.Canvas.Font.Color := clHighlightText;
end else begin
combo.Canvas.Brush.Color := clWindow;
combo.Canvas.Font.Color := clWindowText;
end;
combo.Canvas.FillRect(ARect);
combo.Canvas.Brush.Style := bsClear;
s := combo.Items.Strings[Index];
P := TLocationParam(combo.Items.Objects[Index]);
x := ARect.Left + 2;
y := ARect.Top + 2;
combo.Canvas.Font.Style := [fsBold];
combo.Canvas.TextOut(x, y, s);
inc(y, combo.Canvas.TextHeight('Tg'));
combo.Canvas.Font.Style := [];
combo.Canvas.TextOut(x, y, P.Descr);
end;
procedure TMainForm.CbDistanceUnitsChange(Sender: TObject);
begin
DistanceUnit := TDistanceUnits(CbDistanceUnits.ItemIndex);
UpdateViewPortSize;
end;
procedure TMainForm.ClearFoundLocations;
var
i: Integer;
P: TLocationParam;
begin
for i:=0 to CbFoundLocations.Items.Count-1 do begin
P := TLocationParam(CbFoundLocations.Items.Objects[i]);
P.Free;
end;
CbFoundLocations.Items.Clear;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
I: Integer;
begin
CfgFrame := {$IFDEF WITH_ADDONS}TCfgFrame_with_Addons{$ELSE}TCfgFrame{$ENDIF}.Create(self);
CfgFrame.Parent := pgConfig;
CfgFrame.Align := alClient;
CfgFrame.MapView := MapView;
CfgFrame.OnDrawGPSPoint := @MapViewDrawGpsPoint;
CfgFrame.OnUpdateLayers := @UpdateLayers;
cInputQueryEditSizePercents := 0;
InfoPositionLongitude.Caption := '';
InfoPositionLatitude.Caption := '';
InfoCenterLongitude.Caption := '';
InfoCenterLatitude.Caption := '';
InfoViewportWidth.Caption := '';
InfoViewportHeight.Caption := '';
GPSPointInfo.Caption := '';
for I := 0 to High(TileLayer) do
begin
TileLayer[I] := TGPSTileLayer.Create;
with TileLayer[I] do
begin
Visible := False;
UseThreads := MapView.UseThreads;
DrawMode := idmUseOpacity;
Opacity := 0.25;
case I of
0: MapProvider := 'Google Satellite Only';
1: MapProvider := 'Google Terrain';
2: MapProvider := 'Maps For Free';
otherwise
MapProvider := '';
end;
end;
sgLayers.Cells[1, I + 1] := TileLayer[I].Visible.ToString;
sgLayers.Cells[2, I + 1] := TileLayer[I].MapProvider;
MapView.GPSLayer[I].Add(TileLayer[I], _TILELAYERS_ID_);
end;
ReadFromIni;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
var
I: Integer;
begin
WriteToIni;
for I := 0 to High(TileLayer) do
MapView.GPSLayer[I].Delete(TileLayer[I]);
ClearFoundLocations;
end;
procedure TMainForm.FormShow(Sender: TObject);
begin
MapView.Active := true;
end;
procedure TMainForm.GeoNamesNameFound(const AName: string;
const ADescr: String; const ALoc: TRealPoint);
var
P: TLocationParam;
begin
P := TLocationParam.Create;
P.Descr := ADescr;
P.Loc := ALoc;
CbFoundLocations.Items.AddObject(AName, P);
end;
procedure TMainForm.MapViewChange(Sender: TObject);
begin
UpdateViewportSize;
end;
procedure TMainForm.MapViewDrawGpsPoint(Sender: TObject;
ADrawer: TMvCustomDrawingEngine; APoint: TGpsPoint);
var
P: TPoint;
d: Integer;
sym: TGPSSymbol;
clr: TColor;
extent: TSize;
lMapView: TMapView;
begin
lMapView := TMapView(Sender);
// Screen coordinates of the GPS point
P := lMapView.LatLonToScreen(APoint.RealPoint);
// Draw the GPS point as specified by the data in the point's ExtraData
if (APoint.ExtraData is TGPSExtraData) then
// Get the POI attributes
with TGPSExtraData(APoint.ExtraData) do
begin
clr := Color;
sym := Symbol;
d := Size div 2;
end
else
begin
sym := gpsPlus;
clr := clRed;
d := 5;
end;
// Draw the POI symbol
ADrawer.PenColor := clr;
case sym of
gpsPlus:
begin
ADrawer.Line(P.X - d, P.Y, P.X + d, P.Y);
ADrawer.Line(P.X, P.Y - d, P.X , P.Y + d);
end;
gpsCross:
begin
ADrawer.Line(P.x - d, P.Y - d, P.X + d, P.Y + d);
ADrawer.Line(P.x - d, P.Y + d, P.X + d, P.Y - d);
end;
gpsFilledCircle:
begin
ADrawer.BrushStyle := bsSolid;
ADrawer.BrushColor := clr;
ADrawer.Ellipse(P.X - d, P.Y - d, P.X + d, P.Y + d);
end;
gpsOpenCircle:
begin
ADrawer.BrushStyle := bsClear;
ADrawer.Ellipse(P.X - d, P.Y - d, P.X + d, P.Y + d);
end;
gpsFilledRect:
begin
ADrawer.BrushStyle := bsSolid;
ADrawer.BrushColor := clr;
ADrawer.Rectangle(P.X - d, P.Y - d, P.X + d, P.Y + d);
end;
gpsOpenRect:
begin
ADrawer.BrushStyle := bsClear;
ADrawer.Rectangle(P.X - d, P.Y - d, P.X + d, P.Y + d);
end;
end;
// Prepare text output: background color...
inc(P.Y, d + 4);
extent := ADrawer.TextExtent(APoint.Name);
if CfgFrame.POITextBkColor = clNone then
ADrawer.BrushStyle := bsClear
else
begin
ADrawer.BrushStyle := bsSolid;
ADrawer.BrushColor := CfgFrame.POITextBkColor;
end;
// ... and font
ADrawer.FontColor := MapView.Font.Color;
ADrawer.FontName := MapView.Font.Name;
ADrawer.FontSize := MapView.Font.Size;
ADrawer.FontStyle := MapView.Font.Style;
// Write the POI text
ADrawer.TextOut(P.X - extent.CX div 2, P.Y, APoint.Name);
end;
procedure TMainForm.MapViewMouseLeave(Sender: TObject);
begin
UpdateCoords(MaxInt, MaxInt);
end;
procedure TMainForm.MapViewMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
const
DELTA = 3;
var
rArea: TRealArea;
gpsList: TGpsObjList;
L: TStrings;
i: Integer;
begin
UpdateCoords(X, Y);
rArea.TopLeft := MapView.ScreenToLatLon(Point(X-DELTA, Y-DELTA));
rArea.BottomRight := MapView.ScreenToLatLon(Point(X+DELTA, Y+DELTA));
gpsList := MapView.GpsItems.GetObjectsInArea(rArea);
try
if gpsList.Count > 0 then begin
L := TStringList.Create;
try
for i:=0 to gpsList.Count-1 do
if gpsList[i] is TGpsPoint then
with TGpsPoint(gpsList[i]) do
L.Add(Format('%s' + LineEnding + ' %s / %s', [
Name, LatToStr(Lat, USE_DMS), LonToStr(Lon, USE_DMS)
]));
GPSPointInfo.Caption := L.Text;
finally
L.Free;
end;
end else
GPSPointInfo.Caption := '';
finally
gpsList.Free;
end;
end;
procedure TMainForm.MapViewMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
rPt: TRealPoint;
gpsPt: TGpsPoint;
gpsName: String = '';
gpsSize: Integer = 0;
gpsSymbol: TGPSSymbol = gpsPlus;
gpsColor: TColor = clBlack;
gpsImageIndex: Integer = -1;
begin
if (Button = mbRight) then begin
rPt := MapView.ScreenToLatLon(Point(X, Y));
case CfgFrame.POIMode of
pmDefaultDrawing, pmDefaultImage:
begin
if not InputQuery('Name of GPS location', 'Please enter name', gpsName) then
exit;
gpsPt := TGpsPoint.CreateFrom(rPt);
end;
pmImageList:
begin
if GPSPointForm = nil then
begin
GPSPointForm := TGPSPointForm.Create(Application);
GPSPointForm.Position := poMainFormCenter;
end;
GPSPointForm.SetImageIndexData('', POIImages, -1);
if GPSPointForm.ShowModal <> mrOK then
exit;
gpsPt := TGpsPointOfInterest.CreateFrom(rPt);
GPSPointForm.GetImageIndexData(gpsName, gpsImageIndex);
TGPSPointOfInterest(gpsPt).ImageIndex := gpsImageIndex;
end;
pmCustomDrawing:
begin
if GPSPointForm = nil then
begin
GPSPointForm := TGPSPointForm.Create(Application);
GPSPointForm.Position := poMainFormCenter;
end;
GPSPointForm.SetSymbolData('', clRed, gpsPlus, 10);
if GPSPointForm.ShowModal <> mrOK then
exit;
gpsPt := TGpsPoint.CreateFrom(rPt);
GPSPointForm.GetSymbolData(gpsName, gpsColor, gpsSymbol, gpsSize);
gpsPt.ExtraData := TGPSExtraData.Create(_CLICKED_POINTS_);
with TGPSExtraData(gpsPt.ExtraData) do
begin
Color := gpsColor;
Symbol := gpsSymbol;
Size := gpsSize;
end;
end;
end;
gpsPt.Name := gpsName;
MapView.GpsItems.Add(gpsPt, _CLICKED_POINTS_);
end;
end;
procedure TMainForm.MapViewZoomChange(Sender: TObject);
begin
ZoomTrackbar.Position := MapView.Zoom;
end;
procedure TMainForm.ReadFromIni;
var
ini: TCustomIniFile;
List: TStringList;
L, T, W, H: Integer;
R: TRect;
i: Integer;
s: String;
pt: TRealPoint;
du: TDistanceUnits;
provider: String;
begin
ini := TMemIniFile.Create(CalcIniName);
try
R := Screen.DesktopRect;
L := ini.ReadInteger('MainForm', 'Left', Left);
T := ini.ReadInteger('MainForm', 'Top', Top);
W := ini.ReadInteger('MainForm', 'Width', Width);
H := ini.ReadInteger('MainForm', 'Height', Height);
if L + W > R.Right then L := R.Right - W;
if L < R.Left then L := R.Left;
if T + H > R.Bottom then T := R.Bottom - H;
if T < R.Top then T := R.Top;
SetBounds(L, T, W, H);
HERE_AppID := ini.ReadString('HERE', 'APP_ID', '');
HERE_AppCode := ini.ReadString('HERE', 'APP_CODE', '');
OpenWeatherMap_ApiKey := ini.ReadString('OpenWeatherMap', 'API_Key', '');
ThunderForest_ApiKey := ini.ReadString('ThunderForest', 'API_Key', '');
list := TStringList.Create;
try
MapView.Engine.ClearMapProviders;
MapView.Engine.RegisterProviders;
MapView.GetMapProviders(list);
sgLayers.Columns[1].PickList.Assign(list);
provider := ini.ReadString('MapView', 'Provider', MapView.MapProvider);
if MapView.Engine.MapProviderByName(provider) = nil then
begin
MessageDlg('Map provider "' + provider + '" not found.', mtError, [mbOK], 0);
provider := list[0];
end;
MapView.MapProvider := provider;
finally
list.Free;
end;
MapView.InactiveColor := ini.ReadInteger('MapView', 'MapBkgrColor', MapView.InactiveColor);
MapView.Zoom := ini.ReadInteger('MapView', 'Zoom', MapView.Zoom);
pt.Lon := StrToFloatDef(ini.ReadString('MapView', 'Center.Longitude', ''), 0.0, PointFormatSettings);
pt.Lat := StrToFloatDef(ini.ReadString('MapView', 'Center.Latitude', ''), 0.0, PointFormatSettings);
MapView.Center := pt;
s := ini.ReadString('MapView', 'DistanceUnits', '');
if s <> '' then begin
for du in TDistanceUnits do
if DistanceUnit_Names[du] = s then begin
DistanceUnit := du;
CbDistanceUnits.ItemIndex := ord(du);
break;
end;
end;
List := TStringList.Create;
try
ini.ReadSection('Locations', List);
for i:=0 to List.Count-1 do begin
s := ini.ReadString('Locations', List[i], '');
if s <> '' then
CbLocations.Items.Add(s);
end;
finally
List.Free;
end;
CfgFrame.ReadFromIni(ini);
finally
ini.Free;
end;
end;
procedure TMainForm.sgLayersCheckboxToggled(sender: TObject; aCol,
aRow: Integer; aState: TCheckboxState);
begin
if TileLayer[Pred(sgLayers.Row)].MapProvider.IsEmpty then
Exit;
TileLayer[Pred(sgLayers.Row)].Visible := (aState = cbChecked);
MapView.Redraw;
end;
procedure TMainForm.sgLayersEditingDone(Sender: TObject);
var
S: String;
begin
if sgLayers.Col <> 2 then
Exit;
S := sgLayers.Cells[sgLayers.Col, sgLayers.Row];
TileLayer[Pred(sgLayers.Row)].MapProvider := S;
sgLayers.Cells[sgLayers.Col, sgLayers.Row] := S;
MapView.Redraw;
end;
procedure TMainForm.sgLayersSelection(Sender: TObject; aCol, aRow: Integer);
begin
rgDrawMode.ItemIndex := Ord(TileLayer[Pred(ARow)].DrawMode);
tbOpacity.Position := Round(TileLayer[Pred(ARow)].Opacity * 100);
end;
procedure TMainForm.tbOpacityChange(Sender: TObject);
begin
TileLayer[Pred(sgLayers.Row)].Opacity := tbOpacity.Position / 100;
MapView.Redraw;
end;
procedure TMainForm.UpdateLayers(Sender: TObject);
var
TL: TGPSTileLayer;
begin
// Notify tile layers for drawing engine change, it must be done implicitly
// but there is no other mechanism for now
for TL in TileLayer do
TL.ParentViewChanged;
end;
procedure TMainForm.UpdateCoords(X, Y: Integer);
var
rPt: TRealPoint;
begin
rPt := MapView.Center;
InfoCenterLongitude.Caption := LonToStr(rPt.Lon, USE_DMS);
InfoCenterLatitude.Caption := LatToStr(rPt.Lat, USE_DMS);
if (X <> MaxInt) and (Y <> MaxInt) then begin
rPt := MapView.ScreenToLatLon(Point(X, Y));
InfoPositionLongitude.Caption := LonToStr(rPt.Lon, USE_DMS);
InfoPositionLatitude.Caption := LatToStr(rPt.Lat, USE_DMS);
end else begin
InfoPositionLongitude.Caption := '-';
InfoPositionLatitude.Caption := '-';
end;
end;
procedure TMainForm.UpdateDropdownWidth(ACombobox: TCombobox);
var
cnv: TControlCanvas;
i, w: Integer;
s: String;
P: TLocationParam;
begin
w := 0;
cnv := TControlCanvas.Create;
try
cnv.Control := ACombobox;
cnv.Font.Assign(ACombobox.Font);
for i:=0 to ACombobox.Items.Count-1 do begin
cnv.Font.Style := [fsBold];
s := ACombobox.Items.Strings[i];
w := Max(w, cnv.TextWidth(s));
P := TLocationParam(ACombobox.Items.Objects[i]);
cnv.Font.Style := [];
w := Max(w, cnv.TextWidth(P.Descr));
end;
ACombobox.ItemWidth := w + 16;
ACombobox.ItemHeight := 2 * cnv.TextHeight('Tg') + 6;
finally
cnv.Free;
end;
end;
procedure TMainForm.UpdateLocationHistory(ALocation: String);
var
idx: Integer;
begin
idx := CbLocations.Items.IndexOf(ALocation);
if idx <> -1 then
CbLocations.Items.Delete(idx);
CbLocations.Items.Insert(0, ALocation);
while CbLocations.Items.Count > MAX_LOCATIONS_HISTORY do
CbLocations.Items.Delete(Cblocations.items.Count-1);
CbLocations.Text := ALocation;
end;
procedure TMainForm.UpdateViewportSize;
begin
InfoViewportWidth.Caption := Format('%.2n %s', [
CalcGeoDistance(
MapView.GetVisibleArea.TopLeft.Lat,
MapView.GetVisibleArea.TopLeft.Lon,
MapView.GetVisibleArea.TopLeft.Lat,
MapView.GetVisibleArea.BottomRight.Lon,
DistanceUnit
),
DistanceUnit_Names[DistanceUnit]
]);
InfoViewportHeight.Caption := Format('%.2n %s', [
CalcGeoDistance(
MapView.GetVisibleArea.TopLeft.Lat,
MapView.GetVisibleArea.TopLeft.Lon,
MapView.GetVisibleArea.BottomRight.Lat,
MapView.GetVisibleArea.TopLeft.Lon,
DistanceUnit
),
DistanceUnit_Names[DistanceUnit]
]);
end;
procedure TMainForm.WriteToIni;
var
ini: TCustomIniFile;
i: Integer;
begin
ini := TMemIniFile.Create(CalcIniName);
try
ini.WriteInteger('MainForm', 'Left', Left);
ini.WriteInteger('MainForm', 'Top', Top);
ini.WriteInteger('MainForm', 'Width', Width);
ini.WriteInteger('MainForm', 'Height', Height);
ini.WriteString('MapView', 'Provider', MapView.MapProvider);
ini.WriteInteger('MapView', 'Zoom', MapView.Zoom);
ini.WriteString('MapView', 'Center.Longitude', FloatToStr(MapView.Center.Lon, PointFormatSettings));
ini.WriteString('MapView', 'Center.Latitude', FloatToStr(MapView.Center.Lat, PointFormatSettings));
ini.WriteInteger('MapView', 'MapBkgrColor', MapView.InactiveColor);
ini.WriteString('MapView', 'DistanceUnits', DistanceUnit_Names[DistanceUnit]);
if HERE_AppID <> '' then
ini.WriteString('HERE', 'APP_ID', HERE_AppID);
if HERE_AppCode <> '' then
ini.WriteString('HERE', 'APP_CODE', HERE_AppCode);
if OpenWeatherMap_ApiKey <> '' then
ini.WriteString('OpenWeatherMap', 'API_Key', OpenWeatherMap_ApiKey);
if ThunderForest_ApiKey <> '' then
ini.WriteString('ThunderForest', 'API_Key', ThunderForest_ApiKey);
ini.EraseSection('Locations');
for i := 0 to CbLocations.Items.Count-1 do
ini.WriteString('Locations', 'Item'+IntToStr(i), CbLocations.Items[i]);
CfgFrame.WriteToIni(ini);
finally
ini.Free;
end;
end;
procedure TMainForm.ZoomTrackBarChange(Sender: TObject);
begin
MapView.Zoom := ZoomTrackBar.Position;
LblZoom.Caption := Format('Zoom (%d):', [ZoomTrackbar.Position]);
end;
initialization
PointFormatSettings.DecimalSeparator := '.';
end.