lazmapviewer: Improved drawing code. Extend both fulldemo projects by map layers. Patch by Yuliyan Ivanov. Issue #39063.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9150 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2024-01-18 12:11:41 +00:00
parent 68988c40ab
commit 3750b0a3d7
7 changed files with 1207 additions and 632 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ interface
uses uses
Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, ExtCtrls, Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, ComCtrls, Buttons, IntfGraphics, ColorBox, Spin, PrintersDlgs, StdCtrls, ComCtrls, Buttons, IntfGraphics, ColorBox, Spin, PrintersDlgs,
mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine; mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine, Grids;
type type
@ -81,6 +81,10 @@ type
PrintDialog1: TPrintDialog; PrintDialog1: TPrintDialog;
rgPOIMode: TRadioGroup; rgPOIMode: TRadioGroup;
seProxyPort: TSpinEdit; seProxyPort: TSpinEdit;
sgLayers: TStringGrid;
rgDrawMode: TRadioGroup;
lblOpacity: TLabel;
tbOpacity: TTrackBar;
ZoomTrackBar: TTrackBar; ZoomTrackBar: TTrackBar;
procedure BtnGoToClick(Sender: TObject); procedure BtnGoToClick(Sender: TObject);
procedure BtnLoadGPXFileClick(Sender: TObject); procedure BtnLoadGPXFileClick(Sender: TObject);
@ -118,7 +122,14 @@ type
procedure MapViewZoomChange(Sender: TObject); procedure MapViewZoomChange(Sender: TObject);
procedure BtnLoadMapProvidersClick(Sender: TObject); procedure BtnLoadMapProvidersClick(Sender: TObject);
procedure BtnSaveMapProvidersClick(Sender: TObject); procedure BtnSaveMapProvidersClick(Sender: TObject);
procedure rgDrawModeSelectionChanged(Sender: TObject);
procedure rgPOIModeClick(Sender: TObject); procedure rgPOIModeClick(Sender: TObject);
procedure sgLayersCheckboxToggled(sender: TObject; aCol, aRow: Integer;
aState: TCheckboxState);
procedure sgLayersEditingDone(Sender: TObject);
procedure sgLayersSelection(Sender: TObject; aCol, aRow: Integer);
procedure tbOpacityChange(Sender: TObject);
procedure UpdateLayers;
procedure ZoomTrackBarChange(Sender: TObject); procedure ZoomTrackBarChange(Sender: TObject);
private private
@ -160,9 +171,11 @@ const
MAX_LOCATIONS_HISTORY = 50; MAX_LOCATIONS_HISTORY = 50;
MAP_PROVIDER_FILENAME = 'map-providers.xml'; MAP_PROVIDER_FILENAME = 'map-providers.xml';
USE_DMS = true; USE_DMS = true;
_TILELAYERS_ID_ = 42;
var var
PointFormatSettings: TFormatsettings; PointFormatSettings: TFormatsettings;
TileLayer: array[0..9] of TGPSTileLayer;
function CalcIniName: String; function CalcIniName: String;
begin begin
@ -183,6 +196,7 @@ begin
MapView.GetMapProviders(CbProviders.Items); MapView.GetMapProviders(CbProviders.Items);
CbProviders.ItemIndex := 0; CbProviders.ItemIndex := 0;
MapView.MapProvider := CbProviders.Text; MapView.MapProvider := CbProviders.Text;
sgLayers.Columns[1].PickList.Assign(CbProviders.Items);
end else end else
ShowMessage(msg); ShowMessage(msg);
end; end;
@ -193,6 +207,12 @@ begin
MapView.Engine.WriteProvidersToXML(Application.Location + MAP_PROVIDER_FILENAME); MapView.Engine.WriteProvidersToXML(Application.Location + MAP_PROVIDER_FILENAME);
end; end;
procedure TMainForm.rgDrawModeSelectionChanged(Sender: TObject);
begin
TileLayer[Pred(sgLayers.Row)].DrawMode := TItemDrawMode(rgDrawMode.ItemIndex);
MapView.Redraw;
end;
procedure TMainForm.BtnSearchClick(Sender: TObject); procedure TMainForm.BtnSearchClick(Sender: TObject);
begin begin
ClearFoundLocations; ClearFoundLocations;
@ -349,11 +369,13 @@ end;
procedure TMainForm.cbCyclicViewChange(Sender: TObject); procedure TMainForm.cbCyclicViewChange(Sender: TObject);
begin begin
MapView.Cyclic := cbCyclicView.Checked; MapView.Cyclic := cbCyclicView.Checked;
UpdateLayers;
end; end;
procedure TMainForm.CbDebugTilesChange(Sender: TObject); procedure TMainForm.CbDebugTilesChange(Sender: TObject);
begin begin
MapView.DebugTiles := CbDebugTiles.Checked; MapView.DebugTiles := CbDebugTiles.Checked;
MapView.Invalidate;
end; end;
procedure TMainForm.CbDoubleBufferChange(Sender: TObject); procedure TMainForm.CbDoubleBufferChange(Sender: TObject);
@ -423,6 +445,7 @@ end;
procedure TMainForm.CbUseThreadsChange(Sender: TObject); procedure TMainForm.CbUseThreadsChange(Sender: TObject);
begin begin
MapView.UseThreads := CbUseThreads.Checked; MapView.UseThreads := CbUseThreads.Checked;
UpdateLayers;
end; end;
procedure TMainForm.CbDistanceUnitsChange(Sender: TObject); procedure TMainForm.CbDistanceUnitsChange(Sender: TObject);
@ -458,6 +481,7 @@ var
homeDir: String; homeDir: String;
cacheDir: String; cacheDir: String;
fn: String; fn: String;
I: Integer;
begin begin
cInputQueryEditSizePercents := 0; cInputQueryEditSizePercents := 0;
@ -483,6 +507,7 @@ begin
MapView.CachePath := cacheDir; MapView.CachePath := cacheDir;
MapView.GetMapProviders(CbProviders.Items); MapView.GetMapProviders(CbProviders.Items);
CbProviders.ItemIndex := CbProviders.Items.IndexOf(MapView.MapProvider); CbProviders.ItemIndex := CbProviders.Items.IndexOf(MapView.MapProvider);
sgLayers.Columns[1].PickList.Assign(CbProviders.Items);
MapView.DoubleBuffered := true; MapView.DoubleBuffered := true;
MapView.Zoom := 1; MapView.Zoom := 1;
CbZoomToCursor.Checked := MapView.ZoomToCursor; CbZoomToCursor.Checked := MapView.ZoomToCursor;
@ -499,12 +524,38 @@ begin
InfoViewportHeight.Caption := ''; InfoViewportHeight.Caption := '';
GPSPointInfo.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; ReadFromIni;
end; end;
procedure TMainForm.FormDestroy(Sender: TObject); procedure TMainForm.FormDestroy(Sender: TObject);
var
I: Integer;
begin begin
WriteToIni; WriteToIni;
for I := 0 to High(TileLayer) do
MapView.GPSLayer[I].Delete(TileLayer[I]);
ClearFoundLocations; ClearFoundLocations;
FreeAndNil(POIImage) FreeAndNil(POIImage)
end; end;
@ -742,6 +793,7 @@ begin
MapView.Engine.ClearMapProviders; MapView.Engine.ClearMapProviders;
MapView.Engine.RegisterProviders; MapView.Engine.RegisterProviders;
MapView.GetMapProviders(CbProviders.Items); MapView.GetMapProviders(CbProviders.Items);
sgLayers.Columns[1].PickList.Assign(CbProviders.Items);
end; end;
R := Screen.DesktopRect; R := Screen.DesktopRect;
@ -829,6 +881,47 @@ begin
end; end;
end; end;
procedure TMainForm.sgLayersCheckboxToggled(sender: TObject; aCol,
aRow: Integer; aState: TCheckboxState);
begin
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;
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); procedure TMainForm.UpdateCoords(X, Y: Integer);
var var
rPt: TRealPoint; rPt: TRealPoint;

