Sign in Join
Wiki copytemporary

LazMapViewer-Plugins: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: LazMapViewer-Plugins

OldNewLine
1+## About
2+
3+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|LazMapViewer#Plugins]].
4+
5+## TMvPluginManager
6+
7+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.
8+
9+In the MapView properties you simply select the new PluginManager in the corresponding field.
10+
11+Caution: Without assigning the PluginManager to the corresponding field of a MapView, the plugins are not called for this MapView!
12+
13+The PluginManager does not need too much attention. You simply add the Plugins and go.
14+
15+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.
16+
17+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.
18+```
19+TMvPluginManager = class(TMvCustomPluginManager)
20+ ...
21+ property Item[AIndex: Integer]: TMvCustomPlugin read GetItem; default;
22+ property MapList: TFPList read FMapList;
23+ published
24+ property PluginList: TMvPluginList read FPluginList;
25+ end;
26+```
27+
28+ * The indexed property `Item` allow the access to each Plugin stored in the PluginManager. Due to the wide range of derived plugins, it is a good idea, to access the plugins properties by a local reference instead via this property.
29+ * The property `MapList` allows the access to all MapViews who are attached to this PluginManager. The list is automatically updated when the field PluginManager of the MapView is altered.
30+ * The property `PluginList` allows a different access to the Plugins of this PluginManager.
31+
32+## TMvCustomPlugin
33+
34+The class `TMvCustomPlugin` is the root class of all plugins. The major definitions are:
35+```
36+TMvIndexedComponent = class(TComponent)
37+ ...
38+ public
39+ ...
40+ property Index: Integer read GetIndex write SetIndex;
41+ end;
42+
43+ TMvCustomPlugin = class(TMvIndexedComponent)
44+ ...
45+ protected
46+ procedure AfterDrawObjects(AMapView: TMapView; var Handled: Boolean); virtual;
47+ procedure AfterPaint(AMapView: TMapView; var Handled: Boolean); virtual;
48+ procedure BeforeDrawObjects(AMapView: TMapView; var Handled: Boolean); virtual;
49+ procedure CenterMove(AMapView: TMapView; var Handled: Boolean); virtual;
50+ procedure CenterMoving(AMapView: TMapView; var NewCenter: TRealPoint;
51+ var Allow, Handled: Boolean); virtual;
52+ procedure DrawGPSPoint(AMapView: TMapView; ADrawingEngine: TMvCustomDrawingEngine;
53+ APoint: TGPSPoint; var Handled: Boolean); virtual;
54+ procedure DrawMissingTile(AMapView: TMapView; ADrawingEngine: TMvCustomDrawingEngine;
55+ ATileID: TTileID; ARect: TRect; var Handled: Boolean); virtual;
56+ procedure GPSItemsModified(AMapView: TMapView; ModifiedList: TGPSObjectList;
57+ ActualObjs: TGPSObjList; Adding: Boolean; var Handled: Boolean); virtual;
58+ procedure MouseDown(AMapView: TMapView; Button: TMouseButton; Shift: TShiftState;
59+ X, Y: Integer; var Handled: Boolean); virtual;
60+ procedure MouseEnter(AMapView: TMapView; var Handled: Boolean); virtual;
61+ procedure MouseLeave(AMapView: TMapView; var Handled: Boolean); virtual;
62+ procedure MouseMove(AMapView: TMapView; AShift: TShiftState; X,Y: Integer;
63+ var Handled: Boolean); virtual;
64+ procedure MouseUp(AMapView: TMapView; Button: TMouseButton; Shift: TShiftState;
65+ X,Y: Integer; var Handled: Boolean); virtual;
66+ procedure MouseWheel(AMapView: TMapView; AShift: TShiftState;
67+ AWheelDelta: Integer; AMousePos: TPoint; var Handled: Boolean); virtual;
68+ procedure ZoomChange(AMapView: TMapView; var Handled: Boolean); virtual;
69+ procedure ZoomChanging(AMapView: TMapView; NewZoom: Integer; var Allow, Handled: Boolean); virtual;
70+ protected
71+ property MapView: TMapView read FMapView write SetMapView;
72+ property Enabled: Boolean read FEnabled write SetEnabled default true;
73+ public
74+ property PluginManager: TMvPluginManager read FPluginManager write SetPluginManager;
75+ ...
76+ end;
77+```
78+
79+ * The property `PluginManager` links the Plugin to a PluginManager and must be set to allow the operation. To reorder the plugin within the PluginManager simply use the `Index` property of the derived class. Plugins will be called in order of their index.
80+ * The property `MapView` limit the operation of this plugin to the assigned MapView. If not assigned, the PluginManager will call this plugin for all attached MapViews. While some Plugins can work on multiple MapViews, others can't. See in the documentation for the actual plugin, whether it is mandatory to assign a MapView or not.
81+ * The property `Enabled` allows the operation. Set to false will temporary disable the plugin.
82+
83+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.
84+
85+All Methods have two common parameters `AMapView` and `Handled`.
86+
87+ * The parameter `AMapView` contains the MapView which is operated on. If the property `MapView` is assigned, then the parameter will be always identical to the property and could be ignored. If the property `MapView` is not assigned, then the parameter has be used to interact with the current MapView. It's up to the plugin to deal with the different settings of the MapView to avoid unwanted behavior.
88+ * The var parameter `Handled` informs the plugin whether prior called plugins have already consumed the call. This parameter allows plugins to interact save. For example, if the user press the mouse button and one of the plugins identify that the location of the mouse fits to its use, it will set the Handled parameter to inform the subsequently called plugins, to keep the hands of this MouseEvent.
89+
90+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.
91+
92+The methods are grouped into three main groups: Mouse interaction, Drawing and changes within the MapView.
93+
94+ * The procedure AfterDrawObjects is called when the MapViewer has painted the map and all objects, stored in the Layer property. At this time it is possible to access the DrawingEngine and paint something on top of the current view. Since using the [[DrawingEngnise|MapViewer#The_Drawing_Engine]] allows to alter the displayed map (instead of the screen display), those changes could be seen on images which are saved to file.
95+ * The procedure AfterPaint is called if the painting of the MapViewer is finished. Access to the DrawingEngine will not change the display. Instead it is possible to draw direct to the Canvas of the MapViewer. This allows to display temporary elements (e.g. Selectors, Arrows, UI-Items, etc.) which should be not saved to a file.
96+ * The procedure BeforeDrawObjects is called just before the objects of the Layers are painted. This point allows various change of the objects, including the complete rebuilding of the content. A different usage is the painting to the map prior the objects.
97+ * The procedure CenterMove is called to inform the plugin that the center of the map is moved
98+ * The procedure CenterMoving is called when the user is about to move the center. The plugin may alter the parameter `NewCenter` or set the parameter `Allow` to false to omit the change.
99+ * The procedure DrawGPSPoint allows the drawing of the given `APoint`. The parameter `Handled` should be set if the drawing happened to omit the further drawing of the MapView or the call to the OnDrawGPSPoint-Event. If `Handled` remains false, the MapView will perform the paint of the object.
100+ * The procedure DrawMissingTile is called if a needed map tile is not available. The Plugin may fill the area given in the parameter `ARect` as desired. The parameter `ATileID` informs about the coords of the tile. If the parameter `Handled` remains false, the MapView will continue with the default processing.
101+ * The procedure GPSItemsModified informs the plugin, that the content of the parameter `ModifiedList` might have changed. If some items has been added the parameter `Adding` is `true` and if the parameter `ActualObjs` is assigned, then ActualObjs contains the added items. If the parameter `Adding` is `false` and the parameter `ActualObjs` is assigned, than ActualObjs contains the removed items. If `ActualObjs` is not assigned than the change of the list is unknown due to a encapsulated BeginUpdate..EndUpdate. If the parameter `ModifiedList` is not assigned, than all local references of items to this MapView should be removed.
102+ * The procedure MouseDown is called if the user pressed one of the mouse buttons.
103+ * The procedure MouseEnter is called if the mouse pointer enters the MapView.
104+ * The procedure MouseLeave is called if the mouse pointer leaves the MapView.
105+ * procedure MouseMove is called if the mouse pointer changed it's position.
106+ * procedure MouseUp is called if the user released one of the mouse buttons.
107+ * procedure MouseWheel is called if the mouse wheel changed.
108+ * procedure ZoomChange is called to inform the Plugin that the Zoom-factor of the Map changed.
109+ * procedure ZoomChanging is called if the Zoom-factor of the map is about to change. The plugin may deny the change by setting the paramete `Allow` to `false`
110+
111+## Example of a Plugin
112+
113+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.
114+```
115+unit uMeasureDistPlugin;
116+
117+ {$mode ObjFPC}{$H+}
118+
119+ interface
120+
121+ uses
122+ Classes, SysUtils, Controls, Graphics,
123+ mvMapViewer, mvTypes, mvGeoMath, mvPluginCore;
124+
125+ type
126+
127+ { TMeasureDistPlugin }
128+
129+ TMeasureDistPlugin = class(TMvPlugin)
130+ private
131+ FMeasureActive : Boolean;
132+ FAnchorCoord : TRealPoint;
133+ FCurrentCoord : TRealPoint;
134+ FDistance : Double;
135+ protected
136+ procedure AfterPaint(AMapView: TMapView; var Handled: Boolean); override;
137+ procedure MouseMove(AMapView: TMapView; AShift: TShiftState; X,Y: Integer;
138+ var Handled: Boolean); override;
139+ procedure MouseUp(AMapView: TMapView; Button: TMouseButton; Shift: TShiftState;
140+ X,Y: Integer; var Handled: Boolean); override;
141+ public
142+ end;
143+ implementation
144+
145+ { TMeasureDistPlugin }
146+
147+ procedure TMeasureDistPlugin.AfterPaint(AMapView: TMapView; var Handled: Boolean);
148+ var
149+ ptAnchorScreen, ptCurrentScreen : TPoint;
150+ s : String;
151+ r : Integer;
152+ begin
153+ if FMeasureActive then
154+ begin
155+ MapView.Canvas.Pen.Style:= psSolid;
156+ MapView.Canvas.Pen.Width:= 3;
157+ ptAnchorScreen := MapView.LatLonToScreen(FAnchorCoord);
158+ ptCurrentScreen := MapView.LatLonToScreen(FCurrentCoord);
159+ r := 3;
160+ MapView.Canvas.Pen.Color:= clLime;
161+ MapView.Canvas.Ellipse(ptAnchorScreen.X-r,ptAnchorScreen.Y-r,
162+ ptAnchorScreen.X+r,ptAnchorScreen.Y+r);
163+ MapView.Canvas.Pen.Color:= clRed;
164+ MapView.Canvas.Ellipse(ptCurrentScreen.X-r,ptCurrentScreen.Y-r,
165+ ptCurrentScreen.X+r,ptCurrentScreen.Y+r);
166+
167+ s := Format('%1.1f Km',[FDistance]);
168+ MapView.Canvas.TextOut(ptCurrentScreen.X+10, ptCurrentScreen.Y+10, s);
169+ end;
170+ end;
171+
172+ procedure TMeasureDistPlugin.MouseMove(AMapView: TMapView; AShift: TShiftState;
173+ X, Y: Integer; var Handled: Boolean);
174+ begin
175+ if FMeasureActive then
176+ begin
177+ FCurrentCoord := MapView.ScreenToLatLon(Point(X,Y));
178+ if (FCurrentCoord.Lat = FAnchorCoord.Lat) and
179+ (FCurrentCoord.Lon = FAnchorCoord.Lon) then
180+ FDistance := 0.0
181+ else
182+ FDistance := CalcGeoDistance(FAnchorCoord.Lat,FAnchorCoord.Lon,
183+ FCurrentCoord.Lat, FCurrentCoord.Lon,
184+ duKilometers, esEllipsoid);
185+ MapView.Invalidate;
186+ end;
187+ end;
188+
189+ procedure TMeasureDistPlugin.MouseUp(AMapView: TMapView; Button: TMouseButton;
190+ Shift: TShiftState; X, Y: Integer; var Handled: Boolean);
191+ begin
192+ if Button <> mbRight then Exit;
193+ FMeasureActive := not FMeasureActive;
194+ if FMeasureActive then
195+ begin
196+ FAnchorCoord := MapView.ScreenToLatLon(Point(X,Y));
197+ FCurrentCoord := FAnchorCoord;
198+ end;
199+ if not FMeasureActive then
200+ MapView.Invalidate; // This will remove the two circles and the text
201+ end;
202+
203+ end.
204+```
205+
206+
207+In the main form add a TMapView and a PluginManager. Add the PluginManager in the MapView. setup the MapProvider and activate the MapView.
208+
209+In the FormCreate-event add the following code
210+```
211+procedure TForm1.FormCreate(Sender: TObject);
212+ var
213+ lMeasureDistPlugin : TMeasureDistPlugin;
214+ begin
215+ lMeasureDistPlugin := TMeasureDistPlugin.Create(Self);
216+ lMeasureDistPlugin.MapView := MapView1;
217+ MvPluginManager1.PluginList.Add(lMeasureDistPlugin);
218+ end;
219+```
220+
221+---
222+*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](/wiki-contact).*

Back to history