Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / class / System.Design / System.ComponentModel.Design / SelectionService.cs
1 //
2 // System.ComponentModel.Design.SelectionService
3 //
4 // Authors:
5 //        Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006-2007 Ivan N. Zlatev
8
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;
30 using System.Collections;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
33 using System.Windows.Forms;
34
35 namespace System.ComponentModel.Design
36 {
37         
38         internal class SelectionService : ISelectionService
39         {
40                 
41                 private IServiceProvider _serviceProvider;
42                 private ArrayList _selection;
43                 private IComponent _primarySelection;
44                 
45                 public SelectionService (IServiceProvider provider)
46                 {
47                         _serviceProvider = provider;
48                         _selection = new ArrayList();
49
50                         IComponentChangeService changeService = provider.GetService (typeof (IComponentChangeService)) as IComponentChangeService;
51                         if (changeService != null)
52                                 changeService.ComponentRemoving += new ComponentEventHandler (OnComponentRemoving);
53                 }
54                 
55                 private void OnComponentRemoving (object sender, ComponentEventArgs args)
56                 {
57                         if (this.GetComponentSelected (args.Component))
58                                 this.SetSelectedComponents (new IComponent[] { args.Component }, SelectionTypes.Remove);
59                 }
60                 
61                 public event EventHandler SelectionChanging;
62                 public event EventHandler SelectionChanged;
63                 
64                 public ICollection GetSelectedComponents() 
65                 {
66                         if (_selection != null)
67                                 return _selection.ToArray ();
68
69                         return new object[0];
70                 }
71
72                 protected virtual void OnSelectionChanging ()
73                 {
74                         if (SelectionChanging != null)
75                                 SelectionChanging (this, EventArgs.Empty);
76                 }
77                 
78                 protected virtual void OnSelectionChanged ()
79                 {
80                         if (SelectionChanged != null)
81                                 SelectionChanged (this, EventArgs.Empty);
82                 }
83
84                 public object PrimarySelection {
85                         get { return _primarySelection; }
86                 }
87                 
88                 public int SelectionCount {
89                         get {
90                                 if (_selection != null)
91                                         return _selection.Count;
92
93                                 return 0;
94                         }
95                 }
96
97
98                 private IComponent RootComponent {
99                         get {
100                                 if (_serviceProvider != null) {
101                                         IDesignerHost designerHost = _serviceProvider.GetService (typeof (IDesignerHost)) as IDesignerHost;
102                                         if (designerHost != null)
103                                                 return designerHost.RootComponent;
104                                 }
105                                 return null;
106                         }
107                 }
108                 
109                 public bool GetComponentSelected (object component) 
110                 {
111                         if (_selection != null)
112                                 return _selection.Contains (component);
113
114                         return false;
115                 }
116
117                 public void SetSelectedComponents (ICollection components) 
118                 {
119                         SetSelectedComponents (components, SelectionTypes.Auto);
120                 }
121
122                 // If the array is a null reference or does not contain any components,
123                 // SetSelectedComponents selects the top-level component in the designer.
124                 //
125                 public void SetSelectedComponents (ICollection components, SelectionTypes selectionType)
126                 {
127                         bool primary, add, remove, replace, toggle, auto;
128                         primary = add = remove = replace = toggle = auto = false;
129                         
130                         OnSelectionChanging ();
131
132                         if (_selection == null)
133                                 throw new InvalidOperationException("_selection == null");
134                         
135                         if (components == null || components.Count == 0) {
136                                 components = new ArrayList ();
137                                 ((ArrayList) components).Add (this.RootComponent);
138                                 selectionType = SelectionTypes.Replace;
139                         }
140                         
141                         if (!Enum.IsDefined (typeof (SelectionTypes), selectionType)) {
142                                 selectionType = SelectionTypes.Auto;
143                         }
144
145                         auto = ((selectionType & SelectionTypes.Auto) == SelectionTypes.Auto);
146                         
147                         
148                         if (auto) {
149                                 if ((((Control.ModifierKeys & Keys.Control) == Keys.Control) || ((Control.ModifierKeys & Keys.Shift) == Keys.Shift))) {
150                                         toggle = true;
151                                 }
152                                 else if (components.Count == 1) {
153                                         object component = null;
154                                         foreach (object c in components) {
155                                                 component = c;
156                                                 break;
157                                         }
158
159                                         if (this.GetComponentSelected (component))
160                                                 primary = true;
161                                         else
162                                                 replace = true;
163                                 }
164                                 else {
165                                         replace = true;
166                                 }
167                         }
168                         else {
169                                 primary = ((selectionType & SelectionTypes.Primary) == SelectionTypes.Primary);
170                                 add = ((selectionType & SelectionTypes.Add) == SelectionTypes.Add);
171                                 remove = ((selectionType & SelectionTypes.Remove) == SelectionTypes.Remove);
172                                 toggle = ((selectionType & SelectionTypes.Toggle) == SelectionTypes.Toggle);
173                                 replace = ((selectionType & SelectionTypes.Replace) == SelectionTypes.Replace);
174                                 
175                         }
176
177                         
178                         if (replace) {
179                                 _selection.Clear ();
180                                 add = true;
181                         }
182                                                 
183                         if (add) {
184                                 foreach (object component in components) {
185                                         if (component is IComponent && !_selection.Contains (component)) {
186                                                 _selection.Add (component);
187                                                 _primarySelection = (IComponent) component;
188                                         }
189                                 }
190                         }
191
192                         if (remove) {
193                                 bool rootRemoved = false;
194                                 foreach (object component in components) {
195                                         if (component is IComponent && _selection.Contains (component))
196                                                 _selection.Remove (component);
197                                         if (component == this.RootComponent)
198                                                 rootRemoved = true;
199                                 }
200                                 if (_selection.Count == 0) {
201                                         if (rootRemoved) {
202                                                 _primarySelection = null;
203                                         } else {
204                                                 _primarySelection = this.RootComponent;
205                                                 _selection.Add (this.RootComponent);
206                                         }
207                                 }
208                         }
209
210                         if (toggle) {
211                                 foreach (object component in components) {
212                                         if (component is IComponent) {
213                                                 if (_selection.Contains (component)) {
214                                                         _selection.Remove (component);
215                                                         if (component == _primarySelection)
216                                                                 _primarySelection = this.RootComponent;
217                                                 }
218                                                 else {
219                                                         _selection.Add (component);
220                                                         _primarySelection = (IComponent) component;
221                                                 }
222                                         }
223                                 }
224                         }
225                                 
226                         if (primary) {
227                                 object primarySelection = null;
228
229                                 foreach (object component in components) {
230                                         primarySelection = component;
231                                         break;
232                                 }
233
234                                 if (!this.GetComponentSelected (primarySelection))
235                                         _selection.Add (primarySelection);
236
237                                 _primarySelection = (IComponent) primarySelection;
238                         }                               
239                                                 
240                         OnSelectionChanged ();
241                 }
242         }
243 }