View File

@ -6,7 +6,7 @@ interface
uses uses
Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs,
ExtCtrls, StdCtrls, ComCtrls, Buttons, IntfGraphics, ColorBox, Spin, ExtCtrls, StdCtrls, ComCtrls, Buttons, IntfGraphics, ColorBox, Spin, Grids,
mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine, mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine,
mvDE_RGBGraphics, mvDE_BGRA, mvDLEFPC, mvDLEWin, mvDLESynapse; mvDE_RGBGraphics, mvDE_BGRA, mvDLEFPC, mvDLEWin, mvDLESynapse;
@ -16,6 +16,7 @@ type
TMainForm = class(TForm) TMainForm = class(TForm)
Bevel1: TBevel; Bevel1: TBevel;
Bevel2: TBevel;
BtnSearch: TButton; BtnSearch: TButton;
BtnGoTo: TButton; BtnGoTo: TButton;
BtnGPSPoints: TButton; BtnGPSPoints: TButton;
@ -27,6 +28,8 @@ type
CbFoundLocations: TComboBox; CbFoundLocations: TComboBox;
CbLocations: TComboBox; CbLocations: TComboBox;
CbProviders: TComboBox; CbProviders: TComboBox;
lblOpacity: TLabel;
rgDrawMode: TRadioGroup;
rbProxyData: TRadioButton; rbProxyData: TRadioButton;
rbSystemProxy: TRadioButton; rbSystemProxy: TRadioButton;
CbUseThreads: TCheckBox; CbUseThreads: TCheckBox;
@ -83,6 +86,9 @@ type
PgConfig: TTabSheet; PgConfig: TTabSheet;
rbNoProxy: TRadioButton; rbNoProxy: TRadioButton;
seProxyPort: TSpinEdit; seProxyPort: TSpinEdit;
pgLayers: TTabSheet;
sgLayers: TStringGrid;
tbOpacity: TTrackBar;
ZoomTrackBar: TTrackBar; ZoomTrackBar: TTrackBar;
procedure BtnGoToClick(Sender: TObject); procedure BtnGoToClick(Sender: TObject);
procedure BtnLoadGPXFileClick(Sender: TObject); procedure BtnLoadGPXFileClick(Sender: TObject);
@ -121,6 +127,13 @@ type
procedure BtnLoadMapProvidersClick(Sender: TObject); procedure BtnLoadMapProvidersClick(Sender: TObject);
procedure BtnSaveMapProvidersClick(Sender: TObject); procedure BtnSaveMapProvidersClick(Sender: TObject);
procedure rbProxyChange(Sender: TObject); procedure rbProxyChange(Sender: TObject);
procedure rgDrawModeSelectionChanged(Sender: TObject);
procedure sgLayersCheckboxToggled(Sender: TObject; aCol, aRow: Integer;
aState: TCheckboxState);
procedure sgLayersEditingDone(Sender: TObject);
procedure sgLayersSelection(Sender: TObject; aCol, aRow: Integer);
procedure tbOpacityChange(Sender: TObject);
procedure UpdateLayers;
procedure ZoomTrackBarChange(Sender: TObject); procedure ZoomTrackBarChange(Sender: TObject);
private private
@ -167,9 +180,11 @@ const
MAX_LOCATIONS_HISTORY = 50; MAX_LOCATIONS_HISTORY = 50;
MAP_PROVIDER_FILENAME = 'map-providers.xml'; MAP_PROVIDER_FILENAME = 'map-providers.xml';
USE_DMS = true; USE_DMS = true;
_TILELAYERS_ID_ = 42;
var var
PointFormatSettings: TFormatsettings; PointFormatSettings: TFormatsettings;
TileLayer: array[0..9] of TGPSTileLayer;
function CalcIniName: String; function CalcIniName: String;
@ -177,7 +192,6 @@ begin
Result := ChangeFileExt(Application.ExeName, '.ini'); Result := ChangeFileExt(Application.ExeName, '.ini');
end; end;
{ TMainForm } { TMainForm }
procedure TMainForm.BtnLoadMapProvidersClick(Sender: TObject); procedure TMainForm.BtnLoadMapProvidersClick(Sender: TObject);
@ -191,6 +205,7 @@ begin
MapView.GetMapProviders(CbProviders.Items); MapView.GetMapProviders(CbProviders.Items);
CbProviders.ItemIndex := 0; CbProviders.ItemIndex := 0;
MapView.MapProvider := CbProviders.Text; MapView.MapProvider := CbProviders.Text;
sgLayers.Columns[1].PickList.Assign(CbProviders.Items);
end else end else
ShowMessage(msg); ShowMessage(msg);
end; end;
@ -206,6 +221,53 @@ begin
UpdateDownloadEngineProxy; UpdateDownloadEngineProxy;
end; end;
procedure TMainForm.rgDrawModeSelectionChanged(Sender: TObject);
begin
TileLayer[Pred(sgLayers.Row)].DrawMode := TItemDrawMode(rgDrawMode.ItemIndex);
MapView.Redraw;
end;
procedure TMainForm.sgLayersCheckboxToggled(Sender: TObject; aCol,
aRow: Integer; aState: TCheckboxState);
begin
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;
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.BtnSearchClick(Sender: TObject); procedure TMainForm.BtnSearchClick(Sender: TObject);
begin begin
ClearFoundLocations; ClearFoundLocations;
@ -284,6 +346,7 @@ end;
procedure TMainForm.CbDebugTilesChange(Sender: TObject); procedure TMainForm.CbDebugTilesChange(Sender: TObject);
begin begin
MapView.DebugTiles := CbDebugTiles.Checked; MapView.DebugTiles := CbDebugTiles.Checked;
MapView.Invalidate;
end; end;
procedure TMainForm.CbDownloadEngineChange(Sender: TObject); procedure TMainForm.CbDownloadEngineChange(Sender: TObject);
@ -328,6 +391,7 @@ begin
MapView.DrawingEngine := FBGRADrawingEngine; MapView.DrawingEngine := FBGRADrawingEngine;
end; end;
end; end;
UpdateLayers;
end; end;
procedure TMainForm.CbDoubleBufferChange(Sender: TObject); procedure TMainForm.CbDoubleBufferChange(Sender: TObject);
@ -390,6 +454,7 @@ end;
procedure TMainForm.CbUseThreadsChange(Sender: TObject); procedure TMainForm.CbUseThreadsChange(Sender: TObject);
begin begin
MapView.UseThreads := CbUseThreads.Checked; MapView.UseThreads := CbUseThreads.Checked;
UpdateLayers;
end; end;
procedure TMainForm.CbDistanceUnitsChange(Sender: TObject); procedure TMainForm.CbDistanceUnitsChange(Sender: TObject);
@ -406,6 +471,7 @@ end;
procedure TMainForm.CbCyclicChange(Sender: TObject); procedure TMainForm.CbCyclicChange(Sender: TObject);
begin begin
MapView.Cyclic := CbCyclic.Checked; MapView.Cyclic := CbCyclic.Checked;
UpdateLayers;
end; end;
procedure TMainForm.clbBackColorColorChanged(Sender: TObject); procedure TMainForm.clbBackColorColorChanged(Sender: TObject);
@ -430,6 +496,7 @@ var
fn: String; fn: String;
homeDir: String; homeDir: String;
cacheDir: String; cacheDir: String;
I: Integer;
begin begin
cInputQueryEditSizePercents := 0; cInputQueryEditSizePercents := 0;
@ -454,6 +521,7 @@ begin
end; end;
MapView.CachePath := cacheDir; MapView.CachePath := cacheDir;
MapView.GetMapProviders(CbProviders.Items); MapView.GetMapProviders(CbProviders.Items);
sgLayers.Columns[1].PickList.Assign(CbProviders.Items);
CbProviders.ItemIndex := CbProviders.Items.IndexOf(MapView.MapProvider); CbProviders.ItemIndex := CbProviders.Items.IndexOf(MapView.MapProvider);
MapView.DoubleBuffered := true; MapView.DoubleBuffered := true;
MapView.Zoom := 1; MapView.Zoom := 1;
@ -471,10 +539,34 @@ begin
InfoViewportHeight.Caption := ''; InfoViewportHeight.Caption := '';
GPSPointInfo.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; ReadFromIni;
end; end;
procedure TMainForm.FormDestroy(Sender: TObject); procedure TMainForm.FormDestroy(Sender: TObject);
var
I: Integer;
begin begin
WriteToIni; WriteToIni;
ClearFoundLocations; ClearFoundLocations;
@ -629,6 +721,7 @@ begin
MapView.Engine.ClearMapProviders; MapView.Engine.ClearMapProviders;
MapView.Engine.RegisterProviders; MapView.Engine.RegisterProviders;
MapView.GetMapProviders(CbProviders.Items); MapView.GetMapProviders(CbProviders.Items);
sgLayers.Columns[1].PickList.Assign(CbProviders.Items);
end; end;
R := Screen.DesktopRect; R := Screen.DesktopRect;

