/*
* 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();
}
}
}
}