~ubuntu-branches/ubuntu/karmic/mono-addins/karmic

« back to all changes in this revision

Viewing changes to Mono.Addins/Mono.Addins/ExtensionNode.cs

  • Committer: Bazaar Package Importer
  • Author(s): Mirco Bauer
  • Date: 2007-07-14 12:07:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070714120748-2elczfsjlrdsrpms
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// ExtensionNode.cs
 
3
//
 
4
// Author:
 
5
//   Lluis Sanchez Gual
 
6
//
 
7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
 
8
//
 
9
// Permission is hereby granted, free of charge, to any person obtaining
 
10
// a copy of this software and associated documentation files (the
 
11
// "Software"), to deal in the Software without restriction, including
 
12
// without limitation the rights to use, copy, modify, merge, publish,
 
13
// distribute, sublicense, and/or sell copies of the Software, and to
 
14
// permit persons to whom the Software is furnished to do so, subject to
 
15
// the following conditions:
 
16
// 
 
17
// The above copyright notice and this permission notice shall be
 
18
// included in all copies or substantial portions of the Software.
 
19
// 
 
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
//
 
28
 
 
29
 
 
30
using System;
 
31
using System.Collections;
 
32
using System.Xml;
 
33
using System.Reflection;
 
34
using Mono.Addins.Description;
 
35
 
 
36
namespace Mono.Addins
 
