[reflection] Coop handles icalls in System.Reflection and System.RuntimeTypeHandle...
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Annotations / AnnotationManager.cs
1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //----------------------------------------------------------------
6
7 namespace System.Activities.Presentation.Annotations
8 {
9     using System.Activities.Presentation.Hosting;
10     using System.Activities.Presentation.Model;
11     using System.Activities.Presentation.View;
12     using System.ComponentModel;
13     using System.Runtime;
14     using System.Windows;
15     using System.Windows.Threading;
16
17     internal class AnnotationManager
18     {
19         private bool isInitialized;
20
21         private WorkflowViewElement workflowViewElement;
22         private IAnnotationVisualProvider annotationVisualProvider;
23
24         private ModelItem modelItem;
25         private EditingContext editingContext;
26         private IAnnotationIndicator indicator;
27         private IDockedAnnotation dockedAnnotation;
28         private IFloatingAnnotation floatingAnnotation;
29
30         private bool isViewStateChangedInternally;
31         private AnnotationStatus status;
32         private AnnotationAdorner annotationAdorner;
33         private DispatcherTimer tryHideTimer;
34         private bool hasAnnotation;
35
36         private IIntegratedHelpService helpService;
37
38         internal AnnotationManager(WorkflowViewElement workflowViewElement)
39         {
40             this.workflowViewElement = workflowViewElement;
41         }
42
43         public IAnnotationVisualProvider AnnotationVisualProvider
44         {
45             get
46             {
47                 return this.annotationVisualProvider;
48             }
49
50             set
51             {
52                 if (this.annotationVisualProvider != value)
53                 {
54                     if (this.isInitialized)
55                     {
56                         throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotChangeValueAfterInitialization));
57                     }
58
59                     this.annotationVisualProvider = value;
60                 }
61             }
62         }
63
64         protected internal virtual AnnotationAdornerService AnnotationAdornerService
65         {
66             get
67             {
68                 return this.EditingContext.Services.GetService<AnnotationAdornerService>();
69             }
70         }
71
72         private ModelItem ModelItem
73         {
74             get
75             {
76                 return this.modelItem;
77             }
78
79             set
80             {
81                 if (this.modelItem != value)
82                 {
83                     Fx.Assert(!this.isInitialized, "could not change value after initialization");
84
85                     this.modelItem = value;
86                 }
87             }
88         }
89
90         private EditingContext EditingContext
91         {
92             get
93             {
94                 return this.editingContext;
95             }
96
97             set
98             {
99                 if (this.editingContext != value)
100                 {
101                     Fx.Assert(!this.isInitialized, "could not change value after initialization");
102
103                     this.editingContext = value;
104                 }
105             }
106         }
107
108         private IAnnotationIndicator Indicator
109         {
110             get
111             {
112                 if (this.indicator == null)
113                 {
114                     this.indicator = this.AnnotationVisualProvider.GetAnnotationIndicator();
115                 }
116
117                 return this.indicator;
118             }
119         }
120
121         private IFloatingAnnotation FloatingAnnotation
122         {
123             get
124             {
125                 if (this.floatingAnnotation == null)
126                 {
127                     this.floatingAnnotation = this.AnnotationVisualProvider.GetFloatingAnnotation();
128
129                     this.floatingAnnotation.IsReadOnly = this.EditingContext.Items.GetValue<ReadOnlyState>().IsReadOnly;
130                     this.floatingAnnotation.IsMouseOverChanged += new EventHandler(this.OnFloatingAnnotationIsMouseOverChanged);
131                     this.floatingAnnotation.IsKeyboardFocusWithinChanged += new DependencyPropertyChangedEventHandler(this.OnFloatingAnnotationIsKeyboardFocusWithinChanged);
132                     this.floatingAnnotation.DockButtonClicked += new Action(this.OnDockButtonClicked);
133                     this.floatingAnnotation.ModelItem = this.ModelItem;
134                 }
135
136                 return this.floatingAnnotation;
137             }
138         }
139
140         private IDockedAnnotation DockedAnnotation
141         {
142             get
143             {
144                 if (this.dockedAnnotation == null)
145                 {
146                     this.dockedAnnotation = this.AnnotationVisualProvider.GetDockedAnnotation();
147
148                     this.dockedAnnotation.IsReadOnly = this.EditingContext.Items.GetValue<ReadOnlyState>().IsReadOnly;
149                     this.dockedAnnotation.UndockButtonClicked += new Action(this.OnUndockButtonClicked);
150                 }
151
152                 return this.dockedAnnotation;
153             }
154         }
155
156         private ViewStateService ViewStateService
157         {
158             get
159             {
160                 return this.EditingContext.Services.GetService<ViewStateService>();
161             }
162         }
163
164         private AnnotationAdorner AnnotationAdorner
165         {
166             get
167             {
168                 if (this.annotationAdorner == null)
169                 {
170                     this.annotationAdorner = new AnnotationAdorner(this.workflowViewElement);
171                     this.annotationAdorner.Content = this.FloatingAnnotation as UIElement;
172                 }
173
174                 return this.annotationAdorner;
175             }
176         }
177
178         private bool IsAnnotationDocked
179         {
180             get
181             {
182                 bool? value = this.ViewStateService.RetrieveViewState(this.ModelItem, Annotation.IsAnnotationDockedViewStateName) as bool?;
183                 if (value.HasValue)
184                 {
185                     return value.Value;
186                 }
187                 else
188                 {
189                     return false;
190                 }
191             }
192
193             set
194             {
195                 this.isViewStateChangedInternally = true;
196                 this.ViewStateService.StoreViewState(this.ModelItem, Annotation.IsAnnotationDockedViewStateName, value);
197                 this.isViewStateChangedInternally = false;
198             }
199         }
200
201         private DispatcherTimer TryHideTimer
202         {
203             get
204             {
205                 if (this.tryHideTimer == null)
206                 {
207                     this.tryHideTimer = new DispatcherTimer();
208                     this.tryHideTimer.Interval = TimeSpan.FromMilliseconds(200);
209                     this.tryHideTimer.Tick += this.TryHideAnnotation;
210                 }
211
212                 return this.tryHideTimer;
213             }
214         }
215
216         public void Initialize()
217         {
218             if (this.isInitialized)
219             {
220                 return;
221             }
222
223             this.ModelItem = this.workflowViewElement.ModelItem;
224             this.EditingContext = this.workflowViewElement.Context;
225
226             if (!this.CanInitialize())
227             {
228                 return;
229             }
230
231             this.EditingContext.Items.Subscribe<ReadOnlyState>(this.OnReadOnlyStateChanged);
232             this.ViewStateService.ViewStateChanged += new ViewStateChangedEventHandler(this.OnViewStateChanged);
233             this.ModelItem.PropertyChanged += new PropertyChangedEventHandler(this.OnModelItemPropertyChanged);
234             this.Indicator.IsMouseOverChanged += new EventHandler(this.OnIndicatorIsMouseOverChanged);
235             this.helpService = this.EditingContext.Services.GetService<IIntegratedHelpService>();
236
237             this.hasAnnotation = this.ModelItem.Properties[Annotation.AnnotationTextPropertyName].ComputedValue != null;
238
239             if (this.ModelItem.Properties[Annotation.AnnotationTextPropertyName].ComputedValue == null)
240             {
241                 this.Indicator.Visibility = Visibility.Collapsed;
242                 if (this.dockedAnnotation != null)
243                 {
244                     this.DockedAnnotation.Visibility = Visibility.Collapsed;
245                 }
246             }
247             else
248             {
249                 if (this.IsAnnotationDocked)
250                 {
251                     this.Indicator.Visibility = Visibility.Collapsed;
252                     this.DockedAnnotation.Visibility = Visibility.Visible;
253                     this.status = AnnotationStatus.Docked;
254                 }
255                 else
256                 {
257                     this.Indicator.Visibility = Visibility.Visible;
258                     this.DockedAnnotation.Visibility = Visibility.Collapsed;
259                 }
260             }
261
262             this.isInitialized = true;
263         }
264
265         public void Uninitialize()
266         {
267             if (!this.isInitialized)
268             {
269                 return;
270             }
271
272             this.EditingContext.Items.Unsubscribe<ReadOnlyState>(this.OnReadOnlyStateChanged);
273             this.ViewStateService.ViewStateChanged -= new ViewStateChangedEventHandler(this.OnViewStateChanged);
274             this.ModelItem.PropertyChanged -= new PropertyChangedEventHandler(this.OnModelItemPropertyChanged);
275             this.Indicator.IsMouseOverChanged -= new EventHandler(this.OnIndicatorIsMouseOverChanged);
276
277             if (this.dockedAnnotation != null)
278             {
279                 this.dockedAnnotation.UndockButtonClicked -= new Action(this.OnUndockButtonClicked);
280             }
281
282             if (this.floatingAnnotation != null)
283             {
284                 this.floatingAnnotation.IsMouseOverChanged -= new EventHandler(this.OnFloatingAnnotationIsMouseOverChanged);
285                 this.floatingAnnotation.IsKeyboardFocusWithinChanged -= new DependencyPropertyChangedEventHandler(this.OnFloatingAnnotationIsKeyboardFocusWithinChanged);
286                 this.floatingAnnotation.DockButtonClicked -= new Action(this.OnDockButtonClicked);
287             }
288
289             if (this.tryHideTimer != null)
290             {
291                 this.tryHideTimer.Tick -= this.TryHideAnnotation;
292                 if (this.tryHideTimer.IsEnabled)
293                 {
294                     this.tryHideTimer.Stop();
295                 }
296             }
297
298             this.tryHideTimer = null;
299
300             this.isInitialized = false;
301         }
302
303         public void OnEditAnnotation()
304         {
305             if (!this.isInitialized)
306             {
307                 return;
308             }
309
310             if (this.status == AnnotationStatus.Docked)
311             {
312                 this.DockedAnnotation.FocusOnContent();
313                 return;
314             }
315
316             if (this.status == AnnotationStatus.Hidden)
317             {
318                 this.ShowAnnotation();
319             }
320
321             this.FloatingAnnotation.FocusOnContent();
322         }
323
324         private void OnReadOnlyStateChanged(ReadOnlyState state)
325         {
326             if (this.floatingAnnotation != null)
327             {
328                 this.floatingAnnotation.IsReadOnly = state.IsReadOnly;
329             }
330
331             if (this.dockedAnnotation != null)
332             {
333                 this.dockedAnnotation.IsReadOnly = state.IsReadOnly;
334             }
335         }
336
337         private void OnViewStateChanged(object sender, ViewStateChangedEventArgs e)
338         {
339             if (e.ParentModelItem == this.ModelItem && e.Key == Annotation.IsAnnotationDockedViewStateName && !this.isViewStateChangedInternally)
340             {
341                 bool? isAnnotationDocked = e.NewValue as bool?;
342                 if (isAnnotationDocked.HasValue)
343                 {
344                     if (this.hasAnnotation)
345                     {
346                         if (isAnnotationDocked.Value)
347                         {
348                             this.DockAnnotation();
349                         }
350                         else
351                         {
352                             this.HideAnnotation();
353                         }
354                     }
355                 }
356             }
357         }
358
359         private void OnModelItemPropertyChanged(object sender, PropertyChangedEventArgs e)
360         {
361             if (e.PropertyName == Annotation.AnnotationTextPropertyName)
362             {
363                 bool previouslyHadAnnotation = this.hasAnnotation;
364                 this.hasAnnotation = this.ModelItem.Properties[Annotation.AnnotationTextPropertyName].ComputedValue != null;
365
366                 if (!this.hasAnnotation)
367                 {
368                     //// annotation is removed
369
370                     if (this.status == AnnotationStatus.Floating)
371                     {
372                         this.AnnotationAdornerService.Hide(this.AnnotationAdorner);
373                     }
374
375                     this.Indicator.Visibility = Visibility.Collapsed;
376                     if (this.dockedAnnotation != null)
377                     {
378                         this.dockedAnnotation.Visibility = Visibility.Collapsed;
379                     }
380
381                     this.status = AnnotationStatus.Hidden;
382                 }
383                 else if (!previouslyHadAnnotation)
384                 {
385                     //// annotation is added
386
387                     if (this.IsAnnotationDocked)
388                     {
389                         this.Indicator.Visibility = Visibility.Collapsed;
390                         this.DockedAnnotation.Visibility = Visibility.Visible;
391                         this.status = AnnotationStatus.Docked;
392                     }
393                     else
394                     {
395                         this.Indicator.Visibility = Visibility.Visible;
396                     }
397                 }
398             }
399         }
400
401         private void OnUndockButtonClicked()
402         {
403             this.ShowAnnotation();
404             this.OnEditAnnotation();
405         }
406
407         private void OnFloatingAnnotationIsMouseOverChanged(object sender, EventArgs e)
408         {
409             if (!this.FloatingAnnotation.IsMouseOver)
410             {
411                 if (this.status == AnnotationStatus.Floating)
412                 {
413                     this.DelayedTryHide();
414                 }
415             }
416         }
417
418         private void OnFloatingAnnotationIsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
419         {
420             if (!this.FloatingAnnotation.IsKeyboardFocusWithin)
421             {
422                 this.TryHideAnnotation(null, null);
423                 if (this.helpService != null)
424                 {
425                     this.helpService.RemoveContextAttribute(string.Empty, typeof(Annotation).FullName);
426                     this.helpService.AddContextAttribute(string.Empty, WorkflowViewManager.GetF1HelpTypeKeyword(this.ModelItem.ItemType), ComponentModel.Design.HelpKeywordType.F1Keyword);
427                 }
428             }
429             else
430             {
431                 Selection.SelectOnly(this.EditingContext, this.ModelItem);
432                 if (this.helpService != null)
433                 {
434                     this.helpService.RemoveContextAttribute(string.Empty, WorkflowViewManager.GetF1HelpTypeKeyword(this.ModelItem.ItemType));
435                     this.helpService.AddContextAttribute(string.Empty, typeof(Annotation).FullName, ComponentModel.Design.HelpKeywordType.F1Keyword);
436                 }
437             }
438         }
439
440         private void OnIndicatorIsMouseOverChanged(object sender, EventArgs e)
441         {
442             if (this.Indicator.IsMouseOver)
443             {
444                 if (this.status == AnnotationStatus.Hidden)
445                 {
446                     this.ShowAnnotation();
447                 }
448             }
449             else
450             {
451                 if (this.status == AnnotationStatus.Floating)
452                 {
453                     this.DelayedTryHide();
454                 }
455             }
456         }
457
458         private void OnDockButtonClicked()
459         {
460             this.DockAnnotation();
461         }
462
463         private bool CanInitialize()
464         {
465             return this.ModelItem != null &&
466                    this.EditingContext != null &&
467                    this.AnnotationVisualProvider != null &&
468                    this.EditingContext.Services.GetService<DesignerConfigurationService>().AnnotationEnabled;
469         }
470
471         private void TryHideAnnotation(object sender, EventArgs e)
472         {
473             DispatcherTimer timer = sender as DispatcherTimer;
474             if (timer != null)
475             {
476                 timer.Stop();
477             }
478
479             if (this.status == AnnotationStatus.Floating)
480             {
481                 if (!this.FloatingAnnotation.IsMouseOver &&
482                     !this.Indicator.IsMouseOver &&
483                     !this.FloatingAnnotation.IsKeyboardFocusWithin)
484                 {
485                     this.HideAnnotation();
486                 }
487             }
488         }
489
490         private void DelayedTryHide()
491         {
492             if (this.TryHideTimer.IsEnabled)
493             {
494                 this.TryHideTimer.Stop();
495             }
496
497             this.TryHideTimer.Start();
498         }
499
500         private void ShowAnnotation()
501         {
502             System.Diagnostics.Debug.WriteLine("ShowAnnotation called.");
503
504             switch (this.status)
505             {
506                 case AnnotationStatus.Floating:
507                     return;
508                 case AnnotationStatus.Hidden:
509                     this.AnnotationAdornerService.Show(this.AnnotationAdorner);
510                     break;
511                 case AnnotationStatus.Docked:
512                     if (this.Indicator != null)
513                     {
514                         this.Indicator.Visibility = Visibility.Visible;
515                     }
516
517                     this.DockedAnnotation.Visibility = Visibility.Collapsed;
518
519                     this.AnnotationAdornerService.Show(this.AnnotationAdorner);
520                     break;
521             }
522
523             this.status = AnnotationStatus.Floating;
524             this.IsAnnotationDocked = false;
525         }
526
527         private void HideAnnotation()
528         {
529             System.Diagnostics.Debug.WriteLine("HideAnnotation called.");
530
531             if (this.status == AnnotationStatus.Hidden)
532             {
533                 return;
534             }
535
536             if (this.status == AnnotationStatus.Floating)
537             {
538                 this.FloatingAnnotation.UpdateModelItem();
539                 this.AnnotationAdornerService.Hide(this.AnnotationAdorner);
540             }
541
542             if (this.status == AnnotationStatus.Docked)
543             {
544                 this.Indicator.Visibility = Visibility.Visible;
545
546                 this.DockedAnnotation.Visibility = Visibility.Collapsed;
547             }
548
549             this.status = AnnotationStatus.Hidden;
550             this.IsAnnotationDocked = false;
551         }
552
553         private void DockAnnotation()
554         {
555             System.Diagnostics.Debug.WriteLine("DockAnnotation called.");
556
557             if (this.status == AnnotationStatus.Docked)
558             {
559                 return;
560             }
561
562             if (this.status == AnnotationStatus.Floating)
563             {
564                 this.AnnotationAdornerService.Hide(this.AnnotationAdorner);
565             }
566
567             this.Indicator.Visibility = Visibility.Collapsed;
568             this.DockedAnnotation.Visibility = Visibility.Visible;
569
570             this.status = AnnotationStatus.Docked;
571             this.IsAnnotationDocked = true;
572         }
573     }
574 }