unit IngeoPaintHints;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
	Classes, SysUtils, ComObj, ActiveX, Graphics, Contnrs, StdVcl, Ingeo_TLB,
	RefObjects,	InScripting_TLB, GraphicUtils;


type
	TPaintHint = class;
	TPaintHintList = class;
	TPaintHintManager = class;

	TPaintHint = class(TRefObject)
	private
		FOwner: TPaintHintManager;
		FAttr: TPenAttrsEx;
		FContour: IIngeoContour;
		FVisible: Boolean;
		FWorld: Boolean;

		FUpdateCount: Integer;

		procedure SetVisible(const Value: Boolean);
	public
		constructor Create(aContour: IIngeoContour; anAttr: TPenAttrsEx; aWorld: Boolean = True);

		procedure BeginUpdate;
		procedure EndUpdate;
		procedure RepaintDragging(aSurface: IIngeoPaintSurface);
		procedure Refresh;

		property Attr: TPenAttrsEx read FAttr;
		property Visible: Boolean read FVisible write SetVisible;
		property Contour: IIngeoContour read FContour;
	end;

	TPaintHintList = class(TRefObjectList)
	private
		function GetItem(Index: Integer): TPaintHint;
	public
		function  Add(anItem: TPaintHint): TPaintHint;
		property Items[Index: Integer]: TPaintHint read GetItem; default;
	end;

	TPaintHintManager = class(TPaintHintList)
	private
		FMapWindow: IIngeoMapWindow;
		FDraggingVisible: Boolean;
		FVisible: Boolean;

		procedure SetVisible(const Value: Boolean);
	protected
		procedure Notify(Ptr: Pointer; Action: TListNotification); override;
	public
		constructor Create(aMapWindow: IIngeoMapWindow);

		function  Add(anItem: TPaintHint): TPaintHint;

		procedure RepaintDragging(aSurface: IIngeoPaintSurface);
		procedure Show;
		procedure Hide;

		property DraggingVisible: Boolean read FDraggingVisible;
		property Visible: Boolean read FVisible write SetVisible;
	end;

implementation

uses ComServ;

{ TPaintHint }

constructor TPaintHint.Create(aContour: IIngeoContour; anAttr: TPenAttrsEx;
	aWorld: Boolean);
begin
	inherited Create;
	FContour := aContour;
	FAttr := anAttr;
	FWorld := aWorld;
	FVisible := True;
end;

procedure TPaintHint.BeginUpdate;
begin
	if not Assigned(FOwner) or not Assigned(FOwner.FMapWindow) or
		not Assigned(FOwner.FMapWindow.Surface)
	then
		Exit;
	if FOwner.DraggingVisible and Visible then
		RepaintDragging(FOwner.FMapWindow.Surface);
	Inc(FUpdateCount);
end;

procedure TPaintHint.EndUpdate;
begin
	if not Assigned(FOwner) or not Assigned(FOwner.FMapWindow) or
		not Assigned(FOwner.FMapWindow.Surface)
	then
		Exit;
	Assert(FUpdateCount > 0);
	Dec(FUpdateCount);
	if (FUpdateCount = 0) and FOwner.DraggingVisible and Visible then
		RepaintDragging(FOwner.FMapWindow.Surface);
end;

procedure TPaintHint.RepaintDragging(aSurface: IIngeoPaintSurface);
begin
	if FUpdateCount > 0 then
		Exit;

	if Assigned(aSurface) then begin
		with aSurface do begin
			Pen.Style := ord(FAttr.Style);
			Pen.WidthInMM := FAttr.WidthInMM;
			Pen.ForZoomScale := FAttr.ForZoomScale;
			Pen.Color := FAttr.Color;
			Pen.Mode := inpmXor;
			Brush.Style := inbsClear;

			PaintContour(FContour, FWorld);
		end;
	end;
end;

procedure TPaintHint.SetVisible(const Value: Boolean);
begin
	if FVisible <> Value then begin
		FVisible := Value;
		if Assigned(FOwner) and Assigned(FOwner.FMapWindow) and FOwner.DraggingVisible then
			RepaintDragging(FOwner.FMapWindow.Surface)
	end;
end;


procedure TPaintHint.Refresh;
begin
	if not Visible then
		Exit;
	Visible := False;
	Visible := True;
end;

{ TPaintHintList }

function TPaintHintList.Add(anItem: TPaintHint): TPaintHint;
begin
	Result := anItem;
	inherited Add(anItem);
end;

function TPaintHintList.GetItem(Index: Integer): TPaintHint;
begin
	Result := TPaintHint(inherited Items[Index]);
end;


{ TPaintHintManager }

function TPaintHintManager.Add(anItem: TPaintHint): TPaintHint;
begin
	anItem.FOwner := Self;
	Result := inherited Add(anItem);
end;

constructor TPaintHintManager.Create(aMapWindow: IIngeoMapWindow);
begin
	inherited Create;
	FMapWindow := aMapWindow;
	FDraggingVisible := True;
	FVisible := True;
end;

procedure TPaintHintManager.Show;
var
	i: Integer;
begin
	if not FVisible then begin
		FVisible := True;
		for i := 0 to Count - 1 do
			Items[i].Visible := True;
	end;
end;

procedure TPaintHintManager.Hide;
var
	i: Integer;
begin
	if FVisible then begin
		FVisible := False;
		if FDraggingVisible then
			if Assigned(FMapWindow) and Assigned(FMapWindow.Surface) then
				RepaintDragging(FMapWindow.Surface);

		try
			for i := 0 to Count - 1 do
				Items[i].Visible := False;
		finally
			FDraggingVisible := True;
		end;
	end;
end;

procedure TPaintHintManager.Notify(Ptr: Pointer;	Action: TListNotification);
begin
	if Assigned(FMapWindow) and Assigned(FMapWindow.Surface) and
		FDraggingVisible and Assigned(Ptr)
	then begin
		TPaintHint(Ptr).RepaintDragging(FMapWindow.Surface);
	end;
	inherited;
end;

procedure TPaintHintManager.RepaintDragging(aSurface: IIngeoPaintSurface);
var
	i: Integer;
begin
	if not Assigned(aSurface) then
		Exit;
	FDraggingVisible := not FDraggingVisible;
	for i := 0 to Count - 1 do
		if Items[i].Visible then
			Items[i].RepaintDragging(aSurface);
end;

procedure TPaintHintManager.SetVisible(const Value: Boolean);
begin
	if FVisible = Value then
		Exit;
	if Value then
		Show
	else
		Hide;
end;


end.