37
{
 
38
        public class ExtensionNode
 
39
        {
 
40
                bool childrenLoaded;
 
41
                TreeNode treeNode;
 
42
                ExtensionNodeList childNodes;
 
43
                RuntimeAddin addin;
 
44
                string addinId;
 
45
                ExtensionNodeType nodeType;
 
46
                event ExtensionNodeEventHandler extensionNodeChanged;
 
47
                
 
48
                public string Id {
 
49
                        get { return treeNode != null ? treeNode.Id : string.Empty; }
 
50
                }
 
51
                
 
52
                public string Path {
 
53
                        get { return treeNode != null ? treeNode.GetPath () : string.Empty; }
 
54
                }
 
55
                
 
56
                public bool HasId {
 
57
                        get { return !Id.StartsWith (ExtensionTree.AutoIdPrefix); }
 
58
                }
 
59
                
 
60
                internal void SetTreeNode (TreeNode node)
 
61
                {
 
62
                        treeNode = node;
 
63
                }
 
64
                
 
65
                internal void SetData (string plugid, ExtensionNodeType nodeType)
 
66
                {
 
67
                        this.addinId = plugid;
 
68
                        this.nodeType = nodeType;
 
69
                }
 
70
                
 
71
                internal string AddinId {
 
72
                        get { return addinId; }
 
73
                }
 
74
                
 
75
                internal TreeNode TreeNode {
 
76
                        get { return treeNode; }
 
77
                }
 
78
                
 
79
                public RuntimeAddin Addin {
 
80
                        get {
 
81
                                if (addin == null && addinId != null) {
 
82
                                        if (!AddinManager.SessionService.IsAddinLoaded (addinId))
 
83
                                                AddinManager.SessionService.LoadAddin (null, addinId, true);
 
84
                                        addin = AddinManager.SessionService.GetAddin (addinId);
 
85
                                }
 
86
                                if (addin == null)
 
87
                                        throw new InvalidOperationException ("Add-in '" + addinId + "' could not be loaded.");
 
88
                                return addin; 
 
89
                        }
 
90
                }
 
91
                
 
92
                public event ExtensionNodeEventHandler ExtensionNodeChanged {
 
93
                        add {
 
94
                                extensionNodeChanged += value;
 
95
                                foreach (ExtensionNode node in ChildNodes)
 
96
                                        extensionNodeChanged (this, new ExtensionNodeEventArgs (ExtensionChange.Add, node));
 
97
                        }
 
98
                        remove {
 
99
                                extensionNodeChanged -= value;
 
100
                        }
 
101
                }
 
102
                
 
103
                public ExtensionNodeList ChildNodes {
 
104
                        get {
 
105
                                if (childrenLoaded)
 
106
                                        return childNodes;
 
107
                                
 
108
                                childrenLoaded = true;
 
109
                                
 
110
                                try {
 
111
                                        if (treeNode.Children.Count == 0) {
 
112
                                                childNodes = ExtensionNodeList.Empty;
 
113
                                                return childNodes;
 
114
                                        }
 
115
                                }
 
116
                                catch (Exception ex) {
 
117
                                        AddinManager.ReportError (null, null, ex, false);
 
118
                                        childNodes = ExtensionNodeList.Empty;
 
119
                                        return childNodes;
 
120
                                }
 
121
 
 
122
                                ArrayList list = new ArrayList ();
 
123
                                foreach (TreeNode cn in treeNode.Children) {
 
124
                                        
 
125
                                        // For each node check if it is visible for the current context.
 
126
                                        // If something fails while evaluating the condition, just ignore the node.
 
127
                                        
 
128
                                        try {
 
129
                                                if (cn.ExtensionNode != null && cn.IsEnabled)
 
130
                                                        list.Add (cn.ExtensionNode);
 
131
                                        } catch (Exception ex) {
 
132
                                                AddinManager.ReportError (null, null, ex, false);
 
133
                                        }
 
134
                                }
 
135
                                if (list.Count > 0)
 
136
                                        childNodes = new ExtensionNodeList (list);
 
137
                                else
 
138
                                        childNodes = ExtensionNodeList.Empty;
 
139
                        
 
140
                                return childNodes;
 
141
                        }
 
142
                }
 
143
                
 
144
                public object[] GetChildObjects ()
 
145
                {
 
146
                        return GetChildObjects (typeof(object), true);
 
147
                }
 
148
                
 
149
                public object[] GetChildObjects (bool reuseCachedInstance)
 
150
                {
 
151
                        return GetChildObjects (typeof(object), reuseCachedInstance);
 
152
                }
 
153
                
 
154
                public object[] GetChildObjects (Type arrayElementType)
 
155
                {
 
156
                        return GetChildObjects (arrayElementType, true);
 
157
                }
 
158
                
 
159
                public object[] GetChildObjects (Type arrayElementType, bool reuseCachedInstance)
 
160
                {
 
161
                        ArrayList list = new ArrayList (ChildNodes.Count);
 
162
                        
 
163
                        for (int n=0; n<ChildNodes.Count; n++) {
 
164
                                InstanceExtensionNode node = ChildNodes [n] as InstanceExtensionNode;
 
165
                                if (node == null) {
 
166
                                        AddinManager.ReportError ("Error while getting object for node in path '" + Path + "'. Extension node is not a subclass of InstanceExtensionNode.", null, null, false);
 
167
                                        continue;
 
168
                                }
 
169
                                
 
170
                                try {
 
171
                                        if (reuseCachedInstance)
 
172
                                                list.Add (node.GetInstance (arrayElementType));
 
173
                                        else
 
174
                                                list.Add (node.CreateInstance (arrayElementType));
 
175
                                }
 
176
                                catch (Exception ex) {
 
177
                                        AddinManager.ReportError ("Error while getting object for node in path '" + Path + "'.", null, ex, false);
 
178
                                }
 
179
                        }
 
180
                        return (object[]) list.ToArray (arrayElementType);
 
181
                }
 
182
                
 
183
                internal protected virtual void Read (NodeElement elem)
 
184
                {
 
185
                        if (nodeType == null || nodeType.Fields == null)
 
186
                                return;
 
187
 
 
188
                        NodeAttribute[] attributes = elem.Attributes;
 
189
                        string[] required = nodeType.RequiredFields != null ? (string[]) nodeType.RequiredFields.Clone () : null;
 
190
                        int nreq = required != null ? required.Length : 0;
 
191
                        
 
192
                        foreach (NodeAttribute at in attributes) {
 
193
                                
 
194
                                FieldInfo f = (FieldInfo) nodeType.Fields [at.name];
 
195
                                if (f == null)
 
196
                                        continue;
 
197
                                        
 
198
                                if (required != null) {
 
199
                                        int i = Array.IndexOf (required, at.name);
 
200
                                        if (i != -1) {
 
201
                                                required [i] = null;
 
202
                                                nreq--;
 
203
                                        }
 
204
                                }
 
205
                                        
 
206
                                object val;
 
207
 
 
208
                                if (f.FieldType == typeof(string)) {
 
209
                                        val = at.value;
 
210
                                }
 
211
                                else if (f.FieldType == typeof(string[])) {
 
212
                                        string[] ss = at.value.Split (',');
 
213
                                        if (ss.Length == 0 && ss[0].Length == 0)
 
214
                                                val = new string [0];
 
215
                                        else {
 
216
                                                for (int n=0; n<ss.Length; n++)
 
217
                                                        ss [n] = ss[n].Trim ();
 
218
                                                val = ss;
 
219
                                        }
 
220
                                }
 
221
                                else if (f.FieldType.IsEnum) {
 
222
                                        val = Enum.Parse (f.FieldType, at.value);
 
223
                                }
 
224
                                else {
 
225
                                        try {
 
226
                                                val = Convert.ChangeType (at.Value, f.FieldType);
 
227
                                        } catch (InvalidCastException) {
 
228
                                                throw new InvalidOperationException ("Property type not supported by [NodeAttribute]: " + f.DeclaringType + "." + f.Name);
 
229
                                        }
 
230
                                }
 
231
                                        
 
232
                                f.SetValue (this, val);
 
233
                        }
 
234
                        if (nreq > 0) {
 
235
                                foreach (string s in required)
 
236
                                        if (s != null)
 
237
                                                throw new InvalidOperationException ("Required attribute '" + s + "' not found.");
 
238
                        }
 
239
                }
 
240
                
 
241
                internal bool NotifyChildChanged ()
 
242
                {
 
243
                        if (!childrenLoaded)
 
244
                                return false;
 
245
 
 
246
                        ExtensionNodeList oldList = childNodes;
 
247
                        childrenLoaded = false;
 
248
                        
 
249
                        bool changed = false;
 
250
                        
 
251
                        foreach (ExtensionNode nod in oldList) {
 
252
                                if (ChildNodes [nod.Id] == null) {
 
253
                                        changed = true;
 
254
                                        OnChildNodeRemoved (nod);
 
255
                                }
 
256
                        }
 
257
                        foreach (ExtensionNode nod in ChildNodes) {
 
258
                                if (oldList [nod.Id] == null) {
 
259
                                        changed = true;
 
260
                                        OnChildNodeAdded (nod);
 
261
                                }
 
262
                        }
 
263
                        if (changed)
 
264
                                OnChildrenChanged ();
 
265
                        return changed;
 
266
                }
 
267
                
 
268
                // Called when the add-in that defined this extension node is actually
 
269
                // loaded in memory.
 
270
                internal protected virtual void OnAddinLoaded ()
 
271
                {
 
272
                }
 
273
                
 
274
                // Called when the add-in that defined this extension node is being
 
275
                // unloaded from memory.
 
276
                internal protected virtual void OnAddinUnloaded ()
 
277
                {
 
278
                }
 
279
                
 
280
                // Called when the children list of this node has changed. It may be due to add-ins
 
281
                // being loaded/unloaded, or to conditions being changed.
 
282
                protected virtual void OnChildrenChanged ()
 
283
                {
 
284
                }
 
285
                
 
286
                protected virtual void OnChildNodeAdded (ExtensionNode node)
 
287
                {
 
288
                        if (extensionNodeChanged != null)
 
289
                                extensionNodeChanged (this, new ExtensionNodeEventArgs (ExtensionChange.Add, node));
 
290
                }
 
291
                
 
292
                protected virtual void OnChildNodeRemoved (ExtensionNode node)
 
293
                {
 
294
                        if (extensionNodeChanged != null)
 
295
                                extensionNodeChanged (this, new ExtensionNodeEventArgs (ExtensionChange.Remove, node));
 
296
                }
 
297
        }
 
298
}