0cc9b272290b8caebd3ac1ad2d633f6662c9160d
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Base / Core / Internal / PropertyEditing / PropertyToolBar.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.Internal.PropertyEditing 
5 {
6     using System;
7     using System.ComponentModel;
8     using System.Diagnostics;
9     using System.Diagnostics.CodeAnalysis;
10     using System.Windows;
11     using System.Windows.Automation.Peers;
12     using System.Windows.Controls;
13     using System.Runtime;
14
15     using System.Activities.Presentation.Internal.PropertyEditing.Automation;
16     using System.Activities.Presentation.Internal.PropertyEditing.State;
17     using System.Activities.Presentation.Internal.PropertyEditing.Views;
18
19     // <summary>
20     // Container control that hosts both the property-search UI as well as the view-switching UI
21     // </summary>
22     internal sealed class PropertyToolBar : Control, INotifyPropertyChanged 
23     {
24
25         // <summary>
26         // Property representing the currently-selected IPropertyViewManager
27         // </summary>
28         public static DependencyProperty CurrentViewManagerProperty = DependencyProperty.Register(
29             "CurrentViewManager",
30             typeof(IPropertyViewManager),
31             typeof(PropertyToolBar),
32             new PropertyMetadata(null, OnCurrentViewManagerChanged));
33
34         // <summary>
35         // Property containing a link to the CategoryList control instance that this
36         // PropertyToolBar controls.  We need this link to be able to change the appearance
37         // of each new generated CategoryContainer (whether it should show a header or not).
38         // That way CategoryList doesn't need to know anything about this class.
39         // </summary>
40         public static DependencyProperty CategoryListProperty = DependencyProperty.Register(
41             "CategoryList",
42             typeof(CategoryList),
43             typeof(PropertyToolBar),
44             new PropertyMetadata(null, OnCategoryListChanged));
45
46         private string _persistenceId;
47         private bool _persistViewManagerChanges = true;
48
49         public PropertyToolBar() 
50         {
51             this.Loaded += new RoutedEventHandler(OnLoaded);
52             this.Unloaded += new RoutedEventHandler(OnUnloaded);
53         }
54
55         // <summary>
56         // Event we fire when the CurrentViewManager changes
57         // </summary>
58         public event EventHandler CurrentViewManagerChanged;
59
60         public event PropertyChangedEventHandler PropertyChanged;
61
62         // <summary>
63         // Gets or set the currently selected IPropertyViewManager
64         // </summary>
65         public IPropertyViewManager CurrentViewManager 
66         {
67             get { return (IPropertyViewManager)this.GetValue(CurrentViewManagerProperty); }
68             set { this.SetValue(CurrentViewManagerProperty, value); }
69         }
70
71         // <summary>
72         // Gets or set the value of the CategoryListProperty
73         // </summary>
74         public CategoryList CategoryList 
75         {
76             get { return (CategoryList)this.GetValue(CategoryListProperty); }
77             set { this.SetValue(CategoryListProperty, value); }
78         }
79
80         // <summary>
81         // Gets or sets a string ID that we use to differentiate between the states of different
82         // PropertyToolBar instances.  Currently, we only care about two different PropertyToolBar
83         // buckets - (1) the PTBs we use in the main PI and (2) the PTBs we use in collection editors.
84         // </summary>
85         public string PersistenceId 
86         {
87             get {
88                 return _persistenceId;
89             }
90             set {
91                 if (_persistenceId != value) 
92                 {
93                     _persistenceId = value;
94
95                     if (this.CurrentViewManager == null) 
96                     {
97                         bool oldPersistViewManagerChanges = _persistViewManagerChanges;
98                         try 
99                         {
100                             _persistViewManagerChanges = false;
101                             this.CurrentViewManager = PropertyViewManagerStateContainer.Instance.GetPropertyViewManager(_persistenceId);
102                         }
103                         finally 
104                         {
105                             _persistViewManagerChanges = oldPersistViewManagerChanges;
106                         }
107                     }
108
109                     OnPropertyChanged("PersistenceId");
110                 }
111             }
112         }
113
114         // <summary>
115         // Convenience accessor for the UI data binding
116         // </summary>
117         public bool IsCategoryViewSelected 
118         {
119             get {
120                 if (this.CurrentViewManager != null)
121                 {
122                     return this.CurrentViewManager == ByCategoryViewManager.Instance;
123                 }
124
125                 return false;
126             }
127             set {
128                 // No need to fire PropertyChanged events here - changing CurrentViewManager
129                 // will fire those events as a side-effect
130                 //
131                 if (this.CurrentViewManager == ByCategoryViewManager.Instance ^ value) 
132                 {
133                     if (value)
134                     {
135                         this.CurrentViewManager = ByCategoryViewManager.Instance;
136                     }
137                     else
138                     {
139                         this.CurrentViewManager = AlphabeticalViewManager.Instance;
140                     }
141                 }
142             }
143         }
144
145         // <summary>
146         // Convenience accessor for the UI data binding
147         // </summary>
148         public bool IsAlphaViewSelected 
149         {
150             get {
151                 if (this.CurrentViewManager != null)
152                 {
153                     return this.CurrentViewManager == AlphabeticalViewManager.Instance;
154                 }
155
156                 return false;
157             }
158             set {
159                 // No need to fire PropertyChanged events here - changing CurrentViewManager
160                 // will fire those events as a side-effect
161                 //
162                 if (this.CurrentViewManager == AlphabeticalViewManager.Instance ^ value) 
163                 {
164                     if (value)
165                     {
166                         this.CurrentViewManager = AlphabeticalViewManager.Instance;
167                     }
168                     else
169                     {
170                         this.CurrentViewManager = ByCategoryViewManager.Instance;
171                     }
172                 }
173             }
174         }
175
176         // AutomationPeer Stuff
177
178         internal RadioButton ByCategoryViewButton 
179         { get { return VisualTreeUtils.GetNamedChild<RadioButton>(this, "PART_ByCategoryViewButton"); } }
180         internal RadioButton AlphaViewButton 
181         { get { return VisualTreeUtils.GetNamedChild<RadioButton>(this, "PART_AlphaViewButton"); } }
182         internal TextBlock SearchLabel 
183         { get { return VisualTreeUtils.GetNamedChild<TextBlock>(this, "PART_SearchLabel"); } }
184         internal TextBox SearchTextBox 
185         { get { return VisualTreeUtils.GetNamedChild<TextBox>(this, "PART_SearchTextBox"); } }
186         internal Button SearchClearButton 
187         { get { return VisualTreeUtils.GetNamedChild<Button>(this, "PART_SearchClearButton"); } }
188
189         private void OnLoaded(object sender, RoutedEventArgs e) 
190         {
191             PropertyViewManagerStateContainer.Instance.ContentRestored += new EventHandler(OnGlobalPropertyViewManagerRestored);
192         }
193
194         private void OnUnloaded(object sender, RoutedEventArgs e) 
195         {
196             PropertyViewManagerStateContainer.Instance.ContentRestored -= new EventHandler(OnGlobalPropertyViewManagerRestored);
197         }
198
199         private void OnGlobalPropertyViewManagerRestored(object sender, EventArgs e) 
200         {
201
202             // If the state of PropertyViewManagerStateContainer has been restored
203             // update the current view of the PropertyToolBar based on the restored state
204
205             if (this.PersistenceId != null) 
206             {
207                 bool oldPersistViewManagerChanges = _persistViewManagerChanges;
208                 try 
209                 {
210                     _persistViewManagerChanges = false;
211                     this.CurrentViewManager = PropertyViewManagerStateContainer.Instance.GetPropertyViewManager(this.PersistenceId);
212                 }
213                 finally 
214                 {
215                     _persistViewManagerChanges = oldPersistViewManagerChanges;
216                 }
217             }
218         }
219
220         // CurrentViewManager DP
221
222         private static void OnCurrentViewManagerChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
223         {
224             PropertyToolBar theThis = obj as PropertyToolBar;
225             if (theThis == null) 
226             {
227                 return;
228             }
229
230             theThis.OnPropertyChanged("IsCategoryViewSelected");
231             theThis.OnPropertyChanged("IsAlphaViewSelected");
232
233             // Store and persist the CurrentViewManager value only if:
234             // 
235             // * this change did not come from PropertyViewManagerStateContainer itself
236             // * we have a persistence ID to differentiate this control instance by
237             // * this is not the first time the value was set - in other words, only
238             //   store values that were triggered by the user making a conscious change
239             //
240             if (theThis.PersistenceId != null && theThis._persistViewManagerChanges && e.OldValue != null)
241             {
242                 PropertyViewManagerStateContainer.Instance.StorePropertyViewManager(theThis.PersistenceId, e.NewValue as IPropertyViewManager);
243             }
244
245             // fire this event after we have stored the propertyviewmanager, so that the StateChanged event will get
246             // the updated view-manager
247             if (theThis.CurrentViewManagerChanged != null)
248             {
249                 theThis.CurrentViewManagerChanged(theThis, EventArgs.Empty);
250             }
251
252             //refresh filter 
253             if (null != theThis.CategoryList)
254             {
255                 theThis.CategoryList.RefreshFilter();
256             }
257
258         }
259
260
261
262         // CategoryList DP
263
264         private static void OnCategoryListChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
265         {
266             PropertyToolBar theThis = obj as PropertyToolBar;
267             if (theThis == null) 
268             {
269                 return;
270             }
271
272             if (e.OldValue != null)
273             {
274                 theThis.UnhookEvents(e.OldValue as CategoryList);
275             }
276
277             if (e.NewValue != null)
278             {
279                 theThis.HookEvents(e.NewValue as CategoryList);
280             }
281         }
282
283         private void HookEvents(CategoryList categoryList) 
284         {
285             if (categoryList == null) 
286             {
287                 Debug.Fail("This method shouldn't be called when there is no CategoryList instance to process.");
288                 return;
289             }
290
291             categoryList.ContainerGenerated += new ContainerGeneratedHandler(OnCategoryContainerGenerated);
292         }
293
294         private void UnhookEvents(CategoryList categoryList) 
295         {
296             if (categoryList == null) 
297             {
298                 Debug.Fail("This method shouldn't be called when there is no CategoryList instance to process.");
299                 return;
300             }
301
302             categoryList.ContainerGenerated -= new ContainerGeneratedHandler(OnCategoryContainerGenerated);
303         }
304
305         private void OnCategoryContainerGenerated(object sender, ContainerGeneratedEventArgs e) 
306         {
307             if (e.Container == null) 
308             {
309                 return;
310             }
311             e.Container.ShowCategoryHeader = this.CurrentViewManager == null ? true : this.CurrentViewManager.ShowCategoryHeaders;
312         }
313
314
315
316         protected override AutomationPeer OnCreateAutomationPeer() 
317         {
318             return new UIElementAutomationPeer(this);
319         }
320
321
322
323         // INotifyPropertyChanged Members
324
325         private void OnPropertyChanged(string propertyName) 
326         {
327             if (PropertyChanged != null)
328             {
329                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
330             }
331         }
332
333
334     }
335 }