using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using Demo.WindowsPresentation.Controls;
using GMap.NET.WindowsPresentation;
namespace Demo.WindowsPresentation.CustomMarkers{
public class CircleVisual : FrameworkElement
{
public readonly Popup Popup = new Popup();
public readonly TrolleyTooltip Tooltip = new TrolleyTooltip();
public readonly GMapMarker Marker;
public CircleVisual(GMapMarker m, Brush background)
{
Marker = m;
Marker.ZIndex = 100;
Popup.AllowsTransparency = true;
Popup.PlacementTarget = this;
Popup.Placement = PlacementMode.Mouse;
Popup.Child = Tooltip;
Popup.Child.Opacity = 0.777;
SizeChanged += new SizeChangedEventHandler(CircleVisual_SizeChanged);
MouseEnter += new System.Windows.Input.MouseEventHandler(CircleVisual_MouseEnter);
MouseLeave += new System.Windows.Input.MouseEventHandler(CircleVisual_MouseLeave);
Loaded += new RoutedEventHandler(OnLoaded);
Text = "?";
StrokeArrow.EndLineCap = PenLineCap.Triangle;
StrokeArrow.LineJoin = PenLineJoin.Round;
RenderTransform = scale;
Width = Height = 22;
FontSize = (Width/1.55);
Stroke.Thickness = Width/22;
Background = background;
Angle = null;
}
void CircleVisual_SizeChanged(object sender, SizeChangedEventArgs e)
{
Marker.Offset = new System.Windows.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);
}
ScaleTransform scale = new ScaleTransform(1, 1);
void CircleVisual_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Stroke.Thickness -= 2;
if(Popup.IsOpen)
{
Popup.IsOpen = false;
}
Marker.ZIndex -= 10000;
Cursor = Cursors.Arrow;
this.Effect = null;
scale.ScaleY = 1;
scale.ScaleX = 1;
}
void CircleVisual_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
Stroke.Thickness += 2;
if(!Popup.IsOpen)
{
Popup.IsOpen = true;
}
Marker.ZIndex += 10000;
Cursor = Cursors.Hand;
this.Effect = ShadowEffect;
scale.ScaleY = 1.5;
scale.ScaleX = 1.5;
}
public DropShadowEffect ShadowEffect;
static Typeface Font = new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Bold, FontStretches.Normal);
FormattedText FText;
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, 10.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
{
return angle;
}
set
{
if(!Angle.HasValue || !value.HasValue || (Angle.HasValue && value.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);
IsChanged = true;
}
string text;
public string Text
{
get
{
return text;
}
set
{
if(text != value)
{
text = value;
ForceUpdateText();
}
}
}
Visual _child;
public virtual Visual Child
{
get
{
return _child;
}
set
{
if(_child != value)
{
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 = 0;
private DrawingVisual Create()
{
countCreate++;
var square = new DrawingVisualFx();
using(DrawingContext 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));
{
PolyLineSegment polySeg = new PolyLineSegment(new Point[] { new Point(Width*0.2, Height*0.3), new Point(Width*0.8, Height*0.3) }, true);
PathFigure pathFig = new PathFigure(new Point(Width*0.5, -Height*0.22), new PathSegment[] { polySeg }, true);
PathGeometry pathGeo = new PathGeometry(new PathFigure[] { 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), new PropertyChangedCallback(OnEffectChanged)));
public Effect Effect
{
get
{
return (Effect) GetValue(EffectProperty);
}
set
{
SetValue(EffectProperty, value);
}
}
private static void OnEffectChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DrawingVisualFx drawingVisualFx = o as DrawingVisualFx;
if(drawingVisualFx != null)
{
drawingVisualFx.setMyProtectedVisualEffect((Effect) e.NewValue);
}
}
private void setMyProtectedVisualEffect(Effect effect)
{
VisualEffect = effect;
}
}
}
|