Back to index

lightning-sunbird  0.9+nobinonly
MenuBuilder.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 DynamicMenuBuilder : ContentBuilder, IDataStoreObserver
00049   {
00053     protected MenuItem mParent = null;
00054 
00055     protected Menu.MenuItemCollection mParentItems = null;
00056     
00062     protected MenuItem mBefore = null;
00063     protected MenuItem mAfter = null;
00064     
00068     protected Hashtable mMenus = null;
00069 
00075     protected int mInsertionPoint = 0;
00076     
00077     public DynamicMenuBuilder(MainMenu aMainMenu, MenuItem aParent)
00078     {
00079       if (aParent != null) 
00080       {
00081         mParent = aParent;
00082         mParentItems = aParent.MenuItems;
00083       }
00084       else
00085         mParentItems = aMainMenu.MenuItems;
00086       
00087       InitializeComponent();
00088     }
00089     
00090     public DynamicMenuBuilder(MainMenu aMainMenu, MenuItem aParent, MenuItem aBefore, MenuItem aAfter)
00091     {
00092       if (aParent != null) 
00093       {
00094         mParent = aParent;
00095         mParentItems = aParent.MenuItems;
00096       }
00097       else
00098         mParentItems = aMainMenu.MenuItems;
00099       
00100       
00101       // XXX we do jack shit to handle this at the moment. TBD. 
00102       mBefore = aBefore;
00103       mAfter = aAfter;
00104       
00105       ResetInsertionPoint();
00106     
00107       InitializeComponent();
00108     }
00109     
00110     private void ResetInsertionPoint()
00111     {
00112       if (mBefore != null) 
00113       {
00114         // The insertion point is the position immediately after |mBefore|
00115         mInsertionPoint = mParentItems.IndexOf(mBefore) + 1;
00116       }
00117       else
00118         mInsertionPoint = 0;
00119     }
00120     
00121     protected virtual void InitializeComponent()
00122     {
00123       mMenus = new Hashtable();
00124       
00125       // XXX for now, just be stupid and generate everything when the root
00126       //     menu is opened. 
00127       mParent.Popup += new EventHandler(OnParentPopup);
00128     }
00129     
00130     protected void OnParentPopup(Object sender, EventArgs e)
00131     {
00132       // XXX make this smarter. 
00133       Build();
00134     }
00135 
00137     // ContentBuilder Implementation
00138 
00139     public void OnNodeChanging(Object aOldNode, Object aNewNode)
00140     {
00141       // Not Implemented.
00142     }
00143     public void OnNodeChanged(Object aOldNode, Object aNewNode)
00144     {
00145       // Enumerate each of the properties that affect FE presentation, test
00146       // for difference, and update the FE if necessary.
00147       
00148       CommandTarget oldTarget = aOldNode as CommandTarget;
00149       CommandTarget newTarget = aNewNode as CommandTarget;
00150       
00151       if (oldTarget == null && newTarget == null)
00152         return;
00153       
00154       // Check for Label/AccessKey change. 
00155       if (newTarget.Label != oldTarget.Label || newTarget.AccessKey != oldTarget.AccessKey) 
00156       {
00157         int itemKey = newTarget.Data.GetHashCode();
00158         if (mMenus.ContainsKey(itemKey)) 
00159         {
00160           ManticoreMenuItem item = mMenus[itemKey] as ManticoreMenuItem;
00161           // Re-generate AccessKey and update display Text
00162           item.Text = ManticoreMenuItem.GenerateAccessKeyString(newTarget.Label, newTarget.AccessKey);;
00163         }
00164       }
00165     }
00166 
00167     public void OnNodeAdding(Object aNewNode, Object aParentNode, int aIndex)
00168     {
00169       // Not Implemented. 
00170     }
00171     public void OnNodeAdded(Object aChildNode, Object aParentNode, int aIndex)
00172     {
00173       // A new Element has been added somewhere. We must find the 
00174       // parent menu and append it. To interoperate with the Content Builder,
00175       // the DataStore must provide |CommandTarget|s to this method. 
00176       CommandTarget childTarget = aChildNode as CommandTarget;
00177       CommandTarget parentTarget = aParentNode as CommandTarget;
00178       if (childTarget == null && parentTarget == null)
00179         return;
00180 
00181       int childKey = childTarget.Data.GetHashCode();
00182       if (!mMenus.ContainsKey(childKey)) 
00183       {
00184         int parentKey = parentTarget.Data.GetHashCode();
00185 
00186         ManticoreMenuItem parentMenu;
00187         if (mMenus.ContainsKey(parentKey))
00188           parentMenu = mMenus[parentKey] as ManticoreMenuItem;
00189         else
00190           parentMenu = mParent as ManticoreMenuItem;
00191         
00192         if (parentMenu != null) 
00193         {
00194           String label = childTarget.Label;
00195           if (childTarget.AccessKey != "")
00196             label = ManticoreMenuItem.GenerateAccessKeyString(childTarget.Label, 
00197               childTarget.AccessKey);
00198           ManticoreMenuItem childMenu = new ManticoreMenuItem(label, 
00199                                                               new EventHandler(OnCommandInternal), 
00200                                                               "bookmarks-item", childTarget.Data);
00201           if (parentMenu != null) 
00202           {
00203             int pos = aIndex == -1 ? parentMenu.MenuItems.Count : aIndex;
00204             parentMenu.MenuItems.Add(pos, childMenu);
00205             mMenus.Add(childKey, childMenu);
00206           }
00207         }
00208       }
00209     }
00210 
00211     public void OnNodeRemoving(Object aNodeRemoving)
00212     {
00213       // Not Implemented.
00214     }
00215     public void OnNodeRemoved(Object aNodeRemoved)
00216     {
00217       CommandTarget childTarget = aNodeRemoved as CommandTarget;
00218 
00219       // Remove |MenuItem| representation of |aChildNode|.
00220       int childKey = childTarget.Data.GetHashCode();
00221       if (mMenus.ContainsKey(childKey)) 
00222       {
00223         ManticoreMenuItem childMenu = mMenus[childKey] as ManticoreMenuItem;
00224         ManticoreMenuItem parentMenu = childMenu.Parent as ManticoreMenuItem;
00225         parentMenu.MenuItems.Remove(childMenu);
00226         mMenus.Remove(childKey);
00227       }
00228     }
00229 
00233     public override void Build()
00234     {
00235       if (mDataStore == null || mRoot == null) 
00236         throw new Exception();
00237 
00238       // XXX implement acknowledgement of |LazyState|
00239 
00240       Recurse(mRoot, mParentItems);
00241     }
00242 
00243     public void Recurse(String aRoot, Menu.MenuItemCollection aParentItems)
00244     {
00245       IEnumerator items;
00246       mDataStore.GetElements(aRoot, out items);
00247       items.Reset();
00248       
00249       MenuItem item;
00250       
00251       while (items.MoveNext()) 
00252       {
00253         // |id| is the item's unique identifier within the DataStore. 
00254         // The handling code can use this to probe for more information
00255         // about the selected item. 
00256         CommandTarget current = items.Current as CommandTarget;
00257         if (current != null) 
00258         {
00259           String id = current.Data as String; 
00260           
00261           int idKey = id.GetHashCode();
00262           
00263           if (!mMenus.ContainsKey(idKey)) 
00264           {
00265             item = new ManticoreMenuItem(current.Label, 
00266                                          new EventHandler(OnCommandInternal), 
00267                                          "bookmarks-item", id);
00268             if (aRoot != Root)
00269               aParentItems.Add(item);
00270             else
00271               aParentItems.Add(mInsertionPoint++, item);
00272             mMenus.Add(id.GetHashCode(), item);
00273 
00274             if (current.IsContainer)
00275               Recurse(current.Data as String, item.MenuItems);
00276           }
00277         }
00278       }
00279       
00280       ResetInsertionPoint();
00281     }
00282 
00287     public event EventHandler OnCommand;
00288 
00295     protected void OnCommandInternal(Object sender, EventArgs e)
00296     {
00297       if (OnCommand != null) 
00298         OnCommand(sender, e);
00299     }
00300 
00302     //
00303 
00304     public MenuItem Parent
00305     {
00306       get 
00307       {
00308         return mParent;
00309       }
00310       set 
00311       {
00312         mParent = value;
00313       }
00314     }
00315 
00316     public MenuItem Before
00317     {
00318       get 
00319       {
00320         return mBefore;
00321       }
00322       set 
00323       {
00324         mBefore = value;
00325       }
00326     }
00327 
00328     public MenuItem After 
00329     {
00330       get 
00331       {
00332         return mAfter;
00333       }
00334       set 
00335       {
00336         mAfter = value;
00337       }
00338     }
00339   }
00340   
00341   public class BaseMenuBuilder : DynamicMenuBuilder
00342   {
00343     public BaseMenuBuilder(MainMenu aMainMenu, 
00344                            MenuItem aParent) : base(aMainMenu, aParent)
00345     {
00346       InitializeComponent();
00347     }
00348     
00349     public BaseMenuBuilder(MainMenu aMainMenu,
00350                            MenuItem aParent, 
00351                            MenuItem aBefore, 
00352                            MenuItem aAfter) : base(aMainMenu, aParent, aBefore, aAfter)
00353     {
00354       InitializeComponent();
00355     }
00356 
00357     protected override void InitializeComponent()
00358     {
00359       base.InitializeComponent();
00360 
00361       mDataStore = new SampleDataStore();
00362       mDataStore.AddObserver(this as IDataStoreObserver);
00363     } 
00364   }
00365 }