svn path=/trunk/mcs/; revision=104772
[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 #if NET_2_0
59                                 this.SetSelectedComponents (new IComponent[] { args.Component }, SelectionTypes.Remove);
60 #else
61                                 this.SetSelectedComponents (new IComponent[] { this.RootComponent }, SelectionTypes.Click);
62 #endif
63                 }
64                 
65                 public event EventHandler SelectionChanging;
66                 public event EventHandler SelectionChanged;
67                 
68                 public ICollection GetSelectedComponents() 
69                 {
70                         if (_selection != null)
71                                 return _selection.ToArray ();
72
73                         return new object[0];
74                 }
75
76                 protected virtual void OnSelectionChanging ()
77                 {
78                         if (SelectionChanging != null)
79                                 SelectionChanging (this, EventArgs.Empty);
80                 }
81                 
82                 protected virtual void OnSelectionChanged ()
83                 {
84                         if (SelectionChanged != null)
85                                 SelectionChanged (this, EventArgs.Empty);
86                 }
87
88                 public object PrimarySelection {
89                         get { return _primarySelection; }
90                 }
91                 
92                 public int SelectionCount {
93                         get {
94                                 if (_selection != null)
95                                         return _selection.Count;
96
97                                 return 0;
98                         }
99                 }
100
101
102                 private IComponent RootComponent {
103                         get {
104                                 if (_serviceProvider != null) {
105                                         IDesignerHost designerHost = _serviceProvider.GetService (typeof (IDesignerHost)) as IDesignerHost;
106                                         if (designerHost != null)
107                                                 return designerHost.RootComponent;
108
109                                 }
110                                 return null;
111                         }
112                 }
113                 
114                 public bool GetComponentSelected (object component) 
115                 {
116                         if (_selection != null)
117                                 return _selection.Contains (component);
118
119                         return false;
120                 }
121
122                 public void SetSelectedComponents (ICollection components) 
123                 {
124 #if NET_2_0
125                         SetSelectedComponents (components, SelectionTypes.Auto);
126 #else                   
127                         SetSelectedComponents (components, SelectionTypes.Normal);
128 #endif
129                 }
130
131                 // If the array is a null reference or does not contain any components,
132                 // SetSelectedComponents selects the top-level component in the designer.
133                 //
134                 public void SetSelectedComponents (ICollection components, SelectionTypes selectionType)
135                 {
136                         bool primary, add, remove, replace, toggle, auto;
137                         primary = add = remove = replace = toggle = auto = false;
138                         
139                         OnSelectionChanging ();
140
141                         if (_selection == null)
142                                 throw new InvalidOperationException("_selection == null");
143                         
144                         if (components == null || components.Count == 0) {
145                                 components = new ArrayList ();
146                                 ((ArrayList) components).Add (this.RootComponent);
147                                 selectionType = SelectionTypes.Replace;
148                         }
149                         
150                         if (!Enum.IsDefined (typeof (SelectionTypes), selectionType)) {
151 #if NET_2_0     
152                                 selectionType = SelectionTypes.Auto;
153 #else
154                                 selectionType = SelectionTypes.Normal;                                  
155 #endif
156                         }
157
158 #if NET_2_0             
159                         auto = ((selectionType & SelectionTypes.Auto) == SelectionTypes.Auto);
160 #else
161                         if ((selectionType & SelectionTypes.Normal) == SelectionTypes.Normal ||
162                                 (selectionType & SelectionTypes.MouseDown) == SelectionTypes.MouseDown ||
163                                 (selectionType & SelectionTypes.MouseUp) == SelectionTypes.MouseUp) {
164
165                                         auto = true;
166                         }               
167 #endif                  
168                         
169                         
170                         if (auto) {
171                                 if ((((Control.ModifierKeys & Keys.Control) == Keys.Control) || ((Control.ModifierKeys & Keys.Shift) == Keys.Shift))) {
172                                         toggle = true;
173                                 }
174                                 else if (components.Count == 1) {
175                                         object component = null;
176                                         foreach (object c in components) {
177                                                 component = c;
178                                                 break;
179                                         }
180
181                                         if (this.GetComponentSelected (component))
182                                                 primary = true;
183                                         else
184                                                 replace = true;
185                                 }
186                                 else {
187                                         replace = true;
188                                 }
189                         }
190                         else {
191 #if NET_2_0                        
192                                 primary = ((selectionType & SelectionTypes.Primary) == SelectionTypes.Primary);
193                                 add = ((selectionType & SelectionTypes.Add) == SelectionTypes.Add);
194                                 remove = ((selectionType & SelectionTypes.Remove) == SelectionTypes.Remove);
195                                 toggle = ((selectionType & SelectionTypes.Toggle) == SelectionTypes.Toggle);
196 #else
197                                 primary = ((selectionType & SelectionTypes.Click) == SelectionTypes.Click);
198 #endif                          
199                                 replace = ((selectionType & SelectionTypes.Replace) == SelectionTypes.Replace);
200                                 
201                         }
202
203                         
204                         if (replace) {
205                                 _selection.Clear ();
206                                 add = true;
207                         }
208                                                 
209                         if (add) {
210                                 foreach (object component in components) {
211                                         if (component is IComponent && !_selection.Contains (component)) {
212                                                 _selection.Add (component);
213                                                 _primarySelection = (IComponent) component;
214                                         }
215                                 }
216                         }
217
218                         if (remove) {
219                                 foreach (object component in components) {
220                                         if (component is IComponent && _selection.Contains (component)) {
221                                                 _selection.Remove (component);
222                                         }
223                                 }
224                                 if (_selection.Count == 0) {
225                                         _primarySelection = this.RootComponent;
226                                         _selection.Add (this.RootComponent);
227                                 }
228                         }
229
230                         if (toggle) {
231                                 foreach (object component in components) {
232                                         if (component is IComponent) {
233                                                 if (_selection.Contains (component)) {
234                                                         _selection.Remove (component);
235                                                         if (component == _primarySelection)
236                                                                 _primarySelection = this.RootComponent;
237                                                 }
238                                                 else {
239                                                         _selection.Add (component);
240                                                         _primarySelection = (IComponent) component;
241                                                 }
242                                         }
243                                 }
244                         }
245                                 
246                         if (primary) {
247                                 object primarySelection = null;
248
249                                 foreach (object component in components) {
250                                         primarySelection = component;
251                                         break;
252                                 }
253
254                                 if (!this.GetComponentSelected (primarySelection))
255                                         _selection.Add (_primarySelection);
256
257                                 _primarySelection = (IComponent) primarySelection;
258                         }                               
259                                                 
260                         OnSelectionChanged ();
261                 }
262         }
263 }