Back to index

lightning-sunbird  0.9+nobinonly
TreeBuilder.cs
Go to the documentation of this file.
00001 /* -*- Mode: C#; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Manticore.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Silverstone Interactive.
00020  * Portions created by the Initial Developer are Copyright (C) 2001
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Ben Goodger <ben@netscape.com> (Original Author)
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039  
00040 namespace Silverstone.Manticore.Toolkit
00041 {
00042   using System;
00043   using System.Windows.Forms;
00044   using System.Collections;
00045 
00046   using Silverstone.Manticore.Core;
00047 
00048   public abstract class DynamicTreeBuilder : ContentBuilder, IDataStoreObserver
00049   {
00053     protected TreeNode mParent = null;
00054 
00055     protected TreeNodeCollection mParentNodes = null;
00056     
00062     protected TreeNode mBefore = null;
00063     protected TreeNode mAfter = null;
00064 
00068     protected ManticoreTreeView mTreeView = null;
00069 
00073     protected Hashtable mNodes = null;
00074     
00075 
00081     protected int mInsertionPoint = 0;
00082     
00083     public DynamicTreeBuilder(ManticoreTreeView aTreeView, TreeNode aParent)
00084     {
00085       if (aTreeView == null) 
00086         throw new Exception();
00087 
00088       if (aParent != null) 
00089       {
00090         mParent = aParent;
00091         mParentNodes = aParent.Nodes;
00092       }
00093       else 
00094         mParentNodes = aTreeView.Nodes;
00095 
00096       mTreeView = aTreeView;
00097       
00098       InitializeComponent();
00099     }
00100     
00101     public DynamicTreeBuilder(ManticoreTreeView aTreeView, TreeNode aParent, TreeNode aBefore, TreeNode aAfter)
00102     {
00103       mParent = aParent;
00104       mTreeView = aTreeView;
00105       
00106       // XXX we do jack shit to handle this at the moment. TBD. 
00107       mBefore = aBefore;
00108       mAfter = aAfter;
00109       
00110       ResetInsertionPoint();
00111     
00112       InitializeComponent();
00113     }
00114     
00115     private void ResetInsertionPoint()
00116     {
00117       if (mBefore != null) 
00118       {
00119         // The insertion point is the position immediately after |mBefore|
00120         mInsertionPoint = mParentNodes.IndexOf(mBefore) + 1;
00121       }
00122       else
00123         mInsertionPoint = 0;
00124     }
00125     
00126     protected virtual void InitializeComponent()
00127     {
00128       mNodes = new Hashtable();
00129       
00130       // XXX for now, just be stupid and generate everything when the root
00131       //     menu is opened. 
00132       mTreeView.BeforeExpand += new TreeViewCancelEventHandler(OnBeforeExpand);
00133     }
00134 
00140     protected virtual void OnBeforeExpand(Object sender, TreeViewCancelEventArgs e)
00141     {
00142       // XXX make this smarter. 
00143       Build();
00144     }
00145 
00147     // ContentBuilder Implementation
00148 
00149     public void OnNodeChanging(Object aOldNode, Object aNewNode)
00150     {
00151       // Not Implemented.
00152     }
00153     public void OnNodeChanged(Object aOldNode, Object aNewNode)
00154     {
00155       // Enumerate each of the properties that affect FE presentation, test
00156       // for difference, and update the FE if necessary.
00157       
00158       CommandTarget oldTarget = aOldNode as CommandTarget;
00159       CommandTarget newTarget = aNewNode as CommandTarget;
00160       
00161       if (oldTarget == null && newTarget == null)
00162         return;
00163       
00164       int itemKey = newTarget.Data.GetHashCode();
00165       if (mNodes.ContainsKey(itemKey)) 
00166       {
00167         ManticoreTreeNode item = mNodes[itemKey] as ManticoreTreeNode;
00168         // Check for Label/AccessKey change. 
00169         if (newTarget.Label != oldTarget.Label) 
00170           item.Text = newTarget.Label;
00171         if (newTarget.IsContainer) 
00172           item.ImageIndex = mTreeView.GetIconIndex(newTarget);
00173       }
00174     }
00175 
00176     public void OnNodeAdding(Object aNewNode, Object aParentNode, int aIndex)
00177     {
00178       // Not Implemented. 
00179     }
00180     public void OnNodeAdded(Object aChildNode, Object aParentNode, int aIndex)
00181     {
00182       // A new Element has been added somewhere. We must find the 
00183       // parent menu and append it. To interoperate with the Content Builder,
00184       // the DataStore must provide |CommandTarget|s to this method. 
00185       CommandTarget childTarget = aChildNode as CommandTarget;
00186       CommandTarget parentTarget = aParentNode as CommandTarget;
00187       if (childTarget == null && parentTarget == null)
00188         return;
00189 
00190       // Determine based on conditions defined by the |TreeView|
00191       // whether or not this node should be built. 
00192       if (!mTreeView.ShouldBuild(childTarget))
00193         return;
00194 
00195       int childKey = childTarget.Data.GetHashCode();
00196       if (!mNodes.ContainsKey(childKey)) 
00197       {
00198         int parentKey = parentTarget.Data.GetHashCode();
00199 
00200         ManticoreTreeNode parentNode;
00201         if (mNodes.ContainsKey(parentKey))
00202           parentNode = mNodes[parentKey] as ManticoreTreeNode;
00203         else
00204           parentNode = mParent as ManticoreTreeNode;
00205         
00206         if (parentNode != null) 
00207         {
00208           ManticoreTreeNode childNode = new ManticoreTreeNode(childTarget.Label,
00209             childTarget.Data);
00210           if (parentNode != null) 
00211           {
00212             int imageIndex = mTreeView.GetIconIndex(childTarget);
00213             if (imageIndex > -1) 
00214               childNode.ImageIndex = imageIndex;
00215 
00216             parentNode.Nodes.Insert(aIndex, childNode);
00217             if (childTarget.IsContainer && childTarget.IsOpen)
00218               childNode.Expand();
00219             mNodes.Add(childKey, childNode);
00220           }
00221         }
00222       }
00223     }
00224 
00225     public void OnNodeRemoving(Object aNodeRemoving)
00226     {
00227       // Not Implemented.
00228     }
00229     public void OnNodeRemoved(Object aNodeRemoved)
00230     {
00231       CommandTarget childTarget = aNodeRemoved as CommandTarget;
00232 
00233       // Remove |MenuItem| representation of |aChildNode|.
00234       int childKey = childTarget.Data.GetHashCode();
00235       if (mNodes.ContainsKey(childKey)) 
00236       {
00237         ManticoreTreeNode childNode = mNodes[childKey] as ManticoreTreeNode;
00238         ManticoreTreeNode parentNode = childNode.Parent as ManticoreTreeNode;
00239         if (parentNode != null)
00240           parentNode.Nodes.Remove(childNode);
00241         else
00242           mTreeView.Nodes.Remove(childNode);
00243         
00244         mNodes.Remove(childKey);
00245       }
00246     }
00247 
00251     public override void Build()
00252     {
00253       if (mDataStore == null || mRoot == null) 
00254         throw new Exception();
00255 
00256       // XXX implement acknowledgement of |LazyState|
00257       Recurse(mRoot, mParentNodes);
00258     }
00259 
00260     public void Recurse(String aRoot, TreeNodeCollection aNodes)
00261     {
00262       IEnumerator items;
00263       mDataStore.GetElements(aRoot, out items);
00264       items.Reset();
00265       
00266       ManticoreTreeNode node;
00267       
00268       while (items.MoveNext()) 
00269       {
00270         // |id| is the item's unique identifier within the DataStore. 
00271         // The handling code can use this to probe for more information
00272         // about the selected item. 
00273         CommandTarget current = items.Current as CommandTarget;
00274         if (current != null) 
00275         {
00276           // Determine based on conditions defined by the |TreeView|
00277           // whether or not this node should be built. 
00278           if (!mTreeView.ShouldBuild(current))
00279             continue;
00280 
00281           String id = current.Data as String; 
00282          
00283           int idKey = id.GetHashCode();
00284           
00285           if (!mNodes.ContainsKey(idKey)) 
00286           {
00287             node = new ManticoreTreeNode(current.Label, id);
00288 
00289             int imageIndex = mTreeView.GetIconIndex(current);
00290             if (imageIndex > -1) 
00291               node.ImageIndex = imageIndex;
00292             aNodes.Insert(mInsertionPoint++, node);
00293             if (current.IsContainer && current.IsOpen)
00294               node.Expand();
00295             mNodes.Add(id.GetHashCode(), node);
00296 
00297             // If we're a container, recurse 
00298             if (current.IsContainer)
00299               Recurse(id, node.Nodes);
00300           }
00301         }
00302       }
00303       
00304       ResetInsertionPoint();
00305     }
00306 
00308     //
00309 
00310     public TreeNode Parent
00311     {
00312       get 
00313       {
00314         return mParent;
00315       }
00316       set 
00317       {
00318         mParent = value;
00319       }
00320     }
00321 
00322     public TreeNode Before
00323     {
00324       get 
00325       {
00326         return mBefore;
00327       }
00328       set 
00329       {
00330         mBefore = value;
00331       }
00332     }
00333 
00334     public TreeNode After 
00335     {
00336       get 
00337       {
00338         return mAfter;
00339       }
00340       set 
00341       {
00342         mAfter = value;
00343       }
00344     }
00345   }
00346   
00347   public class BaseTreeBuilder : DynamicTreeBuilder
00348   {
00349     public BaseTreeBuilder(ManticoreTreeView aTreeView, TreeNode aParent) : base(aTreeView, aParent)
00350     {
00351       InitializeComponent();
00352     }
00353     
00354     public BaseTreeBuilder(ManticoreTreeView aTreeView, 
00355                            TreeNode aParent, 
00356                            TreeNode aBefore, 
00357                            TreeNode aAfter) : base(aTreeView, aParent, aBefore, aAfter)
00358     {
00359       InitializeComponent();
00360     }
00361 
00362     protected override void InitializeComponent()
00363     {
00364       base.InitializeComponent();
00365 
00366       mDataStore = new SampleDataStore();
00367       mDataStore.AddObserver(this as IDataStoreObserver);
00368     }
00369   }
00370 }