From d40fed5ce2bc806a91245adb18039634eac13ed0 Mon Sep 17 00:00:00 2001 From: MichaelTheShifter Date: Wed, 20 Jul 2016 09:40:36 -0400 Subject: Move ShiftUI source code to ShiftOS This'll be a lot easier to work on. --- source/ShiftUI/Theming/Default/.gitattributes | 5 + source/ShiftUI/Theming/Default/ButtonPainter.cs | 189 ++++++++ source/ShiftUI/Theming/Default/CheckBoxPainter.cs | 357 +++++++++++++++ source/ShiftUI/Theming/Default/LabelPainter.cs | 57 +++ source/ShiftUI/Theming/Default/LinkLabelPainter.cs | 120 +++++ .../ShiftUI/Theming/Default/RadioButtonPainter.cs | 239 ++++++++++ .../ShiftUI/Theming/Default/TabControlPainter.cs | 507 +++++++++++++++++++++ source/ShiftUI/Theming/Default/ToolStripPainter.cs | 189 ++++++++ 8 files changed, 1663 insertions(+) create mode 100644 source/ShiftUI/Theming/Default/.gitattributes create mode 100644 source/ShiftUI/Theming/Default/ButtonPainter.cs create mode 100644 source/ShiftUI/Theming/Default/CheckBoxPainter.cs create mode 100644 source/ShiftUI/Theming/Default/LabelPainter.cs create mode 100644 source/ShiftUI/Theming/Default/LinkLabelPainter.cs create mode 100644 source/ShiftUI/Theming/Default/RadioButtonPainter.cs create mode 100644 source/ShiftUI/Theming/Default/TabControlPainter.cs create mode 100644 source/ShiftUI/Theming/Default/ToolStripPainter.cs (limited to 'source/ShiftUI/Theming/Default') diff --git a/source/ShiftUI/Theming/Default/.gitattributes b/source/ShiftUI/Theming/Default/.gitattributes new file mode 100644 index 0000000..fdf3545 --- /dev/null +++ b/source/ShiftUI/Theming/Default/.gitattributes @@ -0,0 +1,5 @@ +/ButtonPainter.cs -crlf +/CheckBoxPainter.cs -crlf +/RadioButtonPainter.cs -crlf +/TabWidgetPainter.cs -crlf +/ToolStripPainter.cs -crlf diff --git a/source/ShiftUI/Theming/Default/ButtonPainter.cs b/source/ShiftUI/Theming/Default/ButtonPainter.cs new file mode 100644 index 0000000..366b17d --- /dev/null +++ b/source/ShiftUI/Theming/Default/ButtonPainter.cs @@ -0,0 +1,189 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Andreia Gaita (avidigal@novell.com) + +using System; +using System.Drawing; + +namespace ShiftUI.Theming.Default +{ + /// + /// Summary description for Button. + /// + internal class ButtonPainter + { + public ButtonPainter () + { + + } + + protected SystemResPool ResPool { get { return ThemeEngine.Current.ResPool; } } + + #region Buttons + #region Standard Button + public virtual void Draw (Graphics g, Rectangle bounds, ButtonThemeState state, Color backColor, Color foreColor) { + bool is_themecolor = backColor.ToArgb () == ThemeEngine.Current.ColorControl.ToArgb () || backColor == Color.Empty ? true : false; + CPColor cpcolor = is_themecolor ? CPColor.Empty : ResPool.GetCPColor (backColor); + Pen pen; + + switch (state) { + case ButtonThemeState.Normal: + case ButtonThemeState.Entered: + case ButtonThemeState.Disabled: + pen = is_themecolor ? SystemPens.ControlLightLight : ResPool.GetPen (cpcolor.LightLight); + g.DrawLine (pen, bounds.X, bounds.Y, bounds.X, bounds.Bottom - 2); + g.DrawLine (pen, bounds.X + 1, bounds.Y, bounds.Right - 2, bounds.Y); + + pen = is_themecolor ? SystemPens.Control : ResPool.GetPen (backColor); + g.DrawLine (pen, bounds.X + 1, bounds.Y + 1, bounds.X + 1, bounds.Bottom - 3); + g.DrawLine (pen, bounds.X + 2, bounds.Y + 1, bounds.Right - 3, bounds.Y + 1); + + pen = is_themecolor ? SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark); + g.DrawLine (pen, bounds.X + 1, bounds.Bottom - 2, bounds.Right - 2, bounds.Bottom - 2); + g.DrawLine (pen, bounds.Right - 2, bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 3); + + pen = is_themecolor ? SystemPens.ControlDarkDark : ResPool.GetPen (cpcolor.DarkDark); + g.DrawLine (pen, bounds.X, bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1); + g.DrawLine (pen, bounds.Right - 1, bounds.Y, bounds.Right - 1, bounds.Bottom - 2); + break; + case ButtonThemeState.Pressed: + g.DrawRectangle (ResPool.GetPen (foreColor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + + bounds.Inflate (-1, -1); + pen = is_themecolor ? SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark); + g.DrawRectangle (pen, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + break; + case ButtonThemeState.Default: + g.DrawRectangle (ResPool.GetPen (foreColor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + + bounds.Inflate (-1, -1); + pen = is_themecolor ? SystemPens.ControlLightLight : ResPool.GetPen (cpcolor.LightLight); + g.DrawLine (pen, bounds.X, bounds.Y, bounds.X, bounds.Bottom - 2); + g.DrawLine (pen, bounds.X + 1, bounds.Y, bounds.Right - 2, bounds.Y); + + pen = is_themecolor ? SystemPens.Control : ResPool.GetPen (backColor); + g.DrawLine (pen, bounds.X + 1, bounds.Y + 1, bounds.X + 1, bounds.Bottom - 3); + g.DrawLine (pen, bounds.X + 2, bounds.Y + 1, bounds.Right - 3, bounds.Y + 1); + + pen = is_themecolor ? SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark); + g.DrawLine (pen, bounds.X + 1, bounds.Bottom - 2, bounds.Right - 2, bounds.Bottom - 2); + g.DrawLine (pen, bounds.Right - 2, bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 3); + + pen = is_themecolor ? SystemPens.ControlDarkDark : ResPool.GetPen (cpcolor.DarkDark); + g.DrawLine (pen, bounds.X, bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1); + g.DrawLine (pen, bounds.Right - 1, bounds.Y, bounds.Right - 1, bounds.Bottom - 2); + break; + } + } + #endregion + + #region FlatStyle Button + public virtual void DrawFlat (Graphics g, Rectangle bounds, ButtonThemeState state, Color backColor, Color foreColor, FlatButtonAppearance appearance) { + bool is_themecolor = backColor.ToArgb () == ThemeEngine.Current.ColorControl.ToArgb () || backColor == Color.Empty ? true : false; + CPColor cpcolor = is_themecolor ? CPColor.Empty : ResPool.GetCPColor (backColor); + Pen pen; + + switch (state) { + case ButtonThemeState.Normal: + case ButtonThemeState.Disabled: + // This will just use the BackColor + break; + case ButtonThemeState.Entered: + case ButtonThemeState.Default | ButtonThemeState.Entered: + if (appearance.MouseOverBackColor != Color.Empty) + g.FillRectangle (ResPool.GetSolidBrush (appearance.MouseOverBackColor), bounds); + else + g.FillRectangle (ResPool.GetSolidBrush (ChangeIntensity (backColor, .9F)), bounds); + break; + case ButtonThemeState.Pressed: + if (appearance.MouseDownBackColor != Color.Empty) + g.FillRectangle (ResPool.GetSolidBrush (appearance.MouseDownBackColor), bounds); + else + g.FillRectangle (ResPool.GetSolidBrush (ChangeIntensity (backColor, .95F)), bounds); + break; + case ButtonThemeState.Default: + if (appearance.CheckedBackColor != Color.Empty) + g.FillRectangle (ResPool.GetSolidBrush (appearance.CheckedBackColor), bounds); + break; + } + + if (appearance.BorderColor == Color.Empty) + pen = is_themecolor ? SystemPens.ControlDarkDark : ResPool.GetSizedPen (cpcolor.DarkDark, appearance.BorderSize); + else + pen = ResPool.GetSizedPen (appearance.BorderColor, appearance.BorderSize); + + bounds.Width -= 1; + bounds.Height -= 1; + + if (appearance.BorderSize > 0) + g.DrawRectangle (pen, bounds); + } + #endregion + + #region Popup Button + public virtual void DrawPopup (Graphics g, Rectangle bounds, ButtonThemeState state, Color backColor, Color foreColor) { + bool is_themecolor = backColor.ToArgb () == ThemeEngine.Current.ColorControl.ToArgb () || backColor == Color.Empty ? true : false; + CPColor cpcolor = is_themecolor ? CPColor.Empty : ResPool.GetCPColor (backColor); + Pen pen; + + switch (state) { + case ButtonThemeState.Normal: + case ButtonThemeState.Disabled: + case ButtonThemeState.Pressed: + case ButtonThemeState.Default: + pen = is_themecolor ? SystemPens.ControlDarkDark : ResPool.GetPen (cpcolor.DarkDark); + + bounds.Width -= 1; + bounds.Height -= 1; + g.DrawRectangle (pen, bounds); + + if (state == ButtonThemeState.Default || state == ButtonThemeState.Pressed) { + bounds.Inflate (-1, -1); + g.DrawRectangle (pen, bounds); + } + break; + case ButtonThemeState.Entered: + pen = is_themecolor ? SystemPens.ControlLightLight : ResPool.GetPen (cpcolor.LightLight); + g.DrawLine (pen, bounds.X, bounds.Y, bounds.X, bounds.Bottom - 2); + g.DrawLine (pen, bounds.X + 1, bounds.Y, bounds.Right - 2, bounds.Y); + + pen = is_themecolor ? SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark); + g.DrawLine (pen, bounds.X, bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1); + g.DrawLine (pen, bounds.Right - 1, bounds.Y, bounds.Right - 1, bounds.Bottom - 2); + break; + } + } + #endregion + #endregion + + private static Color ChangeIntensity (Color baseColor, float percent) + { + int H, I, S; + + WidgetPaint.Color2HBS (baseColor, out H, out I, out S); + int NewIntensity = Math.Min (255, (int)(I * percent)); + + return WidgetPaint.HBS2Color (H, NewIntensity, S); + } + } +} diff --git a/source/ShiftUI/Theming/Default/CheckBoxPainter.cs b/source/ShiftUI/Theming/Default/CheckBoxPainter.cs new file mode 100644 index 0000000..a759fbf --- /dev/null +++ b/source/ShiftUI/Theming/Default/CheckBoxPainter.cs @@ -0,0 +1,357 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Jonathan Pobst (monkey@jpobst.com) + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Theming.Default +{ + /// + /// Summary description for Button. + /// + internal class CheckBoxPainter + { + public CheckBoxPainter () + { + } + + protected SystemResPool ResPool { get { return ThemeEngine.Current.ResPool; } } + + public void PaintCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, ElementState state, FlatStyle style, CheckState checkState) + { + switch (style) { + case FlatStyle.Standard: + case FlatStyle.System: + switch (state) { + case ElementState.Normal: + DrawNormalCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Hot: + DrawHotCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Pressed: + DrawPressedCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Disabled: + DrawDisabledCheckBox (g, bounds, backColor, foreColor, checkState); + break; + } + break; + case FlatStyle.Flat: + switch (state) { + case ElementState.Normal: + DrawFlatNormalCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Hot: + DrawFlatHotCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Pressed: + DrawFlatPressedCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Disabled: + DrawFlatDisabledCheckBox (g, bounds, backColor, foreColor, checkState); + break; + } + break; + case FlatStyle.Popup: + switch (state) { + case ElementState.Normal: + DrawPopupNormalCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Hot: + DrawPopupHotCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Pressed: + DrawPopupPressedCheckBox (g, bounds, backColor, foreColor, checkState); + break; + case ElementState.Disabled: + DrawPopupDisabledCheckBox (g, bounds, backColor, foreColor, checkState); + break; + } + break; + } + } + + #region Standard + public virtual void DrawNormalCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + int check_box_visible_size = (bounds.Height > bounds.Width) ? bounds.Width : bounds.Height; + int x_pos = Math.Max (0, bounds.X + (bounds.Width / 2) - check_box_visible_size / 2); + int y_pos = Math.Max (0, bounds.Y + (bounds.Height / 2) - check_box_visible_size / 2); + + Rectangle rect = new Rectangle (x_pos, y_pos, check_box_visible_size, check_box_visible_size); + + g.FillRectangle (SystemBrushes.ControlLightLight, rect.X + 2, rect.Y + 2, rect.Width - 3, rect.Height - 3); + + Pen pen = SystemPens.ControlDark; + g.DrawLine (pen, rect.X, rect.Y, rect.X, rect.Bottom - 2); + g.DrawLine (pen, rect.X + 1, rect.Y, rect.Right - 2, rect.Y); + + pen = SystemPens.ControlDarkDark; + g.DrawLine (pen, rect.X + 1, rect.Y + 1, rect.X + 1, rect.Bottom - 3); + g.DrawLine (pen, rect.X + 2, rect.Y + 1, rect.Right - 3, rect.Y + 1); + + pen = SystemPens.ControlLightLight; + g.DrawLine (pen, rect.Right - 1, rect.Y, rect.Right - 1, rect.Bottom - 1); + g.DrawLine (pen, rect.X, rect.Bottom - 1, rect.Right - 1, rect.Bottom - 1); + + // oh boy, matching ms is like fighting against windmills + using (Pen h_pen = new Pen (ResPool.GetHatchBrush (HatchStyle.Percent50, + Color.FromArgb (Clamp (ColorControl.R + 3, 0, 255), + ColorControl.G, ColorControl.B), ColorControl))) { + g.DrawLine (h_pen, rect.X + 1, rect.Bottom - 2, rect.Right - 2, rect.Bottom - 2); + g.DrawLine (h_pen, rect.Right - 2, rect.Y + 1, rect.Right - 2, rect.Bottom - 2); + } + + if (state == CheckState.Checked) + DrawCheck (g, bounds, Color.Black); + else if (state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDark); + } + + public virtual void DrawHotCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + DrawNormalCheckBox (g, bounds, backColor, foreColor, state); + } + + public virtual void DrawPressedCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + int check_box_visible_size = (bounds.Height > bounds.Width) ? bounds.Width : bounds.Height; + int x_pos = Math.Max (0, bounds.X + (bounds.Width / 2) - check_box_visible_size / 2); + int y_pos = Math.Max (0, bounds.Y + (bounds.Height / 2) - check_box_visible_size / 2); + + Rectangle rect = new Rectangle (x_pos, y_pos, check_box_visible_size, check_box_visible_size); + + g.FillRectangle (ResPool.GetHatchBrush (HatchStyle.Percent50, + Color.FromArgb (Clamp (ColorControl.R + 3, 0, 255), + ColorControl.G, ColorControl.B), + ColorControl), rect.X + 2, rect.Y + 2, rect.Width - 3, rect.Height - 3); + + Pen pen = SystemPens.ControlDark; + g.DrawLine (pen, rect.X, rect.Y, rect.X, rect.Bottom - 2); + g.DrawLine (pen, rect.X + 1, rect.Y, rect.Right - 2, rect.Y); + + pen = SystemPens.ControlDarkDark; + g.DrawLine (pen, rect.X + 1, rect.Y + 1, rect.X + 1, rect.Bottom - 3); + g.DrawLine (pen, rect.X + 2, rect.Y + 1, rect.Right - 3, rect.Y + 1); + + pen = SystemPens.ControlLightLight; + g.DrawLine (pen, rect.Right - 1, rect.Y, rect.Right - 1, rect.Bottom - 1); + g.DrawLine (pen, rect.X, rect.Bottom - 1, rect.Right - 1, rect.Bottom - 1); + + // oh boy, matching ms is like fighting against windmills + using (Pen h_pen = new Pen (ResPool.GetHatchBrush (HatchStyle.Percent50, + Color.FromArgb (Clamp (ColorControl.R + 3, 0, 255), + ColorControl.G, ColorControl.B), ColorControl))) { + g.DrawLine (h_pen, rect.X + 1, rect.Bottom - 2, rect.Right - 2, rect.Bottom - 2); + g.DrawLine (h_pen, rect.Right - 2, rect.Y + 1, rect.Right - 2, rect.Bottom - 2); + } + + if (state == CheckState.Checked) + DrawCheck (g, bounds, Color.Black); + else if (state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawDisabledCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + DrawPressedCheckBox (g, bounds, backColor, foreColor, CheckState.Unchecked); + + if (state == CheckState.Checked || state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDark); + } + #endregion + + #region FlatStyle + public virtual void DrawFlatNormalCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + Rectangle checkbox_rectangle; + Rectangle fill_rectangle; + + // set up our rectangles first + // clip two pixels from bottom right for non popup rendered checkboxes + checkbox_rectangle = new Rectangle (bounds.X, bounds.Y, Math.Max (bounds.Width - 2, 0), Math.Max (bounds.Height - 2, 0)); + fill_rectangle = new Rectangle (checkbox_rectangle.X + 1, checkbox_rectangle.Y + 1, Math.Max (checkbox_rectangle.Width - 2, 0), Math.Max (checkbox_rectangle.Height - 2, 0)); + + g.FillRectangle (ResPool.GetSolidBrush (WidgetPaint.LightLight (backColor)), fill_rectangle); + WidgetPaint.DrawBorder (g, checkbox_rectangle, foreColor, ButtonBorderStyle.Solid); + + bounds.Offset (-1, 0); + + if (state == CheckState.Checked) + DrawCheck (g, bounds, Color.Black); + else if (state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawFlatHotCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + Rectangle checkbox_rectangle; + Rectangle fill_rectangle; + + // set up our rectangles first + // clip two pixels from bottom right for non popup rendered checkboxes + checkbox_rectangle = new Rectangle (bounds.X, bounds.Y, Math.Max (bounds.Width - 2, 0), Math.Max (bounds.Height - 2, 0)); + fill_rectangle = new Rectangle (checkbox_rectangle.X + 1, checkbox_rectangle.Y + 1, Math.Max (checkbox_rectangle.Width - 2, 0), Math.Max (checkbox_rectangle.Height - 2, 0)); + + g.FillRectangle (ResPool.GetSolidBrush (backColor), fill_rectangle); + WidgetPaint.DrawBorder (g, checkbox_rectangle, foreColor, ButtonBorderStyle.Solid); + + bounds.Offset (-1, 0); + + if (state == CheckState.Checked) + DrawCheck (g, bounds, Color.Black); + else if (state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawFlatPressedCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + DrawFlatNormalCheckBox (g, bounds, backColor, foreColor, state); + } + + public virtual void DrawFlatDisabledCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + Rectangle checkbox_rectangle; + + checkbox_rectangle = new Rectangle (bounds.X, bounds.Y, Math.Max (bounds.Width - 2, 0), Math.Max (bounds.Height - 2, 0)); + + WidgetPaint.DrawBorder (g, checkbox_rectangle, foreColor, ButtonBorderStyle.Solid); + + bounds.Offset (-1, 0); + + if (state == CheckState.Checked || state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDarkDark); + } + #endregion + + #region Popup + public virtual void DrawPopupNormalCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + DrawFlatNormalCheckBox (g, bounds, backColor, foreColor, state); + } + + public virtual void DrawPopupHotCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + Rectangle checkbox_rectangle; + Rectangle fill_rectangle; + + // clip one pixel from bottom right for non popup rendered checkboxes + checkbox_rectangle = new Rectangle (bounds.X, bounds.Y, Math.Max (bounds.Width - 1, 0), Math.Max (bounds.Height - 1, 0)); + fill_rectangle = new Rectangle (checkbox_rectangle.X + 1, checkbox_rectangle.Y + 1, Math.Max (checkbox_rectangle.Width - 3, 0), Math.Max (checkbox_rectangle.Height - 3, 0)); + + g.FillRectangle (ResPool.GetSolidBrush (WidgetPaint.LightLight (backColor)), fill_rectangle); + + // draw sunken effect + ThemeEngine.Current.CPDrawBorder3D (g, checkbox_rectangle, Border3DStyle.SunkenInner, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom, backColor); + + bounds.Offset (-1, 0); + + if (state == CheckState.Checked) + DrawCheck (g, bounds, Color.Black); + else if (state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawPopupPressedCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + Rectangle checkbox_rectangle; + Rectangle fill_rectangle; + + // clip one pixel from bottom right for non popup rendered checkboxes + checkbox_rectangle = new Rectangle (bounds.X, bounds.Y, Math.Max (bounds.Width - 1, 0), Math.Max (bounds.Height - 1, 0)); + fill_rectangle = new Rectangle (checkbox_rectangle.X + 1, checkbox_rectangle.Y + 1, Math.Max (checkbox_rectangle.Width - 3, 0), Math.Max (checkbox_rectangle.Height - 3, 0)); + + g.FillRectangle (ResPool.GetSolidBrush (backColor), fill_rectangle); + + // draw sunken effect + ThemeEngine.Current.CPDrawBorder3D (g, checkbox_rectangle, Border3DStyle.SunkenInner, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom, backColor); + + bounds.Offset (-1, 0); + + if (state == CheckState.Checked) + DrawCheck (g, bounds, Color.Black); + else if (state == CheckState.Indeterminate) + DrawCheck (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawPopupDisabledCheckBox (Graphics g, Rectangle bounds, Color backColor, Color foreColor, CheckState state) + { + DrawFlatDisabledCheckBox (g, bounds, backColor, foreColor, state); + } + #endregion + + #region Check + public virtual void DrawCheck (Graphics g, Rectangle bounds, Color checkColor) + { + int check_size = (bounds.Height > bounds.Width) ? bounds.Width / 2 : bounds.Height / 2; + + Pen check_pen = ResPool.GetPen (checkColor); + + if (check_size < 7) { + int lineWidth = Math.Max (3, check_size / 3); + int Scale = Math.Max (1, check_size / 9); + + Rectangle rect = new Rectangle (bounds.X + (bounds.Width / 2) - (check_size / 2) - 1, bounds.Y + (bounds.Height / 2) - (check_size / 2) - 1, + check_size, check_size); + + for (int i = 0; i < lineWidth; i++) { + g.DrawLine (check_pen, rect.Left + lineWidth / 2, rect.Top + lineWidth + i, rect.Left + lineWidth / 2 + 2 * Scale, rect.Top + lineWidth + 2 * Scale + i); + g.DrawLine (check_pen, rect.Left + lineWidth / 2 + 2 * Scale, rect.Top + lineWidth + 2 * Scale + i, rect.Left + lineWidth / 2 + 6 * Scale, rect.Top + lineWidth - 2 * Scale + i); + } + } else { + int lineWidth = Math.Max (3, check_size / 3) + 1; + + int x_half = bounds.Width / 2; + int y_half = bounds.Height / 2; + + Rectangle rect = new Rectangle (bounds.X + x_half - (check_size / 2) - 1, bounds.Y + y_half - (check_size / 2), + check_size, check_size); + + int gradient_left = check_size / 3; + int gradient_right = check_size - gradient_left - 1; + + for (int i = 0; i < lineWidth; i++) { + g.DrawLine (check_pen, rect.X, rect.Bottom - 1 - gradient_left - i, rect.X + gradient_left, rect.Bottom - 1 - i); + g.DrawLine (check_pen, rect.X + gradient_left, rect.Bottom - 1 - i, rect.Right - 1, rect.Bottom - i - 1 - gradient_right); + } + } + } + #endregion + + #region Private Methods + private int Clamp (int value, int lower, int upper) + { + if (value < lower) return lower; + else if (value > upper) return upper; + else return value; + } + + private Color ColorControl { + get { return SystemColors.Control; } + } + #endregion + } +} diff --git a/source/ShiftUI/Theming/Default/LabelPainter.cs b/source/ShiftUI/Theming/Default/LabelPainter.cs new file mode 100644 index 0000000..15ca995 --- /dev/null +++ b/source/ShiftUI/Theming/Default/LabelPainter.cs @@ -0,0 +1,57 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Everaldo Canuto (ecanuto@novell.com) + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Theming.Default +{ + internal class LabelPainter + { + public LabelPainter () + { + } + + public virtual void Draw (Graphics dc, Rectangle client_rectangle, Label label) + { + Rectangle rect = label.PaddingClientRectangle; + + label.DrawImage (dc, label.Image, rect, label.ImageAlign); + + if (label.Enabled) { + dc.DrawString (label.Text, label.Font, + ThemeEngine.Current.ResPool.GetSolidBrush (label.ForeColor), + rect, label.string_format); + } else { + WidgetPaint.DrawStringDisabled ( + dc, label.Text, label.Font, label.BackColor, rect, label.string_format); + } + } + + public virtual Size DefaultSize { + get { return new Size (100, 23); } + } + } +} \ No newline at end of file diff --git a/source/ShiftUI/Theming/Default/LinkLabelPainter.cs b/source/ShiftUI/Theming/Default/LinkLabelPainter.cs new file mode 100644 index 0000000..6ac39a0 --- /dev/null +++ b/source/ShiftUI/Theming/Default/LinkLabelPainter.cs @@ -0,0 +1,120 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Everaldo Canuto (ecanuto@novell.com) + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Theming.Default +{ + internal class LinkLabelPainter + { + public LinkLabelPainter () + { + } + + private Color GetPieceColor (LinkLabel label, LinkLabel.Piece piece, int i) + { + if (!label.Enabled) + return label.DisabledLinkColor; + + if (piece.link == null) + return label.ForeColor; + + if (!piece.link.Enabled) + return label.DisabledLinkColor; + + if (piece.link.Active) + return label.ActiveLinkColor; + + if ((label.LinkVisited && i == 0) || piece.link.Visited) + return label.VisitedLinkColor; + + return label.LinkColor; + } + + public virtual void Draw (Graphics dc, Rectangle clip_rectangle, LinkLabel label) + { + Rectangle client_rect = label.PaddingClientRectangle; + + label.DrawImage (dc, label.Image, client_rect, label.ImageAlign); + + if (label.pieces == null) + return; + + // Paint all text as disabled. + if (!label.Enabled) { + dc.SetClip (clip_rectangle); + ThemeEngine.Current.CPDrawStringDisabled ( + dc, label.Text, label.Font, label.BackColor, client_rect, label.string_format); + return; + } + + Font font, link_font = ThemeEngine.Current.GetLinkFont (label); + + Region text_region = new Region (new Rectangle()); + + // Draw links. + for (int i = 0; i < label.pieces.Length; i ++) { + LinkLabel.Piece piece = label.pieces[i]; + + if (piece.link == null) { + text_region.Union (piece.region); + continue; + } + + Color color = GetPieceColor (label, piece, i); + + if ( (label.LinkBehavior == LinkBehavior.AlwaysUnderline) || + (label.LinkBehavior == LinkBehavior.SystemDefault) || + ((label.LinkBehavior == LinkBehavior.HoverUnderline) && piece.link.Hovered) ) + font = link_font; + else + font = label.Font; + + dc.Clip = piece.region; + dc.Clip.Intersect (clip_rectangle); + dc.DrawString (label.Text, font, + ThemeEngine.Current.ResPool.GetSolidBrush (color), + client_rect, label.string_format); + + // Draw focus rectangle + if ((piece.link != null) && piece.link.Focused) { + foreach (RectangleF rect in piece.region.GetRegionScans (dc.Transform)) + WidgetPaint.DrawFocusRectangle (dc, Rectangle.Round (rect), label.ForeColor, label.BackColor); + } + } + + // Draw normal text (without links). + if (!text_region.IsEmpty (dc)) { + dc.Clip = text_region; + dc.Clip.Intersect (clip_rectangle); + if (!dc.Clip.IsEmpty (dc)) + dc.DrawString(label.Text, label.Font, + ThemeEngine.Current.ResPool.GetSolidBrush(label.ForeColor), + client_rect, label.string_format); + } + } + } +} \ No newline at end of file diff --git a/source/ShiftUI/Theming/Default/RadioButtonPainter.cs b/source/ShiftUI/Theming/Default/RadioButtonPainter.cs new file mode 100644 index 0000000..83885ed --- /dev/null +++ b/source/ShiftUI/Theming/Default/RadioButtonPainter.cs @@ -0,0 +1,239 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Jonathan Pobst (monkey@jpobst.com) + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Theming.Default +{ + /// + /// Summary description for Button. + /// + internal class RadioButtonPainter + { + public RadioButtonPainter () + { + } + + protected SystemResPool ResPool { get { return ThemeEngine.Current.ResPool; } } + + public void PaintRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, ElementState state, FlatStyle style, bool isChecked) + { + switch (style) { + case FlatStyle.Standard: + case FlatStyle.System: + switch (state) { + case ElementState.Normal: + DrawNormalRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Hot: + DrawHotRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Pressed: + DrawPressedRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Disabled: + DrawDisabledRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + } + break; + case FlatStyle.Flat: + switch (state) { + case ElementState.Normal: + DrawFlatNormalRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Hot: + DrawFlatHotRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Pressed: + DrawFlatPressedRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Disabled: + DrawFlatDisabledRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + } + break; + case FlatStyle.Popup: + switch (state) { + case ElementState.Normal: + DrawPopupNormalRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Hot: + DrawPopupHotRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Pressed: + DrawPopupPressedRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + case ElementState.Disabled: + DrawPopupDisabledRadioButton (g, bounds, backColor, foreColor, isChecked); + break; + } + break; + } + } + + #region Standard + public virtual void DrawNormalRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + ButtonState bs = ButtonState.Normal; + + if (isChecked) + bs |= ButtonState.Checked; + + WidgetPaint.DrawRadioButton (g, bounds, bs); + } + + public virtual void DrawHotRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + DrawNormalRadioButton (g, bounds, backColor, foreColor, isChecked); + } + + public virtual void DrawPressedRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + ButtonState bs = ButtonState.Pushed; + + if (isChecked) + bs |= ButtonState.Checked; + + WidgetPaint.DrawRadioButton (g, bounds, bs); + } + + public virtual void DrawDisabledRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + ButtonState bs = ButtonState.Inactive; + + if (isChecked) + bs |= ButtonState.Checked; + + WidgetPaint.DrawRadioButton (g, bounds, bs); + } + #endregion + + #region FlatStyle + public virtual void DrawFlatNormalRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.DrawArc (SystemPens.ControlDarkDark, bounds, 0, 359); + g.FillPie (SystemBrushes.ControlLightLight, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawFlatHotRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.DrawArc (SystemPens.ControlDarkDark, bounds, 0, 359); + g.FillPie (SystemBrushes.ControlLight, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawFlatPressedRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.DrawArc (SystemPens.ControlDarkDark, bounds, 0, 359); + g.FillPie (SystemBrushes.ControlLightLight, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawFlatDisabledRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.FillPie (SystemBrushes.Control, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + g.DrawArc (SystemPens.ControlDark, bounds, 0, 359); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDark); + } + #endregion + + #region Popup + public virtual void DrawPopupNormalRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.FillPie (SystemBrushes.ControlLightLight, bounds, 0, 359); + g.DrawArc (SystemPens.ControlDark, bounds, 0, 359); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawPopupHotRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.FillPie (SystemBrushes.ControlLightLight, bounds, 0, 359); + g.DrawArc (SystemPens.ControlLight, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + + g.DrawArc (SystemPens.ControlDark, bounds, 135, 180); + g.DrawArc (SystemPens.ControlLightLight, bounds, 315, 180); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawPopupPressedRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.FillPie (SystemBrushes.ControlLightLight, bounds, 0, 359); + g.DrawArc (SystemPens.ControlLight, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + + g.DrawArc (SystemPens.ControlDark, bounds, 135, 180); + g.DrawArc (SystemPens.ControlLightLight, bounds, 315, 180); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + + public virtual void DrawPopupDisabledRadioButton (Graphics g, Rectangle bounds, Color backColor, Color foreColor, bool isChecked) + { + g.FillPie (SystemBrushes.Control, bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2, 0, 359); + g.DrawArc (SystemPens.ControlDark, bounds, 0, 359); + + if (isChecked) + DrawFlatRadioGlyphDot (g, bounds, SystemColors.ControlDarkDark); + } + #endregion + + #region Glyph + protected void DrawFlatRadioGlyphDot (Graphics g, Rectangle bounds, Color dotColor) + { + int lineWidth = Math.Max (1, Math.Min (bounds.Width, bounds.Height) / 3); + + Pen dot_pen = ResPool.GetPen (dotColor); + Brush dot_brush = ResPool.GetSolidBrush (dotColor); + + if (bounds.Height > 13) { + g.FillPie (dot_brush, bounds.X + lineWidth, bounds.Y + lineWidth, bounds.Width - lineWidth * 2, bounds.Height - lineWidth * 2, 0, 359); + } else { + int x_half_pos = (bounds.Width / 2) + bounds.X; + int y_half_pos = (bounds.Height / 2) + bounds.Y; + + g.DrawLine (dot_pen, x_half_pos - 1, y_half_pos, x_half_pos + 2, y_half_pos); + g.DrawLine (dot_pen, x_half_pos - 1, y_half_pos + 1, x_half_pos + 2, y_half_pos + 1); + + g.DrawLine (dot_pen, x_half_pos, y_half_pos - 1, x_half_pos, y_half_pos + 2); + g.DrawLine (dot_pen, x_half_pos + 1, y_half_pos - 1, x_half_pos + 1, y_half_pos + 2); + } + } + #endregion + } +} diff --git a/source/ShiftUI/Theming/Default/TabControlPainter.cs b/source/ShiftUI/Theming/Default/TabControlPainter.cs new file mode 100644 index 0000000..2ecdacd --- /dev/null +++ b/source/ShiftUI/Theming/Default/TabControlPainter.cs @@ -0,0 +1,507 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Andreia Gaita (avidigal@novell.com) + +using System; +using System.Drawing; +using System.Drawing.Text; +using ShiftUI; +using ShiftUI.VisualStyles; + +namespace ShiftUI.Theming.Default +{ + /// + /// Summary description for TabWidget. + /// + internal class TabWidgetPainter { + protected SystemResPool ResPool { get { return ThemeEngine.Current.ResPool; } } + + #region private + + private Size defaultItemSize; + private Point defaultPadding; + private int minimumTabWidth; + private Rectangle selectedTabDelta; + + private Point tabPanelOffset; + + private int selectedSpacing; + + private Size rowSpacingNormal; + private Size rowSpacingButtons; + private Size rowSpacingFlatButtons; + private int scrollerWidth; + private Point focusRectSpacing; + private Rectangle tabPageSpacing; + private int colSpacing; + private int flatButtonSpacing; + + private Point imagePadding; + + private StringFormat defaultFormatting; + + private Rectangle borderThickness; + + #endregion + + #region Properties + + public virtual Size DefaultItemSize { + get { return defaultItemSize; } + set { defaultItemSize = value; } + } + + public virtual Point DefaultPadding { + get { return defaultPadding; } + set { defaultPadding = value; } + } + + public virtual int MinimumTabWidth { + get { return minimumTabWidth; } + set { minimumTabWidth = value; } + } + + public virtual Rectangle SelectedTabDelta { + get { return selectedTabDelta; } + set { selectedTabDelta = value; } + } + + public virtual Point TabPanelOffset { + get { return tabPanelOffset; } + set { tabPanelOffset = value; } + } + + public virtual int SelectedSpacing { + get { return selectedSpacing; } + set { selectedSpacing = value; } + } + + public virtual Size RowSpacingNormal { + get { return rowSpacingNormal; } + set { rowSpacingNormal = value; } + } + + public virtual Size RowSpacingButtons { + get { return rowSpacingButtons; } + set { rowSpacingButtons = value; } + } + + public virtual Size RowSpacingFlatButtons { + get { return rowSpacingFlatButtons; } + set { rowSpacingFlatButtons = value; } + } + + public virtual Point FocusRectSpacing { + get { return focusRectSpacing; } + set { focusRectSpacing = value; } + } + + public virtual int ColSpacing { + get { return colSpacing; } + set { colSpacing = value; } + } + + public virtual int FlatButtonSpacing { + get { return flatButtonSpacing; } + set { flatButtonSpacing = value; } + } + + public virtual Rectangle TabPageSpacing { + get { return tabPageSpacing; } + set { tabPageSpacing = value; } + } + + public virtual Point ImagePadding { + get { return imagePadding; } + set { imagePadding = value; } + } + + public virtual StringFormat DefaultFormatting { + get { return defaultFormatting; } + set { defaultFormatting = value; } + } + + public virtual Rectangle BorderThickness { + get { return borderThickness; } + set { borderThickness = value; } + } + + public virtual int ScrollerWidth { + get { return scrollerWidth; } + set { scrollerWidth = value; } + } + + public virtual Size RowSpacing (ShiftUI.TabWidget tab) { + switch (tab.Appearance) { + case TabAppearance.Normal: + return rowSpacingNormal; + case TabAppearance.Buttons: + return rowSpacingButtons; + case TabAppearance.FlatButtons: + return rowSpacingFlatButtons; + default: + throw new Exception ("Invalid Appearance value: " + tab.Appearance); + } + } + #endregion + + public TabWidgetPainter () + { + defaultItemSize = new Size (42, 16); + defaultPadding = new Point (6, 3); + selectedTabDelta = new Rectangle (2, 2, 4, 3); + selectedSpacing = 0; + + rowSpacingNormal = new Size (0, 0); + rowSpacingButtons = new Size (3, 3); + rowSpacingFlatButtons = new Size (9, 3); + + colSpacing = 0; + + minimumTabWidth = 42; + scrollerWidth = 17; + focusRectSpacing = new Point (2, 2); + tabPanelOffset = new Point (4, 0); + flatButtonSpacing = 8; + tabPageSpacing = new Rectangle (4, 2, 3, 4); + + imagePadding = new Point (2, 3); + + defaultFormatting = new StringFormat(); + // Horizontal Alignment is handled in the Draw method + defaultFormatting.Alignment = StringAlignment.Near; + defaultFormatting.LineAlignment = StringAlignment.Center; + defaultFormatting.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.NoClip; + defaultFormatting.HotkeyPrefix = HotkeyPrefix.Show; + + borderThickness = new Rectangle (1, 1, 2, 2); + } + + public virtual Rectangle GetLeftScrollRect (ShiftUI.TabWidget tab) + { + switch (tab.Alignment) { + case TabAlignment.Top: + return new Rectangle (tab.ClientRectangle.Right - (scrollerWidth * 2), tab.ClientRectangle.Top + 1, scrollerWidth, scrollerWidth); + default: + Rectangle panel_rect = GetTabPanelRect (tab); + return new Rectangle (tab.ClientRectangle.Right - (scrollerWidth * 2), panel_rect.Bottom + 2, scrollerWidth, scrollerWidth); + } + } + + public virtual Rectangle GetRightScrollRect (ShiftUI.TabWidget tab) + { + switch (tab.Alignment) { + case TabAlignment.Top: + return new Rectangle (tab.ClientRectangle.Right - (scrollerWidth), tab.ClientRectangle.Top + 1, scrollerWidth, scrollerWidth); + default: + Rectangle panel_rect = GetTabPanelRect (tab); + return new Rectangle (tab.ClientRectangle.Right - (scrollerWidth), panel_rect.Bottom + 2, scrollerWidth, scrollerWidth); + } + } + + public Rectangle GetDisplayRectangle (ShiftUI.TabWidget tab) + { + Rectangle ext = GetTabPanelRect (tab); + // Account for border size + return new Rectangle (ext.Left + tabPageSpacing.X, ext.Top + tabPageSpacing.Y, + ext.Width - tabPageSpacing.X - tabPageSpacing.Width, ext.Height - tabPageSpacing.Y - tabPageSpacing.Height); + } + + public Rectangle GetTabPanelRect (ShiftUI.TabWidget tab) + { + // Offset the tab page (panel) from the top corner + Rectangle res = tab.ClientRectangle; + + if (tab.TabCount == 0) + return res; + + int spacing = RowSpacing (tab).Height; + int tabOffset = (tab.ItemSize.Height + spacing - selectedTabDelta.Height) * tab.RowCount + selectedTabDelta.Y; + switch (tab.Alignment) { + case TabAlignment.Top: + res.Y += tabOffset; + res.Height -= tabOffset; + break; + case TabAlignment.Bottom: + res.Height -= tabOffset; + break; + case TabAlignment.Left: + res.X += tabOffset; + res.Width -= tabOffset; + break; + case TabAlignment.Right: + res.Width -= tabOffset; + break; + } + + return res; + } + + public virtual void Draw (Graphics dc, Rectangle area, TabWidget tab) + { + DrawBackground (dc, area, tab); + + int start = 0; + int end = tab.TabPages.Count; + int delta = 1; + + if (tab.Alignment == TabAlignment.Top) { + start = end; + end = 0; + delta = -1; + } + + if (tab.SizeMode == TabSizeMode.Fixed) + defaultFormatting.Alignment = StringAlignment.Center; + else + defaultFormatting.Alignment = StringAlignment.Near; + + int counter = start; + for (; counter != end; counter += delta) { + for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) { + if (i == tab.SelectedIndex) + continue; + if (counter != tab.TabPages[i].Row) + continue; + Rectangle rect = tab.GetTabRect (i); + if (!rect.IntersectsWith (area)) + continue; + DrawTab (dc, tab.TabPages[i], tab, rect, false); + } + } + + if (tab.SelectedIndex != -1 && tab.SelectedIndex >= tab.SliderPos) { + Rectangle rect = tab.GetTabRect (tab.SelectedIndex); + if (rect.IntersectsWith (area)) + DrawTab (dc, tab.TabPages[tab.SelectedIndex], tab, rect, true); + } + + if (tab.ShowSlider) { + Rectangle right = GetRightScrollRect (tab); + Rectangle left = GetLeftScrollRect (tab); + DrawScrollButton (dc, right, area, ScrollButton.Right, tab.RightSliderState); + DrawScrollButton (dc, left, area, ScrollButton.Left, tab.LeftSliderState); + } + } + + protected virtual void DrawScrollButton (Graphics dc, Rectangle bounds, Rectangle clippingArea, ScrollButton button, PushButtonState state) + { + WidgetPaint.DrawScrollButton (dc, bounds, button, GetButtonState (state)); + } + + static ButtonState GetButtonState (PushButtonState state) + { + switch (state) { + case PushButtonState.Pressed: + return ButtonState.Pushed; + default: + return ButtonState.Normal; + } + } + + protected virtual void DrawBackground (Graphics dc, Rectangle area, TabWidget tab) + { + Brush brush = SystemBrushes.Control; + dc.FillRectangle (brush, area); + Rectangle panel_rect = GetTabPanelRect (tab); + + if (tab.Appearance == TabAppearance.Normal) { + WidgetPaint.DrawBorder3D (dc, panel_rect, Border3DStyle.RaisedInner, Border3DSide.Left | Border3DSide.Top); + WidgetPaint.DrawBorder3D (dc, panel_rect, Border3DStyle.Raised, Border3DSide.Right | Border3DSide.Bottom); + } + } + + protected virtual int DrawTab (Graphics dc, ShiftUI.TabPage page, ShiftUI.TabWidget tab, Rectangle bounds, bool is_selected) + { + Rectangle interior; + int res = bounds.Width; + + dc.FillRectangle (ResPool.GetSolidBrush (tab.BackColor), bounds); + + if (tab.Appearance == TabAppearance.Buttons || tab.Appearance == TabAppearance.FlatButtons) { + // Separators + if (tab.Appearance == TabAppearance.FlatButtons) { + int width = bounds.Width; + bounds.Width += (flatButtonSpacing - 2); + res = bounds.Width; + if (tab.Alignment == TabAlignment.Top || tab.Alignment == TabAlignment.Bottom) + ThemeEngine.Current.CPDrawBorder3D (dc, bounds, Border3DStyle.Etched, Border3DSide.Right); + else + ThemeEngine.Current.CPDrawBorder3D (dc, bounds, Border3DStyle.Etched, Border3DSide.Top); + bounds.Width = width; + } + + if (is_selected) { + ThemeEngine.Current.CPDrawBorder3D (dc, bounds, Border3DStyle.Sunken, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom); + } else if (tab.Appearance != TabAppearance.FlatButtons) { + ThemeEngine.Current.CPDrawBorder3D (dc, bounds, Border3DStyle.Raised, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom); + } + + + } else { + CPColor cpcolor = ResPool.GetCPColor (tab.BackColor); + + Pen light = ResPool.GetPen (cpcolor.LightLight); + + switch (tab.Alignment) { + + case TabAlignment.Top: + + dc.DrawLine (light, bounds.Left, bounds.Bottom - 1, bounds.Left, bounds.Top + 3); + dc.DrawLine (light, bounds.Left, bounds.Top + 3, bounds.Left + 2, bounds.Top); + dc.DrawLine (light, bounds.Left + 2, bounds.Top, bounds.Right - 3, bounds.Top); + + dc.DrawLine (SystemPens.ControlDark, bounds.Right - 2, bounds.Top + 1, bounds.Right - 2, bounds.Bottom - 1); + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Right - 2, bounds.Top + 1, bounds.Right - 1, bounds.Top + 2); + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Right - 1, bounds.Top + 2, bounds.Right - 1, bounds.Bottom - 1); + break; + + case TabAlignment.Bottom: + + dc.DrawLine (light, bounds.Left, bounds.Top, bounds.Left, bounds.Bottom - 2); + dc.DrawLine (light, bounds.Left, bounds.Bottom - 2, bounds.Left + 3, bounds.Bottom); + + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Left + 3, bounds.Bottom, bounds.Right - 3, bounds.Bottom); + dc.DrawLine (SystemPens.ControlDark, bounds.Left + 3, bounds.Bottom - 1, bounds.Right - 3, bounds.Bottom - 1); + + dc.DrawLine (SystemPens.ControlDark, bounds.Right - 2, bounds.Bottom - 1, bounds.Right - 2, bounds.Top + 1); + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Right - 2, bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 2); + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Right - 1, bounds.Bottom - 2, bounds.Right - 1, bounds.Top + 1); + + break; + + case TabAlignment.Left: + + dc.DrawLine (light, bounds.Left - 2, bounds.Top, bounds.Right, bounds.Top); + dc.DrawLine (light, bounds.Left, bounds.Top + 2, bounds.Left - 2, bounds.Top); + dc.DrawLine (light, bounds.Left, bounds.Top + 2, bounds.Left, bounds.Bottom - 2); + + dc.DrawLine (SystemPens.ControlDark, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom - 1); + + dc.DrawLine (SystemPens.ControlDark, bounds.Left + 2, bounds.Bottom - 1, bounds.Right, bounds.Bottom - 1); + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Left + 2, bounds.Bottom, bounds.Right, bounds.Bottom); + + break; + + default: // TabAlignment.Right + + dc.DrawLine (light, bounds.Left, bounds.Top, bounds.Right - 3, bounds.Top); + dc.DrawLine (light, bounds.Right - 3, bounds.Top, bounds.Right, bounds.Top + 3); + + dc.DrawLine (SystemPens.ControlDark, bounds.Right - 1, bounds.Top + 1, bounds.Right - 1, bounds.Bottom - 1); + dc.DrawLine (SystemPens.ControlDark, bounds.Left, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom - 1); + + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Right, bounds.Top + 3, bounds.Right, bounds.Bottom - 3); + dc.DrawLine (SystemPens.ControlDarkDark, bounds.Left, bounds.Bottom, bounds.Right - 3, bounds.Bottom); + + break; + } + } + + Point padding = tab.Padding; + interior = new Rectangle (bounds.Left + padding.X - 1, // substract a little offset + bounds.Top + padding.Y, + bounds.Width - (padding.X * 2), + bounds.Height - (padding.Y * 2)); + + if (tab.DrawMode == TabDrawMode.Normal && page.Text != null) { + if (tab.Alignment == TabAlignment.Left) { + dc.TranslateTransform (bounds.Left, bounds.Bottom); + dc.RotateTransform (-90); + dc.DrawString (page.Text, tab.Font, + SystemBrushes.ControlText, + tab.Padding.X - 2, // drawstring adds some extra unwanted leading spaces, so trimming + tab.Padding.Y, + defaultFormatting); + dc.ResetTransform (); + } else if (tab.Alignment == TabAlignment.Right) { + dc.TranslateTransform (bounds.Right, bounds.Top); + dc.RotateTransform (90); + dc.DrawString (page.Text, tab.Font, + SystemBrushes.ControlText, + tab.Padding.X - 2, // drawstring adds some extra unwanted leading spaces, so trimming + tab.Padding.Y, + defaultFormatting); + dc.ResetTransform (); + } else { + Rectangle str_rect = interior; + + if (is_selected) { + // Reduce the interior size to match the inner size of non-selected tabs + str_rect.X += selectedTabDelta.X; + str_rect.Y += selectedTabDelta.Y; + str_rect.Width -= selectedTabDelta.Width; + str_rect.Height -= selectedTabDelta.Height; + + str_rect.Y -= selectedTabDelta.Y; // Move up the text / image of the selected tab + } + + if (tab.ImageList != null && page.ImageIndex >= 0 && page.ImageIndex < tab.ImageList.Images.Count) { + int image_x; + if (tab.SizeMode != TabSizeMode.Fixed) { + image_x = str_rect.X; + } + else { + image_x = str_rect.X + (str_rect.Width - tab.ImageList.ImageSize.Width) / 2; + if (page.Text != null) { + SizeF textSize = dc.MeasureString(page.Text, page.Font, str_rect.Size); + image_x -= (int)(textSize.Width / 2); + } + } + int image_y = str_rect.Y + (str_rect.Height - tab.ImageList.ImageSize.Height) / 2; + tab.ImageList.Draw (dc, new Point (image_x, image_y), page.ImageIndex); + str_rect.X += tab.ImageList.ImageSize.Width + 2; + str_rect.Width -= tab.ImageList.ImageSize.Width + 2; + } + dc.DrawString (page.Text, tab.Font, + SystemBrushes.ControlText, + str_rect, + defaultFormatting); + + } + } else if (page.Text != null) { + DrawItemState state = DrawItemState.None; + if (page == tab.SelectedTab) + state |= DrawItemState.Selected; + DrawItemEventArgs e = new DrawItemEventArgs (dc, + tab.Font, bounds, tab.IndexForTabPage (page), + state, page.ForeColor, page.BackColor); + tab.OnDrawItemInternal (e); + return res; + } + + // TabWidget ignores the value of ShowFocusCues + if (page.Parent.Focused && is_selected) { + Rectangle focus_rect = bounds; + focus_rect.Inflate (-2, -2); + ThemeEngine.Current.CPDrawFocusRectangle (dc, focus_rect, tab.BackColor, tab.ForeColor); + } + + return res; + } + + public virtual bool HasHotElementStyles (TabWidget tabWidget) { + return false; + } + } +} diff --git a/source/ShiftUI/Theming/Default/ToolStripPainter.cs b/source/ShiftUI/Theming/Default/ToolStripPainter.cs new file mode 100644 index 0000000..4876dd5 --- /dev/null +++ b/source/ShiftUI/Theming/Default/ToolStripPainter.cs @@ -0,0 +1,189 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2007 Novell, Inc. +// +// Authors: +// Jonathan Pobst (monkey@jpobst.com) + +using System; +using System.Drawing; + +namespace ShiftUI.Theming.Default +{ + internal class ToolStripPainter + { + public ToolStripPainter () + { + } + + protected SystemResPool ResPool { get { return ThemeEngine.Current.ResPool; } } + + #region Painting + public virtual void OnRenderButtonBackground (ToolStripItemRenderEventArgs e) + { + if (e.Item.Enabled == false) + return; + + Rectangle paint_here = new Rectangle (0, 0, e.Item.Width, e.Item.Height); + + ToolStripButton tsb = e.Item as ToolStripButton; + + if (e.Item.Pressed || (tsb != null && tsb.Checked)) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.SunkenOuter); + else if (e.Item.Selected) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.RaisedInner); + else if (e.Item.BackColor != Widget.DefaultBackColor && e.Item.BackColor != Color.Empty) + e.Graphics.FillRectangle (ResPool.GetSolidBrush (e.Item.BackColor), paint_here); + } + + public virtual void OnRenderDropDownButtonBackground (ToolStripItemRenderEventArgs e) + { + if (e.Item.Enabled == false) + return; + + Rectangle paint_here = new Rectangle (0, 0, e.Item.Width, e.Item.Height); + + if (e.Item.Pressed) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.SunkenOuter); + else if (e.Item.Selected) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.RaisedInner); + else if (e.Item.BackColor != Widget.DefaultBackColor && e.Item.BackColor != Color.Empty) + e.Graphics.FillRectangle (ResPool.GetSolidBrush (e.Item.BackColor), paint_here); + } + + public virtual void OnRenderGrip (ToolStripGripRenderEventArgs e) + { + if (e.GripStyle == ToolStripGripStyle.Hidden) + return; + + if (e.GripDisplayStyle == ToolStripGripDisplayStyle.Vertical) { + e.Graphics.DrawLine (Pens.White, 0, 2, 1, 2); + e.Graphics.DrawLine (Pens.White, 0, 2, 0, e.GripBounds.Height - 3); + e.Graphics.DrawLine (SystemPens.ControlDark, 2, 2, 2, e.GripBounds.Height - 3); + e.Graphics.DrawLine (SystemPens.ControlDark, 2, e.GripBounds.Height - 3, 0, e.GripBounds.Height - 3); + } + else { + e.Graphics.DrawLine (Pens.White, 2, 0, e.GripBounds.Width - 3, 0); + e.Graphics.DrawLine (Pens.White, 2, 0, 2, 1); + e.Graphics.DrawLine (SystemPens.ControlDark, e.GripBounds.Width - 3, 0, e.GripBounds.Width - 3, 2); + e.Graphics.DrawLine (SystemPens.ControlDark, 2, 2, e.GripBounds.Width - 3, 2); + } + } + + public virtual void OnRenderMenuItemBackground (ToolStripItemRenderEventArgs e) + { + ToolStripMenuItem tsmi = (ToolStripMenuItem)e.Item; + Rectangle paint_here = new Rectangle (Point.Empty, tsmi.Size); + + if (tsmi.IsOnDropDown) { + // Drop down menu item + if (e.Item.Selected || e.Item.Pressed) + e.Graphics.FillRectangle (SystemBrushes.Highlight, paint_here); + } else { + // Top level menu item + if (e.Item.Pressed) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.SunkenOuter); + else if (e.Item.Selected) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.RaisedInner); + else if (e.Item.BackColor != Widget.DefaultBackColor && e.Item.BackColor != Color.Empty) + e.Graphics.FillRectangle (ResPool.GetSolidBrush (e.Item.BackColor), paint_here); + } + } + + public virtual void OnRenderOverflowButtonBackground (ToolStripItemRenderEventArgs e) + { + Rectangle paint_here = new Rectangle (Point.Empty, e.Item.Size); + + if (e.Item.Pressed) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.SunkenOuter); + else if (e.Item.Selected) + WidgetPaint.DrawBorder3D (e.Graphics, paint_here, Border3DStyle.RaisedInner); + else if (e.Item.BackColor != Widget.DefaultBackColor && e.Item.BackColor != Color.Empty) + e.Graphics.FillRectangle (ResPool.GetSolidBrush (e.Item.BackColor), paint_here); + + // Paint the arrow + ToolStripRenderer.DrawDownArrow (e.Graphics, SystemPens.ControlText, e.Item.Width / 2 - 3, e.Item.Height / 2 - 1); + } + + public virtual void OnRenderSeparator (ToolStripSeparatorRenderEventArgs e) + { + if (e.Vertical) { + e.Graphics.DrawLine (Pens.White, 4, 3, 4, e.Item.Height - 1); + e.Graphics.DrawLine (SystemPens.ControlDark, 3, 3, 3, e.Item.Height - 1); + } else { + if (!e.Item.IsOnDropDown) { + e.Graphics.DrawLine (Pens.White, 2, 4, e.Item.Right - 1, 4); + e.Graphics.DrawLine (SystemPens.ControlDark, 2, 3, e.Item.Right - 1, 3); + } else { + e.Graphics.DrawLine (Pens.White, 3, 4, e.Item.Right - 4, 4); + e.Graphics.DrawLine (SystemPens.ControlDark, 3, 3, e.Item.Right - 4, 3); + } + } + } + + public virtual void OnRenderSplitButtonBackground (ToolStripItemRenderEventArgs e) + { + ToolStripSplitButton tssb = (ToolStripSplitButton)e.Item; + + Rectangle button_part = new Rectangle (Point.Empty, tssb.ButtonBounds.Size); + Point drop_start = new Point (tssb.Width - tssb.DropDownButtonBounds.Width, 0); + Rectangle drop_part = new Rectangle (drop_start, tssb.DropDownButtonBounds.Size); + + // Regular button part + if (tssb.ButtonPressed) + WidgetPaint.DrawBorder3D (e.Graphics, button_part, Border3DStyle.SunkenOuter); + else if (tssb.ButtonSelected) + WidgetPaint.DrawBorder3D (e.Graphics, button_part, Border3DStyle.RaisedInner); + else if (e.Item.BackColor != Widget.DefaultBackColor && e.Item.BackColor != Color.Empty) + e.Graphics.FillRectangle (ResPool.GetSolidBrush (e.Item.BackColor), button_part); + + // Drop down button part + if (tssb.DropDownButtonPressed || tssb.ButtonPressed) + WidgetPaint.DrawBorder3D (e.Graphics, drop_part, Border3DStyle.SunkenOuter); + else if (tssb.DropDownButtonSelected || tssb.ButtonSelected) + WidgetPaint.DrawBorder3D (e.Graphics, drop_part, Border3DStyle.RaisedInner); + else if (e.Item.BackColor != Widget.DefaultBackColor && e.Item.BackColor != Color.Empty) + e.Graphics.FillRectangle (ResPool.GetSolidBrush (e.Item.BackColor), drop_part); + } + + public virtual void OnRenderToolStripBackground (ToolStripRenderEventArgs e) + { + if (e.ToolStrip.BackgroundImage == null) + e.Graphics.Clear (e.BackColor); + + if (e.ToolStrip is StatusStrip) + e.Graphics.DrawLine (Pens.White, e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Right, e.AffectedBounds.Top); + } + + public virtual void OnRenderToolStripBorder (ToolStripRenderEventArgs e) + { + if (e.ToolStrip is StatusStrip) + return; + + if (e.ToolStrip is ToolStripDropDown) + WidgetPaint.DrawBorder3D (e.Graphics, e.AffectedBounds, Border3DStyle.Raised); + else { + e.Graphics.DrawLine (SystemPens.ControlDark, new Point (e.ToolStrip.Left, e.ToolStrip.Height - 2), new Point (e.ToolStrip.Right, e.ToolStrip.Height - 2)); + e.Graphics.DrawLine (Pens.White, new Point (e.ToolStrip.Left, e.ToolStrip.Height - 1), new Point (e.ToolStrip.Right, e.ToolStrip.Height - 1)); + } + } + #endregion + } +} -- cgit v1.2.3