home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2005 November / PCWELT_11_2005.ISO / pcwsoft / Commandbar-Source.z.exe / CommandBar / MacroMenu.cs < prev   
Encoding:
Text File  |  2002-06-10  |  7.5 KB  |  269 lines

  1. // Pavel Zolnikov[http://www.codeproject.com/script/profile/whos_who.asp?id=35980], 2002
  2.  
  3. using System;
  4. using System.Text;
  5. using System.Xml;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Resources;
  9. using System.Reflection;
  10. using System.Windows.Forms;
  11. using System.Drawing.Drawing2D;
  12. using System.Xml.Serialization;
  13. using System.Runtime.InteropServices;
  14.  
  15. using ZCommon;
  16.  
  17. namespace CommandBar
  18. {
  19.     /// <summary>
  20.     /// Provides drop down menu for the 'Script' toolbar button based on the xml macro file.
  21.     /// Traks changes to the file so menu always stays updated.
  22.     /// </summary>
  23.     [ComVisible(false)]
  24.     public class MacroMenuBuilder
  25.     {
  26.         /// <summary>
  27.         /// Watches for changes in a macro file so if there is one menu is being rebuilt.
  28.         /// </summary>
  29.         FileSystemWatcher fsw;
  30.         readonly String macroFilePath;
  31.         readonly ContextMenu menu2Build;
  32.  
  33.         /// <summary>
  34.         /// 
  35.         /// </summary>
  36.         /// <param name="path">path to the xml file with macro</param>
  37.         /// <param name="menu">reference to menu that will be populated</param>
  38.         public MacroMenuBuilder(String path, ContextMenu menu)
  39.         {
  40.             macroFilePath = path;
  41.             menu2Build = menu;
  42.             reBuildMacroMenu();
  43.  
  44.             menu2Build.Popup += new EventHandler( handlePopup );
  45.  
  46.             if( macroFilePath != "" )
  47.             {
  48.                 String dir = Path.GetDirectoryName(macroFilePath);
  49.                 if( Directory.Exists(dir) )
  50.                 {
  51.                     fsw = new FileSystemWatcher();
  52.                     fsw.Path = dir;
  53.                     fsw.Filter = Path.GetFileName(macroFilePath);
  54.                     fsw.NotifyFilter = NotifyFilters.LastWrite;
  55.                     fsw.Changed += new FileSystemEventHandler( handleMacroFileChanged );
  56.                     fsw.EnableRaisingEvents = true;
  57.                 }
  58.             }
  59.         }
  60.  
  61.         /// <summary>
  62.         /// If there was an error parsing xml macro file then contains description of it. Otherwise null.
  63.         /// </summary>
  64.         public string MacroFileError
  65.         {
  66.             get
  67.             {
  68.                 return macroFileError;
  69.             }
  70.         }string macroFileError;
  71.  
  72.         /// <summary>
  73.         /// Raised when menu item was selected.
  74.         /// </summary>
  75.         public event EventHandler MenuItemClick;
  76.         /// <summary>
  77.         /// Raised when menu was changed.
  78.         /// </summary>
  79.         public event EventHandler MenuChanged;
  80.  
  81.         bool bMacroFileChanged;
  82.         void handleMacroFileChanged(object sender, FileSystemEventArgs fsa)
  83.         {
  84.             bMacroFileChanged = true;
  85.         }
  86.  
  87.         void handleMenuItemClick(object sender, System.EventArgs e)
  88.         {
  89.             if( MenuItemClick != null )
  90.                 MenuItemClick(sender, EventArgs.Empty );
  91.         }
  92.         /// <summary>
  93.         /// MenuItems of macro menu are ownerdrawn. Implementtion uses MeasureString for the current system MenuFont and text.
  94.         /// </summary>
  95.         void handleMeasureItem(object sender, MeasureItemEventArgs e )
  96.         {
  97.             TagMenuItem mi = (TagMenuItem)sender;
  98.             item script = (item)mi.Tag;
  99.  
  100.             Size bounds = e.Graphics.MeasureString( script.text, SystemInformation.MenuFont ).ToSize();
  101.  
  102.             e.ItemHeight = bounds.Height;
  103.             e.ItemWidth = bounds.Width + SystemInformation.MenuCheckSize.Width;
  104.         }
  105.         /// <summary>
  106.         /// MenuItems of macro menu are ownerdrawn. Draws text and 'enter' symbol to the left of it if command autoexecutes.
  107.         /// </summary>
  108.         void handleDrawMenuItem(object sender, DrawItemEventArgs e )
  109.         {
  110.             TagMenuItem mi = (TagMenuItem)sender;
  111.             item script = (item)mi.Tag;
  112.  
  113.             Rectangle textPosition = e.Bounds;
  114.             textPosition.Offset( SystemInformation.MenuCheckSize.Width, 0 );
  115.             e.DrawBackground();
  116.             e.Graphics.DrawString( script.text, e.Font, new SolidBrush(e.ForeColor), textPosition );
  117.  
  118.             if( script is macro && ((macro)script).execute )
  119.             {
  120.                 Font f = new Font("Symbol", e.Font.SizeInPoints, FontStyle.Regular, GraphicsUnit.Point );
  121.             
  122.                 StringFormat sf = new StringFormat();
  123.                 sf.Alignment = StringAlignment.Far;
  124.  
  125.                 e.Graphics.DrawString( "\xBF", f, new SolidBrush(e.ForeColor), e.Bounds, sf );
  126.             }
  127.         }
  128.  
  129.         /// <summary>
  130.         /// Desrializes xml in macro file into graph of item-derived objects. Builds context menu from this graph.
  131.         /// </summary>
  132.         void reBuildMacroMenu()
  133.         {
  134.             group scripts = null;
  135.             macroFileError = null;
  136.             menu2Build.MenuItems.Clear();
  137.  
  138.             Stream sr = null;
  139.             try
  140.             {
  141.                 if( File.Exists(macroFilePath) )
  142.                 {
  143.                     sr = File.OpenRead( macroFilePath );
  144.                     scripts = (group)new XmlSerializer(typeof(group)).Deserialize( sr );
  145.                 }
  146.                 else
  147.                 {
  148.                     ResourceManager rm = new ResourceManager("CommandBar.macro",GetType().Assembly);
  149.                     XmlTextReader xtr = new XmlTextReader(rm.GetString("macro"), XmlNodeType.Document, null);
  150.                     scripts = (group)new XmlSerializer(typeof(group)).Deserialize( xtr );
  151.                 }
  152.             }
  153.             catch(Exception e)
  154.             {
  155.                 macroFileError = e.Message;
  156.             }
  157.             finally
  158.             {
  159.                 if( sr != null ) sr.Close();
  160.             }
  161.  
  162.             if( scripts != null && macroFileError == null )
  163.             {
  164.                 scripts.BuildContextMenu( menu2Build, new EventHandler(instrumentMenuItem) );
  165.                 bMacroFileChanged = false;
  166.             }
  167.             
  168.             if( MenuChanged!= null )
  169.                 MenuChanged( this, EventArgs.Empty );            
  170.         }
  171.  
  172.         /// <summary>
  173.         /// Called by item,macro and group during the process of building menu. Allows for tweaking all created MenuItem objects.
  174.         /// </summary>
  175.         /// <param name="sender"></param>
  176.         /// <param name="ea"></param>
  177.         void instrumentMenuItem(Object sender, EventArgs ea)
  178.         {
  179.             MenuItem mi =(MenuItem)sender;
  180.             mi.Click += new EventHandler(handleMenuItemClick);
  181.             mi.OwnerDraw = true;
  182.             mi.DrawItem += new DrawItemEventHandler( handleDrawMenuItem );
  183.             mi.MeasureItem += new MeasureItemEventHandler( handleMeasureItem );
  184.         }
  185.  
  186.         void handlePopup(Object sender, EventArgs ea)
  187.         {
  188.             if( bMacroFileChanged )
  189.                 reBuildMacroMenu();
  190.         }
  191.  
  192.  
  193.         /// <summary>
  194.         /// Base class for (de)serializing macro menu in xml format.
  195.         /// </summary>
  196.         [ComVisible(false)]
  197.         public class item
  198.         {
  199.             public item(){}
  200.             public item(String t) { text = t; }
  201.  
  202.             [XmlAttribute]
  203.             public String        text;
  204.         
  205.             public virtual TagMenuItem BuildMenu(Menu menu, EventHandler instrumentMenuItem)
  206.             {
  207.                 TagMenuItem mi = new TagMenuItem(text,this);
  208.                 menu.MenuItems.Add( mi );
  209.  
  210.                 instrumentMenuItem(mi, EventArgs.Empty);
  211.                 return mi;
  212.             }
  213.         }
  214.  
  215.         /// <summary>
  216.         /// Represents group tag in xml macro file.
  217.         /// </summary>
  218.         [ComVisible(false)]
  219.         public class group : item
  220.         {
  221.             public group() {}
  222.             public group(String t) : base(t) {}
  223.  
  224.             /// <summary>
  225.             /// group contains list of chile items. As this list may consist of <code>macro</code> and
  226.             /// <code>group</code> elements we must specify both these types in <code>XmlElement</code> attribute
  227.             /// </summary>
  228.             [XmlElement(typeof(group))]
  229.             [XmlElement(typeof(macro))]
  230.             public item[]        items;
  231.  
  232.             public void BuildContextMenu(ContextMenu menu, EventHandler instrumentMenuItem)
  233.             {
  234.                 if( items != null )
  235.                     foreach(item m in items)
  236.                         m.BuildMenu( menu, instrumentMenuItem );
  237.             }
  238.  
  239.             public override TagMenuItem BuildMenu(Menu menu, EventHandler instrumentMenuItem)
  240.             {
  241.                 TagMenuItem mi = base.BuildMenu( menu, instrumentMenuItem );
  242.  
  243.                 if( items != null )
  244.                     foreach(item m in items)
  245.                         m.BuildMenu( mi, instrumentMenuItem );
  246.  
  247.                 return mi;
  248.             }
  249.         }
  250.  
  251.         /// <summary>
  252.         /// Represents macro tag in xml macro file.
  253.         /// </summary>
  254.         [ComVisible(false)]
  255.         public class macro : item
  256.         {
  257.             [XmlAttribute]
  258.             public bool            execute = true;
  259.  
  260.             [XmlAttribute]
  261.             public String        command;
  262.  
  263.             public macro(){}
  264.             public macro(String t) : base(t) {}
  265.             public macro(String t, bool b) : base(t) { execute = b; }
  266.             public macro(String t, String c, bool b) : base(t) { command = c; execute = b; }
  267.         }
  268.     }
  269. }