View File

@ -69,7 +69,6 @@ type
procedure SetFontStyle(AValue: TFontStyles); override; procedure SetFontStyle(AValue: TFontStyles); override;
procedure SetPenColor(AValue: TColor); override; procedure SetPenColor(AValue: TColor); override;
procedure SetPenWidth(AValue: Integer); override; procedure SetPenWidth(AValue: Integer); override;
public public
destructor Destroy; override; destructor Destroy; override;
procedure CreateBuffer(AWidth, AHeight: Integer); override; procedure CreateBuffer(AWidth, AHeight: Integer); override;

View File

@ -36,6 +36,8 @@ type
TDrawStretchedTileEvent = procedure (const TileId: TTileId; X,Y: Integer; TDrawStretchedTileEvent = procedure (const TileId: TTileId; X,Y: Integer;
TileImg: TPictureCacheItem; const R: TRect) of object; TileImg: TPictureCacheItem; const R: TRect) of object;
TEraseBackgroundEvent = procedure (const R: TRect) of Object;
TTileDownloadedEvent = procedure (const TileId: TTileId) of object; TTileDownloadedEvent = procedure (const TileId: TTileId) of object;
TTileIdArray = Array of TTileId; TTileIdArray = Array of TTileId;
@ -74,6 +76,7 @@ type
FOnChange: TNotifyEvent; FOnChange: TNotifyEvent;
FOnDrawTile: TDrawTileEvent; FOnDrawTile: TDrawTileEvent;
FOnDrawStretchedTile: TDrawStretchedTileEvent; FOnDrawStretchedTile: TDrawStretchedTileEvent;
FOnEraseBackground: TEraseBackgroundEvent;
FOnTileDownloaded: TTileDownloadedEvent; FOnTileDownloaded: TTileDownloadedEvent;
FOnZoomChange: TNotifyEvent; FOnZoomChange: TNotifyEvent;
lstProvider : TStringList; lstProvider : TStringList;
@ -123,6 +126,7 @@ type
function GetTileName(const Id: TTileId): String; function GetTileName(const Id: TTileId): String;
procedure evDownload(Data: TObject; Job: TJob); procedure evDownload(Data: TObject; Job: TJob);
procedure TileDownloaded(Data: PtrInt); procedure TileDownloaded(Data: PtrInt);
procedure EraseBackground(const R: TRect);
procedure DrawTileFromCache(constref ATile: TTileId; constref AWin: TMapWindow); procedure DrawTileFromCache(constref ATile: TTileId; constref AWin: TMapWindow);
procedure DrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TPictureCacheItem; const R: TRect); procedure DrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TPictureCacheItem; const R: TRect);
Procedure DrawTile(const TileId: TTileId; X,Y: integer; TileImg: TPictureCacheItem); Procedure DrawTile(const TileId: TTileId; X,Y: integer; TileImg: TPictureCacheItem);
@ -194,6 +198,7 @@ type
property OnChange: TNotifyEvent Read FOnChange write FOnchange; //called when visiable area change property OnChange: TNotifyEvent Read FOnChange write FOnchange; //called when visiable area change
property OnDrawStretchedTile: TDrawStretchedTileEvent read FOnDrawStretchedTile write FOnDrawStretchedTile; property OnDrawStretchedTile: TDrawStretchedTileEvent read FOnDrawStretchedTile write FOnDrawStretchedTile;
property OnDrawTile: TDrawTileEvent read FOnDrawTile write FOnDrawTile; property OnDrawTile: TDrawTileEvent read FOnDrawTile write FOnDrawTile;
property OnEraseBackground: TEraseBackgroundEvent read FOnEraseBackground write FOnEraseBackground;
property OnTileDownloaded: TTileDownloadedEvent read FOnTileDownloaded write FOnTileDownloaded; property OnTileDownloaded: TTileDownloadedEvent read FOnTileDownloaded write FOnTileDownloaded;
property OnZoomChange: TNotifyEvent read FOnZoomChange write FOnZoomChange; property OnZoomChange: TNotifyEvent read FOnZoomChange write FOnZoomChange;
end; end;
@ -357,25 +362,25 @@ function TMapViewerEngine.CalculateVisibleTiles(const aWin: TMapWindow; out
Area: TArea): Boolean; Area: TArea): Boolean;
var var
MaxX, MaxY, startX, startY: int64; MaxX, MaxY, startX, startY: int64;
WorldSize: Int64; WorldMax: Int64;
begin begin
Area := Default(TArea); Area := Default(TArea);
Result := True; Result := (aWin.X <= 0) and (aWin.Y <= 0);
WorldSize := 1 shl AWin.Zoom; WorldMax := 1 shl AWin.Zoom - 1;
MaxX := Int64(aWin.Width) div TILE_SIZE + 1; MaxX := Int64(aWin.Width) div TILE_SIZE + 1;
MaxY := Int64(aWin.Height) div TILE_SIZE + 1; MaxY := Int64(aWin.Height) div TILE_SIZE + 1;
if (MaxX > WorldSize) or (MaxY > WorldSize) then if (MaxX > WorldMax) or (MaxY > WorldMax) then
begin begin
Result := False; Result := False;
MaxX := Min(WorldSize - 1, MaxX); MaxX := Min(WorldMax, MaxX);
MaxY := Min(WorldSize - 1, MaxY); MaxY := Min(WorldMax, MaxY);
end; end;
startX := -aWin.X div TILE_SIZE; startX := -aWin.X div TILE_SIZE;
startY := -aWin.Y div TILE_SIZE; startY := -aWin.Y div TILE_SIZE;
if (startX < 0) or (startY < 0) then if (startX < 0) or (startY < 0) then
begin begin
startX := Max(0, -aWin.X div TILE_SIZE); startX := Max(0, startX);
startY := Max(0, -aWin.Y div TILE_SIZE); startY := Max(0, startY);
Result := False; Result := False;
end; end;
Area.Left := startX; Area.Left := startX;
@ -1025,13 +1030,27 @@ var
end; end;
end; end;
procedure EraseBackground; procedure EraseAround;
var var
I, J: Integer; T, L, B, R: Integer;
begin begin
for J := 0 to (AWin.Height div TILE_SIZE) + 1 do T := -AWin.Y div TILE_SIZE - Max(0, Sign(AWin.Y));
for I := 0 to (AWin.Width div TILE_SIZE) + 1 do B := T + AWin.Height div TILE_SIZE + 1;
DrawTile(tile, I * TILE_SIZE, J * TILE_SIZE, Nil); L := -AWin.X div TILE_SIZE - Max(0, Sign(AWin.X));
R := L + AWin.Width div TILE_SIZE + 1;
if T < TilesVis.top then // Erase above top
EraseBackground(Rect(0, 0, AWin.Width, AWin.Y + TilesVis.top * TILE_SIZE));
if L < TilesVis.left then // Erase on the left
EraseBackground(Rect(0, AWin.Y + TilesVis.top * TILE_SIZE,
AWin.X + TilesVis.left * TILE_SIZE,
AWin.Y + (TilesVis.bottom + 1) * TILE_SIZE));
if R > TilesVis.right then // Erase on the right
EraseBackground(Rect(AWin.X + (TilesVis.right + 1) * TILE_SIZE,
AWin.Y + TilesVis.top * TILE_SIZE, AWin.Width,
AWin.Y + (TilesVis.bottom + 1) * TILE_SIZE));
if B > TilesVis.bottom then // Erase below
EraseBackground(Rect(0, AWin.Y + (TilesVis.bottom + 1) * TILE_SIZE,
AWin.Width, AWin.Height));
end; end;
begin begin
@ -1039,7 +1058,7 @@ begin
Exit; Exit;
if not CalculateVisibleTiles(AWin, TilesVis) then if not CalculateVisibleTiles(AWin, TilesVis) then
EraseBackground; EraseAround;
SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1)); SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1));
iTile := Low(Tiles); iTile := Low(Tiles);
numTiles := 1 shl AWin.Zoom; numTiles := 1 shl AWin.Zoom;
@ -1273,6 +1292,12 @@ begin
end; end;
end; end;
procedure TMapViewerEngine.EraseBackground(const R: TRect);
begin
if Assigned(FOnEraseBackground) then
FOnEraseBackground(R);
end;
procedure TMapViewerEngine.DrawTileFromCache(constref ATile: TTileId; constref procedure TMapViewerEngine.DrawTileFromCache(constref ATile: TTileId; constref
AWin: TMapWindow); AWin: TMapWindow);
var var

