[amd64/tramp] hide interpreter specific trampoline behind ifdef
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / FreeFormEditing / Connector.cs
1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //----------------------------------------------------------------
6
7 namespace System.Activities.Presentation.FreeFormEditing
8 {
9     using System;
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;
15     using System.Runtime;
16     using System.Windows;
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;
22
23     internal class Connector : UserControl
24     {
25         public const double ArrowShapeWidth = 5;
26         
27         public static readonly DependencyProperty PointsProperty = DependencyProperty.Register(
28             "Points", 
29             typeof(PointCollection), 
30             typeof(Connector), 
31             new FrameworkPropertyMetadata(new PointCollection()));
32         
33         public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
34             "IsSelected", 
35             typeof(bool), 
36             typeof(Connector), 
37             new FrameworkPropertyMetadata(false));
38         
39         public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register(
40             "LabelText", 
41             typeof(string), 
42             typeof(Connector), 
43             new FrameworkPropertyMetadata(null));
44
45         public static readonly DependencyProperty HighlightOnHoverProperty = DependencyProperty.Register(
46             "HighlightOnHover",
47             typeof(bool),
48             typeof(Connector),
49             new FrameworkPropertyMetadata(false));
50
51         public static readonly DependencyProperty IsHighlightedForAutoSplitProperty = DependencyProperty.Register(
52             "IsHighlightedForAutoSplit",
53             typeof(bool),
54             typeof(Connector),
55             new FrameworkPropertyMetadata(false));
56
57         public static readonly DependencyProperty IdentityProperty = DependencyProperty.Register(
58             "Identity", 
59             typeof(Guid), 
60             typeof(Connector));
61
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;
64
65         private DesignerConfigurationService designerConfigurationService = null;
66
67         private FreeFormPanel panel = null;
68         
69         public Connector()
70         {
71             this.Loaded += (sender, e) =>
72             {
73                 this.Identity = Guid.NewGuid();
74             };
75         }
76
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
80         {
81             get { return (PointCollection)GetValue(Connector.PointsProperty); }
82             set { SetValue(Connector.PointsProperty, value); }
83         }
84
85         public bool IsSelected
86         {
87             get { return (bool)GetValue(Connector.IsSelectedProperty); }
88             set { SetValue(Connector.IsSelectedProperty, value); }
89         }
90
91         public string LabelText
92         {
93             get { return (string)GetValue(Connector.LabelTextProperty); }
94             set { SetValue(Connector.LabelTextProperty, value); }
95         }
96
97         public bool HighlightOnHover
98         {
99             get { return (bool)GetValue(Connector.HighlightOnHoverProperty); }
100             set { SetValue(Connector.HighlightOnHoverProperty, value); }
101         }
102
103         public bool IsHighlightedForAutoSplit
104         {
105             get { return (bool)GetValue(Connector.IsHighlightedForAutoSplitProperty); }
106             set { SetValue(Connector.IsHighlightedForAutoSplitProperty, value); }
107         }
108
109         public Guid Identity
110         {
111             get { return (Guid)GetValue(Connector.IdentityProperty); }
112             set { SetValue(Connector.IdentityProperty, value); }
113         }
114
115         public UIElement SourceShape
116         {
117             get
118             {
119                 ConnectionPoint sourceConnectionPoint = FreeFormPanel.GetSourceConnectionPoint(this);
120                 if (sourceConnectionPoint != null)
121                 {
122                     return sourceConnectionPoint.ParentDesigner;
123                 }
124
125                 return null;
126             }
127         }
128
129         public UIElement DestinationShape
130         {
131             get
132             {
133                 ConnectionPoint destinationConnectionPoint = FreeFormPanel.GetDestinationConnectionPoint(this);
134                 if (destinationConnectionPoint != null)
135                 {
136                     return destinationConnectionPoint.ParentDesigner;
137                 }
138
139                 return null;
140             }
141         }
142
143         public IAutoSplitContainer AutoSplitContainer
144         {
145             get;
146             set;
147         }
148
149         public virtual FrameworkElement StartDot
150         {
151             get
152             {
153                 return null;
154             }
155         }
156
157         private FreeFormPanel Panel
158         {
159             get
160             {
161                 if (this.panel == null)
162                 {
163                     this.panel = VisualTreeUtils.FindVisualAncestor<FreeFormPanel>(this);
164                 }
165
166                 return this.panel;
167             }
168         }
169
170         private bool AutoSplitEnabled
171         {
172             get
173             {
174                 if (this.designerConfigurationService == null)
175                 {
176                     DesignerView view = VisualTreeUtils.FindVisualAncestor<DesignerView>(this);
177                     if (view != null)
178                     {
179                         this.designerConfigurationService = view.Context.Services.GetService<DesignerConfigurationService>();
180                         return this.designerConfigurationService.AutoSplitEnabled;
181                     }
182                     else
183                     {
184                         return false;
185                     }
186                 }
187                 else
188                 {
189                     return this.designerConfigurationService.AutoSplitEnabled;
190                 }
191             }
192         }
193
194         public virtual void SetLabelToolTip(object toolTip)
195         {
196             // subclass should be able to override this method to provide ToolTip of connector
197         }
198
199         protected override AutomationPeer OnCreateAutomationPeer()
200         {
201             return new ConnectorAutomationPeer(this, base.OnCreateAutomationPeer());
202         }
203
204         protected override void OnDragEnter(DragEventArgs e)
205         {
206             if (this.AutoSplitEnabled && this.AutoSplitContainer != null && DragDropHelper.GetDraggedObjectCount(e) == 1 && this.AutoSplitContainer.CanAutoSplit(e))
207             {
208                 this.HighlightForAutoSplit();
209                 this.Panel.RemoveAutoConnectAdorner();
210                 this.Panel.CurrentAutoSplitTarget = this;
211             }
212
213             base.OnDragEnter(e);
214         }
215
216         protected override void OnDragLeave(DragEventArgs e)
217         {
218             if (this.IsHighlightedForAutoSplit)
219             {
220                 this.DehighlightForAutoSplit();
221                 this.Panel.CurrentAutoSplitTarget = null;
222             }
223
224             base.OnDragLeave(e);
225         }
226
227         protected override void OnDrop(DragEventArgs e)
228         {
229             if (this.AutoSplitEnabled && this.IsHighlightedForAutoSplit)
230             {
231                 try
232                 {
233                     this.AutoSplitContainer.DoAutoSplit(e, this);
234                 }
235                 finally
236                 {
237                     this.DehighlightForAutoSplit();
238                     this.Panel.CurrentAutoSplitTarget = null;
239                     e.Handled = true;
240                 }
241             }
242
243             base.OnDrop(e);
244         }
245
246         private void AddAutoSplitAdorner(UIElement shape)
247         {
248             AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(shape);
249             Fx.Assert(adornerLayer != null, "AdornerLayer should not be null.");
250             adornerLayer.Add(new AutoSplitAdorner(shape));
251         }
252
253         private void RemoveAutoSplitAdorner(UIElement shape)
254         {
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)
259             {
260                 if (adorner is AutoSplitAdorner)
261                 {
262                     adornerLayer.Remove(adorner);
263                     return;
264                 }
265             }
266         }
267
268         private void HighlightForAutoSplit()
269         {
270             this.IsHighlightedForAutoSplit = true;
271             this.AddAutoSplitAdorner(this.SourceShape);
272             this.AddAutoSplitAdorner(this.DestinationShape);
273         }
274
275         private void DehighlightForAutoSplit()
276         {
277             this.IsHighlightedForAutoSplit = false;
278             this.RemoveAutoSplitAdorner(this.SourceShape);
279             this.RemoveAutoSplitAdorner(this.DestinationShape);
280         }
281
282         private class ConnectorAutomationPeer : UIElementAutomationPeer
283         {
284             private AutomationPeer wrappedAutomationPeer;
285
286             public ConnectorAutomationPeer(FrameworkElement owner, AutomationPeer wrappedAutomationPeer)
287                 : base(owner)
288             {
289                 this.wrappedAutomationPeer = wrappedAutomationPeer;
290             }
291
292             protected override string GetItemStatusCore()
293             {
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);
299             }
300
301             protected override string GetClassNameCore()
302             {
303                 return this.wrappedAutomationPeer.GetClassName();
304             }
305
306             protected override string GetNameCore()
307             {
308                 return this.wrappedAutomationPeer.GetName();
309             }
310
311             protected override string GetAutomationIdCore()
312             {
313                 return this.wrappedAutomationPeer.GetAutomationId();
314             }
315         }
316     }
317 }