1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //----------------------------------------------------------------
7 namespace System.Activities.Presentation.FreeFormEditing
10 using System.Activities.Presentation.Internal.PropertyEditing;
11 using System.Activities.Presentation.Model;
12 using System.Activities.Presentation.View;
13 using System.Diagnostics.CodeAnalysis;
14 using System.Globalization;
17 using System.Windows.Automation;
18 using System.Windows.Automation.Peers;
19 using System.Windows.Controls;
20 using System.Windows.Documents;
21 using System.Windows.Media;
23 internal class Connector : UserControl
25 public const double ArrowShapeWidth = 5;
27 public static readonly DependencyProperty PointsProperty = DependencyProperty.Register(
29 typeof(PointCollection),
31 new FrameworkPropertyMetadata(new PointCollection()));
33 public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
37 new FrameworkPropertyMetadata(false));
39 public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register(
43 new FrameworkPropertyMetadata(null));
45 public static readonly DependencyProperty HighlightOnHoverProperty = DependencyProperty.Register(
49 new FrameworkPropertyMetadata(false));
51 public static readonly DependencyProperty IsHighlightedForAutoSplitProperty = DependencyProperty.Register(
52 "IsHighlightedForAutoSplit",
55 new FrameworkPropertyMetadata(false));
57 public static readonly DependencyProperty IdentityProperty = DependencyProperty.Register(
62 // Label will be shown only if there is one segment in the connector whose length is greater than this.
63 internal const int MinConnectorSegmentLengthForLabel = 30;
65 private DesignerConfigurationService designerConfigurationService = null;
67 private FreeFormPanel panel = null;
71 this.Loaded += (sender, e) =>
73 this.Identity = Guid.NewGuid();
77 [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
78 Justification = "PointCollection is a special WPF class and got special Clone logic, the setter of this property is used several places.")]
79 public PointCollection Points
81 get { return (PointCollection)GetValue(Connector.PointsProperty); }
82 set { SetValue(Connector.PointsProperty, value); }
85 public bool IsSelected
87 get { return (bool)GetValue(Connector.IsSelectedProperty); }
88 set { SetValue(Connector.IsSelectedProperty, value); }
91 public string LabelText
93 get { return (string)GetValue(Connector.LabelTextProperty); }
94 set { SetValue(Connector.LabelTextProperty, value); }
97 public bool HighlightOnHover
99 get { return (bool)GetValue(Connector.HighlightOnHoverProperty); }
100 set { SetValue(Connector.HighlightOnHoverProperty, value); }
103 public bool IsHighlightedForAutoSplit
105 get { return (bool)GetValue(Connector.IsHighlightedForAutoSplitProperty); }
106 set { SetValue(Connector.IsHighlightedForAutoSplitProperty, value); }
111 get { return (Guid)GetValue(Connector.IdentityProperty); }
112 set { SetValue(Connector.IdentityProperty, value); }
115 public UIElement SourceShape
119 ConnectionPoint sourceConnectionPoint = FreeFormPanel.GetSourceConnectionPoint(this);
120 if (sourceConnectionPoint != null)
122 return sourceConnectionPoint.ParentDesigner;
129 public UIElement DestinationShape
133 ConnectionPoint destinationConnectionPoint = FreeFormPanel.GetDestinationConnectionPoint(this);
134 if (destinationConnectionPoint != null)
136 return destinationConnectionPoint.ParentDesigner;
143 public IAutoSplitContainer AutoSplitContainer
149 public virtual FrameworkElement StartDot
157 private FreeFormPanel Panel
161 if (this.panel == null)
163 this.panel = VisualTreeUtils.FindVisualAncestor<FreeFormPanel>(this);
170 private bool AutoSplitEnabled
174 if (this.designerConfigurationService == null)
176 DesignerView view = VisualTreeUtils.FindVisualAncestor<DesignerView>(this);
179 this.designerConfigurationService = view.Context.Services.GetService<DesignerConfigurationService>();
180 return this.designerConfigurationService.AutoSplitEnabled;
189 return this.designerConfigurationService.AutoSplitEnabled;
194 public virtual void SetLabelToolTip(object toolTip)
196 // subclass should be able to override this method to provide ToolTip of connector
199 protected override AutomationPeer OnCreateAutomationPeer()
201 return new ConnectorAutomationPeer(this, base.OnCreateAutomationPeer());
204 protected override void OnDragEnter(DragEventArgs e)
206 if (this.AutoSplitEnabled && this.AutoSplitContainer != null && DragDropHelper.GetDraggedObjectCount(e) == 1 && this.AutoSplitContainer.CanAutoSplit(e))
208 this.HighlightForAutoSplit();
209 this.Panel.RemoveAutoConnectAdorner();
210 this.Panel.CurrentAutoSplitTarget = this;
216 protected override void OnDragLeave(DragEventArgs e)
218 if (this.IsHighlightedForAutoSplit)
220 this.DehighlightForAutoSplit();
221 this.Panel.CurrentAutoSplitTarget = null;
227 protected override void OnDrop(DragEventArgs e)
229 if (this.AutoSplitEnabled && this.IsHighlightedForAutoSplit)
233 this.AutoSplitContainer.DoAutoSplit(e, this);
237 this.DehighlightForAutoSplit();
238 this.Panel.CurrentAutoSplitTarget = null;
246 private void AddAutoSplitAdorner(UIElement shape)
248 AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(shape);
249 Fx.Assert(adornerLayer != null, "AdornerLayer should not be null.");
250 adornerLayer.Add(new AutoSplitAdorner(shape));
253 private void RemoveAutoSplitAdorner(UIElement shape)
255 AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(shape);
256 Fx.Assert(adornerLayer != null, "AdornerLayer should not be null.");
257 Adorner[] adorners = adornerLayer.GetAdorners(shape);
258 foreach (Adorner adorner in adorners)
260 if (adorner is AutoSplitAdorner)
262 adornerLayer.Remove(adorner);
268 private void HighlightForAutoSplit()
270 this.IsHighlightedForAutoSplit = true;
271 this.AddAutoSplitAdorner(this.SourceShape);
272 this.AddAutoSplitAdorner(this.DestinationShape);
275 private void DehighlightForAutoSplit()
277 this.IsHighlightedForAutoSplit = false;
278 this.RemoveAutoSplitAdorner(this.SourceShape);
279 this.RemoveAutoSplitAdorner(this.DestinationShape);
282 private class ConnectorAutomationPeer : UIElementAutomationPeer
284 private AutomationPeer wrappedAutomationPeer;
286 public ConnectorAutomationPeer(FrameworkElement owner, AutomationPeer wrappedAutomationPeer)
289 this.wrappedAutomationPeer = wrappedAutomationPeer;
292 protected override string GetItemStatusCore()
294 UIElement sourceDesigner = VirtualizedContainerService.TryGetVirtualizedElement(FreeFormPanel.GetSourceConnectionPoint(this.Owner).ParentDesigner);
295 string sourceId = sourceDesigner.GetValue(AutomationProperties.ItemStatusProperty) as string;
296 UIElement destinationDesigner = VirtualizedContainerService.TryGetVirtualizedElement(FreeFormPanel.GetDestinationConnectionPoint(this.Owner).ParentDesigner);
297 string destinationId = destinationDesigner.GetValue(AutomationProperties.ItemStatusProperty) as string;
298 return string.Format(CultureInfo.InvariantCulture, "Source={0} Destination={1} Points={2}", sourceId, destinationId, ((Connector)this.Owner).Points);
301 protected override string GetClassNameCore()
303 return this.wrappedAutomationPeer.GetClassName();
306 protected override string GetNameCore()
308 return this.wrappedAutomationPeer.GetName();
311 protected override string GetAutomationIdCore()
313 return this.wrappedAutomationPeer.GetAutomationId();