/* * SimpleToolBar.cs - Simple toolbar with icons and tooltips. * * Copyright (C) 2004 - 2011 Andreas Scherrer * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; namespace Level9 { /// /// Simple toolbar with icons and tooltips. /// public class SimpleToolBar : Panel { // -- Constants ------------------------------------------------------ /// /// The horizontal spacing between icons in pixels. /// const int H_SPACING = 6; /// /// The vertical spacing between component border and icons in pixels. /// const int V_SPACING = 4; /// /// The horizontal spacing between component border and icons in pixels. /// const int H_OFFSET = 6; /// /// The icon border spacing in pixels. /// const int BORDER_SPACING = 3; /// /// The width of a toolbar separator in pixels. /// const int SEPARATOR_WIDTH = 2; // -- Attributes ----------------------------------------------------- /// /// A list of toolbar buttons. /// List toolbarButtons = new List(); /// /// The number of the currently selected button. A value of -1 means /// that no button is selected. /// int selected = -1; /// /// The number of the currently pressed button. A value of -1 means that /// no button is pressed. /// int pressed = -1; /// /// The maximum height of a toolbar icon in pixels. /// int maxIconHeight = 0; /// /// The toolbar's tooltip. /// ToolTip toolTip = new ToolTip(); /// /// A grey scale matrix to display disabled toolbar buttons. /// private static float[][] greyScaleMatrix = new float[][] { new float[] { 0.2222f, 0.2222f, 0.2222f, 0.0000f, 0.0000f }, new float[] { 0.2222f, 0.2222f, 0.2222f, 0.0000f, 0.0000f }, new float[] { 0.2222f, 0.2222f, 0.2222f, 0.0000f, 0.0000f }, new float[] { 0.3333f, 0.3333f, 0.3333f, 0.7500f, 0.0000f }, new float[] { 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f } }; // -- Events --------------------------------------------------------- /// Occurs when a toolbar button has been clicked. public event ToolbarButtonClickedEventHandler ButtonClicked; // -- Constructor ---------------------------------------------------- /// /// Initializes a new instance of the SimpleToolBar class. /// public SimpleToolBar() { this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.ResizeRedraw, true); } // -- Event handling ------------------------------------------------- /// /// Handles the MouseMove event. /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); int button = GetButtonByPoint(new Point(e.X, e.Y)); if (button >= 0) { if (button != selected) { if (selected >= 0) { int prevSelected = selected; selected = button; InvalidateButton(prevSelected); InvalidateButton(selected); } else { selected = button; InvalidateButton(selected); } SimpleToolBarButton toolbarButton = toolbarButtons[button]; toolTip.SetToolTip(this, toolbarButton.ToolTip); } } else { if (pressed != -1) { InvalidateButton(pressed); } else if (selected != -1) { InvalidateButton(selected); } selected = -1; pressed = -1; toolTip.SetToolTip(this, null); } } /// /// Handles the MouseDown event. /// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); int button = GetButtonByPoint(new Point(e.X, e.Y)); if (button >= 0) { pressed = button; InvalidateButton(button); } } /// /// Handles the MouseUp event. /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); int button = GetButtonByPoint(new Point(e.X, e.Y)); if (button >= 0) { pressed = -1; SimpleToolBarButton toolbarButton = toolbarButtons[button]; if (ButtonClicked != null && toolbarButton.Enabled) { ToolbarButtonClickedEventArgs args = new ToolbarButtonClickedEventArgs( toolbarButtons[button]); ButtonClicked(this, args); } InvalidateButton(button); } } /// /// Handles the MouseLeave event. /// protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (pressed != -1) { InvalidateButton(pressed); } else if (selected != -1) { InvalidateButton(selected); } selected = -1; pressed = -1; } /// /// Handles the Paint event. /// protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics g = e.Graphics; // // Line // g.DrawLine(SystemPens.ControlDark, e.ClipRectangle.Left, 0, e.ClipRectangle.Right, 0); g.DrawLine(SystemPens.ControlLightLight, e.ClipRectangle.Left, 1, e.ClipRectangle.Right, 1); // // Buttons // for (int i = 0; i < toolbarButtons.Count; i++) { SimpleToolBarButton button = toolbarButtons[i]; Rectangle rect = GetButtonRect(i); if (!rect.IntersectsWith(e.ClipRectangle)) { continue; } if (button.IsSeparator) { g.DrawLine(SystemPens.ControlDark, rect.Left, rect.Top, rect.Left, rect.Bottom); g.DrawLine(SystemPens.ControlLightLight, rect.Left + 1, rect.Top, rect.Left + 1, rect.Bottom); } else { if (button.Enabled) { g.DrawImage(button.Image, rect.Left + BORDER_SPACING, rect.Top + BORDER_SPACING, button.Image.Width, button.Image.Height); } else { Rectangle imageRect = new Rectangle( rect.Left + BORDER_SPACING, rect.Top + BORDER_SPACING, button.Image.Width, button.Image.Height); ImageAttributes greyScale = new ImageAttributes(); greyScale.SetColorMatrix( new ColorMatrix(greyScaleMatrix)); g.DrawImage(button.Image, imageRect, 0, 0, button.Image.Width, button.Image.Height, GraphicsUnit.Pixel, greyScale); } if ((i == pressed || i == selected) && button.Enabled) { Pen pen1, pen2; if (i == pressed) { pen1 = SystemPens.ControlDark; pen2 = SystemPens.ControlLightLight; } else { pen1 = SystemPens.ControlLightLight; pen2 = SystemPens.ControlDark; } g.DrawLine(pen1, rect.Left, rect.Top, rect.Left, rect.Bottom - 1); g.DrawLine(pen1, rect.Left, rect.Top, rect.Right - 1, rect.Top); g.DrawLine(pen2, rect.Right - 1, rect.Top, rect.Right - 1, rect.Bottom - 1); g.DrawLine(pen2, rect.Left, rect.Bottom - 1, rect.Right - 1, rect.Bottom - 1); } } } } /// /// Invoked when the enabled state of a toolbar button has changed. /// /// the object that originated the event /// an EventArgs that contains the event data void ToolbarButtonEnabledChanged(SimpleToolBarButton sender, EventArgs e) { InvalidateButton(toolbarButtons.IndexOf(sender)); } // -- Methods -------------------------------------------------------- /// /// Adds a toolbar button to the toolbar. /// /// a toolbar button public void AddButton(SimpleToolBarButton toolbarButton) { bool addButton = toolbarButton != null && (toolbarButton.Image != null || toolbarButton.IsSeparator); if (addButton) { toolbarButtons.Add(toolbarButton); toolbarButton.EnabledChanged += new ToolbarButtonEnabledChangedEventHandler( ToolbarButtonEnabledChanged); if (toolbarButton.Image != null && toolbarButton.Image.Height > maxIconHeight) { maxIconHeight = toolbarButton.Image.Height; this.Height = V_SPACING * 2 + BORDER_SPACING * 2 + maxIconHeight; } } } /// /// Invalidates a toolbar button that must be redrawn. /// /// a toolbar button void InvalidateButton(int button) { this.Invalidate(GetButtonRect(button)); } /// /// Provides the button number that's associated with a point on the /// toolbar. /// /// a point on the toolbar /// the button number int GetButtonByPoint(Point point) { for (int i = 0; i < toolbarButtons.Count; i++) { Rectangle buttonRect = GetButtonRect(i); if (buttonRect.Contains(point)) { return i; } } return -1; } /// /// Provides the rectangle that's associated with a toolbar button. /// /// the button number /// a rectangle Rectangle GetButtonRect(int button) { SimpleToolBarButton toolbarButton = null; int offset = H_OFFSET; for (int i = 0; i < button; i++) { toolbarButton = toolbarButtons[i]; if (toolbarButton.IsSeparator) { offset += H_SPACING + SEPARATOR_WIDTH; } else { offset += H_SPACING + BORDER_SPACING * 2 + toolbarButton.Image.Width; } } toolbarButton = toolbarButtons[button]; int height = this.Height - 2 * V_SPACING; int width = toolbarButton.IsSeparator ? SEPARATOR_WIDTH : toolbarButton.Image.Width + 2 * BORDER_SPACING; return new Rectangle(offset, V_SPACING, width, height); } } /// /// Represents the method that handles a ToolbarButtonClicked event. /// public delegate void ToolbarButtonClickedEventHandler(Object sender, ToolbarButtonClickedEventArgs e); /// /// Provides data for the ToolbarButtonClicked event. /// public class ToolbarButtonClickedEventArgs : EventArgs { // -- Attributes ----------------------------------------------------- /// /// The toolbar button. /// SimpleToolBarButton button = null; // -- Constructors --------------------------------------------------- /// /// Initializes a new instance of the ToolbarButtonClickedEventArgs /// class. /// /// a toolbar button public ToolbarButtonClickedEventArgs(SimpleToolBarButton button) { this.button = button; } // -- Accessors ------------------------------------------------------ /// /// Gets or sets the toolbar button. /// public SimpleToolBarButton Button { get { return button; } set { button = value; } } } /// /// Represents the method that handles a ToolbarButtonEnabledChanged event. /// public delegate void ToolbarButtonEnabledChangedEventHandler( SimpleToolBarButton sender, EventArgs e); /// /// Represents a simple toolbar button. /// public class SimpleToolBarButton { // -- Attributes ----------------------------------------------------- /// /// The toolbar button's image. /// Image image = null; /// /// This property indicates whether the toolbar button acts as a /// separator. /// bool separator = false; /// /// This property indicates whether the toolbar button is enabled. /// bool enabled = true; /// /// The text of the toolbar button's tooltip. /// string toolTip = null; // -- Events --------------------------------------------------------- /// /// Occurs when the enabled state of a toolbar button has changed. /// public event ToolbarButtonEnabledChangedEventHandler EnabledChanged; // -- Constructor ---------------------------------------------------- /// /// Initializes a new instance of the SimpleToolBarButton class. /// /// the toolbar button's image /// /// the text of the toolbar button's tooltip /// public SimpleToolBarButton(Image image, string toolTip) { this.image = image; this.toolTip = toolTip; } /// /// Initializes a new instance of the SimpleToolBarButton class. /// This constructor creates toolbar button separators. /// private SimpleToolBarButton() { separator = true; } // -- Accessors ------------------------------------------------------ /// /// Gets or sets a value that indicates whether the toolbar button /// is enabled. /// public bool Enabled { get { return this.enabled; } set { this.enabled = value; if (EnabledChanged != null) { EnabledChanged(this, new EventArgs()); } } } /// /// Gets or sets the toolbar button image. /// public Image Image { get { return this.image; } set { this.image = value; } } /// /// Gets or sets the text of the toolbar button's tooltip. /// public string ToolTip { get { return this.toolTip; } set { this.toolTip = value; } } /// /// Gets or sets a value that indicates whether the toolbar button acts /// as a seperator. /// public bool IsSeparator { get { return this.separator; } set { this.separator = value; } } /// /// Creates a toolbar separator. /// public static SimpleToolBarButton Separator { get { return new SimpleToolBarButton(); } } } }