7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
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:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
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.
32
using System.Collections;
33
using Mono.Addins.Description;
39
ArrayList childrenList;
40
TreeNodeCollection children;
41
ExtensionNode extensionNode;
45
ExtensionNodeSet nodeTypes;
46
ExtensionPoint extensionPoint;
47
BaseCondition condition;
48
protected AddinEngine addinEngine;
50
public TreeNode (AddinEngine addinEngine, string id)
53
this.addinEngine = addinEngine;
57
childrenLoaded = true;
60
public AddinEngine AddinEngine {
61
get { return addinEngine; }
64
internal void AttachExtensionNode (ExtensionNode enode)
66
this.extensionNode = enode;
67
if (extensionNode != null)
68
extensionNode.SetTreeNode (this);
75
public ExtensionNode ExtensionNode {
77
if (extensionNode == null && extensionPoint != null) {
78
extensionNode = new ExtensionNode ();
79
extensionNode.SetData (addinEngine, extensionPoint.RootAddin, null, null);
80
AttachExtensionNode (extensionNode);
86
public ExtensionPoint ExtensionPoint {
87
get { return extensionPoint; }
88
set { extensionPoint = value; }
91
public ExtensionNodeSet ExtensionNodeSet {
92
get { return nodeTypes; }
93
set { nodeTypes = value; }
96
public TreeNode Parent {
97
get { return parent; }
100
public BaseCondition Condition {
101
get { return condition; }
107
public virtual ExtensionContext Context {
110
return parent.Context;
116
public bool IsEnabled {
118
if (condition == null)
120
ExtensionContext ctx = Context;
124
return condition.Evaluate (ctx);
128
public bool ChildrenLoaded {
129
get { return childrenLoaded; }
132
public void AddChildNode (TreeNode node)
135
if (childrenList == null)
136
childrenList = new ArrayList ();
137
childrenList.Add (node);
140
public void InsertChildNode (int n, TreeNode node)
143
if (childrenList == null)
144
childrenList = new ArrayList ();
145
childrenList.Insert (n, node);
147
// Dont call NotifyChildrenChanged here. It is called by ExtensionTree,
148
// after inserting all children of the node.
151
internal int ChildCount {
152
get { return childrenList == null ? 0 : childrenList.Count; }
155
public ExtensionNode GetExtensionNode (string path, string childId)
157
TreeNode node = GetNode (path, childId);
158
return node != null ? node.ExtensionNode : null;
161
public ExtensionNode GetExtensionNode (string path)
163
TreeNode node = GetNode (path);
164
return node != null ? node.ExtensionNode : null;
167
public TreeNode GetNode (string path, string childId)
169
if (childId == null || childId.Length == 0)
170
return GetNode (path);
172
return GetNode (path + "/" + childId);
175
public TreeNode GetNode (string path)
177
return GetNode (path, false);
180
public TreeNode GetNode (string path, bool buildPath)
182
if (path.StartsWith ("/"))
183
path = path.Substring (1);
185
string[] parts = path.Split ('/');
186
TreeNode curNode = this;
188
foreach (string part in parts) {
189
int i = curNode.Children.IndexOfNode (part);
191
curNode = curNode.Children [i];
196
TreeNode newNode = new TreeNode (addinEngine, part);
197
curNode.AddChildNode (newNode);
205
public TreeNodeCollection Children {
207
if (!childrenLoaded) {
208
childrenLoaded = true;
209
if (extensionPoint != null)
210
Context.LoadExtensions (GetPath ());
211
// We have to keep the relation info, since add-ins may be loaded/unloaded
213
if (childrenList == null)
214
return TreeNodeCollection.Empty;
215
if (children == null)
216
children = new TreeNodeCollection (childrenList);
221
public string GetPath ()
224
TreeNode node = this;
225
while (node != null) {
230
string[] ids = new string [num];
233
while (node != null) {
234
ids [--num] = node.id;
237
return string.Join ("/", ids);
240
public void NotifyAddinLoaded (RuntimeAddin ad, bool recursive)
242
if (extensionNode != null && extensionNode.AddinId == ad.Addin.Id)
243
extensionNode.OnAddinLoaded ();
244
if (recursive && childrenLoaded) {
245
foreach (TreeNode node in Children.Clone ())
246
node.NotifyAddinLoaded (ad, true);
250
public ExtensionPoint FindLoadedExtensionPoint (string path)
252
if (path.StartsWith ("/"))
253
path = path.Substring (1);
255
string[] parts = path.Split ('/');
256
TreeNode curNode = this;
258
foreach (string part in parts) {
259
int i = curNode.Children.IndexOfNode (part);
261
curNode = curNode.Children [i];
262
if (!curNode.ChildrenLoaded)
264
if (curNode.ExtensionPoint != null)
265
return curNode.ExtensionPoint;
273
public void FindAddinNodes (string id, ArrayList nodes)
275
if (id != null && extensionPoint != null && extensionPoint.RootAddin == id) {
276
// It is an extension point created by the add-in. All nodes below this
277
// extension point will be added to the list, even if they come from other add-ins.
281
if (childrenLoaded) {
282
// Deep-first search, to make sure children are removed before the parent.
283
foreach (TreeNode node in Children)
284
node.FindAddinNodes (id, nodes);
287
if (id == null || (ExtensionNode != null && ExtensionNode.AddinId == id))
291
public bool FindExtensionPathByType (IProgressStatus monitor, Type type, string nodeName, out string path, out string pathNodeName)
293
if (extensionPoint != null) {
294
foreach (ExtensionNodeType nt in extensionPoint.NodeSet.NodeTypes) {
295
if (nt.ObjectTypeName.Length > 0 && (nodeName.Length == 0 || nodeName == nt.Id)) {
296
RuntimeAddin addin = addinEngine.GetAddin (extensionPoint.RootAddin);
297
Type ot = addin.GetType (nt.ObjectTypeName);
299
if (ot.IsAssignableFrom (type)) {
300
path = extensionPoint.Path;
301
pathNodeName = nt.Id;
306
monitor.ReportError ("Type '" + nt.ObjectTypeName + "' not found in add-in '" + Id + "'", null);
311
foreach (TreeNode node in Children) {
312
if (node.FindExtensionPathByType (monitor, type, nodeName, out path, out pathNodeName))
321
public void Remove ()
323
if (parent != null) {
324
if (Condition != null)
325
Context.UnregisterNodeCondition (this, Condition);
326
parent.childrenList.Remove (this);
327
parent.NotifyChildrenChanged ();
331
public bool NotifyChildrenChanged ()
333
if (extensionNode != null)
334
return extensionNode.NotifyChildChanged ();
339
public void ResetCachedData ()
341
if (extensionPoint != null) {
342
string aid = Addin.GetIdName (extensionPoint.ParentAddinDescription.AddinId);
343
RuntimeAddin ad = addinEngine.GetAddin (aid);
345
extensionPoint = ad.Addin.Description.ExtensionPoints [GetPath ()];
347
if (childrenList != null) {
348
foreach (TreeNode cn in childrenList)
349
cn.ResetCachedData ();