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;
49
public TreeNode (string id)
55
childrenLoaded = true;
58
internal void AttachExtensionNode (ExtensionNode enode)
60
this.extensionNode = enode;
61
if (extensionNode != null)
62
extensionNode.SetTreeNode (this);
69
public ExtensionNode ExtensionNode {
71
if (extensionNode == null && extensionPoint != null) {
72
extensionNode = new ExtensionNode ();
73
extensionNode.SetData (extensionPoint.RootAddin, null);
74
AttachExtensionNode (extensionNode);
80
public ExtensionPoint ExtensionPoint {
81
get { return extensionPoint; }
82
set { extensionPoint = value; }
85
public ExtensionNodeSet ExtensionNodeSet {
86
get { return nodeTypes; }
87
set { nodeTypes = value; }
90
public TreeNode Parent {
91
get { return parent; }
94
public BaseCondition Condition {
95
get { return condition; }
101
public virtual ExtensionContext Context {
104
return parent.Context;
110
public bool IsEnabled {
112
if (condition == null)
114
ExtensionContext ctx = Context;
118
return condition.Evaluate (ctx);
122
public bool ChildrenLoaded {
123
get { return childrenLoaded; }
126
public void AddChildNode (TreeNode node)
129
if (childrenList == null)
130
childrenList = new ArrayList ();
131
childrenList.Add (node);
134
public void InsertChildNode (int n, TreeNode node)
137
if (childrenList == null)
138
childrenList = new ArrayList ();
139
childrenList.Insert (n, node);
141
// Dont call NotifyChildrenChanged here. It is called by ExtensionTree,
142
// after inserting all children of the node.
145
internal int ChildCount {
146
get { return childrenList == null ? 0 : childrenList.Count; }
149
public ExtensionNode GetExtensionNode (string path, string childId)
151
TreeNode node = GetNode (path, childId);
152
return node != null ? node.ExtensionNode : null;
155
public ExtensionNode GetExtensionNode (string path)
157
TreeNode node = GetNode (path);
158
return node != null ? node.ExtensionNode : null;
161
public TreeNode GetNode (string path, string childId)
163
if (childId == null || childId.Length == 0)
164
return GetNode (path);
166
return GetNode (path + "/" + childId);
169
public TreeNode GetNode (string path)
171
return GetNode (path, false);
174
public TreeNode GetNode (string path, bool buildPath)
176
if (path.StartsWith ("/"))
177
path = path.Substring (1);
179
string[] parts = path.Split ('/');
180
TreeNode curNode = this;
182
foreach (string part in parts) {
183
int i = curNode.Children.IndexOfNode (part);
185
curNode = curNode.Children [i];
190
TreeNode newNode = new TreeNode (part);
191
curNode.AddChildNode (newNode);
199
public TreeNodeCollection Children {
201
if (!childrenLoaded) {
202
childrenLoaded = true;
203
if (extensionPoint != null)
204
Context.LoadExtensions (GetPath ());
205
// We have to keep the relation info, since add-ins may be loaded/unloaded
207
if (childrenList == null)
208
return TreeNodeCollection.Empty;
209
if (children == null)
210
children = new TreeNodeCollection (childrenList);
215
public string GetPath ()
218
TreeNode node = this;
219
while (node != null) {
224
string[] ids = new string [num];
227
while (node != null) {
228
ids [--num] = node.id;
231
return string.Join ("/", ids);
234
public void NotifyAddinLoaded (RuntimeAddin ad, bool recursive)
236
if (extensionNode != null && extensionNode.AddinId == ad.Addin.Id)
237
extensionNode.OnAddinLoaded ();
238
if (recursive && childrenLoaded) {
239
foreach (TreeNode node in Children)
240
node.NotifyAddinLoaded (ad, true);
244
public ExtensionPoint FindExtensionPoint (string path)
246
if (path.StartsWith ("/"))
247
path = path.Substring (1);
249
string[] parts = path.Split ('/');
250
TreeNode curNode = this;
252
foreach (string part in parts) {
253
int i = curNode.Children.IndexOfNode (part);
255
curNode = curNode.Children [i];
256
if (curNode.ExtensionPoint != null)
257
return curNode.ExtensionPoint;
265
public void FindAddinNodes (string id, ArrayList nodes)
267
if (id != null && extensionPoint != null && extensionPoint.RootAddin == id) {
268
// It is an extension point created by the add-in. All nodes below this
269
// extension point will be added to the list, even if they come from other add-ins.
273
if (childrenLoaded) {
274
// Deep-first search, to make sure children are removed before the parent.
275
foreach (TreeNode node in Children)
276
node.FindAddinNodes (id, nodes);
279
if (id == null || (ExtensionNode != null && ExtensionNode.AddinId == id))
283
public bool FindExtensionPathByType (IProgressStatus monitor, Type type, string nodeName, out string path, out string pathNodeName)
285
if (extensionPoint != null) {
286
foreach (ExtensionNodeType nt in extensionPoint.NodeSet.NodeTypes) {
287
if (nt.ObjectTypeName.Length > 0 && (nodeName.Length == 0 || nodeName == nt.Id)) {
288
RuntimeAddin addin = AddinManager.SessionService.GetAddin (extensionPoint.RootAddin);
289
Type ot = addin.GetType (nt.ObjectTypeName);
291
if (ot.IsAssignableFrom (type)) {
292
path = extensionPoint.Path;
293
pathNodeName = nt.Id;
298
monitor.ReportError ("Type '" + nt.ObjectTypeName + "' not found in add-in '" + Id + "'", null);
303
foreach (TreeNode node in Children) {
304
if (node.FindExtensionPathByType (monitor, type, nodeName, out path, out pathNodeName))
313
public void Remove ()
315
if (parent != null) {
316
if (Condition != null)
317
Context.UnregisterNodeCondition (this, Condition);
318
parent.childrenList.Remove (this);
319
parent.NotifyChildrenChanged ();
323
public bool NotifyChildrenChanged ()
325
if (extensionNode != null)
326
return extensionNode.NotifyChildChanged ();