Suggested change to Pushpin class

Dec 8, 2008 at 2:06 PM
First off, kudos to the team for a very useful control you are building.

I'm just learning Silverlight myself and found that the Pushpin class is only partially implemented as a control. In to make templating the control possible (and in particular, animations), I've made some changes that I hope you'll find useful.

I'm a little fuzzy on what the PushPinSelectedHandler delegate is doing, so I've left it alone.

Index: D:/Code/DeepEarth/DeepEarth/Shapes/Pushpin.cs
===================================================================
--- D:/Code/DeepEarth/DeepEarth/Shapes/Pushpin.cs (revision 17515)
+++ D:/Code/DeepEarth/DeepEarth/Shapes/Pushpin.cs (working copy)
@@ -6,17 +6,19 @@
 using System.ComponentModel;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Markup;
 using System.Windows.Media;
-using System.Windows.Markup;
 
 namespace DeepEarth.Shapes
 {
     public delegate void PushPinSelectedHandler(Point location, Size pushPinSize, bool isSelected, Pushpin pushPin);
 
-
+ [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
+ [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
+ [TemplateVisualState(Name = "Selected", GroupName = "CommonStates")]
     public class Pushpin : Shape
     {
-      
         private Size originalSize;
         private Point point;
 
@@ -32,33 +34,63 @@
             _AnchorPoint = (Point)e.NewValue;
         }
 
-
         public Pushpin()
         {
-           
-            DefaultStyleKey = typeof(Pushpin);
-            this.MouseLeftButtonDown += pushPinVisual_MouseLeftButtonDown;
-
+            this.DefaultStyleKey = typeof(Pushpin);
         }
 
+  #region event handlers
 
+  void pushPinVisual_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+  {
+  }
+
+  void Pushpin_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+  {
+   if (this.IsSelected)
+   {
+    VisualStateManager.GoToState(this, "Normal", true);
+   }
+   else
+   {
+    VisualStateManager.GoToState(this, "Selected", true);
+   }
+
+   if (PushPinSelected != null)
+   {
+    PushPinSelected(Point, originalSize, IsSelected, this);
+   }
+
+   IsSelected = !IsSelected;
+   e.Handled = true;
+  }
+
+  void Pushpin_MouseLeave(object sender, MouseEventArgs e)
+  {
+   VisualStateManager.GoToState(this, "Normal", true);
+  }
+
+  void Pushpin_MouseEnter(object sender, MouseEventArgs e)
+  {
+   VisualStateManager.GoToState(this, "MouseOver", true);
+  }
+
+  #endregion
+
         public override void OnApplyTemplate()
         {
-            bool isDesignTime = (System.Windows.Browser.HtmlPage.IsEnabled == false);
-            if (isDesignTime == false)
+            bool isDesignTime = !System.Windows.Browser.HtmlPage.IsEnabled;
+            if (!isDesignTime)
             {
                 ForceMeasure();
                 UpdateLocation();
             }
-        }
 
-        void pushPinVisual_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
-        {
-            if (PushPinSelected != null)
-                PushPinSelected(Point, originalSize, IsSelected, this);
-
-            IsSelected = !IsSelected;
-            //e.Handled = true;
+   // register mouse events
+   this.MouseLeftButtonDown += pushPinVisual_MouseLeftButtonDown;
+   this.MouseLeftButtonUp += Pushpin_MouseLeftButtonUp;
+   this.MouseEnter += Pushpin_MouseEnter;
+   this.MouseLeave += Pushpin_MouseLeave;
         }
 
         public bool IsSelected { get; set; }

Index: D:/Code/DeepEarth/DeepEarth/Shapes/Shape.cs
===================================================================
--- D:/Code/DeepEarth/DeepEarth/Shapes/Shape.cs (revision 17515)
+++ D:/Code/DeepEarth/DeepEarth/Shapes/Shape.cs (working copy)
@@ -8,7 +8,7 @@
 
 namespace DeepEarth.Shapes
 {
-    public abstract class Shape: Control, IMapElement
+    public abstract class Shape: ContentControl, IMapElement
     {
         protected Map _Map;
 
@@ -36,7 +36,8 @@
   public abstract ShapeType ShapeType { get; }
 
   bool _IsVisible = true;
-  public bool IsVisible {
+  public bool IsVisible
+  {
    get { return _IsVisible; }
    set
    {
@@ -138,8 +139,6 @@
             }
         }
 
-
-
         #endregion
     }
 }


Index: D:/Code/DeepEarth/DeepEarth/Themes/generic.xaml
===================================================================
--- D:/Code/DeepEarth/DeepEarth/Themes/generic.xaml (revision 17515)
+++ D:/Code/DeepEarth/DeepEarth/Themes/generic.xaml (working copy)
@@ -1078,8 +1078,9 @@
 
     <!--Style InfoBox -->
     <Style TargetType="DeepShapes:InfoBox">
-        <Setter Property="MinWidth" Value="300"/>
-        <Setter Property="MinHeight" Value="200"/>
+        <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
+        <Setter Property="Width" Value="300"/>
+        <Setter Property="Height" Value="200"/>
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="DeepShapes:InfoBox">
@@ -1114,56 +1115,56 @@
 
     <!--Style Pushpin -->
     <Style TargetType="DeepShapes:Pushpin">
-        <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
+  <Setter Property="Width" Value="50" />
+  <Setter Property="Height" Value="50" />
+  <Setter Property="Foreground">
+   <Setter.Value>
+    <RadialGradientBrush RadiusX="0.72757" RadiusY="0.960692" Center="0.675586,0.0954698" GradientOrigin="0.675586,0.0954698">
+     <RadialGradientBrush.RelativeTransform>
+      <TransformGroup/>
+     </RadialGradientBrush.RelativeTransform>
+     <GradientStop Color="#FF115EDB" Offset="0"/>
+     <GradientStop Color="#FF093BA7" Offset="0.649877"/>
+     <GradientStop Color="#FF021973" Offset="1"/>
+    </RadialGradientBrush>
+   </Setter.Value>
+  </Setter>
+  <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
         <Setter Property="AnchorPoint" Value="0.5,0.5" />
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="DeepShapes:Pushpin">
-
                     <Grid>
                         <Grid.RenderTransform>
                             <ScaleTransform ScaleX="1" ScaleY="1" />
-                        </Grid.RenderTransform>
-                        <Canvas x:Name="Layer_1" Width="50" Height="50" Canvas.Left="0" Canvas.Top="0">
+                        </Grid.RenderTransform>      
+                        <Canvas x:Name="Layer_1" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Canvas.Left="0" Canvas.Top="0">
                             <Path x:Name="DropShaddow" Width="24.3496" Height="39.3937" Canvas.Left="26.3333" Canvas.Top="-16.43966" Stretch="Fill" Fill="#44C6C6C6" Data="F1 M 16.3333,44.8333L 22.5,36.4453C 22.5,36.4453 29.7467,38.7493 33.3333,30.4453C 35.5306,25.3132 32.7806,21.5632 31.5,20C 32.3333,18.444 33,17.2227 33,17.2227C 33,17.2227 37.944,17.444 39.7773,14.444C 41.6107,11.444 40.556,8.16667 37.556,6.5C 34.4909,4.79753 30.9056,5.12565 28.9681,7.62565C 27.2656,10.1094 27.612,13.1107 28.6667,15.1107C 27.6667,17.056 27.5306,17.1257 26.9453,18.1667C 25.2806,17.8757 22.3893,18.2227 21.5,19.1667C 20.6107,20.1107 19.4225,21.459 18.7923,21.7292C 18.4023,21.8958 18.7077,25.8118 18.7077,25.8118C 18.7077,25.8118 25.444,27.4453 23.444,33.3333C 22.3984,36.4134 17.3092,37.6628 16.9375,37.6882C 16.6257,37.7077 16.3333,44.8333 16.3333,44.8333 Z "/>
                             <Path x:Name="Pinpoint" Width="2.35482" Height="7.14648" Canvas.Left="24.5833" Canvas.Top="16.6868" Stretch="Fill" Fill="#FF727272" Data="F1 M 14.5833,37.7708L 15.334,42.112L 16.334,44.8333L 16.778,42L 16.9382,37.6868C 16.9382,37.6868 15.6243,37.9375 14.5833,37.7708 Z "/>
-                            <Path x:Name="Round_base" Width="16.339" Height="12.681" Canvas.Left="17.49589" Canvas.Top="4.1536" Stretch="Fill" Data="F1 M 7.5,32C 7.66797,36.7799 13.1667,37.8346 15.3346,37.8346L 15.3346,37.8346C 17.4987,37.8346 23.7682,36.9349 23.8346,31.1133L 23.8346,31.1133C 23.888,26.0547 16.776,25.2214 15.8893,25.1667L 15.8893,25.1667C 15.7376,25.1589 15.5814,25.1536 15.4238,25.1536L 15.4238,25.1536C 11.9642,25.1536 7.33854,27.4277 7.5,32 Z ">
-                                <Path.Fill>
-                                    <RadialGradientBrush RadiusX="0.560988" RadiusY="0.722815" Center="0.731262,0.259524" GradientOrigin="0.731262,0.259524">
-                                        <RadialGradientBrush.RelativeTransform>
-                                            <TransformGroup/>
-                                        </RadialGradientBrush.RelativeTransform>
-                                        <GradientStop Color="#FF115EDB" Offset="0"/>
-                                        <GradientStop Color="#FF083174" Offset="0.649877"/>
-                                        <GradientStop Color="#FF00040E" Offset="1"/>
-                                    </RadialGradientBrush>
-                                </Path.Fill>
-                            </Path>
-                            <Path x:Name="Base" Width="6.33333" Height="9.14486" Canvas.Left="22.5" Canvas.Top="0.556" Stretch="Fill" Fill="#FF125FDB" Data="F1 M 18.8333,21.556L 18.7773,29.112C 18.7773,29.112 16.1667,32.612 12.5,29.2227L 12.5,21.6667C 16.2507,22.5117 17.5521,22.0918 18.8333,21.556 Z "/>
+       <Path x:Name="Round_base" Width="16.339" Height="12.681" Canvas.Left="17.49589" Canvas.Top="4.1536" Stretch="Fill" Data="F1 M 7.5,32C 7.66797,36.7799 13.1667,37.8346 15.3346,37.8346L 15.3346,37.8346C 17.4987,37.8346 23.7682,36.9349 23.8346,31.1133L 23.8346,31.1133C 23.888,26.0547 16.776,25.2214 15.8893,25.1667L 15.8893,25.1667C 15.7376,25.1589 15.5814,25.1536 15.4238,25.1536L 15.4238,25.1536C 11.9642,25.1536 7.33854,27.4277 7.5,32 Z ">
+        <Path.Fill>
+         <RadialGradientBrush RadiusX="0.560988" RadiusY="0.722815" Center="0.731262,0.259524" GradientOrigin="0.731262,0.259524">
+          <RadialGradientBrush.RelativeTransform>
+           <TransformGroup/>
+          </RadialGradientBrush.RelativeTransform>
+          <GradientStop Color="#FF115EDB" Offset="0"/>
+          <GradientStop Color="#FF083174" Offset="0.649877"/>
+          <GradientStop Color="#FF00040E" Offset="1"/>
+         </RadialGradientBrush>
+        </Path.Fill>
+       </Path>
+       <Path x:Name="Base" Width="6.33333" Height="9.14486" Canvas.Left="22.5" Canvas.Top="0.556" Stretch="Fill" Fill="#FF125FDB" Data="F1 M 18.8333,21.556L 18.7773,29.112C 18.7773,29.112 16.1667,32.612 12.5,29.2227L 12.5,21.6667C 16.2507,22.5117 17.5521,22.0918 18.8333,21.556 Z "/>
                             <Path x:Name="base_shaddow" Width="9.86133" Height="14.7219" Canvas.Left="18.222" Canvas.Top="0.7272" Stretch="Fill" Fill="#83000000" Data="F1 M 12.5703,21.7272C 12.5703,21.7272 15.1113,22.7227 18.0007,22.1107C 18.0553,28.1667 18.0833,29.8958 18.0833,29.8958C 18.0833,29.8958 12.263,36.6309 11.722,36.4453C 9.61133,35.7227 8.222,33.7786 8.222,33.7786C 8.222,33.7786 8.66732,30.6667 12.5007,29.2227C 12.6113,27.6667 12.5703,21.7272 12.5703,21.7272 Z "/>
                             <Path x:Name="Hightlight" Width="1.56287" Height="2.89583" Canvas.Left="28.1667" Canvas.Top="5.9375" Stretch="Fill" Fill="#C5FFFFFF" Data="F1 M 18.8333,26.9375C 18.8333,26.9375 19.7507,27.6042 19.7292,28.2493C 19.7064,28.9616 19.6563,29.1777 19.2507,29.5827C 19.0625,29.7708 18.1667,29.8333 18.1667,29.8333L 18.8548,29.1042L 18.8333,26.9375 Z "/>
-                            <Path x:Name="pin_head" Width="12.3359" Height="9.3425" Canvas.Left="19.83203" Canvas.Top="-8.0534" Stretch="Fill" Data="F1 M 9.83203,17.7227C 9.83203,20.0013 11.8893,22.556 16.0534,22.388L 16.0534,22.388C 20.2214,22.2227 22.168,19.944 22.168,17.6654L 22.168,17.6654C 22.168,15.8333 20.1107,13.1107 16.0534,13.0534L 15.9694,13.0534L 15.9694,13.0534C 12.8333,13.0534 9.83203,15.4642 9.83203,17.7227 Z ">
-                                <Path.Fill>
-                                    <RadialGradientBrush RadiusX="0.72757" RadiusY="0.960692" Center="0.675586,0.0954698" GradientOrigin="0.675586,0.0954698">
-                                        <RadialGradientBrush.RelativeTransform>
-                                            <TransformGroup/>
-                                        </RadialGradientBrush.RelativeTransform>
-                                        <GradientStop Color="#FF115EDB" Offset="0"/>
-                                        <GradientStop Color="#FF093BA7" Offset="0.649877"/>
-                                        <GradientStop Color="#FF021973" Offset="1"/>
-                                    </RadialGradientBrush>
-                                </Path.Fill>
-                            </Path>
+       <Path x:Name="pin_head" Fill="{TemplateBinding Foreground}" Width="12.3359" Height="9.3425" Canvas.Left="19.83203" Canvas.Top="-8.0534" Stretch="Fill" Data="F1 M 9.83203,17.7227C 9.83203,20.0013 11.8893,22.556 16.0534,22.388L 16.0534,22.388C 20.2214,22.2227 22.168,19.944 22.168,17.6654L 22.168,17.6654C 22.168,15.8333 20.1107,13.1107 16.0534,13.0534L 15.9694,13.0534L 15.9694,13.0534C 12.8333,13.0534 9.83203,15.4642 9.83203,17.7227 Z " />
                         </Canvas>
-
                     </Grid>
-
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
 
-    <!--Style Geometry -->
+ <!--Style Geometry -->
     <Style TargetType="DeepShapes:GeometryBase">
         <Setter Property="Template">
             <Setter.Value>
@@ -1196,4 +1197,4 @@
         </Setter>
     </Style>
 
-</ResourceDictionary>
\ No newline at end of file
+</ResourceDictionary>

Coordinator
Dec 8, 2008 at 4:52 PM
Thanks rmatsu,
We will defn make sure this is properly implimented to support the VSM.

We are looking at doing a final rename of a few of the "shape" classes before we release to make it more consistant. This will break your current code but make it much more maintainable in the future.
John.