From f830900825405d30ae00000e282539e17f0fccab Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Tue, 12 Nov 2019 17:46:50 +0000 Subject: [PATCH] lazmapviewer: Duplicate example project to demonstrate usage without external drawing engines. Cache folder is shared between both demos. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7185 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../lazmapviewer/example/MapViewer_Demo.lpi | 12 +- components/lazmapviewer/example/main.lfm | 92 +- components/lazmapviewer/example/main.pas | 31 +- .../example_with_addons/MapViewer_Demo.lpi | 106 +++ .../example_with_addons/MapViewer_Demo.lpr | 21 + .../example_with_addons/globals.pas | 19 + .../example_with_addons/gpslistform.lfm | 259 ++++++ .../example_with_addons/gpslistform.pas | 279 ++++++ .../lazmapviewer/example_with_addons/main.lfm | 847 ++++++++++++++++++ .../lazmapviewer/example_with_addons/main.pas | 704 +++++++++++++++ .../example_with_addons/mapmarker.png | Bin 0 -> 3920 bytes 11 files changed, 2269 insertions(+), 101 deletions(-) create mode 100644 components/lazmapviewer/example_with_addons/MapViewer_Demo.lpi create mode 100644 components/lazmapviewer/example_with_addons/MapViewer_Demo.lpr create mode 100644 components/lazmapviewer/example_with_addons/globals.pas create mode 100644 components/lazmapviewer/example_with_addons/gpslistform.lfm create mode 100644 components/lazmapviewer/example_with_addons/gpslistform.pas create mode 100644 components/lazmapviewer/example_with_addons/main.lfm create mode 100644 components/lazmapviewer/example_with_addons/main.pas create mode 100644 components/lazmapviewer/example_with_addons/mapmarker.png diff --git a/components/lazmapviewer/example/MapViewer_Demo.lpi b/components/lazmapviewer/example/MapViewer_Demo.lpi index df03d1c59..e91860a98 100644 --- a/components/lazmapviewer/example/MapViewer_Demo.lpi +++ b/components/lazmapviewer/example/MapViewer_Demo.lpi @@ -26,19 +26,13 @@ - + - + - - - - - - - + diff --git a/components/lazmapviewer/example/main.lfm b/components/lazmapviewer/example/main.lfm index d148e2857..3ef9ba3ca 100644 --- a/components/lazmapviewer/example/main.lfm +++ b/components/lazmapviewer/example/main.lfm @@ -3,7 +3,7 @@ object MainForm: TMainForm Height = 640 Top = 183 Width = 883 - Caption = 'MainForm' + Caption = 'LazMapViewer' ClientHeight = 640 ClientWidth = 883 OnCreate = FormCreate @@ -18,6 +18,7 @@ object MainForm: TMainForm Top = 0 Width = 608 Align = alClient + CachePath = '../../../../example_cache/' DefaultTrackColor = clBlue DefaultTrackWidth = 3 DownloadEngine = MapView.BuiltInDLE @@ -539,50 +540,12 @@ object MainForm: TMainForm Caption = 'Config' ClientHeight = 612 ClientWidth = 267 - object Label1: TLabel - AnchorSideLeft.Control = CbDrawingEngine + object LblProviders: TLabel + AnchorSideLeft.Control = CbProviders AnchorSideTop.Control = PgConfig Left = 6 Height = 15 - Top = 6 - Width = 86 - BorderSpacing.Top = 6 - Caption = 'Drawing engine:' - ParentColor = False - end - object CbDrawingEngine: TComboBox - AnchorSideLeft.Control = PgConfig - AnchorSideTop.Control = Label1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = PgConfig - AnchorSideRight.Side = asrBottom - Left = 6 - Height = 23 - Top = 23 - Width = 255 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Top = 2 - BorderSpacing.Right = 6 - ItemHeight = 15 - ItemIndex = 0 - Items.Strings = ( - 'default' - 'RGBGraphics' - 'BGRABitmap' - ) - OnChange = CbDrawingEngineChange - Style = csDropDownList - TabOrder = 0 - Text = 'default' - end - object LblProviders: TLabel - AnchorSideLeft.Control = CbProviders - AnchorSideTop.Control = CbDrawingEngine - AnchorSideTop.Side = asrBottom - Left = 6 - Height = 15 - Top = 54 + Top = 8 Width = 52 BorderSpacing.Top = 8 Caption = 'Providers:' @@ -596,7 +559,7 @@ object MainForm: TMainForm AnchorSideRight.Control = BtnLoadMapProviders Left = 6 Height = 23 - Top = 71 + Top = 25 Width = 199 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 6 @@ -606,7 +569,7 @@ object MainForm: TMainForm ItemHeight = 15 OnChange = CbProvidersChange Style = csDropDownList - TabOrder = 1 + TabOrder = 0 end object BtnLoadMapProviders: TSpeedButton AnchorSideLeft.Side = asrBottom @@ -615,7 +578,7 @@ object MainForm: TMainForm AnchorSideRight.Control = BtnSaveMapProviders Left = 209 Height = 22 - Top = 71 + Top = 25 Width = 23 Anchors = [akTop, akRight] BorderSpacing.Right = 4 @@ -666,7 +629,7 @@ object MainForm: TMainForm AnchorSideRight.Side = asrBottom Left = 236 Height = 22 - Top = 71 + Top = 25 Width = 23 Anchors = [akTop, akRight] BorderSpacing.Right = 8 @@ -714,7 +677,7 @@ object MainForm: TMainForm AnchorSideTop.Side = asrBottom Left = 6 Height = 19 - Top = 102 + Top = 56 Width = 81 BorderSpacing.Left = 6 BorderSpacing.Top = 8 @@ -722,7 +685,7 @@ object MainForm: TMainForm Checked = True OnChange = CbUseThreadsChange State = cbChecked - TabOrder = 2 + TabOrder = 1 end object CbDoubleBuffer: TCheckBox AnchorSideLeft.Control = CbUseThreads @@ -730,7 +693,7 @@ object MainForm: TMainForm AnchorSideTop.Side = asrBottom Left = 6 Height = 19 - Top = 127 + Top = 81 Width = 87 BorderSpacing.Top = 6 BorderSpacing.Right = 9 @@ -738,7 +701,7 @@ object MainForm: TMainForm Checked = True OnChange = CbDoubleBufferChange State = cbChecked - TabOrder = 3 + TabOrder = 2 end object CbDebugTiles: TCheckBox AnchorSideLeft.Control = CbDoubleBuffer @@ -746,12 +709,12 @@ object MainForm: TMainForm AnchorSideTop.Side = asrBottom Left = 6 Height = 19 - Top = 152 + Top = 106 Width = 79 BorderSpacing.Top = 6 Caption = 'Debug tiles' OnChange = CbDebugTilesChange - TabOrder = 4 + TabOrder = 3 end object CbShowPOIImage: TCheckBox AnchorSideLeft.Control = CbDebugTiles @@ -759,36 +722,36 @@ object MainForm: TMainForm AnchorSideTop.Side = asrBottom Left = 6 Height = 19 - Top = 189 + Top = 143 Width = 107 BorderSpacing.Top = 6 Caption = 'Show POI image' OnChange = CbShowPOIImageChange - TabOrder = 5 + TabOrder = 4 end object BtnPOITextFont: TButton + AnchorSideLeft.Control = CbShowPOIImage AnchorSideTop.Control = CbShowPOIImage AnchorSideTop.Side = asrBottom Left = 6 Height = 25 - Top = 216 + Top = 170 Width = 93 AutoSize = True BorderSpacing.Top = 8 Caption = 'POI text font' OnClick = BtnPOITextFontClick - TabOrder = 6 + TabOrder = 5 end object cbPOITextBgColor: TColorBox AnchorSideLeft.Control = LblPOITextBgColor AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = BtnPOITextFont AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = CbDrawingEngine AnchorSideRight.Side = asrBottom Left = 154 Height = 22 - Top = 217 + Top = 171 Width = 107 NoneColorColor = clWhite Style = [cbStandardColors, cbExtendedColors, cbIncludeNone, cbCustomColor, cbPrettyNames, cbCustomColors] @@ -796,7 +759,7 @@ object MainForm: TMainForm BorderSpacing.Left = 8 ItemHeight = 16 OnChange = cbPOITextBgColorChange - TabOrder = 7 + TabOrder = 6 end object LblPOITextBgColor: TLabel AnchorSideLeft.Control = BtnPOITextFont @@ -805,21 +768,20 @@ object MainForm: TMainForm AnchorSideTop.Side = asrCenter Left = 107 Height = 15 - Top = 221 + Top = 175 Width = 39 BorderSpacing.Left = 8 Caption = 'Backgr.' ParentColor = False end object Bevel1: TBevel - AnchorSideLeft.Control = CbDrawingEngine + AnchorSideLeft.Control = CbDebugTiles AnchorSideTop.Control = CbDebugTiles AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = CbDrawingEngine AnchorSideRight.Side = asrBottom Left = 6 Height = 4 - Top = 179 + Top = 133 Width = 255 Anchors = [akTop, akLeft, akRight] BorderSpacing.Top = 8 @@ -841,7 +803,7 @@ object MainForm: TMainForm object FontDialog: TFontDialog MinFontSize = 0 MaxFontSize = 0 - left = 648 - top = 280 + left = 680 + top = 296 end end diff --git a/components/lazmapviewer/example/main.pas b/components/lazmapviewer/example/main.pas index 0912adefb..dc96c418f 100644 --- a/components/lazmapviewer/example/main.pas +++ b/components/lazmapviewer/example/main.pas @@ -7,8 +7,7 @@ interface uses Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, ComCtrls, Buttons, IntfGraphics, ColorBox, - mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine, - mvDE_RGBGraphics, mvDE_BGRA; + mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine; type @@ -30,7 +29,6 @@ type CbMouseCoords: TGroupBox; CbDistanceUnits: TComboBox; CbDebugTiles: TCheckBox; - CbDrawingEngine: TComboBox; CbShowPOIImage: TCheckBox; cbPOITextBgColor: TColorBox; FontDialog: TFontDialog; @@ -44,7 +42,6 @@ type InfoBtnGPSPoints: TLabel; GPSPointInfo: TLabel; InfoViewportWidth: TLabel; - Label1: TLabel; LblPOITextBgColor: TLabel; LblSelectLocation: TLabel; LblCenterLatitude: TLabel; @@ -73,7 +70,6 @@ type procedure BtnSaveToFileClick(Sender: TObject); procedure BtnPOITextFontClick(Sender: TObject); procedure CbDebugTilesChange(Sender: TObject); - procedure CbDrawingEngineChange(Sender: TObject); procedure CbDoubleBufferChange(Sender: TObject); procedure CbFoundLocationsDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState); @@ -100,8 +96,6 @@ type procedure ZoomTrackBarChange(Sender: TObject); private - FRGBGraphicsDrawingEngine: TMvRGBGraphicsDrawingEngine; - FBGRADrawingEngine: TMvBGRADrawingEngine; POIImage: TCustomBitmap; procedure ClearFoundLocations; procedure UpdateCoords(X, Y: Integer); @@ -135,7 +129,7 @@ type const MAX_LOCATIONS_HISTORY = 50; - HOMEDIR = ''; + HOMEDIR = '../../../'; // share the cache in both example projects MAP_PROVIDER_FILENAME = 'map-providers.xml'; USE_DMS = true; @@ -252,23 +246,6 @@ begin MapView.DebugTiles := CbDebugTiles.Checked; end; -procedure TMainForm.CbDrawingEngineChange(Sender: TObject); -begin - case CbDrawingEngine.ItemIndex of - 0: MapView.DrawingEngine := nil; - 1: begin - if FRGBGraphicsDrawingEngine = nil then - FRGBGraphicsDrawingEngine := TMvRGBGraphicsDrawingEngine.Create(self); - MapView.DrawingEngine := FRGBGraphicsDrawingEngine; - end; - 2: begin - if FBGRADrawingEngine = nil then - FBGRADrawingEngine := TMvBGRADrawingEngine.Create(self); - MapView.DrawingEngine := FBGRADrawingEngine; - end; - end; -end; - procedure TMainForm.CbDoubleBufferChange(Sender: TObject); begin MapView.DoubleBuffered := CbDoubleBuffer.Checked; @@ -351,8 +328,8 @@ begin POIImage.PixelFormat := pf32bit; POIImage.LoadFromFile('../../mapmarker.png'); - ForceDirectories(HOMEDIR + 'cache/'); - MapView.CachePath := HOMEDIR + 'cache/'; + ForceDirectories(HOMEDIR + 'example_cache/'); + MapView.CachePath := HOMEDIR + 'example_cache/'; MapView.GetMapProviders(CbProviders.Items); CbProviders.ItemIndex := CbProviders.Items.Indexof(MapView.MapProvider); MapView.DoubleBuffered := true; diff --git a/components/lazmapviewer/example_with_addons/MapViewer_Demo.lpi b/components/lazmapviewer/example_with_addons/MapViewer_Demo.lpi new file mode 100644 index 000000000..df03d1c59 --- /dev/null +++ b/components/lazmapviewer/example_with_addons/MapViewer_Demo.lpi @@ -0,0 +1,106 @@ + + + + + + + + + + + + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + </General> + <BuildModes Count="1"> + <Item1 Name="default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + <Modes Count="0"/> + </RunParams> + <RequiredPackages Count="4"> + <Item1> + <PackageName Value="lazmapviewer_bgra"/> + </Item1> + <Item2> + <PackageName Value="lazmapviewer_rgbgraphics"/> + </Item2> + <Item3> + <PackageName Value="lazMapViewerPkg"/> + </Item3> + <Item4> + <PackageName Value="LCL"/> + </Item4> + </RequiredPackages> + <Units Count="4"> + <Unit0> + <Filename Value="MapViewer_Demo.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="main.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="MainForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Main"/> + </Unit1> + <Unit2> + <Filename Value="gpslistform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="GPSListViewer"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit2> + <Unit3> + <Filename Value="globals.pas"/> + <IsPartOfProject Value="True"/> + </Unit3> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="bin\$(TargetCPU)-$(TargetOS)\MapViewer_Demo"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <UseExternalDbgSyms Value="True"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions Count="4"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + <Item4> + <Name Value="EHTTPClient"/> + </Item4> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/components/lazmapviewer/example_with_addons/MapViewer_Demo.lpr b/components/lazmapviewer/example_with_addons/MapViewer_Demo.lpr new file mode 100644 index 000000000..2aebd7ef3 --- /dev/null +++ b/components/lazmapviewer/example_with_addons/MapViewer_Demo.lpr @@ -0,0 +1,21 @@ +program MapViewer_Demo; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}cthreads,{$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, Main, gpslistform, globals + { you can add units after this }; + +{$R *.res} + +begin + RequireDerivedFormResource:=True; + Application.Scaled:=True; + Application.Initialize; + Application.CreateForm(TMainForm, MainForm); + Application.CreateForm(TGPSListViewer, GPSListViewer); + Application.Run; +end. + diff --git a/components/lazmapviewer/example_with_addons/globals.pas b/components/lazmapviewer/example_with_addons/globals.pas new file mode 100644 index 000000000..2e11a8882 --- /dev/null +++ b/components/lazmapviewer/example_with_addons/globals.pas @@ -0,0 +1,19 @@ +unit globals; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, mvEngine; + +const + DistanceUnit_Names: array[TDistanceUnits] of string = ('m', 'km', 'miles'); + +var + DistanceUnit: TDistanceUnits = duKilometers; + +implementation + +end. + diff --git a/components/lazmapviewer/example_with_addons/gpslistform.lfm b/components/lazmapviewer/example_with_addons/gpslistform.lfm new file mode 100644 index 000000000..fcdb89696 --- /dev/null +++ b/components/lazmapviewer/example_with_addons/gpslistform.lfm @@ -0,0 +1,259 @@ +object GPSListViewer: TGPSListViewer + Left = 282 + Height = 356 + Top = 135 + Width = 753 + Caption = 'GPS points' + ClientHeight = 356 + ClientWidth = 753 + LCLVersion = '2.1.0.0' + object ListView: TListView + Left = 6 + Height = 312 + Top = 6 + Width = 741 + Align = alClient + BorderSpacing.Left = 6 + BorderSpacing.Top = 6 + BorderSpacing.Right = 6 + Checkboxes = True + Columns = < + item + Caption = 'ID' + end + item + Caption = 'Name' + Width = 150 + end + item + Caption = 'Latitude' + Width = 150 + end + item + Caption = 'Longitude' + Width = 150 + end> + ReadOnly = True + RowSelect = True + TabOrder = 0 + ViewStyle = vsReport + end + object Panel1: TPanel + Left = 0 + Height = 38 + Top = 318 + Width = 753 + Align = alBottom + AutoSize = True + BevelOuter = bvNone + ClientHeight = 38 + ClientWidth = 753 + TabOrder = 1 + object BtnDeletePoint: TBitBtn + AnchorSideLeft.Control = BtnGoToPoint + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Panel1 + Left = 118 + Height = 26 + Top = 6 + Width = 110 + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'Delete point' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000002F2FE7433535D2FF2525D7450000000000000000000000002828 + E8412F2FD1FF2525D74500000000000000000000000000000000000000000000 + 0000000000004141DEFF3838DBFF2F2FD4FF2626DD43000000002929EF402E2E + DDFF2C2CD8FF2F2FD1FF00000000000000000000000000000000000000000000 + 0000000000003F3FF1454040E5FF3636DEFF2D2DD9FF2929ED802A2AE3FF2B2B + E5FF2E2EDDFF2828E84100000000000000000000000000000000000000000000 + 000000000000000000003939F0433C3CE7FF3131E5FF2B2BE6FF2A2AE8FF2A2A + E3FF2929EF400000000000000000000000000000000000000000000000000000 + 00000000000000000000000000002B2BEF803131ECFF2C2CEBFF2B2BE6FF2929 + ED80000000000000000000000000000000000000000000000000000000000000 + 000000000000000000002929EF403333ECFF2F2FEDFF3030ECFF3131E5FF2D2D + D9FF2626DD430000000000000000000000000000000000000000000000000000 + 0000000000003030EF413838E7FF3232EBFF3333ECFF2B2BEF803C3CE7FF3636 + DEFF2F2FD4FF2525D74500000000000000000000000000000000000000000000 + 0000000000004242E5FF3D3DE9FF3838E7FF2929EF40000000003939F0434040 + E5FF3838DBFF3535D2FF00000000000000000000000000000000000000000000 + 0000000000003F3FF1454242E5FF3030EF410000000000000000000000003F3F + F1454141DEFF2F2FE74300000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + OnClick = BtnDeletePointClick + TabOrder = 0 + end + object BtnGoToPoint: TBitBtn + AnchorSideLeft.Control = Panel1 + AnchorSideTop.Control = Panel1 + Left = 6 + Height = 26 + Top = 6 + Width = 106 + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'Go to point' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 000000000000000000000696F2DC0696F2500000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000069AF3A90694F2FF0697F18400000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000595F1350697F3FB05A2F4F50699F29E0080FF040000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000069BF3D802DBFBFF04B1F6F5059AF3C40099 + EE0F000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000595F26004B0F6F200FEFFFF03BFF8F70699 + F2DE0991EE1E0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000008EFF090698F2F301F1FDFF00FFFFFF03CF + F9FC0598F2EE0593F034000000000000000000000000000000000594F2620694 + F2FF0694F2FF0694F2FF0694F2FF0694F2FF0694F2FF02D4FAFF00FFFFFF00FF + FFFF02DEFBFE0599F2F40696F2500000000000000000000000000080FF06059A + F3C204BDF7F600FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FF + FFFF00FFFFFF01EBFDFF059DF4F50697F1840000000000000000000000000099 + E60A069AF3D203C7F8F900FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FF + FFFF00FFFFFF00FFFFFF01F4FEFF05A5F5F40699F2A20099FF05000000000000 + 00000099F2140699F3E203CFF9FC00FFFFFF00FFFFFF00FFFFFF05A0F4FB0694 + F2FF0694F2FF0694F2FF0694F2FF0694F2FF0694F2FF0594F262000000000000 + 0000000000000992F61C0598F3E902D7FAFD00FFFFFF00FFFFFF01E5FCFF0599 + F2F40893F3420000000000000000000000000000000000000000000000000000 + 000000000000000000000791F1250599F2EF02E0FBFF00FFFFFF00FFFFFF01E5 + FCFF0599F2F40893F34200000000000000000000000000000000000000000000 + 00000000000000000000000000000595F1350699F2F401E5FCFF00FFFFFF00FF + FFFF01E5FCFF0599F2F40893F342000000000000000000000000000000000000 + 0000000000000000000000000000000000000893F3420599F3F501EBFDFF00FF + FFFF00FFFFFF01E5FCFF0599F2F40893F3420000000000000000000000000000 + 000000000000000000000000000000000000000000000695F3570695F2FE0694 + F2FF0694F2FF0694F2FF0694F2FF0695F2E50000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + OnClick = BtnGoToPointClick + TabOrder = 1 + end + object BtnClose: TBitBtn + AnchorSideTop.Control = Panel1 + AnchorSideRight.Control = Panel1 + AnchorSideRight.Side = asrBottom + Left = 672 + Height = 26 + Top = 6 + Width = 75 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'Close' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000B6420000C1B40000CBD10000CDDD0000CBD10000 + C1B40000B6420000000000000000000000000000000000000000000000000000 + 00000000BF040000BBA20000E0EE0000FFFF0000FFFF0000FFFF0000FFFF0000 + FFFF0000E0EE0000BBA20000BF04000000000000000000000000000000000000 + 00000000BBA20000F2FC0000FFFF0000FCFF0000DFEF0000D2E10000E0EF0000 + FCFF0000FFFF0000F2FC0000BBA2000000000000000000000000000000000000 + B3430000E0EE0000FFFF0000EEF60000BFBB0000AE2C0000AA060000AA2D0000 + BFBB0000EEF70000FFFF0000DFEE0000B4410000000000000000000000000000 + C1B50000FFFF0000FCFF0000BFBA000000000000000000000000000000000000 + 00000000BFBB0000FCFF0000FFFF0000C1B40000000000000000000000000000 + CBD20000FFFF0000DFEE0000AC2B000000000000000000000000000000000000 + 00000000AA2D0000DFEF0000FFFF0000CBD20000000000000000000000000000 + CDDC0000FFFF0000D3E10000AA09000000000000000000000000000000000000 + 00000000AA090000D3E20000FFFF0000CEDB0000000000000000000000000000 + CBCC0000FFFF0000E4F50000AC34000000000000B7E40000CEE00000B7E40000 + 00000000AF360000E4F40000FFFF0000CBCC0000000000000000000000000000 + C0B30000FEFF0000FCFF0000BFBA000000000000CEE00000FFFF0000CEE00000 + 00000000C0BA0000FCFF0000FEFF0000C0B10000000000000000000000000000 + B43A0000DFEE0000FFFF0000D2E30000B30A0000CEE00000FFFF0000CEE00000 + 00000000CDDA0000FFFF0000DEEE0000B3390000000000000000000000000000 + 00000000BC9B0000F1F90000D3E20000A20B0000CEE00000FFFF0000CEE00000 + 00000000CDDA0000F0FB0000BD9B000000000000000000000000000000000000 + 0000000080020000BC9F0000BBE90000A20B0000CEE00000FFFF0000CEE00000 + 00000000B9E40000BC9B00008002000000000000000000000000000000000000 + 000000000000000000000000AC34000080020000CEE00000FFFF0000CEE00000 + 00000000AC2B0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000CEE00000FFFF0000CEE00000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000B7E40000CEE00000B7E40000 + 0000000000000000000000000000000000000000000000000000 + } + OnClick = BtnCloseClick + TabOrder = 2 + end + object BtnCalcDistance: TButton + AnchorSideLeft.Control = BtnDeletePoint + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Panel1 + Left = 234 + Height = 25 + Top = 6 + Width = 203 + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'Calc distance between two points' + OnClick = BtnCalcDistanceClick + TabOrder = 3 + end + object BtnSavePts: TButton + AnchorSideLeft.Control = BtnCalcDistance + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Panel1 + Left = 443 + Height = 25 + Top = 6 + Width = 86 + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'Save points' + OnClick = BtnSavePtsClick + TabOrder = 4 + end + object BtnLoadTrack: TButton + AnchorSideLeft.Control = BtnSavePts + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Panel1 + Left = 535 + Height = 25 + Top = 6 + Width = 81 + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'Load track' + OnClick = BtnLoadTrackClick + TabOrder = 5 + end + end + object SaveDialog: TSaveDialog + Title = 'Save gps points as' + DefaultExt = '.*.gps' + Filter = 'GPS points (*.gps)|*.gps|All files (*.*)|*.*' + left = 472 + top = 256 + end + object OpenDialog: TOpenDialog + Title = 'Open gps points file' + DefaultExt = '.gps' + Filter = 'GPS files (*.gps)|*.gps|All files (*.*)|*.*' + left = 560 + top = 256 + end +end diff --git a/components/lazmapviewer/example_with_addons/gpslistform.pas b/components/lazmapviewer/example_with_addons/gpslistform.pas new file mode 100644 index 000000000..97e68755d --- /dev/null +++ b/components/lazmapviewer/example_with_addons/gpslistform.pas @@ -0,0 +1,279 @@ +unit gpslistform; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ButtonPanel, ComCtrls, + ExtCtrls, Buttons, StdCtrls, mvGpsObj, mvMapViewer; + +const + // IDs of GPS items + _CLICKED_POINTS_ = 10; + _TRACK_POINTS_ = 20; + +type + + { TGPSListViewer } + + TGPSListViewer = class(TForm) + BtnDeletePoint: TBitBtn; + BtnGoToPoint: TBitBtn; + BtnClose: TBitBtn; + BtnCalcDistance: TButton; + BtnSavePts: TButton; + BtnLoadTrack: TButton; + ListView: TListView; + OpenDialog: TOpenDialog; + Panel1: TPanel; + SaveDialog: TSaveDialog; + procedure BtnCalcDistanceClick(Sender: TObject); + procedure BtnCloseClick(Sender: TObject); + procedure BtnDeletePointClick(Sender: TObject); + procedure BtnGoToPointClick(Sender: TObject); + procedure BtnSavePtsClick(Sender: TObject); + procedure BtnLoadTrackClick(Sender: TObject); + private + FViewer: TMapView; + FList: TGpsObjList; + procedure SetViewer(AValue: TMapView); + protected + procedure Populate; + + public + destructor Destroy; override; + property MapViewer: TMapView read FViewer write SetViewer; + + end; + +var + GPSListViewer: TGPSListViewer; + +implementation + +{$R *.lfm} + +uses + mvTypes, mvEngine, + globals; + +destructor TGPSListViewer.Destroy; +begin + FList.Free; + inherited; +end; + +procedure TGPSListViewer.Populate; +var + i: Integer; + item: TListItem; + gpsObj: TGpsObj; + area: TRealArea; +begin + if FViewer = nil then begin + ListView.Items.Clear; + exit; + end; + + FViewer.GPSItems.GetArea(area); + FList.Free; + FList := FViewer.GPSItems.GetObjectsInArea(area); + ListView.Items.BeginUpdate; + try + ListView.Items.Clear; + for i:=0 to FList.Count-1 do begin + gpsObj := FList[i]; + item := ListView.Items.Add; + if gpsObj is TGpsPoint then begin + item.SubItems.Add(gpsObj.Name); + item.Subitems.Add(LatToStr(TGpsPoint(gpsObj).Lat, true)); + item.Subitems.Add(LonToStr(TGpsPoint(gpsObj).Lon, true)); + end; + end; + finally + ListView.Items.EndUpdate; + end; +end; + +procedure TGPSListViewer.BtnCloseClick(Sender: TObject); +begin + Close; +end; + +procedure TGPSListViewer.BtnCalcDistanceClick(Sender: TObject); +type + TCoordRec = record + Lon: Double; + Lat: Double; + Name: String; + end; +var + i, iChecked: Integer; + item: TListItem; + rPt: TRealPoint; + CoordArr: array[0..1] of TCoordRec; +begin + // count checked items + iChecked := 0; + for i:=0 to ListView.Items.Count - 1 do begin + if ListView.Items.Item[i].Checked then Inc(iChecked); + end; + + if iChecked <> 2 then begin + ShowMessage('Please select 2 items to calculate the distance.'); + exit; + end; + + iChecked := 0; + for i:=0 to ListView.Items.Count - 1 do begin + if ListView.Items.Item[i].Checked then begin + item := ListView.Items[i]; + if TryStrToGps(item.SubItems[2], rPt.Lon) and TryStrToGps(item.SubItems[1], rPt.Lat) then + begin + CoordArr[iChecked].Lon := rPt.Lon; + CoordArr[iChecked].Lat := rPt.Lat; + CoordArr[iChecked].Name:= item.SubItems[0]; + Inc(iChecked); + end; + end; + end; + // show distance between selected items + ShowMessage(Format('Distance between %s and %s is: %.2n %s.', [ + CoordArr[0].Name, CoordArr[1].Name, + CalcGeoDistance(CoordArr[0].Lat, CoordArr[0].Lon, CoordArr[1].Lat, CoordArr[1].Lon, DistanceUnit), + DistanceUnit_Names[DistanceUnit] + ])); +end; + +procedure TGPSListViewer.BtnDeletePointClick(Sender: TObject); +var + gpsObj: TGpsObj; + i: Integer; + rPt: TRealPoint; + item: TListItem; +begin + if ListView.Selected <> nil then begin + gpsObj := FList[ListView.Selected.Index]; + ListView.Selected.Free; + FViewer.GpsItems.Clear(_CLICKED_POINTS_); + for i:=0 to ListView.Items.Count-1 do begin + item := ListView.Items[i]; + if TryStrToGps(item.SubItems[2], rPt.Lon) and TryStrToGps(item.SubItems[1], rPt.Lat) then + begin + gpsObj := TGpsPoint.CreateFrom(rPt); + gpsObj.Name := item.SubItems[0]; + FViewer.GPSItems.Add(gpsObj, _CLICKED_POINTS_); + end; + end; + end; +end; + +procedure TGPSListViewer.BtnGoToPointClick(Sender: TObject); +var + gpsPt: TGpsPoint; + gpsObj: TGpsObj; +begin + if ListView.Selected <> nil then begin + gpsObj := FList[ListView.Selected.Index]; + if gpsObj is TGpsPoint then begin + gpsPt := TGpsPoint(gpsObj); + if Assigned(FViewer) then FViewer.Center := gpsPt.RealPoint; + end; + end; +end; + +procedure TGPSListViewer.BtnSavePtsClick(Sender: TObject); +var + i: Integer; + gpsPt: TGpsPoint; + gpsObj: TGpsObj; + L: TStrings; + s: String; +begin + if (OpenDialog.FileName <> '') and (SaveDialog.FileName = '') then + SaveDialog.FileName := OpenDialog.FileName; + if SaveDialog.FileName <> '' then + SaveDialog.InitialDir := ExtractFileDir(SaveDialog.FileName); + if not SaveDialog.Execute then exit; + + L := TStringList.Create; + try + s := 'Index'#9'Name'#9'Longitude'#9'Latitude'; + L.Add(s); + for i:=0 to FList.Count-1 do begin + gpsObj := FList[i]; + if gpsObj is TGpsPoint then begin + gpsPt := TGpsPoint(gpsObj); + s := Format('%d'#9'%s'#9'%s'#9'%s', [ + i, gpsPt.Name, LonToStr(gpsPt.Lon, true), LatToStr(gpsPt.Lat, true) + ]); + L.Add(s); + end; + L.SaveToFile(SaveDialog.FileName); + end; + finally + L.Free; + end; +end; + +procedure TGPSListViewer.BtnLoadTrackClick(Sender: TObject); +var + L: TStrings; + gpsTrack: TGpsTrack; + gpsPt: TGpsPoint; + sa: TStringArray; + lon, lat: Double; + i: Integer; + item: TListItem; +begin + if (SaveDialog.FileName <> '') and (OpenDialog.FileName = '') then + OpenDialog.FileName := SaveDialog.FileName; + if OpenDialog.FileName <> '' then + OpenDialog.InitialDir := ExtractFileDir(OpenDialog.FileName); + if not OpenDialog.Execute then exit; + + gpsTrack := TGpsTrack.Create; + L := TStringList.Create; + try + L.LoadFromFile(OpenDialog.FileName); + for i := 1 to L.Count - 1 do begin // i=1 --> skip header line + if L[i] = '' then Continue; + sa := L[i].Split(#9); + if TryStrToGps(sa[2], lon) and TryStrToGps(sa[3], lat) then begin + gpsPt := TGpsPoint.Create(lon, lat); + gpsPt.Name := sa[1]; + gpsTrack.Points.Add(gpsPt); + end; + end; + FViewer.GPSItems.Add(gpsTrack, _TRACK_POINTS_); + FViewer.Center := gpsPt.RealPoint; + finally + L.Free; + end; + + ListView.Items.BeginUpdate; + try + ListView.Items.Clear; + for i:=0 to gpsTrack.Points.Count - 1 do begin + gpsPt := gpsTrack.Points[i]; + item := ListView.Items.Add; + item.SubItems.Add(gpsPt.Name); + item.SubItems.Add(LatToStr(gpsPt.Lat, true)); + item.SubItems.Add(LonToStr(gpsPt.Lon, true)); + end; + finally + ListView.Items.EndUpdate; + end; +end; + +procedure TGPSListViewer.SetViewer(AValue: TMapView); +begin + if FViewer = AValue then + exit; + FViewer := AValue; + Populate; +end; + +end. + diff --git a/components/lazmapviewer/example_with_addons/main.lfm b/components/lazmapviewer/example_with_addons/main.lfm new file mode 100644 index 000000000..3d93cfd12 --- /dev/null +++ b/components/lazmapviewer/example_with_addons/main.lfm @@ -0,0 +1,847 @@ +object MainForm: TMainForm + Left = 332 + Height = 640 + Top = 183 + Width = 883 + Caption = 'LazMapViewer' + ClientHeight = 640 + ClientWidth = 883 + OnCreate = FormCreate + OnDestroy = FormDestroy + OnShow = FormShow + ShowHint = True + LCLVersion = '2.1.0.0' + object MapView: TMapView + Left = 0 + Height = 640 + Hint = 'Displays the map' + Top = 0 + Width = 608 + Align = alClient + DefaultTrackColor = clBlue + DefaultTrackWidth = 3 + DownloadEngine = MapView.BuiltInDLE + DrawingEngine = MapView.BuiltInDE + Font.Color = clBlack + MapProvider = 'OpenStreetMap Mapnik' + UseThreads = True + Zoom = 0 + OnZoomChange = MapViewZoomChange + OnChange = MapViewChange + OnMouseLeave = MapViewMouseLeave + OnMouseMove = MapViewMouseMove + OnMouseUp = MapViewMouseUp + end + object PageControl: TPageControl + Left = 608 + Height = 640 + Top = 0 + Width = 275 + ActivePage = PgConfig + Align = alRight + TabIndex = 1 + TabOrder = 1 + object PgData: TTabSheet + Caption = 'Data' + ClientHeight = 612 + ClientWidth = 267 + object ZoomTrackBar: TTrackBar + AnchorSideLeft.Control = PgData + AnchorSideTop.Control = LblZoom + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = PgData + AnchorSideRight.Side = asrBottom + Left = 2 + Height = 40 + Top = 21 + Width = 263 + Max = 19 + Min = 1 + OnChange = ZoomTrackBarChange + Position = 1 + TickMarks = tmBoth + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 2 + BorderSpacing.Right = 2 + TabOrder = 0 + end + object LblZoom: TLabel + AnchorSideLeft.Control = PgData + AnchorSideTop.Control = PgData + Left = 6 + Height = 15 + Top = 6 + Width = 35 + BorderSpacing.Left = 6 + BorderSpacing.Top = 6 + Caption = 'Zoom:' + ParentColor = False + end + object CbMouseCoords: TGroupBox + AnchorSideLeft.Control = PgData + AnchorSideTop.Control = ZoomTrackBar + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = PgData + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 66 + Top = 69 + Width = 255 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BorderSpacing.Left = 6 + BorderSpacing.Top = 8 + BorderSpacing.Right = 6 + Caption = 'Mouse position' + ClientHeight = 46 + ClientWidth = 251 + TabOrder = 1 + object LblPositionLongitude: TLabel + AnchorSideLeft.Control = CbMouseCoords + AnchorSideTop.Control = CbMouseCoords + Left = 8 + Height = 15 + Top = 4 + Width = 54 + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + Caption = 'Longitude' + ParentColor = False + end + object LblPositionLatitude: TLabel + AnchorSideLeft.Control = CbMouseCoords + AnchorSideTop.Control = LblPositionLongitude + AnchorSideTop.Side = asrBottom + Left = 8 + Height = 15 + Top = 23 + Width = 43 + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + BorderSpacing.Bottom = 8 + Caption = 'Latitude' + ParentColor = False + end + object InfoPositionLongitude: TLabel + AnchorSideLeft.Control = CbMouseCoords + AnchorSideTop.Control = CbMouseCoords + AnchorSideRight.Control = CbMouseCoords + AnchorSideRight.Side = asrBottom + Left = 201 + Height = 15 + Top = 4 + Width = 34 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 16 + Caption = 'Label2' + ParentColor = False + end + object InfoPositionLatitude: TLabel + AnchorSideLeft.Control = CbMouseCoords + AnchorSideTop.Control = InfoPositionLongitude + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = CbMouseCoords + AnchorSideRight.Side = asrBottom + Left = 201 + Height = 15 + Top = 23 + Width = 34 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 16 + BorderSpacing.Bottom = 8 + Caption = 'Label2' + ParentColor = False + end + end + object GbCenterCoords: TGroupBox + AnchorSideLeft.Control = LblZoom + AnchorSideTop.Control = CbMouseCoords + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = CbMouseCoords + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 66 + Top = 143 + Width = 255 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BorderSpacing.Top = 8 + Caption = 'Center' + ClientHeight = 46 + ClientWidth = 251 + TabOrder = 2 + object LblCenterLongitude: TLabel + AnchorSideLeft.Control = GbCenterCoords + AnchorSideTop.Control = GbCenterCoords + Left = 8 + Height = 15 + Top = 4 + Width = 54 + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + Caption = 'Longitude' + ParentColor = False + end + object LblCenterLatitude: TLabel + AnchorSideLeft.Control = GbCenterCoords + AnchorSideTop.Control = LblCenterLongitude + AnchorSideTop.Side = asrBottom + Left = 8 + Height = 15 + Top = 23 + Width = 43 + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + BorderSpacing.Bottom = 8 + Caption = 'Latitude' + ParentColor = False + end + object InfoCenterLongitude: TLabel + AnchorSideLeft.Control = GbCenterCoords + AnchorSideTop.Control = GbCenterCoords + AnchorSideRight.Control = GbCenterCoords + AnchorSideRight.Side = asrBottom + Left = 201 + Height = 15 + Top = 4 + Width = 34 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 16 + Caption = 'Label2' + ParentColor = False + end + object InfoCenterLatitude: TLabel + AnchorSideLeft.Control = GbCenterCoords + AnchorSideTop.Control = InfoCenterLongitude + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbCenterCoords + AnchorSideRight.Side = asrBottom + Left = 201 + Height = 15 + Top = 23 + Width = 34 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 16 + BorderSpacing.Bottom = 8 + Caption = 'Label2' + ParentColor = False + end + end + object GbScreenSize: TGroupBox + AnchorSideLeft.Control = GbCenterCoords + AnchorSideTop.Control = GbCenterCoords + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbCenterCoords + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 66 + Top = 217 + Width = 255 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BorderSpacing.Top = 8 + Caption = 'Viewport size' + ClientHeight = 46 + ClientWidth = 251 + TabOrder = 3 + object LblViewportWidth: TLabel + AnchorSideLeft.Control = GbScreenSize + AnchorSideTop.Control = GbScreenSize + Left = 8 + Height = 15 + Top = 4 + Width = 32 + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + Caption = 'Width' + ParentColor = False + end + object LblViewportHeight: TLabel + AnchorSideLeft.Control = GbScreenSize + AnchorSideTop.Control = LblViewportWidth + AnchorSideTop.Side = asrBottom + Left = 8 + Height = 15 + Top = 23 + Width = 36 + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + BorderSpacing.Bottom = 8 + Caption = 'Height' + ParentColor = False + end + object InfoViewportWidth: TLabel + AnchorSideTop.Control = GbScreenSize + AnchorSideRight.Control = GbScreenSize + AnchorSideRight.Side = asrBottom + Left = 201 + Height = 15 + Top = 4 + Width = 34 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 16 + Caption = 'Label2' + ParentColor = False + end + object InfoViewportHeight: TLabel + AnchorSideTop.Control = InfoViewportWidth + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbScreenSize + AnchorSideRight.Side = asrBottom + Left = 201 + Height = 15 + Top = 23 + Width = 34 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 16 + BorderSpacing.Bottom = 8 + Caption = 'Label2' + ParentColor = False + end + end + object CbDistanceUnits: TComboBox + AnchorSideTop.Control = GbCenterCoords + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbCenterCoords + AnchorSideRight.Side = asrBottom + Left = 189 + Height = 23 + Top = 215 + Width = 64 + Anchors = [akTop, akRight] + BorderSpacing.Top = 6 + BorderSpacing.Right = 8 + ItemHeight = 15 + ItemIndex = 1 + Items.Strings = ( + 'm' + 'km' + 'miles' + ) + OnChange = CbDistanceUnitsChange + Style = csDropDownList + TabOrder = 4 + Text = 'km' + end + object GbSearch: TGroupBox + AnchorSideLeft.Control = GbScreenSize + AnchorSideTop.Control = GbScreenSize + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbScreenSize + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 105 + Top = 291 + Width = 255 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BorderSpacing.Top = 8 + Caption = 'Search' + ClientHeight = 85 + ClientWidth = 251 + TabOrder = 5 + object CbLocations: TComboBox + AnchorSideLeft.Control = GbSearch + AnchorSideTop.Control = GbSearch + AnchorSideRight.Control = BtnSearch + Left = 8 + Height = 23 + Top = 4 + Width = 172 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + BorderSpacing.Right = 4 + BorderSpacing.Bottom = 4 + DropDownCount = 24 + ItemHeight = 15 + TabOrder = 0 + Text = 'New York' + end + object BtnSearch: TButton + AnchorSideTop.Control = CbLocations + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = GbSearch + AnchorSideRight.Side = asrBottom + Left = 184 + Height = 25 + Top = 3 + Width = 61 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Right = 6 + Caption = 'Search' + OnClick = BtnSearchClick + TabOrder = 1 + end + object LblSelectLocation: TLabel + AnchorSideLeft.Control = CbLocations + AnchorSideTop.Control = CbLocations + AnchorSideTop.Side = asrBottom + Left = 8 + Height = 15 + Top = 35 + Width = 177 + BorderSpacing.Top = 8 + Caption = 'Select one of the found locations:' + ParentColor = False + end + object BtnGoTo: TButton + AnchorSideTop.Control = CbFoundLocations + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = BtnSearch + AnchorSideRight.Side = asrBottom + Left = 190 + Height = 25 + Top = 52 + Width = 55 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Bottom = 8 + Caption = 'Go to' + OnClick = BtnGoToClick + TabOrder = 2 + end + object CbFoundLocations: TComboBox + AnchorSideLeft.Control = LblSelectLocation + AnchorSideTop.Control = LblSelectLocation + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = BtnGoTo + Left = 8 + Height = 21 + Top = 54 + Width = 178 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Right = 4 + BorderSpacing.Bottom = 8 + DropDownCount = 24 + ItemHeight = 15 + ItemWidth = -2 + OnDrawItem = CbFoundLocationsDrawItem + ParentShowHint = False + ShowHint = True + Style = csOwnerDrawFixed + TabOrder = 3 + end + end + object GbGPS: TGroupBox + AnchorSideLeft.Control = GbSearch + AnchorSideTop.Control = GbSearch + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbSearch + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 105 + Top = 404 + Width = 255 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Top = 8 + Caption = 'GPS points' + ClientHeight = 85 + ClientWidth = 251 + TabOrder = 6 + object BtnGPSPoints: TButton + AnchorSideLeft.Control = GbGPS + AnchorSideTop.Control = GbGPS + AnchorSideRight.Control = GbGPS + AnchorSideRight.Side = asrBottom + Left = 192 + Height = 25 + Top = 0 + Width = 53 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Left = 6 + BorderSpacing.Right = 6 + Caption = 'List...' + OnClick = BtnGPSPointsClick + TabOrder = 0 + end + object InfoBtnGPSPoints: TLabel + AnchorSideLeft.Control = GbGPS + AnchorSideTop.Control = BtnGPSPoints + AnchorSideRight.Control = BtnGPSPoints + Left = 8 + Height = 30 + Top = 4 + Width = 178 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 8 + BorderSpacing.Top = 4 + Caption = 'Click with right mouse button to add a GPS point.' + ParentColor = False + WordWrap = True + end + object GPSPointInfo: TLabel + AnchorSideLeft.Control = InfoBtnGPSPoints + AnchorSideTop.Control = InfoBtnGPSPoints + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GbGPS + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = GbGPS + AnchorSideBottom.Side = asrBottom + Left = 8 + Height = 35 + Top = 50 + Width = 237 + Anchors = [akTop, akLeft, akRight, akBottom] + AutoSize = False + BorderSpacing.Top = 16 + BorderSpacing.Right = 6 + Caption = 'GPSPointInfo' + ParentColor = False + WordWrap = True + end + end + object BtnSaveToFile: TButton + AnchorSideLeft.Control = GbGPS + AnchorSideTop.Control = GbGPS + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 25 + Top = 517 + Width = 110 + AutoSize = True + BorderSpacing.Top = 8 + Caption = 'Save map to file' + OnClick = BtnSaveToFileClick + TabOrder = 7 + end + object BtnLoadGPXFile: TButton + AnchorSideLeft.Control = BtnSaveToFile + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnSaveToFile + Left = 124 + Height = 25 + Top = 517 + Width = 105 + AutoSize = True + BorderSpacing.Left = 8 + Caption = 'Load GPX file...' + OnClick = BtnLoadGPXFileClick + TabOrder = 8 + end + end + object PgConfig: TTabSheet + Caption = 'Config' + ClientHeight = 612 + ClientWidth = 267 + object Label1: TLabel + AnchorSideLeft.Control = CbDrawingEngine + AnchorSideTop.Control = PgConfig + Left = 6 + Height = 15 + Top = 6 + Width = 86 + BorderSpacing.Top = 6 + Caption = 'Drawing engine:' + ParentColor = False + end + object CbDrawingEngine: TComboBox + AnchorSideLeft.Control = PgConfig + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = PgConfig + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 23 + Top = 23 + Width = 255 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 6 + BorderSpacing.Top = 2 + BorderSpacing.Right = 6 + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'default' + 'RGBGraphics' + 'BGRABitmap' + ) + OnChange = CbDrawingEngineChange + Style = csDropDownList + TabOrder = 0 + Text = 'default' + end + object LblProviders: TLabel + AnchorSideLeft.Control = CbProviders + AnchorSideTop.Control = CbDrawingEngine + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 15 + Top = 54 + Width = 52 + BorderSpacing.Top = 8 + Caption = 'Providers:' + FocusControl = CbProviders + ParentColor = False + end + object CbProviders: TComboBox + AnchorSideLeft.Control = PgConfig + AnchorSideTop.Control = LblProviders + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = BtnLoadMapProviders + Left = 6 + Height = 23 + Top = 71 + Width = 199 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 6 + BorderSpacing.Top = 2 + BorderSpacing.Right = 4 + DropDownCount = 24 + ItemHeight = 15 + OnChange = CbProvidersChange + Style = csDropDownList + TabOrder = 1 + end + object BtnLoadMapProviders: TSpeedButton + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = CbProviders + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = BtnSaveMapProviders + Left = 209 + Height = 22 + Top = 71 + Width = 23 + Anchors = [akTop, akRight] + BorderSpacing.Right = 4 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000003591 + DBFA439FDDFA439FDDFA429FDDFA429EDDFA419EDCFA419EDCFA419EDCFA419E + DCFA419EDCFA419EDCFA419EDCFA3792DAFB3080DF100000000000000000429C + DEF76EC7EBFF6DC7EAFF6BC6EAFF6AC5E9FF68C4E9FF67C3E8FF65C2E8FF64C1 + E7FF63C0E7FF61BFE6FF60BEE5FF51AFE3FE308CD6450000000000000000409A + DDF47CD0F1FF7BD0F0FF7ACFEFFF79CEEFFF77CDEEFF76CCEEFF74CBEDFF73CA + EDFF71C9ECFF70C8ECFF6EC7EBFF6AC3E9FF3993DB8E00000000000000003E99 + DCEC7ECEF1FF8AD9F6FF89D8F5FF87D7F4FF86D6F4FF84D5F3FF83D5F3FF81D4 + F2FF80D3F2FF7ED2F1FF7DD1F1FF7BD0F0FF439ADEB40000000000000000409B + DDE470C1EDFF99E2FBFF97E2FBFF96E1FAFF94E0F9FF93DFF9FF91DEF8FF90DD + F8FF8EDCF7FF8DDBF7FF8CDAF6FF8AD9F6FF4EA4E2CD00000000000000004AA5 + E0DF61B3E8FFA3E9FFFFA3E9FFFFA3E9FFFFA3E9FFFFA2E8FEFFA0E7FEFF9FE6 + FDFF9DE5FDFF9CE4FCFF9AE3FCFF99E2FBFF5FB3E9E33080DF100000000051A8 + E2DF5EB2E8FFA3E9FFFFA3E9FFFFA3E9FFFFA3E9FFFFA3E9FFFFA3E9FFFFA3E9 + FFFFA3E9FFFFA3E9FFFFA3E9FFFFA3E9FFFF84CFF5FB348CDA450000000058AD + E5DF60B3E8FF61B3E9FF61B3E9FF60B2E9FF60B2E8FF60B2E8FF5FB1E8FF5FB1 + E8FF5EB1E8FF5EB1E8FF5EB1E7FF59ADE7FB55A9E5E33B94DC85000000005FB0 + E8DF9DE4FBFF9AE3FAFF97E1F9FF94DFF8FF91DDF7FF8EDBF5FF8BD9F4FF88D8 + F3FF85D6F2FF82D4F1FF7FD2F0FF4FA7E1DF00000000000000000000000061B1 + E8DFA6EAFFFFA6EAFFFFA6EAFFFFA3E8FEFF7AC6F1ED59ACE6DF58AAE5DF57AA + E5DF56AAE5DF53A9E4DF53A8E4DF3C94DCE20000000000000000000000004096 + DEE25DAEE7DF5DAEE7DF5DAEE7DF57A9E6DF4399DF6E00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + OnClick = BtnLoadMapProvidersClick + end + object BtnSaveMapProviders: TSpeedButton + AnchorSideLeft.Control = BtnLoadMapProviders + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = CbProviders + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = PgConfig + AnchorSideRight.Side = asrBottom + Left = 236 + Height = 22 + Top = 71 + Width = 23 + Anchors = [akTop, akRight] + BorderSpacing.Right = 8 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000A4653455A465 + 34FFA46534FFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BD + BAFFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFB6BDBAFFA46534FFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BD + BAFFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFB6BDBAFFA46534FFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BD + BAFFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFB6BDBAFFA46534FFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BD + BAFFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFB6BDBAFFA46534FFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BD + BAFFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BDBAFFB6BD + BAFFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFA46534FFA46534FFA46534FFA46534FFA46534FFA46534FFA465 + 34FFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFA465 + 34FFA46534FFA46534FFA46534FFA46534FFA46534FFA46534FFA46534FFA465 + 34FFA46534FFA46534FFA46534FFA46534FFA46534FF00000000A46534FFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFA46534FF00000000A46534FFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFA46534FF00000000A46534FFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFA46534FF00000000A46534FFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFA46534FF00000000A46534FFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFA46534FF00000000A46534FFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFECEE + EEFFECEEEEFFECEEEEFFECEEEEFFECEEEEFFA46534FF00000000A46534FF5959 + F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959 + F3FF5959F3FF5959F3FF5959F3FF5959F3FFA46534FF00000000A46534FF5959 + F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959F3FF5959 + F3FF5959F3FF5959F3FF5959F3FF5959F3FFA46534FF00000000 + } + OnClick = BtnSaveMapProvidersClick + end + object CbUseThreads: TCheckBox + AnchorSideLeft.Control = PgConfig + AnchorSideTop.Control = CbProviders + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 19 + Top = 102 + Width = 81 + BorderSpacing.Left = 6 + BorderSpacing.Top = 8 + Caption = 'Use threads' + Checked = True + OnChange = CbUseThreadsChange + State = cbChecked + TabOrder = 2 + end + object CbDoubleBuffer: TCheckBox + AnchorSideLeft.Control = CbUseThreads + AnchorSideTop.Control = CbUseThreads + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 19 + Top = 127 + Width = 87 + BorderSpacing.Top = 6 + BorderSpacing.Right = 9 + Caption = 'DblBuffering' + Checked = True + OnChange = CbDoubleBufferChange + State = cbChecked + TabOrder = 3 + end + object CbDebugTiles: TCheckBox + AnchorSideLeft.Control = CbDoubleBuffer + AnchorSideTop.Control = CbDoubleBuffer + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 19 + Top = 152 + Width = 79 + BorderSpacing.Top = 6 + Caption = 'Debug tiles' + OnChange = CbDebugTilesChange + TabOrder = 4 + end + object CbShowPOIImage: TCheckBox + AnchorSideLeft.Control = CbDebugTiles + AnchorSideTop.Control = Bevel1 + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 19 + Top = 189 + Width = 107 + BorderSpacing.Top = 6 + Caption = 'Show POI image' + OnChange = CbShowPOIImageChange + TabOrder = 5 + end + object BtnPOITextFont: TButton + AnchorSideTop.Control = CbShowPOIImage + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 25 + Top = 216 + Width = 93 + AutoSize = True + BorderSpacing.Top = 8 + Caption = 'POI text font' + OnClick = BtnPOITextFontClick + TabOrder = 6 + end + object cbPOITextBgColor: TColorBox + AnchorSideLeft.Control = LblPOITextBgColor + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnPOITextFont + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = CbDrawingEngine + AnchorSideRight.Side = asrBottom + Left = 154 + Height = 22 + Top = 217 + Width = 107 + NoneColorColor = clWhite + Style = [cbStandardColors, cbExtendedColors, cbIncludeNone, cbCustomColor, cbPrettyNames, cbCustomColors] + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 8 + ItemHeight = 16 + OnChange = cbPOITextBgColorChange + TabOrder = 7 + end + object LblPOITextBgColor: TLabel + AnchorSideLeft.Control = BtnPOITextFont + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnPOITextFont + AnchorSideTop.Side = asrCenter + Left = 107 + Height = 15 + Top = 221 + Width = 39 + BorderSpacing.Left = 8 + Caption = 'Backgr.' + ParentColor = False + end + object Bevel1: TBevel + AnchorSideLeft.Control = CbDrawingEngine + AnchorSideTop.Control = CbDebugTiles + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = CbDrawingEngine + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 4 + Top = 179 + Width = 255 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Top = 8 + Shape = bsTopLine + end + end + end + object GeoNames: TMVGeoNames + OnNameFound = GeoNamesNameFound + left = 240 + top = 192 + end + object OpenDialog: TOpenDialog + DefaultExt = '.pgx' + Filter = 'GPX files (*.gpx)|*.gpx|All files (*.*)|*.*' + left = 240 + top = 456 + end + object FontDialog: TFontDialog + MinFontSize = 0 + MaxFontSize = 0 + left = 648 + top = 280 + end +end diff --git a/components/lazmapviewer/example_with_addons/main.pas b/components/lazmapviewer/example_with_addons/main.pas new file mode 100644 index 000000000..f253c10fa --- /dev/null +++ b/components/lazmapviewer/example_with_addons/main.pas @@ -0,0 +1,704 @@ +unit Main; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, + ExtCtrls, StdCtrls, ComCtrls, Buttons, IntfGraphics, ColorBox, + mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine, + mvDE_RGBGraphics, mvDE_BGRA; + +type + + { TMainForm } + + TMainForm = class(TForm) + Bevel1: TBevel; + BtnSearch: TButton; + BtnGoTo: TButton; + BtnGPSPoints: TButton; + BtnSaveToFile: TButton; + BtnLoadGPXFile: TButton; + BtnPOITextFont: TButton; + CbDoubleBuffer: TCheckBox; + CbFoundLocations: TComboBox; + CbLocations: TComboBox; + CbProviders: TComboBox; + CbUseThreads: TCheckBox; + CbMouseCoords: TGroupBox; + CbDistanceUnits: TComboBox; + CbDebugTiles: TCheckBox; + CbDrawingEngine: TComboBox; + CbShowPOIImage: TCheckBox; + cbPOITextBgColor: TColorBox; + FontDialog: TFontDialog; + GbCenterCoords: TGroupBox; + GbScreenSize: TGroupBox; + GbSearch: TGroupBox; + GbGPS: TGroupBox; + InfoCenterLatitude: TLabel; + InfoViewportHeight: TLabel; + InfoCenterLongitude: TLabel; + InfoBtnGPSPoints: TLabel; + GPSPointInfo: TLabel; + InfoViewportWidth: TLabel; + Label1: TLabel; + LblPOITextBgColor: TLabel; + LblSelectLocation: TLabel; + LblCenterLatitude: TLabel; + LblViewportHeight: TLabel; + LblViewportWidth: TLabel; + LblPositionLongitude: TLabel; + LblPositionLatitude: TLabel; + InfoPositionLongitude: TLabel; + InfoPositionLatitude: TLabel; + LblCenterLongitude: TLabel; + LblProviders: TLabel; + LblZoom: TLabel; + MapView: TMapView; + GeoNames: TMVGeoNames; + BtnLoadMapProviders: TSpeedButton; + BtnSaveMapProviders: TSpeedButton; + OpenDialog: TOpenDialog; + PageControl: TPageControl; + PgData: TTabSheet; + PgConfig: TTabSheet; + ZoomTrackBar: TTrackBar; + procedure BtnGoToClick(Sender: TObject); + procedure BtnLoadGPXFileClick(Sender: TObject); + procedure BtnSearchClick(Sender: TObject); + procedure BtnGPSPointsClick(Sender: TObject); + procedure BtnSaveToFileClick(Sender: TObject); + procedure BtnPOITextFontClick(Sender: TObject); + procedure CbDebugTilesChange(Sender: TObject); + procedure CbDrawingEngineChange(Sender: TObject); + procedure CbDoubleBufferChange(Sender: TObject); + procedure CbFoundLocationsDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); + procedure cbPOITextBgColorChange(Sender: TObject); + procedure CbProvidersChange(Sender: TObject); + procedure CbShowPOIImageChange(Sender: TObject); + procedure CbUseThreadsChange(Sender: TObject); + 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; Shift: TShiftState; X, Y: Integer); + procedure MapViewMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure MapViewZoomChange(Sender: TObject); + procedure BtnLoadMapProvidersClick(Sender: TObject); + procedure BtnSaveMapProvidersClick(Sender: TObject); + procedure ZoomTrackBarChange(Sender: TObject); + + private + FRGBGraphicsDrawingEngine: TMvRGBGraphicsDrawingEngine; + FBGRADrawingEngine: TMvBGRADrawingEngine; + POIImage: TCustomBitmap; + 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, + mvEngine, mvGPX, + globals, gpslistform; + +type + TLocationParam = class + Descr: String; + Loc: TRealPoint; + end; + +const + MAX_LOCATIONS_HISTORY = 50; + HOMEDIR = '../../../'; // share the cache in both example projects + MAP_PROVIDER_FILENAME = 'map-providers.xml'; + USE_DMS = true; + +var + PointFormatSettings: TFormatsettings; + + +function CalcIniName: String; +begin + Result := ChangeFileExt(Application.ExeName, '.ini'); +end; + + +{ TMainForm } + +procedure TMainForm.BtnLoadMapProvidersClick(Sender: TObject); +var + fn: String; + msg: String; +begin + fn := Application.Location + MAP_PROVIDER_FILENAME; + if FileExists(fn) then begin + if MapView.Engine.ReadProvidersFromXML(fn, msg) then begin + MapView.GetMapProviders(CbProviders.Items); + CbProviders.ItemIndex := 0; + MapView.MapProvider := CbProviders.Text; + end else + ShowMessage(msg); + end; +end; + +procedure TMainForm.BtnSaveMapProvidersClick(Sender: TObject); +begin + MapView.Engine.WriteProvidersToXML(Application.Location + MAP_PROVIDER_FILENAME); +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.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.CbDebugTilesChange(Sender: TObject); +begin + MapView.DebugTiles := CbDebugTiles.Checked; +end; + +procedure TMainForm.CbDrawingEngineChange(Sender: TObject); +begin + case CbDrawingEngine.ItemIndex of + 0: MapView.DrawingEngine := nil; + 1: begin + if FRGBGraphicsDrawingEngine = nil then + FRGBGraphicsDrawingEngine := TMvRGBGraphicsDrawingEngine.Create(self); + MapView.DrawingEngine := FRGBGraphicsDrawingEngine; + end; + 2: begin + if FBGRADrawingEngine = nil then + FBGRADrawingEngine := TMvBGRADrawingEngine.Create(self); + MapView.DrawingEngine := FBGRADrawingEngine; + end; + end; +end; + +procedure TMainForm.CbDoubleBufferChange(Sender: TObject); +begin + MapView.DoubleBuffered := CbDoubleBuffer.Checked; +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.cbPOITextBgColorChange(Sender: TObject); +begin + MapView.POITextBgColor := cbPOITextBgColor.Selected; +end; + +procedure TMainForm.CbProvidersChange(Sender: TObject); +begin + MapView.MapProvider := CbProviders.Text; +end; + +procedure TMainForm.CbShowPOIImageChange(Sender: TObject); +begin + if CbShowPOIImage.Checked then + MapView.POIImage.Assign(POIImage) + else + MapView.POIImage.Clear; +end; + +procedure TMainForm.CbUseThreadsChange(Sender: TObject); +begin + MapView.UseThreads := CbUseThreads.Checked; +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); +begin +// FMapMarker := CreateMapMarker(32, clRed, clBlack); + POIImage := TPortableNetworkGraphic.Create; + POIImage.PixelFormat := pf32bit; + POIImage.LoadFromFile('../../mapmarker.png'); + + ForceDirectories(HOMEDIR + 'example_cache/'); + MapView.CachePath := HOMEDIR + 'example_cache/'; + MapView.GetMapProviders(CbProviders.Items); + CbProviders.ItemIndex := CbProviders.Items.Indexof(MapView.MapProvider); + MapView.DoubleBuffered := true; + MapView.Zoom := 1; + CbUseThreads.Checked := MapView.UseThreads; + CbDoubleBuffer.Checked := MapView.DoubleBuffered; + CbPOITextBgColor.Selected := MapView.POITextBgColor; + + InfoPositionLongitude.Caption := ''; + InfoPositionLatitude.Caption := ''; + InfoCenterLongitude.Caption := ''; + InfoCenterLatitude.Caption := ''; + InfoViewportWidth.Caption := ''; + InfoViewportHeight.Caption := ''; + GPSPointInfo.caption := ''; + + ReadFromIni; +end; + +procedure TMainForm.FormDestroy(Sender: TObject); +begin + WriteToIni; + ClearFoundLocations; + FreeAndNil(POIImage) +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); +const + R = 5; +var + P: TPoint; + ext: TSize; +begin + // Screen coordinates of the GPS point + P := TMapView(Sender).LonLatToScreen(APoint.RealPoint); + + // Draw the GPS point with MapMarker bitmap + { + if CbShowPOIImage.Checked and not MapView.POIImage.Empty then begin + ADrawer.DrawBitmap(P.X - MapView.POIImage.Width div 2, P.Y - MapView.POIImage.Height, MapView.POIImage, true); + end else begin + } + // Draw the GPS point as a circle + ADrawer.BrushColor := clRed; + ADrawer.BrushStyle := bsSolid; + ADrawer.Ellipse(P.X - R, P.Y - R, P.X + R, P.Y + R); + P.Y := P.Y + R; + //end; + { + // Draw the caption of the GPS point + ext := ADrawer.TextExtent(APoint.Name); + ADrawer.BrushColor := clWhite; + ADrawer.BrushStyle := bsClear; + ADrawer.TextOut(P.X - ext.CX div 2, P.Y + 5, 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.ScreenToLonLat(Point(X-DELTA, Y-DELTA)); + rArea.BottomRight := MapView.ScreenToLonLat(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 (%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; +begin + if (Button = mbRight) then begin + if not InputQuery('Name of GPS location', 'Please enter name', gpsName) then + exit; + rPt := MapView.ScreenToLonLat(Point(X, Y)); + gpsPt := TGpsPoint.CreateFrom(rPt); + 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; +begin + ini := TMemIniFile.Create(CalcIniName); + try + HERE_AppID := ini.ReadString('HERE', 'APP_ID', ''); + HERE_AppCode := ini.ReadString('HERE', 'APP_CODE', ''); + OpenWeatherMap_ApiKey := ini.ReadString('OpenWeatherMap', 'API_Key', ''); + + if ((HERE_AppID <> '') and (HERE_AppCode <> '')) or + (OpenWeatherMap_ApiKey <> '') then + begin + MapView.Engine.ClearMapProviders; + MapView.Engine.RegisterProviders; + MapView.GetMapProviders(CbProviders.Items); + end; + + 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); + + s := ini.ReadString('MapView', 'Provider', MapView.MapProvider); + if CbProviders.Items.IndexOf(s) = -1 then begin + MessageDlg('Map provider "' + s + '" not found.', mtError, [mbOK], 0); + s := CbProviders.Items[0]; + end; + MapView.MapProvider := s; + CbProviders.Text := MapView.MapProvider; + + 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; + + finally + ini.Free; + end; +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.ScreenToLonLat(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; + L: TStringList; + 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.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); + + ini.EraseSection('Locations'); + for i := 0 to CbLocations.Items.Count-1 do + ini.WriteString('Locations', 'Item'+IntToStr(i), CbLocations.Items[i]); + + 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. + diff --git a/components/lazmapviewer/example_with_addons/mapmarker.png b/components/lazmapviewer/example_with_addons/mapmarker.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd3220682389aee006f9a3a40b529d2d20fec7b GIT binary patch literal 3920 zcmV-W53lfvP)<h;3K|Lk000e1NJLTq001BW001rs1^@s6NpKs4000U%X+uL$b5ch_ zAW20-HZeIiHZ3wPF#rH~oSl|;R8!d&htIt?y-<=6ij>f6Xi@@54ZTQ_E-Enz5K6$1 z03tR-RB%L5k){YTDBysjLy@r}iiH7DvFijGMAUI`6dRUFWUU$Bym{}<o8KSzerun- z&)sM5eb%}Fko<!M!c15RfDEBn6yfK^h>eS9U<UyV@BjmB0N`-5vqBd5Mgo}veAtX^ znG^UIy}Aw{`THu<Ka9Zu|DTk(St2n2P?(J8^7z?Y85hYoJy)D1w@=BKwlq!7FiOrM zS%NZFlXLPcTYUDJWe+*?GK4%C%X7}+W$@(OC*zGd626R)U>O(Z2>7`&z9wUXbV-Il z#&6`Y8GKGQ04S2&F6MJnWNa;Ck|;8QE#r9r;7G||@X{|>%+C|c55>;RS}qbKr-&IQ zTvLXPlM{>K&(BTgi^a?^4mXV>;xX8n8Ce|RasXz}{8<!vZ5gs6JJ>imI52H3ZN4bf ze_i~WlJ|C&UW9+{8AKoW!}eExnGFE2re(F+`iE_46#!l90Z_aBhs|Iw0E)7{bq;-T z9=d#9QpDmcXDh4R++0fmpKB>E=<oWU4u3;me9uz8-S6dLc=MAul5{acUN>%LdZt9g z$j;($`3&Zthxi`{{&gM}5&R^+h%b~yM9Zd3AWW9ETgVfL1(`yIK=_}U_z%PWq}jQa ziQ4!P(3V&Nr6C$XejWfQDiI(Fdt@un?|lo#M+5oIi_w{wo%_#%{(V=tO#a9gB!7-$ zM?^BX5>d|Vn*3S<G#~&)Km+PP8|VWQzy!9y5x4*k-~$3dD2N1cU@_o=6p#T#AQu#X zwV)W3f~{aDs0MYQ5j2A~a2RxfW8gG62QGojU<BL&QZNplfGO|_%s>!?g~$*UQipUP zL&zMmg;<aq<O2mm5l|eI2qi;8NCFi=>!4Do9IA%up=Rh?=qPj=x&RGBx1dpI68aT- z2O}^EromdU5o`ssU{5#*j)WJ%$?!5bA1;Eoz?E<Vd=T!0Ps5ks5m*X8fu|9G5D_|} zi!c!u!bU=ocq9oCA*+xQqylL`+K?WkAGwN1k*CO86b3~_F;GmD3(6lAh2o-?p;n<b zqpDE{P@Skg)K%0dY6|rcO-5^?&C$;20CX%m8J&wRMpvMl&>iTr=n?cd`V|I)p<|3O zju?MT93~aB0<#&j8`F+Cg&D?-VWzQItUA^l>xvD<a<F1-F}4bO5PK4P1v`#?gCpW} zaJD#KTs%&QE5udcT5u<DS8x-!8N3qS5bul+#q;pX@n!f%d=GvIKaQUvC=-kcu7pTJ zDq$_5lF&vtOSnsTK_n9Oh)%?CqJX%DSV=rYJWm`Yz9mseW+XN#fg~YqA?+ufBHbdr zAd|^PWDjyYSxnwSZYG~0-zUFOpek4@1Ss$nRx8vfbShj?c&3O~G*t9dT&$R{SfO}C zaY*s05?;wjiLJy@TBTH@bX4hv(zG&F*+w~3IYW7~a*Of><wq1O#faiV;Zcex`zU89 zV^oByPi0fN)OFNG>RIYI4MQ`g1<+DyrL=EogS06Xii({|v`U^zjmmKqDIK93(F5q| z^fLNk`gQs{RV`IdRle#b)i%{Ds;|}NsClUI)k@Ub)kf6bsWa4l)YH_rsduU0(?DsM zX@qO!YV6TCtMPOWZH~(v?wpc2hv(eZgf-1HBQ#fN?$aF5oYvCT^3%%Fs?s{6^;Da# z?V+8jy+iwi_M{F~$4y6|vqR^k&SQoO!;_KDsATjprgSxR{dFa}^}2()GkV5)QF?`X z?Rxk03HmJkB>f%wz4}uIItC#I1qQ7Kw+-=zEW;GTU55RJuZ@h2VvIHzbs0S}Rx=JT z&Npr~zH34@aW`3J(qMAU6l2OVO*7qXdf5y%vo}jIt1%lghs_<#1?IcWhb_<+P8LFo z28$a^64R5J!)#@aTGB0pEekEXET35!SjAgyv+B3{Xl-wuZrx~o$A)4PXj5p@WAm%6 znJw40#`fA=@?77!tLJvleQsxN$G6*KchjC~A7a13zSsVPgQJ7Uq0M2^(ZDg$vDWbh zi^d9LZDyT!LOXdmt#&%*^w!zIS?qk+`4<<aOPWiI%cFV5^Z4@`=Z(4QxpG|VU8Qae zw?wzSZc=w$caD35`vVVs51vPp$AqV;XR7Bx&u3oNULvm!uh(p6_Dc3CZ^YZryTp6Y zhvF0EQ|)u#SI;-ux7Byb&)#o^-zk5ze~|w+{~G~X0o;J*fT=*oz?Ff0L8PDsLDfMI zg3W?O!95{xNMOkJkh}8@=L_d|g@Vw4(Cwl3!i>X~g?%562@eae34a)26HyS+zks@6 z$%2*zuOhu7%OdYYnM6sVdZQJi6QY}=U&naIl*dS8tzuWkUW(I*6U24LW8<Uao8qSz z`YhbJa6G|2p*Z3CBI8AQi!LnISe(B2_!7k>oFzvR(TOpMEs5_rp_~TJ^wNN(wM(bC zZ0;`Z6P^ce2XB(^$}i_nB)KM)Cp}7bP2Qe7nc|*Ok@8f)7E}wKr~0SXrM^xJP1~RL zDLp2=Jp-4Km~m7{5vB?IGPN`FGKaIwvx>8%%bb_(Ts9>N5;bK**^9Ef#WdN^)PTf9 zvR*Qp<CasC^CmYs_eh>{o-l7<x!Lkf%O~=E^S@q!TESh>TcBI8wqSIn=gRt3(5j`Y zdRObOE?Pal#&6AmwS={4Ykw%TE-Wv6xh`g1Pmxy9nxe7we(PI{6^cd0H#WFzsN0Cz zDA+i-Y3`<~O&?2mB^OJrODjs>Z{}{k_?699m0x|@lC)*8%%N=0R?Jr6*6Z8cw;d=~ zF3&F?+a9vLa|dHb$&Qyhm+ZVyVOLSNi?B<wOIjIR*<EE&wYBPfbxQR}jaN;3t!C|} z+Sj{zyRYo=*wa?0RaaW~Zm(eP&3eE3&IY4~ihY=UIr|<qMmP3<&HB2zNu#N>>BD~E ze(8aT1AWbo&CM;EEoH56tE6@EV8X%6-*|u1-NtOIZ>P7H9s-9XhaP{M`0e$>L5F*f zu#U8SXZT%h2eqT56Y5;vIn|ZYCGC#u9zGg)w718lr{jCe@An_mJyvsE<#^c%!il02 zpHAkVoIaIx>gnm^(__6$dheWxJ#(!uyl?Pq(Ao3ne9xWf_v}A;-u3*k3(gmgUSwVD zy5w-FbHIL};|Kd6ItCpEJBJ*Hx-UCj?irppeBz4xmD5+fub#UWaP88_{E^}7QP*$Y zNVp-r$-DXJR{E{yw{vdK+*xxMeYfPE(!GlNn)e%iH2tw%>L5Kn>ODH}V8MesW8ASP zKV|>)e!S=*`C-L`&P4Mg+egPHeJ3wJUif(YN!F8@r^P=j|6Kdb<k@$>c>FRj6+1Ql zT=e|YubW?}zu5oM?q%<E*!2BZ8Lwtum%LGbbKouOZU4KNcM~(Y@3HSIKbU^#`55%^ z?x&1TpMC@Pg!B84aAqn1000SaNLh0L04^f{04^f|c%?sf000EPNkl<Zc$~GETZmO< z6vx*$bDZPYsKKa&N*Bh5sE3;DVM1*vD7r8YrCo8Vmzg1k62fVqoEeW+N*FzKfxsS$ z2qcA=>|uH^Eg>Zzj6ox?a-thd5~!GSUH#UaeTL(i{q5Tv7i`Wxd#|<r|L?XgJEy9W zL`I!!XcT$aiQL2A+ql+nEeT$q=Q_jn1Kz$qC-UWT)r(2|=He8_oNKBRd3l-0(||X4 z)RqNT3p!ogTvX>i9T#~suljQ)0%x4dH;MEEz7?l+aYV}{Alix1a}e1BgB@#B#}X4@ z)HeaXA4hkj0S+Nz#9zVJgZSLYZ2THaV8XduvHA+*mGc3wAkvJ_qximmf$AwQfy>U_ zkQW)MCU_Z%m4FR_v2LO2$Q%N}njb)MRkgv(NUUOj2f$ia+7q(`0N;kf+9Zy&c;t@o z`&;1ndVX46@o2`8SZi3^_RSJtgWSj(^&|j3I>n~SseT(cyFw<N+fXa=2G7^WxatA( zLpJ5v83G25Q9c6L!c}3X$j$-PX`h}ED>&E6(E9K<;O26afOtL_aCh!6=N4Tj(jG+@ z@a;9KI|gEgWfBl9OgpCl6(UsI!S2be5P1N_#S!2~82M{Sz{|yK`bF-=cWc;t!!+z% z4N6gtSo7YfY4?fQuqS$1<6}M@!?r!p>{DR$r&-tIX~9ckwuIu-jP@3fO0yAYituqb zD|m$uAAu$#u+(SC44e(!#wjGm$5JCu8(}{+Py9F^wMM{-iN>(E)yN4kKF%9~5g!5M zuK5y(@iAfqhQ*)vTdX3At7?1_R8uVxD#JMoG)&X8VQ+a}g9D2}&txG`R}9BBzW0Wm zyCib(8mmJ@7I^eFPdPVOtGYi8I5wL=-W&lwVc59_)lq`QAkQ|2DOy6o(Z@I(gTxmJ z!Q0Hnmy7}#H0+sd$T``~S$s4id)4FcbBMl2tzB5GdM-@wf^&^jqXX!6$4tE%rh(58 zAY`7v`95x+^ce*XUjU#3-9y};z|o(<J3DH3HWZW3!iZ6qWS?P*lvP9%q+B+^<5A25 zFavnVt}Ia!($n+{ua=6BSps#cKQXe`B`B4ymOx+|$NHDj|0}9ur`ivRHb!>)RRTXw zVY93J*_^(B>Dk2jJrz}=Wdy%;8Q=94&*u=Zs7E<v0c3ZT3G~*h{$BY!v^AsTed}(K zr(CfMt_JuqO0@UG%DPYjt*VohQys*H?_6}cP69qLNu%m3>%84D=k$9v<h$H%nGXSE z5B=b<7bnW{AC3&Y{v$!>lUl5U`hx;_b%ahN0sG29T<>NL66JsjaGUe4)vEtR>BW8_ zApsp^DL!Ks9!tsLBWw@FDa8^nVF)jBe(!_CwMq0D{U}LmtGC-pOJI@e-^7Mq2z-!` zz)QZ2nTdc2=XfuzR(o9M3-}P>_LHQ36BDp=Jnmd48S|v?qm_kQLizJ)Vt8T#CS=SX z*^rh@LVH!~qQgE!RgHiN<?$|hxhI%~n=8Oi62jjOZH22zz`pGern`s@hf5_K;8T=X zofg8=`b$k<#z^%WmSQir9l@h_EOck`mBq;90_l}=-p1`XA-ivRMn9PeEK&WJ*s#TR ee$o%qVe&r`BZSeVTOhvx0000<MNUMnLSTY}MtUCr literal 0 HcmV?d00001