Sign in Join
Wiki copytemporary

LazMapViewer-Plugins

About

Plugins are an easy way to extent the functionality of the MapViewer, without the need to change the source of the component itself. Together with the PluginManager, who is the glue between the MapView and the plugins, and the RAD-method of connecting existing parts within the IDE, the system becomes a powerful and user friendly tool. For a simplified explanation see LazMapViewer#Plugins.

TMvPluginManager

To use Plugins within a MapView, you have to create an instance of a TMvPluginManager and attach the MapView instance to the PluginManager. The easiest way to do so, is to drop the PluginManager within the IDE from the components-bar on the Form where your MapView resides.

In the MapView properties you simply select the new PluginManager in the corresponding field.

Caution: Without assigning the PluginManager to the corresponding field of a MapView, the plugins are not called for this MapView!

The PluginManager does not need too much attention. You simply add the Plugins and go.

If you want to use one of the predefined and installed Plugins, you can double click to the PluginManager on the form and add, delete or reorder the plugins. For other plugins you have to create the instances during runtime and add them manually.

The PluginManager is able to serve more than one MapView. This allows to use the same Plugins on more than one MapView. While some of the Plugins support this kind of operation others does not. Having well configured Plugins, the PluginManager can deal with such situations.

pascal
TMvPluginManager = class(TMvCustomPluginManager)
        ...
        property Item[AIndex: Integer]: TMvCustomPlugin read GetItem; default;
        property MapList: TFPList read FMapList;
      published
        property PluginList: TMvPluginList read FPluginList;
      end;

TMvCustomPlugin

The class TMvCustomPlugin is the root class of all plugins. The major definitions are:

