vbAccelerator - Contents of code file: acclExplorerBar_ExplorerBar.cs

using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using vbAccelerator.Components.Controls.ExplorerBarFramework;
using vbAccelerator.Components.Controls.ExplorerBarUtility;

namespace vbAccelerator.Components.Controls
{
   /// <summary>
   /// A single bar within the Explorer Bar control.
   /// </summary>
   public class ExplorerBar : ICloneable, IExplorerBarControlItem
   {
      /// <summary>
      /// Instance of the <see cref="acclExplorerBar"/> control
      /// which owns this bar.
      /// </summary>
      protected acclExplorerBar owner = null;

      private ExplorerBarItemCollection items = null;
      private object tag = null;
      private bool isSpecial = false;
      private Bitmap watermark = null;
      private ExplorerBarWatermarkMode watermarkMode =
       ExplorerBarWatermarkMode.Colourise;
      private ExplorerBarWatermarkAlignment watermarkHAlign =
       ExplorerBarWatermarkAlignment.Far;
      private ExplorerBarWatermarkAlignment watermarkVAlign =
       ExplorerBarWatermarkAlignment.Far;
      private int iconIndex = -1;
      private string text = "";
      private char mnemonicCode = '\0';
      private string toolTipText = "";
      private Color titleBackColorStart = Color.Empty;
      private Color titleBackColorEnd = Color.Empty;
      private Color titleForeColor = Color.Empty;
      private Color titleForeColorHot = Color.Empty;
      private Color backColor = Color.Empty;
      private Font font = null;
      private bool canExpand = true;
      private ExplorerBarState state = ExplorerBarState.Expanded;
      private int marginSize = 12;
      private bool animateStateChanges = true;

      private Bitmap processedWatermark = null;

      private int titleHeightWithScroll = 24;
      private int titleTextHeightWithScroll = 24;
      private bool singleLineTitleWithScroll = true;
      private bool singleLineTitleWithoutScroll = true;

      private int titleHeightWithoutScroll = 24;
      private int titleTextHeightWithoutScroll = 24;

      private int heightWithScroll = 12;
      private int heightWithoutScroll = 12;
      private int top  = 0;
      private bool mouseOver = false;
      private bool mouseDown = false;
      private bool expanding = false;
      private bool collapsing = false;
      private int alpha = 255;
      private int collapseOffset = 0;
      private bool hasFocus = false;

      /// <summary>
      /// Constructs a new, default instance of this class.
      /// </summary>
      public ExplorerBar()
      {
         items = new ExplorerBarItemCollection();
      }

      #region Internal Implementation
      internal bool Animating
      {
         get
         {
            return (expanding || collapsing);
         }
      }

      internal void SetOwner(acclExplorerBar newOwner)
      {
         if (newOwner == null)
         {
            OnSizeChanged();
            if (owner != null)
            {
               owner.InternalOnBarRemoved(this);
            }
            owner = null;
         }
         else
         {
            if (owner == null)
            {
               owner = newOwner;
               // Set the owner of all the child items:
               items.SetOwner(owner);
               OnSizeChanged();
               if (watermark != null)
               {
                  OnWatermarkChanged();
               }
            }
            else if (owner != newOwner)
            {
               owner = newOwner;
               OnSizeChanged();
            }
         }

      }

      internal Bitmap ProcessedWatermark
      {
         get
         {
            return processedWatermark;
         }
         set
         {
            processedWatermark = value;
         }
      }

      internal int HeightWithScroll
      {
         get
         {
            int height = 0;
            if (expanding || collapsing)
            {
               height = heightWithScroll + collapseOffset;
            }
            else
            {
               if (state == ExplorerBarState.Expanded)
               {
                  height = heightWithScroll;
               }
               else
               {
                  height = titleHeightWithScroll;
               }
            }
            return height;
         }
      }

      internal int HeightWithoutScroll
      {
         get
         {
            int height = 0;
            if (collapsing || expanding)
            {
               height = heightWithoutScroll + collapseOffset;
            }
            else
            {
               if (state == ExplorerBarState.Expanded)
               {
                  height = heightWithoutScroll;
               }
               else
               {
                  height = titleHeightWithoutScroll;
               }
            }
            return height;
         }
      }

      internal int TitleHeightWithScroll
      {
         get
         {
            return titleHeightWithScroll;
         }
      }

      internal int TitleHeightWithoutScroll
      {
         get
         {
            return titleHeightWithoutScroll;
         }
      }

      internal void SetAnimationInformation(bool newExpanding, bool
       newCollapsing)
      {
         expanding = newExpanding;
         collapsing = newCollapsing;
      }

      internal void SetAnimationOffset(int offset, int newAlpha)
      {
         collapseOffset = offset;
         alpha = newAlpha;
      }
      #endregion

