lazarus-ccr/components/lazmapviewer/source/mvmapviewerpatheditform.pas
wp_xxyyzz 243e25f62b LazMapViewer: Less hints and warnings
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9473 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2024-09-30 15:44:03 +00:00

485 lines
12 KiB
ObjectPascal

unit mvMapViewerPathEditForm;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
Buttons, ActnList, mvMapViewer;
type
{ TMapViewerPathEditForm }
TMapViewerPathEditForm = class(TForm, IFPObserver)
actDelTP: TAction;
actNewArea: TAction;
actSelect: TAction;
actNewTP: TAction;
actNewTrack: TAction;
actNewPOI: TAction;
actZoomOut: TAction;
actZoomIn: TAction;
alEditActions: TActionList;
cbSelectedLayer: TEdit;
cbSelectedPt: TEdit;
ilImages: TImageList;
lblSelectedPt: TLabel;
lblSelectedLayer: TLabel;
pnlFrame: TPanel;
pnlTools: TPanel;
btnSelect: TSpeedButton;
btnNewTP: TSpeedButton;
btnDelTP: TSpeedButton;
btnNewPOI: TSpeedButton;
btnNewArea: TSpeedButton;
btnNewTrack: TSpeedButton;
btnZoomIn: TSpeedButton;
btnZoomOut: TSpeedButton;
procedure actDelTPExecute(Sender: TObject);
procedure actNewAreaExecute(Sender: TObject);
procedure actNewPOIExecute(Sender: TObject);
procedure actNewTPExecute(Sender: TObject);
procedure actNewTrackExecute(Sender: TObject);
procedure actSelectExecute(Sender: TObject);
procedure actZoomInExecute(Sender: TObject);
procedure actZoomOutExecute(Sender: TObject);
private
FMapLayer: TMapLayer;
FMapView: TMapView;
FInternalSelect: Boolean;
procedure SetMapLayer(AValue: TMapLayer);
procedure SetMapView(AValue: TMapView);
procedure FPOObservedChanged(ASender: TObject; Operation: TFPObservedOperation; Data: Pointer);
protected
procedure UpdateControls;
procedure PersistentAdded({%H-}APersistent: TPersistent; {%H-}Select: Boolean); virtual;
procedure DeletePersistent({%H-}APersistent: TPersistent); virtual;
procedure UnselectPersistent({%H-}APersistent: TPersistent); virtual;
procedure ObjectModified({%H-}AObject: TObject; {%H-}PropName: ShortString = ''); virtual;
procedure SelectInOI(AView: TMapView; {%H-}ForceUpdate: Boolean); virtual;
property InternalSelect: Boolean read FInternalSelect write FInternalSelect;
public
destructor Destroy; override;
property MapView: TMapView read FMapView write SetMapView;
property MapLayer: TMapLayer read FMapLayer write SetMapLayer;
end;
var
MapViewerPathEditForm: TMapViewerPathEditForm;
implementation
uses mvTypes, Math;
{$R *.lfm}
{ TMapViewerPathEditForm }
procedure TMapViewerPathEditForm.actSelectExecute(Sender: TObject);
begin
; //
end;
procedure TMapViewerPathEditForm.actNewPOIExecute(Sender: TObject);
var
CP: TMapPoint;
NP: TPointOfInterest;
R: TRealPoint;
V: TMapView;
begin
V := MapView;
if not Assigned(MapLayer) or not V.EditMark.HasSelection then
Exit;
CP := MapView.EditMark.CurrentPoint;
NP := MapLayer.PointsOfInterest.Add as TPointOfInterest;
NP.Assign(CP);
if CP is TPointOfInterest then
begin
NP.Caption := TPointOfInterest(CP).Caption;
NP.ImageIndex := TPointOfInterest(CP).ImageIndex;
end;
R := MapView.ScreenToLatLon(CP.ToScreen + Point(10, 10));
NP.Latitude := R.Lat;
NP.Longitude := R.Lon;
MapView.EditMark.ClearSelection;
MapView.EditMark.Selection.Insert(0, NP);
try
PersistentAdded(NP, True);
finally
MapView := V;
SelectInOI(V, False);
end;
UpdateControls;
end;
procedure TMapViewerPathEditForm.actNewTrackExecute(Sender: TObject);
var
P, NP: TMapPoint;
T, NT: TMapTrack;
R: TRealPoint;
I: Integer;
V: TMapView;
begin
V := MapView;
if not Assigned(MapLayer) or not V.EditMark.HasSelection or
(V.EditMark.Selection.Count < 2) then
Exit;
T := MapView.EditMark.CurrentTrack;
NT := MapLayer.Tracks.Add as TMapTrack;
for P in V.EditMark.Selection.Points do
begin
NP := NT.Points.Add as TMapPoint;
NP.Assign(P);
R := MapView.ScreenToLatLon(P.ToScreen + Point(10, 10));
NP.Latitude := R.Lat;
NP.Longitude := R.Lon;
end;
MapView.EditMark.ClearSelection;
for I := 0 to Pred(NT.Points.Count) do
begin
MapView.EditMark.Selection.Add(NT.Points);
MapView.EditMark.Selection.Insert(0, NT.Points[I]);
end;
if Assigned(T) then
begin // NT.Assign(T)?
NT.LineColor := T.LineColor;
NT.LineWidth := T.LineWidth;
NT.ConnectColor := T.ConnectColor;
NT.ConnectWidth := T.ConnectWidth;
NT.Opacity := T.Opacity;
end;
try
PersistentAdded(NT, True);
finally
MapView := V;
SelectInOI(V, False);
end;
UpdateControls;
end;
procedure TMapViewerPathEditForm.actNewAreaExecute(Sender: TObject);
var
P, NP: TMapPoint;
A, NA: TMapArea;
R: TRealPoint;
I: Integer;
V: TMapView;
begin
V := MapView;
if not Assigned(MapLayer) or not V.EditMark.HasSelection or
(V.EditMark.Selection.Count < 3) then
Exit;
A := MapView.EditMark.CurrentArea;
NA := MapLayer.Areas.Add as TMapArea;
for P in V.EditMark.Selection.Points do
begin
NP := NA.Points.Add as TMapPoint;
NP.Assign(P);
R := MapView.ScreenToLatLon(P.ToScreen + Point(10, 10));
NP.Latitude := R.Lat;
NP.Longitude := R.Lon;
end;
MapView.EditMark.ClearSelection;
for I := 0 to Pred(NA.Points.Count) do
begin
MapView.EditMark.Selection.Add(NA.Points);
MapView.EditMark.Selection.Insert(0, NA.Points[I]);
end;
if Assigned(A) then
begin // NA.Assign(A)?
NA.LineColor := A.LineColor;
NA.LineWidth := A.LineWidth;
NA.FillColor := A.FillColor;
NA.Opacity := A.Opacity;
end;
try
PersistentAdded(NA, True);
finally
MapView := V;
SelectInOI(V, False);
end;
UpdateControls;
end;
procedure TMapViewerPathEditForm.actNewTPExecute(Sender: TObject);
var
P: TMapPoint;
L: TMapTrack;
A: TMapArea;
C: TCollection;
I, I1, I2: Integer;
V: TMapView;
procedure InsertPt(J: Integer; ANext: TMapPoint);
var
PN: TMapPoint;
begin
PN := C.Insert(J) as TMapPoint;
PN.Latitude := (P.Latitude + ANext.Latitude) / 2;
PN.Longitude := (P.Longitude + ANext.Longitude) / 2;
MapView.EditMark.Selection.Add(C);
MapView.EditMark.Selection.Insert(0, PN);
PersistentAdded(PN, True);
end;
begin
P := MapView.EditMark.CurrentPoint;
L := MapView.EditMark.CurrentTrack;
if Assigned(L) then
C := L.Points
else
begin
A := MapView.EditMark.CurrentArea;
if not Assigned(A) then
Exit;
C := A.Points;
end;
I := P.Index;
if I < 0 then
Exit;
I1 := (I + 1) mod C.Count; // Next point index
if I > 0
then I2 := Pred(I) // Prev point index
else I2 := Pred(C.Count);
V := MapView;
try
// If the next point on track/area is selected
// then insert before next
if MapView.EditMark.IsSelected(C.Items[I1]) then
InsertPt(I1, C.Items[I1] as TMapPoint)
// If the prev point on track/area is selected
// then insert before current
else if MapView.EditMark.IsSelected(C.Items[I2]) then
InsertPt(I, C.Items[I2] as TMapPoint)
// If the current point is not the last
// then insert before next(last)
else if I < Pred(C.Count) then
InsertPt(I1, C.Items[I1] as TMapPoint)
// else insert before current
else
InsertPt(I, C.Items[I2] as TMapPoint);
finally
MapView := V;
SelectInOI(V, False);
end;
UpdateControls;
end;
procedure TMapViewerPathEditForm.actDelTPExecute(Sender: TObject);
var
Pt: TMapPoint;
PtCol: TCollection;
P: TPersistent;
begin
Pt := MapView.EditMark.CurrentPoint;
PtCol := Pt.Collection;
if not (Pt is TPointOfInterest) then
if PtCol.Count < 3 then
; // TODO Just 3 points left?
if MessageDlg('Confirm deletion', 'Are you sure you want to delete ''' +
Pt.DisplayName + '''?', mtConfirmation, mbYesNo, 0 ) <> mrYes then
Exit;
// Exclude from the selection
MapView.EditMark.Selection.DelIfPresent(PtCol);
MapView.EditMark.Selection.DelIfPresent(Pt);
// No points left?
if MapView.EditMark.HasSelection and
not (MapView.EditMark.Selection[0] is TMapPoint) then
MapView.EditMark.ClearSelection; // Clear the whole selection
// Delete from the object inspector
UnselectPersistent(Pt);
P := Pt; DeletePersistent(P);
UpdateControls;
end;
procedure TMapViewerPathEditForm.actZoomInExecute(Sender: TObject);
begin
MapView.Zoom := MapView.Zoom + 1;
UpdateControls;
end;
procedure TMapViewerPathEditForm.actZoomOutExecute(Sender: TObject);
begin
MapView.Zoom := MapView.Zoom - 1;
UpdateControls;
end;
procedure TMapViewerPathEditForm.SetMapLayer(AValue: TMapLayer);
begin
if FMapLayer = AValue then Exit;
FMapLayer := AValue;
end;
procedure TMapViewerPathEditForm.SetMapView(AValue: TMapView);
begin
if FMapView = AValue then
Exit;
// Detach the old FMapView
if Assigned(FMapView) then
begin
FMapView.FPODetachObserver(Self);
FMapView.ControlStyle := FMapView.ControlStyle - [csDesignInteractive];
end;
// Attach the new FMapView
if Assigned(AValue) then
begin
AValue.FPOAttachObserver(Self);
if Visible then
AValue.ControlStyle := AValue.ControlStyle + [csDesignInteractive];
end;
FMapView := AValue;
UpdateControls;
end;
procedure TMapViewerPathEditForm.FPOObservedChanged(ASender: TObject;
Operation: TFPObservedOperation; Data: Pointer);
var
What: TMapObserverCustomOperation;
V: TMapView;
procedure Clicked;
begin
if actSelect.Checked then
Exit;
//...
end;
begin
if Operation <> ooCustom then
Exit;
V := ASender as TMapView;
What := PMapObserverCustomOperation(Data)^;
case What of
mooSelectionCompleted:
SelectInOI(V, False);
mooStartDrag:
Clicked;
mooIsDirty: ;
mooDrag: ;
mooEndDrag:
if V.EditMark.Dirty then
begin
ObjectModified(Self, 'Layers');
V.EditMark.Dirty := False;
end;
end;
end;
procedure TMapViewerPathEditForm.SelectInOI(AView: TMapView; ForceUpdate: Boolean);
begin
if not Assigned(AView) then
Exit;
UpdateControls;
end;
destructor TMapViewerPathEditForm.Destroy;
begin
MapView := Nil;
inherited Destroy;
end;
procedure TMapViewerPathEditForm.UpdateControls;
var
P: TMapPoint;
PtTxt: String;
PtCnt: Integer = 0;
HaveView, HaveLayer, HaveSel, HavePt: Boolean;
begin
HaveView := Assigned(MapView);
HaveSel := HaveView and MapView.EditMark.HasSelection;
HavePt := HaveSel and (MapView.EditMark.Selection[0] is TMapPoint);
HaveLayer := Assigned(MapLayer) and HaveSel;
if HavePt and not HaveLayer then
begin
MapLayer := (MapView.EditMark.Selection[0] as TMapPoint).Layer;
HaveLayer := True;
end;
if HaveView
then Caption := MapView.Name + ': ' + TMapView.ClassName
else Caption := TMapView.ClassName + ' (Not selected)';
// Update layer name
if HaveLayer
then cbSelectedLayer.Text := MapLayer.DisplayName
else cbSelectedLayer.Text := '(none)';
cbSelectedLayer.Hint := cbSelectedLayer.Text;
// Update currently selected point
PtTxt := '(none)';
if HavePt then
begin
for P in MapView.EditMark.Selection.Points do
Inc(PtCnt);
P := TMapPoint(MapView.EditMark.Selection[0]);
if PtCnt > 0 then
begin
PtTxt := P.DisplayName;
if PtTxt <> P.ClassName then
PtTxt := PtTxt + ': ' + P.ClassName;
if PtCnt > 1 then
PtTxt := PtTxt + Format(' +%d more', [PtCnt - 1]);
end;
end;
cbSelectedPt.Text := PtTxt;
cbSelectedPt.Hint := PtTxt;
// Update actions
actZoomIn.Enabled := HaveView and (MapView.Zoom < MapView.ZoomMax);
actZoomOut.Enabled := HaveView and (MapView.Zoom > MapView.ZoomMin);
actNewPOI.Enabled := HaveView and HaveLayer;
actNewTrack.Enabled := HaveView and HaveLayer and InRange(PtCnt, 2, 10);
actNewArea.Enabled := HaveView and HaveLayer and InRange(PtCnt, 3, 10);
actNewTP.Enabled := HaveView and HavePt;
actDelTP.Enabled := HaveView and HavePt;
actSelect.Enabled := HaveView;
end;
procedure TMapViewerPathEditForm.PersistentAdded(APersistent: TPersistent;
Select: Boolean);
begin
;
end;
procedure TMapViewerPathEditForm.DeletePersistent(APersistent: TPersistent);
begin
;
end;
procedure TMapViewerPathEditForm.UnselectPersistent(APersistent: TPersistent);
begin
;
end;
procedure TMapViewerPathEditForm.ObjectModified(AObject: TObject;
PropName: ShortString);
begin
;
end;
end.