pascal
TMvIndexedComponent = class(TComponent)
      ...
      public
      ...
        property Index: Integer read GetIndex write SetIndex;
      end;
    
      TMvCustomPlugin = class(TMvIndexedComponent)
      ...
      protected
        procedure AfterDrawObjects(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure AfterPaint(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure BeforeDrawObjects(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure CenterMove(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure CenterMoving(AMapView: TMapView; var NewCenter: TRealPoint;
          var Allow, Handled: Boolean); virtual;
        procedure DrawGPSPoint(AMapView: TMapView; ADrawingEngine: TMvCustomDrawingEngine;
          APoint: TGPSPoint; var Handled: Boolean); virtual;
        procedure DrawMissingTile(AMapView: TMapView; ADrawingEngine: TMvCustomDrawingEngine;
          ATileID: TTileID; ARect: TRect; var Handled: Boolean); virtual;
        procedure GPSItemsModified(AMapView: TMapView; ModifiedList: TGPSObjectList;
          ActualObjs: TGPSObjList; Adding: Boolean; var Handled: Boolean); virtual;
        procedure MouseDown(AMapView: TMapView; Button: TMouseButton; Shift: TShiftState;
          X, Y: Integer; var Handled: Boolean); virtual;
        procedure MouseEnter(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure MouseLeave(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure MouseMove(AMapView: TMapView; AShift: TShiftState; X,Y: Integer;
          var Handled: Boolean); virtual;
        procedure MouseUp(AMapView: TMapView; Button: TMouseButton; Shift: TShiftState;
          X,Y: Integer; var Handled: Boolean); virtual;
        procedure MouseWheel(AMapView: TMapView; AShift: TShiftState;
          AWheelDelta: Integer; AMousePos: TPoint; var Handled: Boolean); virtual;
        procedure ZoomChange(AMapView: TMapView; var Handled: Boolean); virtual;
        procedure ZoomChanging(AMapView: TMapView; NewZoom: Integer; var Allow, Handled: Boolean); virtual;
      protected
        property MapView: TMapView read FMapView write SetMapView;
        property Enabled: Boolean read FEnabled write SetEnabled default true;
      public
        property PluginManager: TMvPluginManager read FPluginManager write SetPluginManager;
      ...
      end;

To create an actual plugin, some of the predefined protected and virtual methods have to be overwritten an filled with the code. The following section will describe what to expect within the different methods.

All Methods have two common parameters AMapView and Handled.

You may imagine two plugins. The first one operates with markers, the second one displays a clickable link. If the marker is located in front of the link and the user hover the mouse above, then only the first one should alter the mouse pointer according to the possible action and not the second one.

The methods are grouped into three main groups: Mouse interaction, Drawing and changes within the MapView.

Example of a Plugin

The following example implements a plugin, to measure distances on the map. The user can click into the map to set an anchor and then on the mouse move the actual distance between the anchor and the mouse position is calculated. The plugin can only operate on a single MapView.

pascal
unit uMeasureDistPlugin;
    
    {$mode ObjFPC}{$H+}
    
    interface
    
    uses
      Classes, SysUtils, Controls, Graphics,
      mvMapViewer, mvTypes, mvGeoMath, mvPluginCore;
    
    type
    
      { TMeasureDistPlugin }
    
      TMeasureDistPlugin = class(TMvPlugin)
      private
        FMeasureActive : Boolean;
        FAnchorCoord : TRealPoint;
        FCurrentCoord : TRealPoint;
        FDistance : Double;
      protected
        procedure AfterPaint(AMapView: TMapView; var Handled: Boolean); override;
        procedure MouseMove(AMapView: TMapView; AShift: TShiftState; X,Y: Integer;
              var Handled: Boolean); override;
        procedure MouseUp(AMapView: TMapView; Button: TMouseButton; Shift: TShiftState;
              X,Y: Integer; var Handled: Boolean); override;
      public
      end;
    implementation
    
    { TMeasureDistPlugin }
    
    procedure TMeasureDistPlugin.AfterPaint(AMapView: TMapView; var Handled: Boolean);
    var
      ptAnchorScreen, ptCurrentScreen : TPoint;
      s : String;
      r : Integer;
    begin
      if FMeasureActive then
      begin
        MapView.Canvas.Pen.Style:= psSolid;
        MapView.Canvas.Pen.Width:= 3;
        ptAnchorScreen := MapView.LatLonToScreen(FAnchorCoord);
        ptCurrentScreen := MapView.LatLonToScreen(FCurrentCoord);
        r := 3;
        MapView.Canvas.Pen.Color:= clLime;
        MapView.Canvas.Ellipse(ptAnchorScreen.X-r,ptAnchorScreen.Y-r,
                                ptAnchorScreen.X+r,ptAnchorScreen.Y+r);
        MapView.Canvas.Pen.Color:= clRed;
        MapView.Canvas.Ellipse(ptCurrentScreen.X-r,ptCurrentScreen.Y-r,
                                ptCurrentScreen.X+r,ptCurrentScreen.Y+r);
    
        s := Format('%1.1f Km',[FDistance]);
        MapView.Canvas.TextOut(ptCurrentScreen.X+10, ptCurrentScreen.Y+10, s);
      end;
    end;
    
    procedure TMeasureDistPlugin.MouseMove(AMapView: TMapView; AShift: TShiftState;
      X, Y: Integer; var Handled: Boolean);
    begin
      if FMeasureActive then
      begin
        FCurrentCoord := MapView.ScreenToLatLon(Point(X,Y));
        if (FCurrentCoord.Lat = FAnchorCoord.Lat) and
           (FCurrentCoord.Lon = FAnchorCoord.Lon) then
          FDistance := 0.0
        else
          FDistance := CalcGeoDistance(FAnchorCoord.Lat,FAnchorCoord.Lon,
                                       FCurrentCoord.Lat, FCurrentCoord.Lon,
                                       duKilometers, esEllipsoid);
        MapView.Invalidate;
      end;
    end;
    
    procedure TMeasureDistPlugin.MouseUp(AMapView: TMapView; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; var Handled: Boolean);
    begin
      if Button <> mbRight then Exit;
      FMeasureActive := not FMeasureActive;
      if FMeasureActive then
      begin
        FAnchorCoord := MapView.ScreenToLatLon(Point(X,Y));
        FCurrentCoord := FAnchorCoord;
      end;
      if not FMeasureActive then
        MapView.Invalidate; // This will remove the two circles and the text
    end;
    
    end.

In the main form add a TMapView and a PluginManager. Add the PluginManager in the MapView. setup the MapProvider and activate the MapView.

In the FormCreate-event add the following code

pascal
procedure TForm1.FormCreate(Sender: TObject);
    var
      lMeasureDistPlugin : TMeasureDistPlugin;
    begin
      lMeasureDistPlugin := TMeasureDistPlugin.Create(Self);
      lMeasureDistPlugin.MapView := MapView1;
      MvPluginManager1.PluginList.Add(lMeasureDistPlugin);
    end;

From the Free Pascal wiki, page "LazMapViewer-Plugins", as the Internet Archive kept it on 2025-05-15, last changed on 2025-01-04. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.