| 0: | // RichMenuItem.cs | |
| 1: | // Copyright (c) 2001 Mike Krueger | |
| 2: | // | |
| 3: | // This program is free software; you can redistribute it and/or modify | |
| 4: | // it under the terms of the GNU General Public License as published by | |
| 5: | // the Free Software Foundation; either version 2 of the License, or | |
| 6: | // (at your option) any later version. | |
| 7: | // | |
| 8: | // This program is distributed in the hope that it will be useful, | |
| 9: | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10: | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11: | // GNU General Public License for more details. | |
| 12: | // | |
| 13: | // You should have received a copy of the GNU General Public License | |
| 14: | // along with this program; if not, write to the Free Software | |
| 15: | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 16: | ||
| 17: | using System; | |
| 18: | using System.Drawing; | |
| 19: | using System.Diagnostics; | |
| 20: | using System.Drawing.Text; | |
| 21: | using System.Drawing.Imaging; | |
| 22: | using System.Windows.Forms; | |
| 23: | ||
| 24: | using SharpDevelop.Gui.Window; | |
| 25: | using SharpDevelop.Tool.Data; | |
| 26: | using SharpDevelop.Internal.ExternalTool; | |
| 27: | using SharpDevelop.Internal.Text; | |
| 28: | ||
| 29: | namespace SharpDevelop.Gui.Components { | |
| 30: | ||
| 31: | public enum IconMenuStyle { | |
| 32: | Standard, | |
| 33: | Office2000, | |
| 34: | VSNet | |
| 35: | }; | |
| 36: | ||
| 37: | public interface MenuItemStyleDrawer | |
| 38: | { | |
| 39: | void DrawCheckmark(Graphics g, Rectangle bounds, bool selected); | |
| 40: | void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked); | |
| 41: | void DrawSeparator(Graphics g, Rectangle bounds); | |
| 42: | void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon); | |
| 43: | void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut , bool enabled, bool toplevel, DrawItemState state); | |
| 44: | } | |
| 45: | ||
| 46: | public class Office2000Style : MenuItemStyleDrawer | |
| 47: | { | |
| 48: | static int TEXTSTART = 20; | |
| 49: | ||
| 50: | public void DrawCheckmark(Graphics g, Rectangle bounds, bool selected) | |
| 51: | { | |
| 52: | ControlPaint.DrawMenuGlyph(g, new Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark); | |
| 53: | } | |
| 54: | ||
| 55: | public void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked) | |
| 56: | { | |
| 57: | if (enabled) { | |
| 58: | g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2); | |
| 59: | } else | |
| 60: | ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.Control); | |
| 61: | ||
| 62: | if (selected) | |
| 63: | ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, icon.Width + 3, icon.Height + 3, Border3DStyle.RaisedInner); | |
| 64: | } | |
| 65: | ||
| 66: | public void DrawSeparator(Graphics g, Rectangle bounds) | |
| 67: | { | |
| 68: | ControlPaint.DrawBorder3D(g, bounds.X, bounds.Y + 2, bounds.Width, 3, Border3DStyle.Etched, Border3DSide.Top); | |
| 69: | } | |
| 70: | ||
| 71: | public void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon) | |
| 72: | { | |
| 73: | bool selected = (state & DrawItemState.Selected) > 0; | |
| 74: | if (selected ||((state & DrawItemState.HotLight) > 0)) { | |
| 75: | if (toplevel) { | |
| 76: | // g.FillRectangle(SystemBrushes.Highlight, bounds); | |
| 77: | ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, selected ? Border3DStyle.SunkenOuter : Border3DStyle.RaisedInner, Border3DSide.All); | |
| 78: | } else { | |
| 79: | if (hasicon) { | |
| 80: | g.FillRectangle(SystemBrushes.Menu, new Rectangle(bounds.X, bounds.Y, bounds.X + SystemInformation.SmallIconSize.Width + 5, bounds.Height)); | |
| 81: | bounds.X += SystemInformation.SmallIconSize.Width + 5; | |
| 82: | bounds.Width -= SystemInformation.SmallIconSize.Width + 5; | |
| 83: | } | |
| 84: | g.FillRectangle(SystemBrushes.Highlight, bounds); | |
| 85: | } | |
| 86: | } else { | |
| 87: | if (toplevel) { | |
| 88: | g.FillRectangle(SystemBrushes.Control, bounds); | |
| 89: | } else { | |
| 90: | g.FillRectangle(SystemBrushes.Menu, bounds); | |
| 91: | } | |
| 92: | } | |
| 93: | } | |
| 94: | ||
| 95: | public void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state) | |
| 96: | { | |
| 97: | bool selected = (state & DrawItemState.Selected) > 0; | |
| 98: | StringFormat stringformat = new StringFormat(); | |
| 99: | stringformat.HotkeyPrefix = ((state & DrawItemState.NoAccelerator) > 0) ? HotkeyPrefix.Hide : HotkeyPrefix.Show; | |
| 100: | int shortcutwidth = (int)(g.MeasureString(shortcut, SystemInformation.MenuFont).Width); | |
| 101: | int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width); | |
| 102: | int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2: bounds.Left + TEXTSTART; | |
| 103: | ||
| 104: | int y = bounds.Top + 2; | |
| 105: | if (enabled) { | |
| 106: | // normal draw | |
| 107: | Color color = (selected && !toplevel) ? Color.White : SystemColors.MenuText; | |
| 108: | g.DrawString(text, SystemInformation.MenuFont, new SolidBrush(color), x, y, stringformat); | |
| 109: | g.DrawString(shortcut, SystemInformation.MenuFont, new SolidBrush(color), bounds.Left + 130, bounds.Top + 2, stringformat); | |
| 110: | } else { | |
| 111: | // disabled menuitem draw | |
| 112: | if (!selected) { | |
| 113: | g.DrawString(text, SystemInformation.MenuFont, SystemBrushes.ControlLightLight, x + 1, y + 1, stringformat); | |
| 114: | g.DrawString(shortcut, SystemInformation.MenuFont, SystemBrushes.ControlLightLight, bounds.Right - shortcutwidth - 10 + 1, bounds.Top + 2 + 1, stringformat); | |
| 115: | } | |
| 116: | g.DrawString(text, SystemInformation.MenuFont, new SolidBrush(SystemColors.GrayText), x, y, stringformat); | |
| 117: | g.DrawString(shortcut, SystemInformation.MenuFont, new SolidBrush(SystemColors.GrayText), bounds.Right - shortcutwidth - 10, bounds.Top + 2, stringformat); | |
| 118: | } | |
| 119: | } | |
| 120: | } | |
| 121: | ||
| 122: | public class VSNetStyle : MenuItemStyleDrawer | |
| 123: | { | |
| 124: | static Color bgcolor = SystemColors.ControlLightLight; //Color.FromArgb(246, 246, 246); | |
| 125: | static Color ibgcolor = SystemColors.ControlLight; //Color.FromArgb(202, 202, 202); | |
| 126: | ||
| 127: | static Color sbcolor = Color.FromArgb(173, 173, 209); | |
| 128: | static Color sbbcolor = Color.FromArgb( 0, 0, 128); | |
| 129: | ||
| 130: | static int TEXTSTART = 20; | |
| 131: | ||
| 132: | public void DrawCheckmark(Graphics g, Rectangle bounds, bool selected) | |
| 133: | { | |
| 134: | ControlPaint.DrawMenuGlyph(g, new Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark); | |
| 135: | g.DrawRectangle(new Pen(sbbcolor), bounds.X + 1, bounds.Y + 1, 14 + 1, 14 + 1); | |
| 136: | } | |
| 137: | ||
| 138: | public void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked) | |
| 139: | { | |
| 140: | if (enabled) { | |
| 141: | if (selected) { | |
| 142: | ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, Color.Black); | |
| 143: | g.DrawImage(icon, bounds.Left + 1, bounds.Top + 1); | |
| 144: | } else { | |
| 145: | g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2); | |
| 146: | } | |
| 147: | } else | |
| 148: | ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.HighlightText); | |
| 149: | } | |
| 150: | ||
| 151: | public void DrawSeparator(Graphics g, Rectangle bounds) | |
| 152: | { | |
| 153: | int y = bounds.Y + bounds.Height / 2; | |
| 154: | g.DrawLine(new Pen(SystemColors.ControlDark), bounds.X + SystemInformation.SmallIconSize.Width + 7, y, bounds.X + bounds.Width - 2, y); | |
| 155: | } | |
| 156: | ||
| 157: | public void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon) | |
| 158: | { | |
| 159: | bool selected = (state & DrawItemState.Selected) > 0; | |
| 160: | ||
| 161: | if (selected || ((state & DrawItemState.HotLight) > 0)) { | |
| 162: | if (toplevel && selected) { // draw toplevel, selected menuitem | |
| 163: | g.FillRectangle(new SolidBrush(ibgcolor), bounds); | |
| 164: | ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.Flat, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right); | |
| 165: | } else { // draw menuitem, selected OR toplevel, hotlighted | |
| 166: | g.FillRectangle(new SolidBrush(sbcolor), bounds); | |
| 167: | g.DrawRectangle(new Pen(sbbcolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); | |
| 168: | } | |
| 169: | } else { | |
| 170: | if (!toplevel) { // draw menuitem, unselected | |
| 171: | g.FillRectangle(new SolidBrush(ibgcolor), bounds); | |
| 172: | bounds.X += 16 + 5; | |
| 173: | bounds.Width -= 16 + 5; | |
| 174: | g.FillRectangle(new SolidBrush(bgcolor), bounds); | |
| 175: | } else { | |
| 176: | // draw toplevel, unselected menuitem | |
| 177: | g.FillRectangle(SystemBrushes.Control, bounds); | |
| 178: | ||
| 179: | } | |
| 180: | } | |
| 181: | } | |
| 182: | ||
| 183: | public void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state) | |
| 184: | { | |
| 185: | StringFormat stringformat = new StringFormat(); | |
| 186: | stringformat.HotkeyPrefix = ((state & DrawItemState.NoAccelerator) > 0) ? HotkeyPrefix.Hide : HotkeyPrefix.Show; | |
| 187: | int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width); | |
| 188: | int shortcutwidth = (int)(g.MeasureString(shortcut, SystemInformation.MenuFont).Width); | |
| 189: | ||
| 190: | int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2: bounds.Left + TEXTSTART; | |
| 191: | int y = bounds.Top + 2; | |
| 192: | Brush brush = null; | |
| 193: | if (!enabled) | |
| 194: | brush = new SolidBrush(Color.FromArgb(120, SystemColors.MenuText)); | |
| 195: | else | |
| 196: | brush = new SolidBrush(SystemColors.MenuText); | |
| 197: | g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat); | |
| 198: | ||
| 199: | g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Right - shortcutwidth - 10, bounds.Top + 2, stringformat); | |
| 200: | } | |
| 201: | } | |
| 202: | ||
| 203: | public class RichMenuItem : MenuItem | |
| 204: | { | |
| 205: | string shortcuttext = ""; | |
| 206: | StringFormat stringformat = new StringFormat(); | |
| 207: | Bitmap icon = null; | |
| 208: | ||
| 209: | MenuItemStyleDrawer style = null; | |
| 210: | IconMenuStyle menustyle = IconMenuStyle.VSNet; | |
| 211: | ||
| 212: | int shortcuttextwidth; | |
| 213: | ||
| 214: | public IconMenuStyle MenuStyle { | |
| 215: | get { | |
| 216: | return menustyle; | |
| 217: | } | |
| 218: | set { | |
| 219: | switch (value) { | |
| 220: | case IconMenuStyle.Office2000: | |
| 221: | style = new Office2000Style(); | |
| 222: | OwnerDraw = true; | |
| 223: | break; | |
| 224: | case IconMenuStyle.VSNet: | |
| 225: | style = new VSNetStyle(); | |
| 226: | OwnerDraw = true; | |
| 227: | break; | |
| 228: | default: | |
| 229: | style = null; | |
| 230: | OwnerDraw = false; | |
| 231: | break; | |
| 232: | } | |
| 233: | } | |
| 234: | } | |
| 235: | ||
| 236: | public string ShortcutText { | |
| 237: | get { | |
| 238: | return shortcuttext; | |
| 239: | } | |
| 240: | set { | |
| 241: | shortcuttext = value; | |
| 242: | } | |
| 243: | } | |
| 244: | ||
| 245: | public Bitmap Icon { | |
| 246: | get { | |
| 247: | return icon; | |
| 248: | } | |
| 249: | set { | |
| 250: | icon = value; | |
| 251: | } | |
| 252: | } | |
| 253: | public RichMenuItem() | |
| 254: | { | |
| 255: | } | |
| 256: | ||
| 257: | public RichMenuItem(IconMenuStyle style, string name, EventHandler handler, Shortcut shortcut) : this(style, name, handler) | |
| 258: | { | |
| 259: | this.Shortcut = shortcut; | |
| 260: | } | |
| 261: | ||
| 262: | public RichMenuItem(IconMenuStyle style, string name, EventHandler handler) : base(name, handler) | |
| 263: | { | |
| 264: | MenuStyle = style; | |
| 265: | } | |
| 266: | ||
| 267: | public RichMenuItem(IconMenuStyle style, string name, RichMenuItem[] items) : base(name, items) | |
| 268: | { | |
| 269: | MenuStyle = style; | |
| 270: | } | |
| 271: | ||
| 272: | // public override MenuItem CloneMenu() | |
| 273: | // { | |
| 274: | // return (MenuItem)MemberwiseClone(); | |
| 275: | // } | |
| 276: | ||
| 277: | protected override void OnMeasureItem(MeasureItemEventArgs e) | |
| 278: | { | |
| 279: | base.OnMeasureItem(e); | |
| 280: | ||
| 281: | // make shortcut text | |
| 282: | if (Shortcut != Shortcut.None) { | |
| 283: | Keys k = (Keys)Shortcut; | |
| 284: | shortcuttext = System.ComponentModel.TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString(k); | |
| 285: | // string text = ""; | |
| 286: | // int key = (int)Shortcut; | |
| 287: | // int ch = key & 0xFF; | |
| 288: | // if (((int)Keys.Control & key) > 0) | |
| 289: | // text += "Ctrl+"; | |
| 290: | // if (((int)Keys.Shift & key) > 0) | |
| 291: | // text += "Shift+"; | |
| 292: | // if (((int)Keys.Alt & key) > 0) | |
| 293: | // text += "Alt+"; | |
| 294: | // | |
| 295: | // if (ch >= (int)Shortcut.F1 && ch <= (int)Shortcut.F12) | |
| 296: | // text += "F" + (ch - (int)Shortcut.F1 + 1); | |
| 297: | // else | |
| 298: | // text += (char)ch; | |
| 299: | // shortcuttext = text; | |
| 300: | } | |
| 301: | ||
| 302: | if (menustyle != IconMenuStyle.Standard) { | |
| 303: | if (Text == "-") { | |
| 304: | e.ItemHeight = 8; | |
| 305: | e.ItemWidth = 4; | |
| 306: | return; | |
| 307: | } | |
| 308: | int textwidth = (int)(e.Graphics.MeasureString(Text, SystemInformation.MenuFont).Width); | |
| 309: | shortcuttextwidth = (int)( |