View File

@ -111,6 +111,7 @@ Type
procedure DoDrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TPictureCacheItem; const R: TRect); procedure DoDrawStretchedTile(const TileId: TTileID; X, Y: Integer; TileImg: TPictureCacheItem; const R: TRect);
procedure DoDrawTile(const TileId: TTileId; X,Y: integer; TileImg: TPictureCacheItem); procedure DoDrawTile(const TileId: TTileId; X,Y: integer; TileImg: TPictureCacheItem);
procedure DoDrawTileInfo(const {%H-}TileID: TTileID; X,Y: Integer); procedure DoDrawTileInfo(const {%H-}TileID: TTileID; X,Y: Integer);
procedure DoEraseBackground(const R: TRect);
procedure DoTileDownloaded(const TileId: TTileId); procedure DoTileDownloaded(const TileId: TTileId);
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
MousePos: TPoint): Boolean; override; MousePos: TPoint): Boolean; override;
@ -713,20 +714,35 @@ begin
end; end;
procedure TMapView.Paint; procedure TMapView.Paint;
begin
inherited Paint; procedure Inactive;
if IsActive then
begin
Engine.Redraw;
DrawObjects(Default(TTileId), 0, 0, Canvas.Width, Canvas.Height);
DrawingEngine.PaintToCanvas(Canvas);
end
else
begin begin
Canvas.Brush.Color := InactiveColor; Canvas.Brush.Color := InactiveColor;
Canvas.Brush.Style := bsSolid; Canvas.Brush.Style := bsSolid;
Canvas.FillRect(0, 0, ClientWidth, ClientHeight); Canvas.FillRect(0, 0, ClientWidth, ClientHeight);
end; end;
procedure Redrw;
begin
Engine.Redraw;
DrawObjects(Default(TTileId), 0, 0, Canvas.Width, Canvas.Height);
DrawingEngine.PaintToCanvas(Canvas);
end;
procedure Drag;
begin
// Placeholder for dragging visuals
Redrw;
end;
begin
inherited Paint;
if IsActive
then if Engine.InDrag
then Drag
else Redrw
else
Inactive;
end; end;
procedure TMapView.OnGPSItemsModified(Sender: TObject; objs: TGPSObjList; procedure TMapView.OnGPSItemsModified(Sender: TObject; objs: TGPSObjList;
@ -1010,6 +1026,11 @@ begin
DrawingEngine.Line(X, Y + TILE_SIZE, X + TILE_SIZE, Y + TILE_SIZE); DrawingEngine.Line(X, Y + TILE_SIZE, X + TILE_SIZE, Y + TILE_SIZE);
end; end;
procedure TMapView.DoEraseBackground(const R: TRect);
begin
DrawingEngine.FillPixels(R.Left, R.Top, R.Right, R.Bottom, InactiveColor);
end;
procedure TMapView.DoTileDownloaded(const TileId: TTileId); procedure TMapView.DoTileDownloaded(const TileId: TTileId);
begin begin
// TODO: Include tile information to optimize redraw. // TODO: Include tile information to optimize redraw.
@ -1055,6 +1076,7 @@ begin
FEngine.CacheOnDisk := true; FEngine.CacheOnDisk := true;
FEngine.OnDrawTile := @DoDrawTile; FEngine.OnDrawTile := @DoDrawTile;
FEngine.OnDrawStretchedTile := @DoDrawStretchedTile; FEngine.OnDrawStretchedTile := @DoDrawStretchedTile;
FEngine.OnEraseBackground := @DoEraseBackground;
FEngine.OnTileDownloaded := @DoTileDownloaded; FEngine.OnTileDownloaded := @DoTileDownloaded;
FEngine.DrawPreviewTiles := True; FEngine.DrawPreviewTiles := True;
FEngine.DrawTitleInGuiThread := false; FEngine.DrawTitleInGuiThread := false;