      #region Interface Implementation
      /// <summary>
      /// Determines whether this bar's title contains the specified mnemonic.
      /// </summary>
      /// <param name="charCode">Mnemonic key character code.</param>
      /// <returns><c>true</c> if the bar contains the mnemonic code,
       <c>false</c>
      /// otherwise.</returns>
      public bool ContainsMnemonic(char charCode)
      {
         return (mnemonicCode == charCode);
      }
      /// <summary>
      /// Gets/sets whether this item displays the focus in the control.
      /// </summary>
      public bool ShowFocus
      {
         get
         {
            return canExpand;
         }
      }

      /// <summary>
      /// Gets/sets whether this bar has the focus in the control
      /// </summary>
      public bool Focused
      {
         get
         {
            return hasFocus;
         }
         set
         {
            if (canExpand)
            {
               if (hasFocus != value)
               {
                  hasFocus = value;         
                  if ((owner != null) && (value))
                  {
                     owner.InternalOnItemFocus(this);
                  }
                  else
                  {
                     OnAppearanceChanged();
                  }
                  if ((value) & (!mouseDown))
                  {
                     EnsureVisible();
                  }
               }
            }
         }
      }

      /// <summary>
      /// Gets/sets whether the mouse is over the bar's title
      /// </summary>
      public bool MouseOver
      {
         get
         {
            return mouseOver;
         }
         set
         {
            if (mouseOver != value)
            {
               mouseOver = value;
               if (value)
               {
                  owner.InternalOnItemMouseOver(this);
               }
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets whether the mouse is down on this bar's title
      /// </summary>
      public bool MouseDown
      {
         get
         {
            return mouseDown;
         }
         set
         {
            if (mouseDown != value)
            {
               mouseDown = value;
               Focused = value;
               if (value)
               {
                  owner.InternalOnItemMouseDown(this);
               }
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets whether the specified point is within the title of this bar.
      /// </summary>
      /// <param name="location">Location to hit test for.</param>
      /// <param name="width">Client width of the owning control.</param>
      /// <param name="scrollShowing">Whether the scroll bar is displayed in
       the 
      /// owning control.</param>
      public bool HitTest(Point location, int width, bool scrollShowing)
      {
         bool ret = false;
         int testHeight = (scrollShowing ? titleTextHeightWithScroll :
          titleHeightWithoutScroll);
         int testTop = top + (scrollShowing ? 
            titleHeightWithScroll - titleTextHeightWithScroll : 
            titleHeightWithoutScroll - titleTextHeightWithoutScroll);
         
         if ((location.Y >= testTop) && (location.Y <= testTop + testHeight))
         {
            if ((location.X >= marginSize) && (location.X <= width -
             marginSize))
            {
               ret = true;
            }
         }

         return ret;
      }


      /// <summary>
      /// Gets whether this item responds to clicks from the mouse.
      /// </summary>
      public bool Clickable
      {
         get
         {
            return canExpand;
         }
      }

      /// <summary>
      /// Returns a deep clone of this object, including any associated items
      /// which is not associated with an instance of the ExplorerBar control.
      /// </summary>
      /// <returns></returns>
      public object Clone()
      {
         ExplorerBar clonedBar = new ExplorerBar();
         clonedBar.AnimateStateChanges = animateStateChanges;
         clonedBar.BackColor = backColor;
         clonedBar.CanExpand = canExpand;
         clonedBar.Font = font;
         clonedBar.IconIndex = iconIndex;
         clonedBar.IsSpecial = isSpecial;
         clonedBar.State = state;
         clonedBar.Tag = tag;
         clonedBar.Text  = text;
         clonedBar.TitleBackColorEnd = titleBackColorEnd;
         clonedBar.TitleBackColorStart = titleBackColorStart;
         clonedBar.TitleForeColor = titleForeColor;
         clonedBar.TitleForeColorHot = titleForeColorHot;
         clonedBar.ToolTipText = toolTipText;
         clonedBar.Watermark = watermark;
         clonedBar.WatermarkHAlign = watermarkHAlign;
         clonedBar.WatermarkMode = watermarkMode;
         clonedBar.WatermarkVAlign = watermarkVAlign;
         foreach (ExplorerBarItem item in items)
         {
            ExplorerBarItem clonedItem = (ExplorerBarItem) item.Clone();
            clonedBar.Items.Add(clonedItem);
         }
         return clonedBar;
      }

      /// <summary>
      /// Called when the bar is clicked.
      /// </summary>
      public virtual void Click()
      {
      }
      #endregion

      #region Public Implementation

      /// <summary>
      /// Gets the collection of items associated with this bar.
      /// </summary>
      public ExplorerBarItemCollection Items
      {
         get
         {
            return items;
         }
      }

      /// <summary>
      /// Gets/sets an object to be associated with this Bar.
      /// </summary>
      public object Tag
      {
         get
         {
            return tag;
         }
         set
         {
            tag = value;
         }
      }

      /// <summary>
      /// Gets/sets whether this bar is special or not.  A special bar
      /// has different bar colours and is normally used to highlight the most
      /// common bar within a control.
      /// </summary>
      public bool IsSpecial
      {
         get
         {
            return isSpecial;
         }
         set
         {
            if (isSpecial != value)
            {
               isSpecial = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets whether bar state changes should be animated
      /// for this bar.  If the bar contains items which hold controls then the
      /// value will always be <c>false</c> regardless of the setting.
      /// </summary>
      public bool AnimateStateChanges
      {
         get
         {
            return (CanAnimateStateChanges && animateStateChanges);
         }
         set
         {
            animateStateChanges = value;
         }
      }

      /// <summary>
      /// Gets whether it is possible to animate bar state changes or not.
      /// Bars which contain items that hold controls cannot be animated.
      /// </summary>
      public bool CanAnimateStateChanges
      {
         get
         {
            bool canAnimate = true;
            foreach (ExplorerBarItem item in items)
            {
               if
                (typeof(ExplorerBarControlHolderItem).IsAssignableFrom(item.GetT
               ype()))
               {
                  canAnimate = false;
                  break;
               }
            }
            return canAnimate;
         }
      }
      
      /// <summary>
      /// Gets/sets an image used to display a watermark behind the
      /// items in the bar.
      /// </summary>
      public Bitmap Watermark
      {
         get
         {
            return watermark;
         }
         set
         {
            watermark = value;
            OnWatermarkChanged();
            OnAppearanceChanged();
         }
      }

      /// <summary>
      /// Gets/sets the Image Processing effect applied to the 
      /// <see cref="Watermark"/> image for this bar.
      /// </summary>
      public ExplorerBarWatermarkMode WatermarkMode
      {
         get
         {
            return watermarkMode;
         }
         set
         {
            if (watermarkMode != value)
            {
               watermarkMode = value;
               OnWatermarkChanged();
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the horizontal alignment of the <see cref="Watermark"/>
      /// image for this bar.
      /// </summary>
      public ExplorerBarWatermarkAlignment WatermarkHAlign
      {
         get
         {
            return watermarkHAlign;
         }
         set
         {
            if (watermarkHAlign != value)
            {
               watermarkHAlign = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the vertical alignment of the <see cref="Watermark"/>
      /// image for this bar.
      /// </summary>
      public ExplorerBarWatermarkAlignment WatermarkVAlign
      {
         get
         {
            return watermarkVAlign;
         }
         set
         {
            if (watermarkVAlign != value)
            {
               watermarkVAlign = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the 0-based index of an icon in an ImageList to
      /// show in the title for this bar.
      /// </summary>
      public int IconIndex
      {
         get
         {
            return iconIndex;
         }
         set
         {
            if (((iconIndex < 0) && (value > 0)) ||
               ((iconIndex > 0) && (value < 0)))
            {
               iconIndex = value;
               OnSizeChanged();
            }
            else if (iconIndex != value)
            {
               iconIndex = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the title for this bar.
      /// </summary>
      public string Text
      {
         get
         {
            return text;
         }
         set
         {
            if (!text.Equals(value))
            {
               text = value;
               DetermineMnemonicKey();
               OnSizeChanged();
            }
         }
      }

      private void DetermineMnemonicKey()
      {
         int pos = text.IndexOf("&");
         if ((pos > -1) && (pos < text.Length - 1))
         {
            mnemonicCode = text.Substring(pos + 1, 1).ToCharArray()[0];
         }
         else
         {
            mnemonicCode = '\0';
         }
      }


      /// <summary>
      /// Gets/sets the tooltip text that should be shown for this bar.
      /// Setting to an empty string means no tooltip.
      /// </summary>
      public string ToolTipText
      {
         get
         {
            return toolTipText;
         }
         set
         {
            toolTipText = value;
         }
      }

      /// <summary>
      /// Gets/sets the colour to use at the start of the TitleBar
      /// when the control is being drawn in the <see
       cref="ExplorerBarDrawingStyle.Custom"/>
      /// style.
      /// </summary>
      public Color TitleBackColorStart
      {
         get
         {
            return titleBackColorStart;
         }
         set
         {
            if (titleBackColorStart != value)
            {
               titleBackColorStart = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the colour to use at the end of the TitleBar
      /// when the control is being drawn in the <see
       cref="ExplorerBarDrawingStyle.Custom"/>
      /// style.
      /// </summary>
      public Color TitleBackColorEnd
      {
         get
         {
            return titleBackColorEnd;
         }
         set
         {
            if (titleBackColorEnd != value)
            {
               titleBackColorEnd = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the text colour to use for the title of this bar
      /// when the control is being drawn in the <see
       cref="ExplorerBarDrawingStyle.Custom"/>
      /// style.
      /// </summary>
      public Color TitleForeColor
      {
         get
         {
            return titleForeColor;
         }
         set
         {
            if (titleForeColor != value)
            {
               titleForeColor = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the text colour to use for the title of this bar
      /// when the control is being drawn in the <see
       cref="ExplorerBarDrawingStyle.Custom"/>
      /// style and the bar is Hot (MouseOver).
      /// </summary>
      public Color TitleForeColorHot
      {
         get
         {
            return titleForeColorHot;
         }
         set
         {
            if (titleForeColorHot != value)
            {
               titleForeColorHot = value;
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the background colour of this bar.
      /// </summary>
      public Color BackColor
      {
         get
         {
            return backColor;
         }
         set
         {
            if (backColor != value)
            {
               backColor = value;
               if ((watermark != null) && 
                  (watermarkMode == ExplorerBarWatermarkMode.Colourise))
               {
                  OnWatermarkChanged();
               }
               OnAppearanceChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the font to use to draw the title of this bar.
      /// </summary>
      public System.Drawing.Font Font
      {
         get
         {
            return font;
         }
         set
         {
            font = value;
            OnSizeChanged();
         }
      }

      /// <summary>
      /// Gets/sets whether this bar can be expanded or collapsed.
      /// </summary>
      public bool CanExpand
      {
         get
         {
            return canExpand;
         }
         set
         {
            if (canExpand != value)
            {               
               canExpand = value;
               OnSizeChanged();
            }
         }
      }

      /// <summary>
      /// Gets/sets the state of this bar.
      /// </summary>
      public ExplorerBarState State
      {
         get
         {
            return state;
         }
         set
         {
            if (state != value)
            {
               if (owner != null)
               {
                  owner.InternalChangeBarState(this);
               }
            }
         }
      }
      /// <summary>
      /// Ensures that this bar is visible in the control.
      /// </summary>
      public void EnsureVisible()
      {
         if (owner != null)
         {
            owner.InternalEnsureVisible(this);
         }
      }

      #endregion
      internal void InternalSetState(ExplorerBarState newState)
      {
         state = newState;
         InternalMakeControlsVisible((state == ExplorerBarState.Expanded));
      }

      internal void InternalMeasureItem(
         ExplorerBarMeasureItemParams measureItemParams
         )
      {
         MeasureItem(measureItemParams);
      }

      internal void InternalMakeControlsVisible(bool visible)
      {
         foreach (ExplorerBarItem item in items)
         {
            if
             (typeof(ExplorerBarControlHolderItem).IsAssignableFrom(item.GetType
            ()))
            {
               ExplorerBarControlHolderItem controlItem =
                (ExplorerBarControlHolderItem) item;
               if (controlItem.Control != null)
               {
                  if ((state == ExplorerBarState.Expanded) && (!visible))
                  {
                     controlItem.Control.Top = -1000;
                  }
                  else
                  {
                     controlItem.Control.Visible = visible;
                  }
               }
            }
            if (!visible)
            {
               top = -100;
            }
         }
      }


      /// <summary>
      /// Measures the size of this bar.
      /// </summary>
      /// <param name="measureItemParams">Class specifying details required to
       measure the bar.</param>
      protected virtual void MeasureItem(
         ExplorerBarMeasureItemParams measureItemParams         
         )
      {
         if (owner != null)
         {
            // First measure me:
            if ((measureItemParams.Mode == ExplorerBarMode.Search) &&
             (!CanExpand) && (Text.Length == 0))
            {
               titleHeightWithScroll = 0;
               titleHeightWithoutScroll = 0;
               heightWithScroll = 0;
               heightWithoutScroll = 0;
            }
            else
            {            
               MeasureTitle(measureItemParams);            
               heightWithScroll = titleHeightWithScroll + 8;
               heightWithoutScroll = titleHeightWithoutScroll + 8;
            }

            // Now measure all of my subitems:
            foreach (ExplorerBarItem item in items)
            {
               item.InternalMeasureItem(measureItemParams);
               heightWithScroll += item.HeightWithScroll;
               heightWithoutScroll += item.HeightWithoutScroll;
            }


         }
      }

      /// <summary>
      /// Measures the size of the title of this bar.
      /// </summary>
      /// <param name="measureItemParams">Class specifying details required to
       measure the bar.</param>
      private void MeasureTitle(
         ExplorerBarMeasureItemParams measureItemParams
         )
      {
         XpThemeAPI xpTheme = owner.XpTheme;
         BarBitmaps barBitmaps = owner.Bitmaps;

         int origHeightWith = HeightWithScroll;
         int origHeightWithout = HeightWithoutScroll;

         singleLineTitleWithoutScroll = false;
         singleLineTitleWithScroll = false;

         int heightWith = 0;
         int heightWithout = 0;

         if (
            (measureItemParams.Style == ExplorerBarDrawingStyle.XP ||
            (measureItemParams.Style == ExplorerBarDrawingStyle.System &&
             !xpTheme.hTheme.Equals(IntPtr.Zero))) &&
            (measureItemParams.Mode == ExplorerBarMode.Default))
         {
            // the height of the title is the height of the
            // title bar bitmaps
            heightWith = barBitmaps[BarBitmapType.EBP_NORMALGROUPHEAD].Height;
            heightWithout = heightWith;
         }
         else
         {
            // Get the font to use:
            Font useFont = Font;
            bool disposeFont = false;
            if (useFont == null)
            {
               useFont = new
                Font(measureItemParams.DefaultFont.FontFamily.Name, 
                  measureItemParams.DefaultFont.Size, 
                  measureItemParams.DefaultFont.Style | FontStyle.Bold);
               disposeFont = true;
            }
            
            // Set up default measure rectangle for the text:
            Rectangle measureRectF = new Rectangle(
               0, 0, 
               measureItemParams.WidthWithoutScroll - marginSize * 2, 
               512);

            // Check if we have a title icon:
            if ((iconIndex> -1) && (measureItemParams.ImageList != null))
            {
               measureRectF.X += measureItemParams.ImageList.ImageSize.Width +
                4;
               measureRectF.Width -=
                (measureItemParams.ImageList.ImageSize.Width + 4);
            }

            // Check if we have a collapse/expand icon on the bar:
            if (canExpand)
            {
               if (measureItemParams.Style == ExplorerBarDrawingStyle.Classic)
               {
                  measureRectF.Width -= 16;
               }
               else
               {
                  if (barBitmaps[BarBitmapType.EBP_NORMALGROUPCOLLAPSE] != null)
                  {
                     measureRectF.Width -=
                      (barBitmaps[BarBitmapType.EBP_NORMALGROUPCOLLAPSE].Width
                      + 4);
                  }
                  else
                  {
                     measureRectF.Width -= 16;
                  }
               }
            }

            // Now the height depends on whether we're in search mode 
            // or not:
            if (measureItemParams.Mode == ExplorerBarMode.Search)
            {
               // We may have multi-line captions
               measureRectF.Width -= 8;

               // measure a single line:
               StringFormat fmt = new StringFormat(StringFormatFlags.LineLimit
                | StringFormatFlags.NoWrap);
               SizeF sz = measureItemParams.Graphics.MeasureString("Xg",
                useFont, measureItemParams.WidthWithoutScroll, fmt);
               fmt.Dispose();               
               int heightOneLine = (int) sz.Height;

               // Now measure the size without the scroll bar:
               int measureWidth = (int) measureRectF.Width;
               sz = measureItemParams.Graphics.MeasureString(
                  text, useFont, measureWidth);
               if ((int) sz.Height <= heightOneLine + 2)
               {
                  singleLineTitleWithoutScroll = true;
               }
               heightWithout = (int) sz.Height + 9;

               // Measure with the scroll bar:
               measureWidth -= (measureItemParams.WidthWithScroll -
                measureItemParams.WidthWithoutScroll);
               sz = measureItemParams.Graphics.MeasureString(
                  Text, useFont, measureWidth);
               if ((int) sz.Height <= heightOneLine + 2)
               {
                  singleLineTitleWithScroll = true;
               }
               heightWith = (int) sz.Height + 9;

            }
            else
            {
               // captions must be single line
               StringFormat fmt = new StringFormat(StringFormatFlags.LineLimit
                | StringFormatFlags.NoWrap);
               SizeF sz = measureItemParams.Graphics.MeasureString(
                  "Xg", useFont, measureItemParams.WidthWithoutScroll, fmt);
               fmt.Dispose();
               heightWithout = (int) sz.Height + 9;
               heightWith = heightWithout;
            }
            if (disposeFont)
            {
               useFont.Dispose();
            }
         }

         // Ok apply some general checks:
         heightWithout = (heightWithout < 24 ? 24 : heightWithout);
         heightWith = (heightWith < 24 ? 24 : heightWith);

         // Set the title heights:
         titleTextHeightWithoutScroll = heightWithout;
         titleTextHeightWithScroll = heightWith;

         // Ensure we've accommodated the icon:
         if ((iconIndex > -1) && (measureItemParams.TitleImageList != null))
         {
            heightWith = (heightWith <
             measureItemParams.TitleImageList.ImageSize.Height ? 
               measureItemParams.TitleImageList.ImageSize.Height : heightWith);
            heightWithout = (heightWithout <
             measureItemParams.TitleImageList.ImageSize.Height ? 
               measureItemParams.TitleImageList.ImageSize.Height :
                heightWithout);
         }

         // Set:
         titleHeightWithScroll = heightWith;
         titleHeightWithoutScroll = heightWithout;

         // Here we can check whether we had a change, perhaps
         // we need to ask for a refresh of the control...

      }
         

      internal void InternalDrawItem(
         ExplorerBarDrawItemParams drawItemParams
         )
      {
         top = drawItemParams.Top;
         DrawItem(drawItemParams);
      }
      

      /// <summary>
      /// Draws this bar and all of the items contained within it.
      /// </summary>
      /// <param name="drawItemParams">Class specifying information required to 
      /// Draw the bar.</param>
      protected virtual void DrawItem(
         ExplorerBarDrawItemParams drawItemParams
         )
      {         
         // First draw me:
         int overallTitleHeight = DrawTitle(drawItemParams);

         // Now draw the bar
         if ((state == ExplorerBarState.Expanded) ||
            (expanding || collapsing))

         {
            Graphics realGraphics = drawItemParams.Graphics;
            Graphics graphics = realGraphics;

            if (expanding || collapsing)
            {
               if (drawItemParams.AnimationBitmap != null)
               {
                  graphics = Graphics.FromImage(drawItemParams.AnimationBitmap);
                  drawItemParams.SetGraphics(graphics);
               }
            }
            
            DrawBarBackground(drawItemParams, overallTitleHeight);

            //  Now draw the items in the bar
            int newTop = drawItemParams.Top + (drawItemParams.ScrollShowing ? 
               titleHeightWithScroll : titleHeightWithoutScroll);
            int paintTop = newTop;
            newTop += 4;
            int origTop = 0;
            if (expanding || collapsing)
            {
               newTop += collapseOffset;
               origTop = newTop;
               drawItemParams.SetTop(collapseOffset);
            }
            else
            {
               drawItemParams.SetTop(newTop);
            }

            // Then draw all of my subitems:
            foreach (ExplorerBarItem item in items)
            {
               item.InternalDrawItem(drawItemParams);
               newTop  = drawItemParams.Top + (drawItemParams.ScrollShowing ?
                item.HeightWithScroll : item.HeightWithoutScroll);
               drawItemParams.SetTop(newTop);
            }

            if (expanding || collapsing)
            {
               drawItemParams.SetTop(drawItemParams.Top + origTop);
            }

            if (graphics != realGraphics)
            {
               Rectangle destRect = new Rectangle(
                  marginSize, paintTop,
                  (drawItemParams.ScrollShowing ?
                   drawItemParams.WidthWithScroll :
                   drawItemParams.WidthWithoutScroll) - marginSize * 2,
                  (drawItemParams.ScrollShowing ? heightWithScroll -
                   titleHeightWithScroll : heightWithoutScroll -
                   titleHeightWithoutScroll) + collapseOffset);
               float[][] matrixItems =  {
                  new float[] {1, 0, 0, 0, 0},
                  new float[] {0, 1, 0, 0, 0},
                  new float[] {0, 0, 1, 0, 0},
                  new float[] {0, 0, 0, (alpha / 255F), 0},
                  new float[] {0, 0, 0, 0, 1}};

               ColorMatrix colorMatrix = new ColorMatrix(matrixItems);
         
               ImageAttributes imageAttr = new ImageAttributes();
               imageAttr.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default,
                ColorAdjustType.Bitmap);

               realGraphics.DrawImage(drawItemParams.AnimationBitmap,
                  destRect, 
                  destRect.Left, 0, destRect.Width, destRect.Height,
                  GraphicsUnit.Pixel, imageAttr);

               drawItemParams.SetGraphics(realGraphics);
               graphics.Dispose();
            }
         }
      }


      /// <summary>
      /// Draws the title to a bar and returns the height.
      /// </summary>
      /// <param name="drawItemParams">Object containing information needed 
      /// to draw the title</param>
      /// <returns>Height</returns>
      private int DrawTitle(ExplorerBarDrawItemParams drawItemParams)
      {
         // Multi-line title?
         bool multiLineTitle = false;
         if (drawItemParams.Mode == ExplorerBarMode.Search)
         {
            if (drawItemParams.ScrollShowing)
            {
               multiLineTitle = !singleLineTitleWithScroll;
            }
            else
            {
               multiLineTitle = !singleLineTitleWithScroll;
            }
         }

         // Draw the background of the title:
         Rectangle rcTitle = new Rectangle(marginSize, drawItemParams.Top,
            (drawItemParams.ScrollShowing ? drawItemParams.WidthWithScroll :
             drawItemParams.WidthWithoutScroll ) - marginSize * 2, 
            (drawItemParams.ScrollShowing ? titleHeightWithScroll :
             titleHeightWithoutScroll));
         int titleHeight =
          ExplorerBarHelper.DrawBarTitle(drawItemParams.Graphics,
            drawItemParams.Mode, drawItemParams.Style, 
            owner.Bitmaps, owner.XpTheme, 
            rcTitle, 
            isSpecial, mouseOver, mouseDown, state, canExpand, 
            drawItemParams.RightToLeft
            );
         if (hasFocus && owner.ShowingFocusRectangle)
         {
            Rectangle rcFocus = new Rectangle(rcTitle.Location, rcTitle.Size);
            if (!multiLineTitle)
            {
               if (rcFocus.Height > titleHeight)
               {
                  rcFocus.Y += (rcFocus.Height - titleHeight);
                  rcFocus.Height = titleHeight;
               }
            }
            rcFocus.Inflate(-1, -1);
            ControlPaint.DrawFocusRectangle(drawItemParams.Graphics, rcFocus);
         }
         // Draw the icon if any:         
         if ((iconIndex > -1) && (drawItemParams.TitleImageList != null))
         {
            if (drawItemParams.RightToLeft)
            {
               drawItemParams.TitleImageList.Draw(drawItemParams.Graphics, 
                  rcTitle.Width - (marginSize + 2), drawItemParams.Top,
                   iconIndex);
               rcTitle.Width -= (4 +
                drawItemParams.TitleImageList.ImageSize.Width);
            }
            else
            {
               drawItemParams.TitleImageList.Draw(drawItemParams.Graphics, 
                  marginSize + 2, drawItemParams.Top, iconIndex);
               rcTitle.X += (4 + drawItemParams.TitleImageList.ImageSize.Width);
            }            
         }
         else
         {
            if (drawItemParams.RightToLeft)
            {
               rcTitle.Width -= marginSize;
            }
            else
            {
               rcTitle.X += marginSize;
               rcTitle.Width -= marginSize;
            }
         }
         
         // Draw the title text:

         // Font to use
         Font useFont = Font;
         bool disposeFont = false;
         if (useFont == null)
         {
            useFont = new Font(drawItemParams.DefaultFont.FontFamily.Name, 
               drawItemParams.DefaultFont.Size, 
               drawItemParams.DefaultFont.Style | FontStyle.Bold);             
                 
            disposeFont = true;
         }
         
         // Get string format
         StringFormat format = null;

         if (multiLineTitle)
         {
            // Title can be multi-line
            if (drawItemParams.RightToLeft)
            {
               format = new
                StringFormat(StringFormatFlags.DirectionRightToLeft);
            }
            else
            {
               format = new StringFormat();
            }
         }
         else
         {
            // Title is always single line
            
            StringFormatFlags flags = StringFormatFlags.LineLimit |
             StringFormatFlags.NoWrap;
            if (drawItemParams.RightToLeft)
            {
               flags |= StringFormatFlags.DirectionRightToLeft;               
            }
            format = new StringFormat(flags);
            format.LineAlignment = StringAlignment.Center;
            format.Trimming = StringTrimming.EllipsisCharacter;
         }

         // Brush to draw with
         Color brushColor = Color.Empty;
         if (mouseOver)
         {
            brushColor = titleForeColorHot;
            if (brushColor == Color.Empty)
            {
               brushColor = ExplorerBarHelper.BarTitleColor(
                  true, isSpecial, drawItemParams.Style, state, owner.XpTheme);
            }
         }
         else
         {
            brushColor = titleForeColor;            
            if (brushColor == Color.Empty)
            {
               brushColor = ExplorerBarHelper.BarTitleColor(
                  false, isSpecial, drawItemParams.Style, state, owner.XpTheme);
            }
         }
         Brush brush = new SolidBrush(brushColor);

         // Rectangle to draw in
         RectangleF textRectangle = new RectangleF(
            (float) rcTitle.Left, (float) rcTitle.Top, (float) rcTitle.Width,
             (float) rcTitle.Height);
         if (!multiLineTitle)
         {
            textRectangle.Y += (float) (rcTitle.Height - titleHeight);
            textRectangle.Height = (float) titleHeight;
         }
         else
         {
            textRectangle.Y += 2.0F;
            textRectangle.Height -= 4.0F;
         }
         drawItemParams.Graphics.DrawString(text, useFont, brush, 
            textRectangle, format);
         
         // Clear up
         brush.Dispose();
         format.Dispose();
         if (disposeFont)
         {
            useFont.Dispose();
         }

         return rcTitle.Height;
      }

      private void DrawBarBackground(ExplorerBarDrawItemParams drawItemParams,
       int overallTitleHeight)
      {
         // Draw the background to the bar
         int top = 0;
         if (!(expanding || collapsing))
         {
            top = drawItemParams.Top + overallTitleHeight;
         }
         Rectangle rectangle = new Rectangle(
            marginSize,
            top,
            (drawItemParams.ScrollShowing ? drawItemParams.WidthWithScroll :
             drawItemParams.WidthWithoutScroll) - marginSize * 2,
            (drawItemParams.ScrollShowing ? heightWithScroll -
             overallTitleHeight : heightWithoutScroll - overallTitleHeight)
            );
         if (expanding || collapsing)
         {
            rectangle.Height += collapseOffset;
         }

         ExplorerBarHelper.DrawBarBackground(
            drawItemParams.Graphics, 
            drawItemParams.Style,
            drawItemParams.Mode, 
            owner.XpTheme, 
            owner.Bitmaps, 
            rectangle,
            isSpecial,
            backColor, 
            backColor
            );

         if (processedWatermark != null)
         {
            DrawBarWatermark(drawItemParams, rectangle);
         }
      }

      /// <summary>
      /// Draws the watermark in a bar.
      /// </summary>
      /// <param name="drawItemParams">Object containing information needed 
      /// to draw the title</param>
      /// <param name="rectangle">Bounding rectangle of the bar part</param>
      private void DrawBarWatermark(
         ExplorerBarDrawItemParams drawItemParams,
         Rectangle rectangle
         )
      {
         rectangle.X += 2;
         rectangle.Y += 2;
         rectangle.Width -= 4;
         rectangle.Height -= 4;

         int waterMarkX = 2;
         int srcX = 0;
         int srcWidth = processedWatermark.Width;         
         switch (watermarkHAlign)
         {
            case ExplorerBarWatermarkAlignment.Near:
               if (drawItemParams.RightToLeft)
               {
                  waterMarkX = rectangle.Right - processedWatermark.Width;
                  if (waterMarkX < rectangle.Left)
                  {
                     srcX = srcWidth - rectangle.Width;
                     srcWidth = rectangle.Width;
                  }
               }
               else
               {
                  if (waterMarkX + processedWatermark.Width > rectangle.Right)
                  {
                     srcWidth = rectangle.Width;
                  }
               }
               break;
            case ExplorerBarWatermarkAlignment.Far:
               if (drawItemParams.RightToLeft)
               {
                  if (waterMarkX + processedWatermark.Width > rectangle.Width -
                   4)
                  {
                     srcWidth = rectangle.Width;
                  }
               }
               else
               {
                  waterMarkX = rectangle.Right - processedWatermark.Width;     
                                  
                  if (waterMarkX + processedWatermark.Width > rectangle.Right)
                  {
                     srcX = srcWidth - rectangle.Width;
                     srcWidth = rectangle.Width;
                  }
               }                  
               break;
            default:
               waterMarkX = rectangle.Left + (rectangle.Width -
                processedWatermark.Width) / 2;
               if (waterMarkX < 0)
               {
                  srcX = srcWidth - rectangle.Width;
                  srcWidth = rectangle.Width;
                  waterMarkX = 0;
               }
               break;
         }
         int waterMarkY = rectangle.Top;
         int srcY = 0;
         int srcHeight = processedWatermark.Height;
         switch (WatermarkVAlign)
         {
            case ExplorerBarWatermarkAlignment.Near:
               waterMarkY = rectangle.Top;
               if (waterMarkY + srcHeight > rectangle.Height)
               {
                  srcHeight = rectangle.Height;
               }
               break;
            case ExplorerBarWatermarkAlignment.Far:
               waterMarkY = rectangle.Bottom - processedWatermark.Height;
               if (waterMarkY < rectangle.Top)
               {
                  srcY = srcHeight - rectangle.Height;
                  srcHeight = rectangle.Height;
                  waterMarkY = rectangle.Top;
               }
               break;
            default:
               waterMarkY = rectangle.Top + (rectangle.Height -
                processedWatermark.Height) / 2;
               if (waterMarkY < rectangle.Top)
               {
                  srcY = srcHeight - rectangle.Height;
                  srcHeight = rectangle.Height;
                  waterMarkY = rectangle.Top;
               }
               break;
         }

         drawItemParams.Graphics.DrawImage(processedWatermark,
            new Rectangle(waterMarkX, waterMarkY, srcWidth, srcHeight),
            srcX, srcY, srcWidth, srcHeight, GraphicsUnit.Pixel);

      }
         

      /// <summary>
      /// Notifies the parent control when the Watermark changes.
      /// </summary>
      protected virtual void OnWatermarkChanged()
      {
         if (owner != null)
         {
            owner.InternalOnBarWatermarkChanged(this);
         }
      }

      /// <summary>
      /// Notifies the parent control when any aspect of the appearance of
      /// this bar changes.
      /// </summary>
      protected virtual void OnAppearanceChanged()
      {
         if (owner != null)
         {
            owner.InternalOnBarRedraw(this);
         }      
      }

      /// <summary>
      /// Notifies the parent control that the size of this bar has changed.
      /// </summary>
      protected virtual void OnSizeChanged()
      {
         if (owner != null)
         {
            owner.InternalOnBarResized(this);
         }
      }
   }
}