You've already forked lazarus-ccr
LazMapViewer: Avoid drawing artefacts when the mapview is dragged. Patch by Ekkehard Domning.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8830 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -40,9 +40,9 @@ object MainForm: TMainForm
|
|||||||
Height = 640
|
Height = 640
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 275
|
Width = 275
|
||||||
ActivePage = PgData
|
ActivePage = PgConfig
|
||||||
Align = alRight
|
Align = alRight
|
||||||
TabIndex = 0
|
TabIndex = 1
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
object PgData: TTabSheet
|
object PgData: TTabSheet
|
||||||
Caption = 'Data'
|
Caption = 'Data'
|
||||||
@ -834,6 +834,7 @@ object MainForm: TMainForm
|
|||||||
Width = 100
|
Width = 100
|
||||||
BorderSpacing.Left = 6
|
BorderSpacing.Left = 6
|
||||||
BorderSpacing.Top = 8
|
BorderSpacing.Top = 8
|
||||||
|
BorderSpacing.Right = 24
|
||||||
Caption = 'Zoom to cursor'
|
Caption = 'Zoom to cursor'
|
||||||
Checked = True
|
Checked = True
|
||||||
OnChange = CbZoomToCursorChange
|
OnChange = CbZoomToCursorChange
|
||||||
@ -848,13 +849,28 @@ object MainForm: TMainForm
|
|||||||
Height = 19
|
Height = 19
|
||||||
Top = 56
|
Top = 56
|
||||||
Width = 77
|
Width = 77
|
||||||
BorderSpacing.Left = 24
|
|
||||||
Caption = 'Cyclic view'
|
Caption = 'Cyclic view'
|
||||||
Checked = True
|
Checked = True
|
||||||
OnChange = cbCyclicViewChange
|
OnChange = cbCyclicViewChange
|
||||||
State = cbChecked
|
State = cbChecked
|
||||||
TabOrder = 8
|
TabOrder = 8
|
||||||
end
|
end
|
||||||
|
object ColorButton1: TColorButton
|
||||||
|
AnchorSideLeft.Control = cbCyclicView
|
||||||
|
AnchorSideTop.Control = CbUseThreads
|
||||||
|
AnchorSideTop.Side = asrCenter
|
||||||
|
Left = 130
|
||||||
|
Height = 25
|
||||||
|
Top = 78
|
||||||
|
Width = 105
|
||||||
|
BorderWidth = 2
|
||||||
|
ButtonColorAutoSize = False
|
||||||
|
ButtonColorSize = 15
|
||||||
|
ButtonColor = clWhite
|
||||||
|
Caption = 'Map backgr.'
|
||||||
|
Margin = 4
|
||||||
|
OnColorChanged = ColorButton1ColorChanged
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
object GeoNames: TMVGeoNames
|
object GeoNames: TMVGeoNames
|
||||||
@ -872,7 +888,7 @@ object MainForm: TMainForm
|
|||||||
MinFontSize = 0
|
MinFontSize = 0
|
||||||
MaxFontSize = 0
|
MaxFontSize = 0
|
||||||
Left = 808
|
Left = 808
|
||||||
Top = 104
|
Top = 200
|
||||||
end
|
end
|
||||||
object POIImages: TImageList
|
object POIImages: TImageList
|
||||||
Height = 48
|
Height = 48
|
||||||
|
@ -33,6 +33,7 @@ type
|
|||||||
cbPOITextBgColor: TColorBox;
|
cbPOITextBgColor: TColorBox;
|
||||||
CbZoomToCursor: TCheckBox;
|
CbZoomToCursor: TCheckBox;
|
||||||
cbCyclicView: TCheckBox;
|
cbCyclicView: TCheckBox;
|
||||||
|
ColorButton1: TColorButton;
|
||||||
FontDialog: TFontDialog;
|
FontDialog: TFontDialog;
|
||||||
GbCenterCoords: TGroupBox;
|
GbCenterCoords: TGroupBox;
|
||||||
GbScreenSize: TGroupBox;
|
GbScreenSize: TGroupBox;
|
||||||
@ -86,6 +87,7 @@ type
|
|||||||
procedure CbUseThreadsChange(Sender: TObject);
|
procedure CbUseThreadsChange(Sender: TObject);
|
||||||
procedure CbDistanceUnitsChange(Sender: TObject);
|
procedure CbDistanceUnitsChange(Sender: TObject);
|
||||||
procedure CbZoomToCursorChange(Sender: TObject);
|
procedure CbZoomToCursorChange(Sender: TObject);
|
||||||
|
procedure ColorButton1ColorChanged(Sender: TObject);
|
||||||
procedure FormCreate(Sender: TObject);
|
procedure FormCreate(Sender: TObject);
|
||||||
procedure FormDestroy(Sender: TObject);
|
procedure FormDestroy(Sender: TObject);
|
||||||
procedure FormShow(Sender: TObject);
|
procedure FormShow(Sender: TObject);
|
||||||
@ -410,6 +412,11 @@ begin
|
|||||||
MapView.ZoomToCursor := CbZoomToCursor.Checked;
|
MapView.ZoomToCursor := CbZoomToCursor.Checked;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.ColorButton1ColorChanged(Sender: TObject);
|
||||||
|
begin
|
||||||
|
MapView.InactiveColor := ColorButton1.ButtonColor;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMainForm.ClearFoundLocations;
|
procedure TMainForm.ClearFoundLocations;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
@ -732,6 +739,7 @@ begin
|
|||||||
pt.Lon := StrToFloatDef(ini.ReadString('MapView', 'Center.Longitude', ''), 0.0, PointFormatSettings);
|
pt.Lon := StrToFloatDef(ini.ReadString('MapView', 'Center.Longitude', ''), 0.0, PointFormatSettings);
|
||||||
pt.Lat := StrToFloatDef(ini.ReadString('MapView', 'Center.Latitude', ''), 0.0, PointFormatSettings);
|
pt.Lat := StrToFloatDef(ini.ReadString('MapView', 'Center.Latitude', ''), 0.0, PointFormatSettings);
|
||||||
MapView.Center := pt;
|
MapView.Center := pt;
|
||||||
|
MapView.InactiveColor := ini.ReadInteger('MapView', 'MapBkgrColor', MapView.InactiveColor);
|
||||||
|
|
||||||
s := ini.ReadString('MapView', 'DistanceUnits', '');
|
s := ini.ReadString('MapView', 'DistanceUnits', '');
|
||||||
if s <> '' then begin
|
if s <> '' then begin
|
||||||
@ -877,7 +885,7 @@ begin
|
|||||||
ini.WriteInteger('MapView', 'Zoom', MapView.Zoom);
|
ini.WriteInteger('MapView', 'Zoom', MapView.Zoom);
|
||||||
ini.WriteString('MapView', 'Center.Longitude', FloatToStr(MapView.Center.Lon, PointFormatSettings));
|
ini.WriteString('MapView', 'Center.Longitude', FloatToStr(MapView.Center.Lon, PointFormatSettings));
|
||||||
ini.WriteString('MapView', 'Center.Latitude', FloatToStr(MapView.Center.Lat, PointFormatSettings));
|
ini.WriteString('MapView', 'Center.Latitude', FloatToStr(MapView.Center.Lat, PointFormatSettings));
|
||||||
|
ini.WriteInteger('MapView', 'MapBkgrColor', MapView.InactiveColor);
|
||||||
ini.WriteString('MapView', 'DistanceUnits', DistanceUnit_Names[DistanceUnit]);
|
ini.WriteString('MapView', 'DistanceUnits', DistanceUnit_Names[DistanceUnit]);
|
||||||
|
|
||||||
if HERE_AppID <> '' then
|
if HERE_AppID <> '' then
|
||||||
|
@ -20,7 +20,7 @@ unit mvEngine;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, IntfGraphics, Controls, Math,
|
Classes, SysUtils, IntfGraphics, Controls, Math, GraphType, FPImage,
|
||||||
mvTypes, mvJobQueue, mvMapProvider, mvDownloadEngine, mvCache, mvDragObj;
|
mvTypes, mvJobQueue, mvMapProvider, mvDownloadEngine, mvCache, mvDragObj;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -59,9 +59,11 @@ type
|
|||||||
DragObj : TDragObj;
|
DragObj : TDragObj;
|
||||||
Cache : TPictureCache;
|
Cache : TPictureCache;
|
||||||
FActive: boolean;
|
FActive: boolean;
|
||||||
|
FBkColor: TFPColor;
|
||||||
FCyclic: Boolean;
|
FCyclic: Boolean;
|
||||||
FDownloadEngine: TMvCustomDownloadEngine;
|
FDownloadEngine: TMvCustomDownloadEngine;
|
||||||
FDrawTitleInGuiThread: boolean;
|
FDrawTitleInGuiThread: boolean;
|
||||||
|
FEmptyTileImg: TLazIntfImage;
|
||||||
FOnCenterMove: TNotifyEvent;
|
FOnCenterMove: TNotifyEvent;
|
||||||
FOnChange: TNotifyEvent;
|
FOnChange: TNotifyEvent;
|
||||||
FOnDrawTile: TDrawTileEvent;
|
FOnDrawTile: TDrawTileEvent;
|
||||||
@ -81,6 +83,7 @@ type
|
|||||||
function IsValidTile(const aWin: TMapWindow; const aTile: TTIleId): boolean;
|
function IsValidTile(const aWin: TMapWindow; const aTile: TTIleId): boolean;
|
||||||
procedure MoveMapCenter(Sender: TDragObj);
|
procedure MoveMapCenter(Sender: TDragObj);
|
||||||
procedure SetActive(AValue: boolean);
|
procedure SetActive(AValue: boolean);
|
||||||
|
procedure SetBkColor(AValue: TFPColor);
|
||||||
procedure SetCacheOnDisk(AValue: Boolean);
|
procedure SetCacheOnDisk(AValue: Boolean);
|
||||||
procedure SetCachePath(AValue: String);
|
procedure SetCachePath(AValue: String);
|
||||||
procedure SetCenter(ACenter: TRealPoint);
|
procedure SetCenter(ACenter: TRealPoint);
|
||||||
@ -104,6 +107,7 @@ type
|
|||||||
function IsCurrentWin(const aWin: TMapWindow) : boolean;
|
function IsCurrentWin(const aWin: TMapWindow) : boolean;
|
||||||
protected
|
protected
|
||||||
procedure AdjustZoomCenter(var AWin: TMapWindow);
|
procedure AdjustZoomCenter(var AWin: TMapWindow);
|
||||||
|
function CreateBlankImg: TLazIntfImage;
|
||||||
procedure ConstraintZoom(var aWin: TMapWindow);
|
procedure ConstraintZoom(var aWin: TMapWindow);
|
||||||
function GetTileName(const Id: TTileId): String;
|
function GetTileName(const Id: TTileId): String;
|
||||||
procedure evDownload(Data: TObject; Job: TJob);
|
procedure evDownload(Data: TObject; Job: TJob);
|
||||||
@ -143,6 +147,7 @@ type
|
|||||||
WheelDelta: Integer; {%H-}MousePos: TPoint; var Handled: Boolean);
|
WheelDelta: Integer; {%H-}MousePos: TPoint; var Handled: Boolean);
|
||||||
procedure ZoomOnArea(const aArea: TRealArea);
|
procedure ZoomOnArea(const aArea: TRealArea);
|
||||||
|
|
||||||
|
property BkColor: TFPColor read FBkColor write SetBkColor;
|
||||||
property Center: TRealPoint read GetCenter write SetCenter;
|
property Center: TRealPoint read GetCenter write SetCenter;
|
||||||
|
|
||||||
published
|
published
|
||||||
@ -377,6 +382,8 @@ begin
|
|||||||
DragObj.OnDrag := @DoDrag;
|
DragObj.OnDrag := @DoDrag;
|
||||||
Cache := TPictureCache.Create(self);
|
Cache := TPictureCache.Create(self);
|
||||||
lstProvider := TStringList.Create;
|
lstProvider := TStringList.Create;
|
||||||
|
FBkColor := colWhite;
|
||||||
|
FEmptyTileImg := CreateBlankImg;
|
||||||
RegisterProviders;
|
RegisterProviders;
|
||||||
Queue := TJobQueue.Create(8);
|
Queue := TJobQueue.Create(8);
|
||||||
Queue.OnIdle := @Cache.CheckCacheSize;
|
Queue.OnIdle := @Cache.CheckCacheSize;
|
||||||
@ -436,7 +443,7 @@ begin
|
|||||||
startY := -aWin.Y div TILE_SIZE;
|
startY := -aWin.Y div TILE_SIZE;
|
||||||
Result.Left := startX - 1;
|
Result.Left := startX - 1;
|
||||||
Result.Right := startX + MaxX;
|
Result.Right := startX + MaxX;
|
||||||
Result.Top := startY;
|
Result.Top := startY - 1;
|
||||||
Result.Bottom := startY + MaxY;
|
Result.Bottom := startY + MaxY;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -485,6 +492,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TMapViewerEngine.CreateBlankImg: TLazIntfImage;
|
||||||
|
var
|
||||||
|
rawImg: TRawImage;
|
||||||
|
begin
|
||||||
|
rawImg.Init;
|
||||||
|
{$IFDEF DARWIN}
|
||||||
|
rawImg.Description.Init_BPP32_A8R8G8B8_BIO_TTB(TILE_SIZE, TILE_SIZE);
|
||||||
|
{$ELSE}
|
||||||
|
rawImg.Description.Init_BPP32_B8G8R8_BIO_TTB(TILE_SIZE, TILE_SIZE);
|
||||||
|
{$ENDIF}
|
||||||
|
rawImg.CreateData(True);
|
||||||
|
|
||||||
|
Result := TLazIntfImage.Create(rawImg, true);
|
||||||
|
Result.FillPixels(FBkColor);
|
||||||
|
end;
|
||||||
|
|
||||||
{ Returns true when the visible window crosses the date line, i.e. the longitudes
|
{ Returns true when the visible window crosses the date line, i.e. the longitudes
|
||||||
at the left of the window are > 0, and those at the right are < 0. }
|
at the left of the window are > 0, and those at the right are < 0. }
|
||||||
function TMapViewerEngine.CrossesDateline: Boolean;
|
function TMapViewerEngine.CrossesDateline: Boolean;
|
||||||
@ -1028,17 +1051,19 @@ begin
|
|||||||
Redraw(MapWin);
|
Redraw(MapWin);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMapViewerEngine.Redraw(const AWin: TmapWindow);
|
procedure TMapViewerEngine.Redraw(const AWin: TMapWindow);
|
||||||
var
|
var
|
||||||
TilesVis: TArea;
|
TilesVis: TArea;
|
||||||
x, y : Integer; //int64;
|
x, y : Integer; //int64;
|
||||||
Tiles: TTileIdArray = nil;
|
Tiles: TTileIdArray = nil;
|
||||||
iTile: Integer;
|
iTile: Integer;
|
||||||
numTiles: Integer;
|
numTiles: Integer;
|
||||||
|
px, py: Integer;
|
||||||
begin
|
begin
|
||||||
if not(Active) then
|
if not(Active) then
|
||||||
Exit;
|
Exit;
|
||||||
Queue.CancelAllJob(self);
|
Queue.CancelAllJob(self);
|
||||||
|
|
||||||
TilesVis := CalculateVisibleTiles(AWin);
|
TilesVis := CalculateVisibleTiles(AWin);
|
||||||
SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1));
|
SetLength(Tiles, (TilesVis.Bottom - TilesVis.Top + 1) * (TilesVis.Right - TilesVis.Left + 1));
|
||||||
iTile := Low(Tiles);
|
iTile := Low(Tiles);
|
||||||
@ -1055,6 +1080,16 @@ begin
|
|||||||
Tiles[iTile].X := X;
|
Tiles[iTile].X := X;
|
||||||
Tiles[iTile].Y := Y;
|
Tiles[iTile].Y := Y;
|
||||||
Tiles[iTile].Z := AWin.Zoom;
|
Tiles[iTile].Z := AWin.Zoom;
|
||||||
|
|
||||||
|
// Avoid tiling artefacts when a tile does not exist (lowest zoom) or
|
||||||
|
// is not valid
|
||||||
|
if not Cache.InCache(AWin.MapProvider, Tiles[iTile]) then
|
||||||
|
begin
|
||||||
|
py := AWin.Y + Y * TILE_SIZE;
|
||||||
|
px := AWin.X + X * TILE_SIZE;
|
||||||
|
DrawTile(Tiles[iTile], px, py, FEmptyTileImg);
|
||||||
|
end;
|
||||||
|
|
||||||
if IsValidTile(AWin, Tiles[iTile]) then
|
if IsValidTile(AWin, Tiles[iTile]) then
|
||||||
inc(iTile);
|
inc(iTile);
|
||||||
end;
|
end;
|
||||||
@ -1181,6 +1216,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMapViewerEngine.SetBkColor(AValue: TFPColor);
|
||||||
|
begin
|
||||||
|
if FBkColor = AValue then Exit;
|
||||||
|
FBkColor := AValue;
|
||||||
|
FEmptyTileImg.FillPixels(FBkColor);
|
||||||
|
Redraw(MapWin);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMapViewerEngine.SetCacheOnDisk(AValue: Boolean);
|
procedure TMapViewerEngine.SetCacheOnDisk(AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
if Cache.UseDisk = AValue then Exit;
|
if Cache.UseDisk = AValue then Exit;
|
||||||
|
@ -22,7 +22,7 @@ unit mvMapViewer;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Controls, Graphics, IntfGraphics, Forms, ImgList, LCLVersion,
|
Classes, SysUtils, Controls, Graphics, FPImage, IntfGraphics, Forms, ImgList, LCLVersion,
|
||||||
MvTypes, MvGPSObj, MvEngine, MvMapProvider, MvDownloadEngine, MvDrawingEngine;
|
MvTypes, MvGPSObj, MvEngine, MvMapProvider, MvDownloadEngine, MvDrawingEngine;
|
||||||
|
|
||||||
Type
|
Type
|
||||||
@ -41,7 +41,6 @@ Type
|
|||||||
FDrawingEngine: TMvCustomDrawingEngine;
|
FDrawingEngine: TMvCustomDrawingEngine;
|
||||||
FActive: boolean;
|
FActive: boolean;
|
||||||
FGPSItems: TGPSObjectList;
|
FGPSItems: TGPSObjectList;
|
||||||
FInactiveColor: TColor;
|
|
||||||
FPOIImage: TBitmap;
|
FPOIImage: TBitmap;
|
||||||
FPOITextBgColor: TColor;
|
FPOITextBgColor: TColor;
|
||||||
FOnDrawGpsPoint: TDrawGpsPointEvent;
|
FOnDrawGpsPoint: TDrawGpsPointEvent;
|
||||||
@ -63,6 +62,7 @@ Type
|
|||||||
function GetCyclic: Boolean;
|
function GetCyclic: Boolean;
|
||||||
function GetDownloadEngine: TMvCustomDownloadEngine;
|
function GetDownloadEngine: TMvCustomDownloadEngine;
|
||||||
function GetDrawingEngine: TMvCustomDrawingEngine;
|
function GetDrawingEngine: TMvCustomDrawingEngine;
|
||||||
|
function GetInactiveColor: TColor;
|
||||||
function GetMapProvider: String;
|
function GetMapProvider: String;
|
||||||
function GetOnCenterMove: TNotifyEvent;
|
function GetOnCenterMove: TNotifyEvent;
|
||||||
function GetOnChange: TNotifyEvent;
|
function GetOnChange: TNotifyEvent;
|
||||||
@ -150,7 +150,7 @@ Type
|
|||||||
property DrawingEngine: TMvCustomDrawingEngine read GetDrawingEngine write SetDrawingEngine;
|
property DrawingEngine: TMvCustomDrawingEngine read GetDrawingEngine write SetDrawingEngine;
|
||||||
property Font: TFont read FFont write SetFont stored IsFontStored;
|
property Font: TFont read FFont write SetFont stored IsFontStored;
|
||||||
property Height default 150;
|
property Height default 150;
|
||||||
property InactiveColor: TColor read FInactiveColor write SetInactiveColor default clWhite;
|
property InactiveColor: TColor read GetInactiveColor write SetInactiveColor default clWhite;
|
||||||
property MapProvider: String read GetMapProvider write SetMapProvider;
|
property MapProvider: String read GetMapProvider write SetMapProvider;
|
||||||
property POIImage: TBitmap read FPOIImage write SetPOIImage;
|
property POIImage: TBitmap read FPOIImage write SetPOIImage;
|
||||||
property POIImages: TCustomImageList read FPOIImages write SetPOIImages;
|
property POIImages: TCustomImageList read FPOIImages write SetPOIImages;
|
||||||
@ -343,6 +343,11 @@ begin
|
|||||||
Result := FDrawingEngine;
|
Result := FDrawingEngine;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TMapView.GetInactiveColor: TColor;
|
||||||
|
begin
|
||||||
|
Result := FPColorToTColor(Engine.BkColor);
|
||||||
|
end;
|
||||||
|
|
||||||
function TMapView.GetMapProvider: String;
|
function TMapView.GetMapProvider: String;
|
||||||
begin
|
begin
|
||||||
result := Engine.MapProvider;
|
result := Engine.MapProvider;
|
||||||
@ -457,9 +462,7 @@ end;
|
|||||||
|
|
||||||
procedure TMapView.SetInactiveColor(AValue: TColor);
|
procedure TMapView.SetInactiveColor(AValue: TColor);
|
||||||
begin
|
begin
|
||||||
if FInactiveColor = AValue then
|
Engine.BkColor := TColorToFPColor(AValue);
|
||||||
exit;
|
|
||||||
FInactiveColor := AValue;
|
|
||||||
if not IsActive then
|
if not IsActive then
|
||||||
Invalidate;
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
@ -866,7 +869,6 @@ begin
|
|||||||
FActive := false;
|
FActive := false;
|
||||||
FDefaultTrackColor := clRed;
|
FDefaultTrackColor := clRed;
|
||||||
FDefaultTrackWidth := 1;
|
FDefaultTrackWidth := 1;
|
||||||
FInactiveColor := clWhite;
|
|
||||||
|
|
||||||
FGPSItems := TGPSObjectList.Create;
|
FGPSItems := TGPSObjectList.Create;
|
||||||
FGPSItems.OnModified := @OnGPSItemsModified;
|
FGPSItems.OnModified := @OnGPSItemsModified;
|
||||||
@ -879,6 +881,7 @@ begin
|
|||||||
FBuiltinDownloadEngine.Name := 'BuiltInDLE';
|
FBuiltinDownloadEngine.Name := 'BuiltInDLE';
|
||||||
|
|
||||||
FEngine := TMapViewerEngine.Create(self);
|
FEngine := TMapViewerEngine.Create(self);
|
||||||
|
FEngine.BkColor := colWhite;
|
||||||
FEngine.CachePath := 'cache/';
|
FEngine.CachePath := 'cache/';
|
||||||
FEngine.CacheOnDisk := true;
|
FEngine.CacheOnDisk := true;
|
||||||
FEngine.OnDrawTile := @DoDrawTile;
|
FEngine.OnDrawTile := @DoDrawTile;
|
||||||
|
Reference in New Issue
Block a user