mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:06:30 +00:00
babcbc0fc7
clean warnings
343 lines
8.6 KiB
C#
343 lines
8.6 KiB
C#
using System.Globalization;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Effects;
|
|
using GMap.NET.WindowsPresentation;
|
|
|
|
namespace Azaion.Annotator.Controls
|
|
{
|
|
public class CircleVisual : FrameworkElement
|
|
{
|
|
public readonly GMapMarker Marker;
|
|
|
|
public CircleVisual(GMapMarker m, Brush background)
|
|
{
|
|
ShadowEffect = new DropShadowEffect();
|
|
Marker = m;
|
|
Marker.ZIndex = 100;
|
|
|
|
SizeChanged += CircleVisual_SizeChanged;
|
|
MouseEnter += CircleVisual_MouseEnter;
|
|
MouseLeave += CircleVisual_MouseLeave;
|
|
Loaded += OnLoaded;
|
|
|
|
Text = "?";
|
|
|
|
StrokeArrow.EndLineCap = PenLineCap.Triangle;
|
|
StrokeArrow.LineJoin = PenLineJoin.Round;
|
|
|
|
RenderTransform = _scale;
|
|
|
|
Width = Height = 22;
|
|
FontSize = Width / 1.55;
|
|
|
|
Background = background;
|
|
Angle = null;
|
|
}
|
|
|
|
void CircleVisual_SizeChanged(object sender, SizeChangedEventArgs e)
|
|
{
|
|
Marker.Offset = new Point(-e.NewSize.Width / 2, -e.NewSize.Height / 2);
|
|
_scale.CenterX = -Marker.Offset.X;
|
|
_scale.CenterY = -Marker.Offset.Y;
|
|
}
|
|
|
|
void OnLoaded(object sender, RoutedEventArgs e)
|
|
{
|
|
UpdateVisual(true);
|
|
}
|
|
|
|
readonly ScaleTransform _scale = new ScaleTransform(1, 1);
|
|
|
|
void CircleVisual_MouseLeave(object sender, MouseEventArgs e)
|
|
{
|
|
|
|
Marker.ZIndex -= 10000;
|
|
Cursor = Cursors.Arrow;
|
|
|
|
Effect = null;
|
|
|
|
_scale.ScaleY = 1;
|
|
_scale.ScaleX = 1;
|
|
}
|
|
|
|
void CircleVisual_MouseEnter(object sender, MouseEventArgs e)
|
|
{
|
|
Marker.ZIndex += 10000;
|
|
Cursor = Cursors.Hand;
|
|
|
|
Effect = ShadowEffect;
|
|
|
|
_scale.ScaleY = 1.5;
|
|
_scale.ScaleX = 1.5;
|
|
}
|
|
|
|
public DropShadowEffect ShadowEffect;
|
|
|
|
static readonly Typeface Font = new Typeface(new FontFamily("Arial"),
|
|
FontStyles.Normal,
|
|
FontWeights.Bold,
|
|
FontStretches.Normal);
|
|
|
|
FormattedText _fText = null!;
|
|
|
|
private Brush _background = Brushes.Blue;
|
|
|
|
public Brush Background
|
|
{
|
|
get
|
|
{
|
|
return _background;
|
|
}
|
|
set
|
|
{
|
|
if (_background != value)
|
|
{
|
|
_background = value;
|
|
IsChanged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private Brush _foreground = Brushes.White;
|
|
|
|
public Brush Foreground
|
|
{
|
|
get
|
|
{
|
|
return _foreground;
|
|
}
|
|
set
|
|
{
|
|
if (_foreground != value)
|
|
{
|
|
_foreground = value;
|
|
IsChanged = true;
|
|
|
|
ForceUpdateText();
|
|
}
|
|
}
|
|
}
|
|
|
|
private Pen _stroke = new Pen(Brushes.Blue, 2.0);
|
|
|
|
public Pen Stroke
|
|
{
|
|
get
|
|
{
|
|
return _stroke;
|
|
}
|
|
set
|
|
{
|
|
if (_stroke != value)
|
|
{
|
|
_stroke = value;
|
|
IsChanged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private Pen _strokeArrow = new Pen(Brushes.Blue, 2.0);
|
|
|
|
public Pen StrokeArrow
|
|
{
|
|
get
|
|
{
|
|
return _strokeArrow;
|
|
}
|
|
set
|
|
{
|
|
if (_strokeArrow != value)
|
|
{
|
|
_strokeArrow = value;
|
|
IsChanged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public double FontSize = 16;
|
|
|
|
private double? _angle = 0;
|
|
|
|
public double? Angle
|
|
{
|
|
get => _angle;
|
|
set
|
|
{
|
|
if (!_angle.HasValue || !value.HasValue ||
|
|
Angle.HasValue && Math.Abs(_angle.Value - value.Value) > 11)
|
|
{
|
|
_angle = value;
|
|
IsChanged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsChanged = true;
|
|
|
|
void ForceUpdateText()
|
|
{
|
|
|
|
_fText = new FormattedText(_text,
|
|
CultureInfo.InvariantCulture,
|
|
FlowDirection.LeftToRight,
|
|
Font,
|
|
FontSize,
|
|
Foreground, 1.0);
|
|
IsChanged = true;
|
|
}
|
|
|
|
string _text = null!;
|
|
|
|
public string Text
|
|
{
|
|
get
|
|
{
|
|
return _text;
|
|
}
|
|
set
|
|
{
|
|
if (_text != value)
|
|
{
|
|
_text = value;
|
|
ForceUpdateText();
|
|
}
|
|
}
|
|
}
|
|
|
|
Visual _child = null!;
|
|
|
|
public virtual Visual? Child
|
|
{
|
|
get => _child;
|
|
set
|
|
{
|
|
if (_child == value)
|
|
return;
|
|
|
|
if (_child != null)
|
|
{
|
|
RemoveLogicalChild(_child);
|
|
RemoveVisualChild(_child);
|
|
}
|
|
|
|
if (value != null)
|
|
{
|
|
AddVisualChild(value);
|
|
AddLogicalChild(value);
|
|
}
|
|
|
|
// cache the new child
|
|
_child = value!;
|
|
|
|
InvalidateVisual();
|
|
}
|
|
}
|
|
|
|
public bool UpdateVisual(bool forceUpdate)
|
|
{
|
|
if (forceUpdate || IsChanged)
|
|
{
|
|
Child = Create();
|
|
IsChanged = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int _countCreate;
|
|
|
|
private DrawingVisual Create()
|
|
{
|
|
_countCreate++;
|
|
|
|
var square = new DrawingVisualFx();
|
|
|
|
using var dc = square.RenderOpen();
|
|
dc.DrawEllipse(null,
|
|
Stroke,
|
|
new Point(Width / 2, Height / 2),
|
|
Width / 2 + Stroke.Thickness / 2,
|
|
Height / 2 + Stroke.Thickness / 2);
|
|
|
|
if (Angle.HasValue)
|
|
{
|
|
dc.PushTransform(new RotateTransform(Angle.Value, Width / 2, Height / 2));
|
|
{
|
|
var polySeg = new PolyLineSegment(new[]
|
|
{
|
|
new Point(Width * 0.2, Height * 0.3), new Point(Width * 0.8, Height * 0.3)
|
|
},
|
|
true);
|
|
var pathFig = new PathFigure(new Point(Width * 0.5, -Height * 0.22),
|
|
new PathSegment[] {polySeg},
|
|
true);
|
|
var pathGeo = new PathGeometry(new[] {pathFig});
|
|
dc.DrawGeometry(Brushes.AliceBlue, StrokeArrow, pathGeo);
|
|
}
|
|
dc.Pop();
|
|
}
|
|
|
|
dc.DrawEllipse(Background, null, new Point(Width / 2, Height / 2), Width / 2, Height / 2);
|
|
dc.DrawText(_fText, new Point(Width / 2 - _fText.Width / 2, Height / 2 - _fText.Height / 2));
|
|
|
|
return square;
|
|
}
|
|
|
|
#region Necessary Overrides -- Needed by WPF to maintain bookkeeping of our hosted visuals
|
|
|
|
protected override int VisualChildrenCount
|
|
{
|
|
get
|
|
{
|
|
return Child == null ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
protected override Visual? GetVisualChild(int index)
|
|
{
|
|
return Child;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class DrawingVisualFx : DrawingVisual
|
|
{
|
|
public static readonly DependencyProperty EffectProperty = DependencyProperty.Register("Effect",
|
|
typeof(Effect),
|
|
typeof(DrawingVisualFx),
|
|
new FrameworkPropertyMetadata(null,
|
|
FrameworkPropertyMetadataOptions.AffectsRender,
|
|
OnEffectChanged));
|
|
|
|
public new Effect Effect
|
|
{
|
|
get
|
|
{
|
|
return (Effect)GetValue(EffectProperty);
|
|
}
|
|
set
|
|
{
|
|
SetValue(EffectProperty, value);
|
|
}
|
|
}
|
|
|
|
private static void OnEffectChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var drawingVisualFx = o as DrawingVisualFx;
|
|
if (drawingVisualFx != null)
|
|
{
|
|
drawingVisualFx.SetMyProtectedVisualEffect((Effect)e.NewValue);
|
|
}
|
|
}
|
|
|
|
private void SetMyProtectedVisualEffect(Effect effect)
|
|
{
|
|
VisualEffect = effect;
|
|
}
|
|
}
|
|
}
|