[runtime] Fix corlib out of date error with disabled COM
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Base / Core / Internal / PropertyEditing / Automation / CategoryContainerAutomationPeer.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.Internal.PropertyEditing.Automation 
5 {
6     using System;
7     using System.Collections.Generic;
8     using System.ComponentModel;
9     using System.Diagnostics;
10     using System.Text;
11     using System.Windows;
12     using System.Windows.Automation;
13     using System.Windows.Automation.Peers;
14     using System.Windows.Automation.Provider;
15     using System.Windows.Controls;
16     using System.Windows.Media;
17
18     using System.Runtime;
19     using System.Activities.Presentation.PropertyEditing;
20     using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.PropertyInspector;
21
22     using System.Activities.Presentation.Internal.Properties;
23     using System.Activities.Presentation.Internal.PropertyEditing.Model;
24     using System.Activities.Presentation.Internal.PropertyEditing.Selection;
25
26     // <summary>
27     // This class contains the core logic for CategoryContainerAutomationPeer.  It's constructor is
28     // private because it can be instantiated in two different ways, which are exposed through
29     // static methods: CreateStandAloneAutomationPeer() and CreateItemAutomationPeer().
30     //
31     // CreateStandAloneAutomationPeer() returns an AutomationPeer that is agnostic of its parent
32     // CreateItemAutomationPeer() returns an AutomationPeer where the parent is assumed to be an ItemsControl.
33     //
34     // Because in the CategoryList : ItemsControl class we manually override GetContainerForItemOverride()
35     // as a way of reducing control count in PI, we need to provide both versions of the
36     // CategoryContainerAutomationPeer.
37     // </summary>
38     internal class CategoryContainerAutomationPeer : IExpandCollapseProvider, IScrollItemProvider 
39     {
40
41         private CiderCategoryContainer _container;
42         private AutomationPeer _itemAutomationPeer;
43
44         // Private ctor called from two public, static accessors
45         private CategoryContainerAutomationPeer(CiderCategoryContainer container, AutomationPeer itemPeer) 
46         {
47             Fx.Assert(container != null, "CategoryContainer not specified.");
48             Fx.Assert(itemPeer != null, "CategoryContainerItemAutomationPeer not specified.");
49             _container = container;
50             _itemAutomationPeer = itemPeer;
51
52         }
53
54         // <summary>
55         // Gets the expand / collapse state of the contained CategoryContainer
56         // </summary>
57         public ExpandCollapseState ExpandCollapseState 
58         {
59             get {
60                 if (_container == null)
61                 {
62                     return ExpandCollapseState.Collapsed;
63                 }
64
65                 return _container.Expanded ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed;
66             }
67         }
68         
69         // IScrollItemProvider Members
70
71         // <summary>
72         // Creates a CategoryContainerAutomationPeer that can be returned directly from
73         // the CiderCategoryContainer control itself.
74         // </summary>
75         // <param name="container">Container to automate</param>
76         // <returns>Instance of CategoryContainerAutomationPeer that can be returned directly from
77         // the CiderCategoryContainer control itself</returns>
78         public static UIElementAutomationPeer CreateStandAloneAutomationPeer(CiderCategoryContainer container) 
79         {
80             return new CategoryContainerStandAloneAutomationPeer(container);
81         }
82
83         // <summary>
84         // Creates a CategoryContainerAutomationPeer that can be returned for CategoryContainers
85         // belonging to a CategoryList control
86         // </summary>
87         // <param name="category">CategoryEntry instance used by ItemsControl</param>
88         // <param name="container">Container to automate</param>
89         // <param name="parentAutomationPeer">Parent AutomationPeer</param>
90         // <returns>Instance of CategoryContainerAutomationPeer that can be returned for CategoryContainers
91         // belonging to a CategoryList control</returns>
92         public static ItemAutomationPeer CreateItemAutomationPeer(ModelCategoryEntry category, CiderCategoryContainer container, CategoryListAutomationPeer parentAutomationPeer) 
93         {
94             return new CategoryContainerItemAutomationPeer(category, container, parentAutomationPeer);
95         }
96
97         // Gets the children of the contained CategoryContainer, returning AutomationPeers
98         // for CategoryEditors followed by AutomationPeers for any left-over properties
99         private List<AutomationPeer> GetChildrenCore() 
100         {
101             List<AutomationPeer> children = new List<AutomationPeer>();
102
103             if (_container != null) 
104             {
105                 AddCategoryEditors(children, VisualTreeUtils.GetNamedChild<ItemsControl>(_container, "PART_BasicCategoryEditors"), Resources.PropertyEditing_BasicCategoryEditors);
106                 AddCategoryProperties(children, VisualTreeUtils.GetNamedChild<ItemsControl>(_container, "PART_BasicPropertyList"));
107
108                 if (_container.Expanded) 
109                 {
110
111                     Expander advancedExpander = VisualTreeUtils.GetNamedChild<Expander>(_container, "PART_AdvancedExpander");
112
113                     if (advancedExpander != null &&
114                         advancedExpander.Visibility == Visibility.Visible) 
115                     {
116                         children.Add(new AdvancedCategoryContainerAutomationPeer(_container, advancedExpander));
117                     }
118                 }
119             }
120
121             return children;
122         }
123
124         // Adds AutomationPeers for all CategoryEditors displayed within the contained CategoryContainer
125         private static void AddCategoryEditors(List<AutomationPeer> peers, ItemsControl editors, string containerDisplayName) 
126         {
127             if (editors == null || editors.Items.Count == 0)
128             {
129                 return;
130             }
131
132             peers.Add(new CategoryEditorListAutomationPeer(containerDisplayName, editors));
133         }
134
135         // Adds AutomationPeers for all PropertyEntries not consumed by the CategoryEditors within this
136         // CategoryContainer
137         private static void AddCategoryProperties(List<AutomationPeer> peers, ItemsControl properties) 
138         {
139             if (properties == null)
140             {
141                 return;
142             }
143
144             int childCount = properties.Items.Count;
145
146             for (int i = 0; i < childCount; i++) 
147             {
148                 PropertyContainer propertyContainer = properties.ItemContainerGenerator.ContainerFromIndex(i) as PropertyContainer;
149
150                 if (propertyContainer != null)
151                 {
152                     peers.Add(new PropertyContainerAutomationPeer(propertyContainer));
153                 }
154             }
155         }
156
157         // Gets the implementation of the specified pattern if one exists.
158         // Currently supported patterns: ExpandCollapse
159         private object GetPattern(PatternInterface patternInterface) 
160         {
161             if (patternInterface == PatternInterface.ExpandCollapse)
162             {
163                 return this;
164             }
165             else if (patternInterface == PatternInterface.ScrollItem)
166             {
167                 return this;
168             }
169
170             return null;
171         }
172
173         // Returns the name of the represented category
174         private string GetNameCore() 
175         {
176             if (_container != null)
177             {
178                 return _container.Category.CategoryName;
179             }
180
181             return string.Empty;
182         }
183
184         // Return "CategoryContainer"
185         private static string GetClassNameCore() 
186         {
187             return typeof(CategoryContainer).Name;
188         }
189
190         // Gets the help text to associated with the contained CategoryContainer
191         private static string GetHelpTextCore() 
192         {
193             return Resources.PropertyEditing_CategoryContainerAutomationPeerHelp;
194         }
195
196         // IExpandCollapseProvider Members
197
198         // <summary>
199         // Collapses the contained CategoryContainer
200         // </summary>
201         public void Collapse() 
202         {
203             if (_container != null)
204             {
205                 _container.Expanded = false;
206             }
207         }
208
209         // <summary>
210         // Expands the contained CategoryContainer
211         // </summary>
212         public void Expand() 
213         {
214             if (_container != null)
215             {
216                 _container.Expanded = true;
217             }
218         }
219
220         // <summary>
221         // Scrolls the contained CategoryContainer into view
222         // </summary>
223         public void ScrollIntoView() 
224         {
225             if (_container != null)
226             {
227                 _container.BringIntoView();
228             }
229         }
230
231
232         // RaiseSelectionEventsForScreenReader
233
234         // <summary>
235         //  This public method is called when parent creates the CategoryContainerItemAutomationPeer
236         //  in the GetChildrenCore, thus listening to the changes in the IsSelectedProperty.
237         // </summary>
238         public void AddFocusEvents() 
239         {
240             if (_container != null) 
241             {
242                 HookUpFocusEvents(VisualTreeUtils.GetNamedChild<Expander>(_container, "PART_MainExpander"), OnIsSelectedValueChanged);
243             }
244         }
245
246         // <summary>
247         // Private helper function to listen to the changes in the IsSelectedProperty,
248         // which then fires the OnValueChanged event.
249         // </summary>
250         // <param name="expander">Expander control</param>
251         // <param name="valueChangedEvent">ValueChanged event</param>
252         private static void HookUpFocusEvents(Expander expander, EventHandler valueChangedEvent) 
253         {
254             if (expander != null) 
255             {
256                 FrameworkElement expanderGrid = VisualTreeUtils.GetNamedChild<FrameworkElement>(expander, "PART_BasicSection");
257                 if (expanderGrid != null) 
258                 {
259                     DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(PropertySelection.IsSelectedProperty, typeof(Grid));
260                     if (dpd != null) 
261                     {
262                         dpd.AddValueChanged(expanderGrid, valueChangedEvent);
263                     }
264                 }
265             }
266         }
267
268         // <summary>
269         // The actual event handler, that fires when the IsSelected DP changes.
270         // Here we raise the AutomationFocus event.
271         // </summary>
272         // <param name="sender">Expander</param>
273         // <param name="e">EventArgs</param>
274         private void OnIsSelectedValueChanged(object sender, EventArgs e) 
275         {
276             // Add logic to respond to "Selection"
277             bool curVal = PropertySelection.GetIsSelected(sender as DependencyObject);
278             if (curVal) 
279             {
280                 _itemAutomationPeer.RaiseAutomationEvent(AutomationEvents.AutomationFocusChanged);
281             }
282         }
283
284
285
286         // <summary>
287         //  This public method is called when parent creates the CategoryContainerItemAutomationPeer
288         //  in the GetChildrenCore, thus clearing off all the event listeners before we add new ones
289         // </summary>
290         public void RemoveFocusEvents() 
291         {
292             if (_container != null) 
293             {
294                 UnHookFocusEvents(VisualTreeUtils.GetNamedChild<Expander>(_container, "PART_MainExpander"), OnIsSelectedValueChanged);
295             }
296         }
297
298         // <summary>
299         // Private method to unhook the ValueChanged event.
300         // </summary>
301         // <param name="expander">Expander</param>
302         // <param name="valueChangedEvent">ValueChanged event</param>
303         private static void UnHookFocusEvents(Expander expander, EventHandler valueChangedEvent) 
304         {
305             if (expander != null) 
306             {
307                 FrameworkElement expanderGrid = VisualTreeUtils.GetNamedChild<FrameworkElement>(expander, "PART_BasicSection");
308                 if (expanderGrid != null) 
309                 {
310                     DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(PropertySelection.IsSelectedProperty, typeof(Grid));
311                     if (dpd != null) 
312                     {
313                         dpd.RemoveValueChanged(expanderGrid, valueChangedEvent);
314                     }
315                 }
316             }
317         }
318
319         // end RaiseSelectionEventsForScreenReader
320
321         // <summary>
322         // Helper AutomationPeer that represents CategoryContainerAutomationPeer when the CategoryContainer
323         // is hosted in a CategoryList control.  All of its methods delegate to CategoryContainerAutomationPeer
324         // </summary>
325         internal class CategoryContainerItemAutomationPeer : ItemAutomationPeer, IAutomationFocusChangedEventSource 
326         {
327
328             private CategoryContainerAutomationPeer _coreLogic;
329             private List<AutomationPeer> _children;
330
331             public CategoryContainerItemAutomationPeer(
332                 ModelCategoryEntry item,
333                 CiderCategoryContainer container,
334                 CategoryListAutomationPeer parentAutomationPeer)
335                 : base(item, parentAutomationPeer) 
336             {
337                 _coreLogic = new CategoryContainerAutomationPeer(container, this);
338                 _coreLogic.AddFocusEvents();
339             }
340
341             // Implementation of this method is specific to CategoryContainerItemAutomationPeer
342             protected override AutomationControlType GetAutomationControlTypeCore() 
343             {
344                 return AutomationControlType.List;
345             }
346
347             protected override List<AutomationPeer> GetChildrenCore() 
348             {
349                 _children = _coreLogic.GetChildrenCore();
350                 return _children;
351             }
352
353             protected override string GetNameCore() 
354             {
355                 return _coreLogic.GetNameCore();
356             }
357
358             protected override string GetClassNameCore() 
359             {
360                 return CategoryContainerAutomationPeer.GetClassNameCore();
361             }
362
363             protected override string GetHelpTextCore() 
364             {
365                 return CategoryContainerAutomationPeer.GetHelpTextCore();
366             }
367
368             public override object GetPattern(PatternInterface patternInterface) 
369             {
370                 return _coreLogic.GetPattern(patternInterface);
371             }
372
373             // IAutomationFocusChangedEventSource Members
374             public void UnloadEventHook() 
375             {
376                 _coreLogic.RemoveFocusEvents();
377                 if (_children != null) 
378                 {
379                     foreach (AutomationPeer peer in _children) 
380                     {
381                         IAutomationFocusChangedEventSource unhookEventPeer = peer as IAutomationFocusChangedEventSource;
382                         if (unhookEventPeer != null) 
383                         {
384                             unhookEventPeer.UnloadEventHook();
385                         }
386                     }
387                 }
388             }
389         }
390
391         // <summary>
392         // Automation peer we use to display the list of CategoryEditors
393         // </summary>
394         private class CategoryEditorListAutomationPeer : ItemsControlAutomationPeer 
395         {
396
397             private string _displayName;
398
399             // Note: the display name we use here is for completeness only.  This class is hidden
400             // from screen readers.
401             public CategoryEditorListAutomationPeer(string displayName, ItemsControl owner)
402                 : base(owner) 
403             {
404                 _displayName = displayName ?? string.Empty;
405             }
406
407             protected override ItemAutomationPeer CreateItemAutomationPeer(object item) 
408             {
409                 return new CategoryEditorAutomationPeer(item, this);
410             }
411
412             protected override string GetClassNameCore() 
413             { 
414                 return typeof(ItemsControl).Name; 
415             }
416             protected override string GetNameCore() 
417             { 
418                 return _displayName; 
419             }
420             protected override bool IsControlElementCore() 
421             { 
422                 return false; 
423             }
424             protected override bool IsContentElementCore() 
425             { 
426                 return false; 
427             }
428
429             private class CategoryEditorAutomationPeer : ItemAutomationPeer 
430             {
431
432                 public CategoryEditorAutomationPeer(object item, CategoryEditorListAutomationPeer parent)
433                     : base(item, parent) 
434                 {
435                 }
436
437                 public override object GetPattern(PatternInterface patternInterface) 
438                 { 
439                     return null; 
440                 }
441                 protected override AutomationControlType GetAutomationControlTypeCore() 
442                 { 
443                     return AutomationControlType.Custom; 
444                 }
445                 protected override string GetClassNameCore() 
446                 { 
447                     return typeof(CategoryEditor).Name; 
448                 }
449                 protected override string GetNameCore() 
450                 { 
451                     return Item == null ? string.Empty : Item.GetType().Name; 
452                 }
453                 protected override bool IsContentElementCore() 
454                 { 
455                     return true; 
456                 }
457                 protected override bool IsControlElementCore() 
458                 { 
459                     return true; 
460                 }
461             }
462         }
463
464         // <summary>
465         // Helper AutomationPeer for the advanced portion of the CategoryContainer
466         // </summary>
467         private class AdvancedCategoryContainerAutomationPeer : ExpanderAutomationPeer, IAutomationFocusChangedEventSource 
468         {
469
470             private CiderCategoryContainer _container;
471             private Expander _expander;
472             private List<AutomationPeer> _children;
473
474             public AdvancedCategoryContainerAutomationPeer(CiderCategoryContainer container, Expander expander)
475                 : base(expander) 
476             {
477                 Fx.Assert(container != null, "CategoryContainer not specified.");
478                 Fx.Assert(expander != null, "Expander not specified.");
479                 _expander = expander;
480                 _container = container;
481                 AddFocusEvents();
482             }
483
484             // <summary>
485             //  This public method is called when parent creates the CategoryContainerItemAutomationPeer
486             //  in the GetChildrenCore, thus listening to the changes in the IsSelectedProperty.
487             // </summary>
488             private void AddFocusEvents() 
489             {
490                 if (_container != null) 
491                 {
492                     HookUpFocusEvents(VisualTreeUtils.GetNamedChild<Expander>(_container, "PART_AdvancedExpander"), OnIsSelectedValueChanged);
493                 }
494             }
495
496             protected override List<AutomationPeer> GetChildrenCore() 
497             {
498                 _children = new List<AutomationPeer>();
499                 if (_container != null) 
500                 {
501                     CategoryContainerAutomationPeer.AddCategoryEditors(_children, VisualTreeUtils.GetNamedChild<ItemsControl>(_container, "PART_AdvancedCategoryEditors"), Resources.PropertyEditing_AdvancedCategoryEditors);
502                     CategoryContainerAutomationPeer.AddCategoryProperties(_children, VisualTreeUtils.GetNamedChild<ItemsControl>(_container, "PART_AdvancedPropertyList"));
503                 }
504                 //Add focus events for Subproperty editor
505                 foreach (AutomationPeer peer in _children) 
506                 {
507                     PropertyContainerAutomationPeer pcAutomationPeer = peer as PropertyContainerAutomationPeer;
508                     if (pcAutomationPeer != null) 
509                     {
510                         pcAutomationPeer.AddFocusEvents();
511                     }
512                 }
513                 return _children;
514             }
515
516             protected override string GetNameCore() 
517             {
518                 return _expander.Header.ToString();
519             }
520
521             // <summary>
522             // Private helper function to listen to the changes in the IsSelectedProperty,
523             // which then fires the OnValueChanged event.
524             // </summary>
525             // <param name="expander">Expander control</param>
526             // <param name="valueChangedEvent">ValueChanged event</param>
527             private static void HookUpFocusEvents(Expander expander, EventHandler valueChangedEvent) 
528             {
529                 if (expander != null) 
530                 {
531                     FrameworkElement expanderGrid = VisualTreeUtils.GetNamedChild<FrameworkElement>(expander, "PART_AdvancedSection");
532                     if (expanderGrid != null) 
533                     {
534                         DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(PropertySelection.IsSelectedProperty, typeof(Grid));
535                         if (dpd != null) 
536                         {
537                             dpd.AddValueChanged(expanderGrid, valueChangedEvent);
538                         }
539                     }
540                 }
541             }
542
543             // <summary>
544             // The actual event handler, that fires when the IsSelected DP changes.
545             // Here we raise the AutomationFocus event for the
546             // Advanced (More Properties) properties expander.
547             // </summary>
548             // <param name="sender">Expander</param>
549             // <param name="e">EventArgs</param>
550             private void OnIsSelectedValueChanged(object sender, EventArgs e) 
551             {
552                 // Add logic to respond to "Selection"
553                 bool curVal = PropertySelection.GetIsSelected(sender as DependencyObject);
554                 if (curVal) 
555                 {
556                     this.RaiseAutomationEvent(AutomationEvents.AutomationFocusChanged);
557                 }
558             }
559
560             // <summary>
561             //  This public method is called when parent creates the CategoryContainerItemAutomationPeer
562             //  in the GetChildrenCore, thus clearing off all the event listeners before we add new ones
563             // </summary>
564             public void RemoveFocusEvents() 
565             {
566                 if (_container != null) 
567                 {
568                     UnHookFocusEvents(VisualTreeUtils.GetNamedChild<Expander>(_container, "PART_AdvancedExpander"), OnIsSelectedValueChanged);
569                 }
570             }
571
572             // <summary>
573             // Private method to unhook the ValueChanged event.
574             // </summary>
575             // <param name="expander">Expander</param>
576             // <param name="valueChangedEvent">ValueChanged event</param>
577             private static void UnHookFocusEvents(Expander expander, EventHandler valueChangedEvent) 
578             {
579                 if (expander != null) 
580                 {
581                     FrameworkElement expanderGrid = VisualTreeUtils.GetNamedChild<FrameworkElement>(expander, "PART_AdvancedSection");
582                     if (expanderGrid != null) 
583                     {
584                         DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(PropertySelection.IsSelectedProperty, typeof(Grid));
585                         if (dpd != null) 
586                         {
587                             dpd.RemoveValueChanged(expanderGrid, valueChangedEvent);
588                         }
589                     }
590                 }
591             }
592
593             // IAutomationFocusChangedEventSource Members
594             public void UnloadEventHook() 
595             {
596                 RemoveFocusEvents();
597                 if (_children != null) 
598                 {
599                     foreach (AutomationPeer peer in _children) 
600                     {
601                         IAutomationFocusChangedEventSource unhookEventPeer = peer as IAutomationFocusChangedEventSource;
602                         if (unhookEventPeer != null) 
603                         {
604                             unhookEventPeer.UnloadEventHook();
605                         }
606                     }
607                 }
608             }
609         }
610
611         // <summary>
612         // Helper AutomationPeer that represents CategoryContainerAutomationPeer when the CategoryContainer
613         // sits on its own.  All of its methods delegate to CategoryContainerAutomationPeer
614         // </summary>
615         private class CategoryContainerStandAloneAutomationPeer : UIElementAutomationPeer, IAutomationFocusChangedEventSource
616         {
617
618             private CategoryContainerAutomationPeer _coreLogic;
619
620             public CategoryContainerStandAloneAutomationPeer(CiderCategoryContainer container)
621                 : base(container) 
622             {
623                 _coreLogic = new CategoryContainerAutomationPeer(container, this);
624                 _coreLogic.AddFocusEvents();
625             }
626
627             protected override List<AutomationPeer> GetChildrenCore() 
628             {
629                 return _coreLogic.GetChildrenCore();
630             }
631
632             protected override string GetNameCore() 
633             {
634                 return _coreLogic.GetNameCore();
635             }
636
637             protected override string GetClassNameCore() 
638             {
639                 return CategoryContainerAutomationPeer.GetClassNameCore();
640             }
641
642             protected override string GetHelpTextCore() 
643             {
644                 return CategoryContainerAutomationPeer.GetHelpTextCore();
645             }
646
647             public override object GetPattern(PatternInterface patternInterface) 
648             {
649                 return _coreLogic.GetPattern(patternInterface);
650             }
651
652             // IAutomationFocusChangedEventSource Members
653
654             public void UnloadEventHook() 
655             {
656                 _coreLogic.RemoveFocusEvents();
657             }
658         }
659     }
660 }