diff options
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs')
-rw-r--r-- | mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs | 3402 |
1 files changed, 3402 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs new file mode 100644 index 00000000000..317d0570cc9 --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs @@ -0,0 +1,3402 @@ +// 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) 2004-2005 Novell, Inc. +// +// Authors: +// Alexander Olk, alex.olk@googlemail.com +// +// based on ThemeWin32Classic +// +// - You can activate this Theme with export MONO_THEME=clearlooks +// +// This theme tries to match clearlooks theme +// +// TODO: +// - if an other control draws over a ScrollBar button you can see artefacts on the rounded edges +// (maybe use theme backcolor, but that looks ugly on a white background, need to find a way to get the backcolor of the parent control) +// - more correct drawing of disabled controls + +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Drawing.Text; + +namespace System.Windows.Forms { + internal class ThemeClearlooks : ThemeWin32Classic { + public override Version Version { + get { + return new Version( 0, 0, 0, 2 ); + } + } + + static readonly Color theme_back_color = Color.FromArgb( 239, 235, 231 ); + + static readonly Color gradient_first_color = Color.FromArgb( 250, 248, 247 ); + static readonly Color gradient_second_color = Color.FromArgb( 226, 219, 212 ); + static readonly Color gradient_second_color_nr2 = Color.FromArgb( 234, 229, 224 ); + static readonly Color pressed_gradient_first_color = Color.FromArgb( 217, 207, 202 ); + static readonly Color pressed_gradient_second_color = Color.FromArgb( 199, 193, 187 ); + static readonly Color border_normal_dark_color = Color.FromArgb( 129, 117, 106 ); + static readonly Color border_normal_light_color = Color.FromArgb( 158, 145, 131 ); + static readonly Color border_pressed_dark_color = Color.FromArgb( 109, 103, 98 ); + static readonly Color border_pressed_light_color = Color.FromArgb( 120, 114, 107 ); + static readonly Color button_outer_border_dark_color = Color.FromArgb( 232, 226, 220 ); + static readonly Color button_outer_border_light_color = Color.FromArgb( 250, 248, 247 ); + static readonly Color inner_border_dark_color = Color.FromArgb( 226, 219, 212 ); + static readonly Color pressed_inner_border_dark_color = Color.FromArgb( 192, 181, 169 ); + static readonly Color edge_top_inner_color = Color.FromArgb( 206, 200, 194 ); + static readonly Color edge_bottom_inner_color = Color.FromArgb( 215, 209, 202 ); + static readonly Color button_edge_top_outer_color = Color.FromArgb( 237, 233, 228 ); + static readonly Color button_edge_bottom_outer_color = Color.FromArgb( 243, 239, 236 ); + static readonly Color button_focus_color = Color.FromArgb( 101, 94, 86 ); + static readonly Color button_mouse_entered_second_gradient_color = Color.FromArgb( 230, 226, 219 ); + + static readonly Color scrollbar_background_color = Color.FromArgb( 209, 200, 191 ); + static readonly Color scrollbar_border_color = Color.FromArgb( 170, 156, 143 ); + static readonly Color scrollbar_gradient_first_color = Color.FromArgb( 248, 247, 245 ); + static readonly Color scrollbar_gradient_second_color = Color.FromArgb( 234, 229, 224 ); + + static readonly Color arrow_color = Color.FromArgb( 16, 16, 16 ); + + static readonly Color tab_border_color = Color.FromArgb( 166, 151, 138 ); + static readonly Color tab_not_selected_gradient_first_color = Color.FromArgb( 227, 223, 220 ); + static readonly Color tab_not_selected_gradient_second_color = Color.FromArgb( 214, 209, 204 ); + static readonly Color tab_selected_gradient_first_color = Color.FromArgb( 243, 239, 236 ); + static readonly Color tab_selected_gradient_second_color = Color.FromArgb( 234, 228, 223 ); + static readonly Color tab_edge_color = Color.FromArgb( 200, 196, 191 ); + static readonly Color tab_inner_border_color = Color.FromArgb( 221, 212, 205 ); + static readonly Color tab_top_border_focus_color = Color.FromArgb( 70, 91, 110 ); + static readonly Color tab_focus_color = Color.FromArgb( 105, 147, 185 ); + + static readonly Color menuitem_gradient_first_color = Color.FromArgb( 98, 140, 178 ); + static readonly Color menuitem_gradient_second_color = Color.FromArgb( 81, 113, 142 ); + static readonly Color menuitem_border_color = Color.FromArgb( 80, 112, 141 ); + static readonly Color menu_separator_color = Color.FromArgb( 219, 211, 203 ); + static readonly Color menu_background_color = Color.FromArgb( 248, 245, 242 ); + static readonly Color menu_border_color = Color.FromArgb( 141, 122, 104 ); + static readonly Color menu_inner_border_color = Color.FromArgb( 236, 228, 221 ); + + static readonly Color combobox_border_color = Color.FromArgb( 159, 146, 132 ); + static readonly Color combobox_focus_border_color = Color.FromArgb( 70, 91, 110 ); + static readonly Color combobox_focus_inner_border_color = Color.FromArgb( 167, 198, 225 ); + static readonly Color combobox_button_second_gradient_color = Color.FromArgb( 226, 220, 213 ); + + static readonly Color progressbar_edge_dot_color = Color.FromArgb( 219, 212, 205 ); + static readonly Color progressbar_inner_border_color = Color.FromArgb( 139, 176, 209 ); + static readonly Color progressbar_first_gradient_color = Color.FromArgb( 104, 146, 184 ); + static readonly Color progressbar_second_gradient_color = Color.FromArgb( 91, 133, 172 ); + + static readonly Color checkbox_inner_boder_color = Color.FromArgb( 237, 234, 231 ); + static readonly Color checkbox_pressed_inner_boder_color = Color.FromArgb( 203, 196, 189 ); + static readonly Color checkbox_pressed_backcolor = Color.FromArgb( 212, 207, 202 ); + + static readonly Color trackbar_second_gradient_color = Color.FromArgb( 114, 154, 190 ); + static readonly Color trackbar_third_gradient_color = Color.FromArgb( 130, 168, 202 ); + static readonly Color trackbar_inner_first_gradient_color = Color.FromArgb( 238, 233, 229 ); + static readonly Color trackbar_inner_second_gradient_color = Color.FromArgb( 223, 215, 208 ); + static readonly Color trackbar_inner_pressed_second_gradient_color = Color.FromArgb( 224, 217, 210 ); + + static readonly Color disabled_color_foreground = Color.FromArgb( 182, 180, 173 ); + + static readonly Color active_caption = Color.FromArgb( 85, 152, 215 ); + + static readonly Color radio_button_border_circle_color = Color.FromArgb( 126, 118, 105 ); + static readonly Color radio_button_dot_color = Color.FromArgb( 94, 160, 221 ); + + const int SEPARATOR_HEIGHT = 7; + const int MENU_TAB_SPACE = 8; // Pixels added to the width of an item because of a tab + const int MENU_BAR_ITEMS_SPACE = 8; // Space between menu bar items + + int platform = (int) Environment.OSVersion.Platform; + + static Color control_parent_backcolor; + + #region Principal Theme Methods + public ThemeClearlooks( ) { + ColorControl = theme_back_color; + always_draw_hotkeys = true; + } + + public override Color DefaultControlBackColor { + get { return theme_back_color; } + } + + public override Color DefaultWindowBackColor { + get { return theme_back_color; } + } + + public override Color ColorControl { + get { return theme_back_color;} + } + + public override Color ColorHighlight { + get { return menuitem_gradient_first_color; } + } + + public override Color ColorActiveCaption { + get { return active_caption; } + } + + public override Size Border3DSize { + get { + return new Size( 3, 3 ); + } + } + + public override Image Images(UIIcon index, int size) { + switch (index) { + case UIIcon.PlacesRecentDocuments: + if ((platform == 4) || (platform == 128)) + return MimeIconEngine.GetIconForMimeTypeAndSize( "recently/recently", new Size(size, size) ); + else + return base.Images (UIIcon.PlacesRecentDocuments, size); + case UIIcon.PlacesDesktop: + if ((platform == 4) || (platform == 128)) + return MimeIconEngine.GetIconForMimeTypeAndSize( "desktop/desktop", new Size(size, size) ); + else + return base.Images (UIIcon.PlacesDesktop, size); + case UIIcon.PlacesPersonal: + if ((platform == 4) || (platform == 128)) + return MimeIconEngine.GetIconForMimeTypeAndSize( "directory/home", new Size(size, size) ); + else + return base.Images (UIIcon.PlacesPersonal, size); + case UIIcon.PlacesMyComputer: + if ((platform == 4) || (platform == 128)) + return MimeIconEngine.GetIconForMimeTypeAndSize( "workplace/workplace", new Size(size, size) ); + else + return base.Images (UIIcon.PlacesMyComputer, size); + case UIIcon.PlacesMyNetwork: + if ((platform == 4) || (platform == 128)) + return MimeIconEngine.GetIconForMimeTypeAndSize( "network/network", new Size(size, size) ); + else + return base.Images (UIIcon.PlacesMyNetwork, size); + + // Icons for message boxes + case UIIcon.MessageBoxError: return base.Images (UIIcon.MessageBoxError, size); + case UIIcon.MessageBoxInfo: return base.Images (UIIcon.MessageBoxInfo, size); + case UIIcon.MessageBoxQuestion: return base.Images (UIIcon.MessageBoxQuestion, size); + case UIIcon.MessageBoxWarning: return base.Images (UIIcon.MessageBoxWarning, size); + + // misc Icons + case UIIcon.NormalFolder: + if ((platform == 4) || (platform == 128)) + return MimeIconEngine.GetIconForMimeTypeAndSize( "inode/directory", new Size(size, size) ); + else + return base.Images (UIIcon.NormalFolder, size); + + default: { + throw new ArgumentException("Invalid Icon type requested", "index"); + } + } + } + #endregion // Internal Methods + + #region ButtonBase + protected override void ButtonBase_DrawButton( ButtonBase button, Graphics dc ) { + dc.FillRectangle( ResPool.GetSolidBrush( button.BackColor ), button.ClientRectangle ); + + Color first_gradient_color = gradient_first_color; + Color second_gradient_color = gradient_second_color; + + if (((button is CheckBox) && (((CheckBox)button).check_state == CheckState.Checked)) || + ((button is RadioButton) && (((RadioButton)button).check_state == CheckState.Checked))) { + first_gradient_color = button.is_entered ? gradient_second_color : pressed_gradient_first_color; + second_gradient_color = button.is_entered ? gradient_second_color : pressed_gradient_second_color; + } else + if (!button.is_enabled) { + button.is_entered = false; + } else + if (button.is_entered) { + if (!button.is_pressed) { + first_gradient_color = Color.White; + second_gradient_color = button_mouse_entered_second_gradient_color; + } else { + first_gradient_color = pressed_gradient_first_color; + second_gradient_color = pressed_gradient_second_color; + } + } + + bool paint_acceptbutton_black_border = false; + Form form = button.TopLevelControl as Form; + + if (form != null && (form.AcceptButton == button as IButtonControl)) + paint_acceptbutton_black_border = true; + + CL_Draw_Button(dc, button.ClientRectangle, button.flat_style, + button.is_entered, button.is_enabled, button.is_pressed, + first_gradient_color, second_gradient_color, + paint_acceptbutton_black_border); + } + + private void CL_Draw_Button(Graphics dc, Rectangle buttonRectangle, FlatStyle flat_style, + bool is_entered, bool is_enabled, bool is_pressed, + Color first_gradient_color, Color second_gradient_color, + bool paint_acceptbutton_black_border) + { + Rectangle lgbRectangle = new Rectangle (buttonRectangle.X + 3, buttonRectangle.Y + 3, + is_pressed ? buttonRectangle.Width - 5 : buttonRectangle.Width - 6, + buttonRectangle.Height - 6); + + if (flat_style != FlatStyle.Popup || ((flat_style == FlatStyle.Popup) && is_entered)) { + LinearGradientBrush lgbr; + if (flat_style == FlatStyle.Flat) + lgbr = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 3), + new Point (buttonRectangle.X, buttonRectangle.Bottom - 3), + second_gradient_color, first_gradient_color); + else + lgbr = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 3), + new Point (buttonRectangle.X, buttonRectangle.Bottom - 3), + first_gradient_color, second_gradient_color); + dc.FillRectangle (lgbr, lgbRectangle); + lgbr.Dispose (); + + Point[] points_top = { + new Point (buttonRectangle.X + 2, buttonRectangle.Y + 2), + new Point (buttonRectangle.X + 3, buttonRectangle.Y + 1), + new Point (buttonRectangle.Right - 4, buttonRectangle.Y + 1), + new Point (buttonRectangle.Right - 3 , buttonRectangle.Y + 2) + }; + + Point[] points_bottom = { + new Point (buttonRectangle.X + 2, buttonRectangle.Bottom - 3), + new Point (buttonRectangle.X + 3, buttonRectangle.Bottom - 2), + new Point (buttonRectangle.Right - 4, buttonRectangle.Bottom - 2), + new Point (buttonRectangle.Right - 3, buttonRectangle.Bottom - 3) + }; + + Point[] points_top_outer = { + new Point (buttonRectangle.X + 1, buttonRectangle.Y + 1), + new Point (buttonRectangle.X + 2, buttonRectangle.Y), + new Point (buttonRectangle.Right - 3, buttonRectangle.Y), + new Point (buttonRectangle.Right - 2 , buttonRectangle.Y + 1) + }; + + Point[] points_bottom_outer = { + new Point (buttonRectangle.X + 1, buttonRectangle.Bottom - 2), + new Point (buttonRectangle.X + 2, buttonRectangle.Bottom - 1), + new Point (buttonRectangle.Right - 3, buttonRectangle.Bottom - 1), + new Point (buttonRectangle.Right - 2, buttonRectangle.Bottom - 2) + }; + + Pen pen = null; + + // normal border + if (is_enabled) { + Color top_color = Color.Black; + Color bottom_color = Color.Black; + + if (!paint_acceptbutton_black_border) { + top_color = is_pressed ? border_pressed_dark_color : border_normal_dark_color; + bottom_color = is_pressed ? border_pressed_light_color : border_normal_light_color; + } + + pen = ResPool.GetPen (top_color); + dc.DrawLines (pen, points_top); + pen = ResPool.GetPen (bottom_color); + dc.DrawLines (pen, points_bottom); + + using (LinearGradientBrush lgbr2 = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 3), + new Point (buttonRectangle.X, buttonRectangle.Bottom - 3), + top_color, bottom_color)) { + dc.FillRectangle (lgbr2, buttonRectangle.X + 1, buttonRectangle.Y + 3, 1, buttonRectangle.Height - 6); + dc.FillRectangle (lgbr2, buttonRectangle.Right - 2, buttonRectangle.Y + 3, 1, buttonRectangle.Height - 6); + } + } else { + Point[] points_button_complete = { + new Point (buttonRectangle.X + 1, buttonRectangle.Y + 3), + new Point (buttonRectangle.X + 3, buttonRectangle.Y + 1), + new Point (buttonRectangle.Right - 4, buttonRectangle.Y + 1), + new Point (buttonRectangle.Right - 2, buttonRectangle.Y + 3), + new Point (buttonRectangle.Right - 2, buttonRectangle.Bottom - 4), + new Point (buttonRectangle.Right - 4, buttonRectangle.Bottom - 2), + new Point (buttonRectangle.X + 3, buttonRectangle.Bottom - 2), + new Point (buttonRectangle.X + 1, buttonRectangle.Bottom - 4), + new Point (buttonRectangle.X + 1, buttonRectangle.Y + 3) + }; + + pen = ResPool.GetPen (pressed_inner_border_dark_color); + dc.DrawLines (pen, points_button_complete); + } + + // outer border + pen = ResPool.GetPen (button_outer_border_dark_color); + dc.DrawLines (pen, points_top_outer); + pen = ResPool.GetPen (button_outer_border_light_color); + dc.DrawLines (pen, points_bottom_outer); + + using (LinearGradientBrush lgbr2 = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 2), + new Point (buttonRectangle.X, buttonRectangle.Bottom - 1), + button_outer_border_dark_color, button_outer_border_light_color)) { + dc.FillRectangle (lgbr2, buttonRectangle.X, buttonRectangle.Y + 2, 1, buttonRectangle.Height - 4); + dc.FillRectangle (lgbr2, buttonRectangle.Right - 1, buttonRectangle.Y + 2, 1, buttonRectangle.Height - 4); + } + + // inner border + pen = ResPool.GetPen (is_pressed ? pressed_inner_border_dark_color : inner_border_dark_color); + if (!is_pressed) { + dc.DrawLine (pen, buttonRectangle.Right - 3, buttonRectangle.Y + 3, buttonRectangle.Right - 3, buttonRectangle.Bottom - 4); + } + dc.DrawLine (pen, buttonRectangle.X + 3, buttonRectangle.Bottom - 3, buttonRectangle.Right - 4, buttonRectangle.Bottom - 3); + pen = ResPool.GetPen (is_pressed ? pressed_inner_border_dark_color : Color.White); + dc.DrawLine (pen, buttonRectangle.X + 2, buttonRectangle.Y + 3, buttonRectangle.X + 2, buttonRectangle.Bottom - 4); + dc.DrawLine (pen, buttonRectangle.X + 3 , buttonRectangle.Y + 2, buttonRectangle.Right - 4, buttonRectangle.Y + 2); + + // edges + pen = ResPool.GetPen (edge_top_inner_color); + dc.DrawLine (pen, buttonRectangle.X + 1, buttonRectangle.Y + 2, buttonRectangle.X + 2, buttonRectangle.Y + 1); + dc.DrawLine (pen, buttonRectangle.Right - 3, buttonRectangle.Y + 1, buttonRectangle.Right - 2, buttonRectangle.Y + 2); + + pen = ResPool.GetPen (button_edge_top_outer_color); + dc.DrawLine (pen, buttonRectangle.X, buttonRectangle.Y + 1, buttonRectangle.X + 1, buttonRectangle.Y); + dc.DrawLine (pen, buttonRectangle.Right - 2, buttonRectangle.Y, buttonRectangle.Right - 1, buttonRectangle.Y + 1); + + pen = ResPool.GetPen (edge_bottom_inner_color); + dc.DrawLine (pen, buttonRectangle.X + 1, buttonRectangle.Bottom - 3, buttonRectangle.X + 2, buttonRectangle.Bottom - 2); + dc.DrawLine (pen, buttonRectangle.Right - 2, buttonRectangle.Bottom - 3, buttonRectangle.Right - 3, buttonRectangle.Bottom - 2); + + pen = ResPool.GetPen (button_edge_bottom_outer_color); + dc.DrawLine (pen, buttonRectangle.X, buttonRectangle.Bottom - 2, buttonRectangle.X + 1, buttonRectangle.Bottom - 1); + dc.DrawLine (pen, buttonRectangle.Right - 1, buttonRectangle.Bottom - 2, buttonRectangle.Right - 2, buttonRectangle.Bottom - 1); + } + } + + protected override void ButtonBase_DrawFocus( ButtonBase button, Graphics dc ) { + + if ( !button.is_enabled || button.flat_style == FlatStyle.Popup ) + return; + + Pen pen = ResPool.GetPen( button_focus_color ); + DashStyle old_dash_style = pen.DashStyle; + pen.DashStyle = DashStyle.Dot; + + Rectangle focus_rect = new Rectangle( button.ClientRectangle.X + 4, button.ClientRectangle.Y + 4, button.ClientRectangle.Width - 9, button.ClientRectangle.Height - 9 ); + + dc.DrawRectangle( pen, focus_rect ); + + pen.DashStyle = old_dash_style; + } + + // FIXME: remove if libgdiplus DrawOrMeasureString is fixed + protected override void ButtonBase_DrawText( ButtonBase button, Graphics dc ) { + if ( !( button is CheckBox ) && !( button is RadioButton ) ) { + Rectangle buttonRectangle = button.ClientRectangle; + Rectangle text_rect = Rectangle.Inflate( buttonRectangle, -4, -4 ); + + string text = button.Text; + + if ( text.Length > 1 ) { + SizeF sizef = dc.MeasureString( text, button.Font, text_rect.Width, button.text_format ); + + if ( (int)sizef.Width > text_rect.Width - 3 ) { + for ( int i = 1; i < text.Length + 1; i++ ) { + sizef = dc.MeasureString( text.Substring( 0, i ), button.Font, text_rect.Width, button.text_format ); + + if ( (int)sizef.Width > text_rect.Width - 3 ) { + text = text.Substring( 0, i - 1 ); + break; + } + } + } + } + + if ( button.is_pressed ) { + text_rect.X++; + text_rect.Y++; + } + + if ( button.is_enabled ) { + dc.DrawString( text, button.Font, ResPool.GetSolidBrush( button.ForeColor ), text_rect, button.text_format ); + } else { + if ( button.FlatStyle == FlatStyle.Flat || button.FlatStyle == FlatStyle.Popup ) { + dc.DrawString( text, button.Font, ResPool.GetSolidBrush( ControlPaint.DarkDark( this.ColorControl ) ), text_rect, button.text_format ); + } else { + CPDrawStringDisabled( dc, text, button.Font, ColorControlText, text_rect, button.text_format ); + } + } + } + } + #endregion // ButtonBase + + #region CheckBox + protected override void CheckBox_DrawCheckBox( Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle ) { + dc.FillRectangle( ResPool.GetSolidBrush( checkbox.BackColor ), checkbox.ClientRectangle ); + // render as per normal button + if ( checkbox.appearance == Appearance.Button ) { + DrawButtonBase( dc, checkbox.ClientRectangle, checkbox ); + } else { + // establish if we are rendering a flat style of some sort + if ( checkbox.FlatStyle == FlatStyle.Flat || checkbox.FlatStyle == FlatStyle.Popup ) { + DrawFlatStyleCheckBox( dc, checkbox_rectangle, checkbox ); + } else { + ControlPaint.DrawCheckBox( dc, checkbox_rectangle, state ); + } + } + } + #endregion // CheckBox + + #region ComboBox + + // Drawing + public override void DrawComboBoxEditDecorations( Graphics dc, ComboBox ctrl, Rectangle cl ) { + + Color inner_border = (ctrl.Focused && !ctrl.DroppedDown) ? combobox_focus_inner_border_color : Color.White; // Color.White should be the backcolor of the textctrl + Color border_color = (ctrl.Focused && !ctrl.DroppedDown) ? combobox_focus_border_color : combobox_border_color; + + Point[] border_points = null; + + Pen tmp_pen = ResPool.GetPen( inner_border ); + + dc.DrawLine( tmp_pen, cl.X + 1, cl.Y + 1, cl.X + 1, cl.Bottom - 2 ); + + if (!ctrl.Focused || (ctrl.Focused && ctrl.DropDownStyle == ComboBoxStyle.Simple)) + { + dc.DrawLine( tmp_pen, cl.X + 2, cl.Y + 1, cl.Right - 2, cl.Y + 1 ); + dc.DrawLine( tmp_pen, cl.X + 2, cl.Bottom - 2, cl.Right - 2, cl.Bottom - 2 ); + dc.DrawLine( tmp_pen, cl.Right - 2, cl.Y + 1, cl.Right - 2, cl.Bottom - 2 ); + } else { + dc.DrawLine( tmp_pen, cl.X + 2, cl.Y + 1, cl.Right - ctrl.combobox_info.button_rect.Width - 3, cl.Y + 1 ); + dc.DrawLine( tmp_pen, cl.X + 2, cl.Bottom - 2, cl.Right - ctrl.combobox_info.button_rect.Width - 3, cl.Bottom - 2 ); + } + if (ctrl.combobox_info.show_button) { + border_points = new Point[6] { + new Point( cl.Right - ctrl.combobox_info.button_rect.Width - 3, cl.Y ), + new Point( cl.X + 2, cl.Y ), + new Point( cl.X, cl.Y + 2 ), + new Point( cl.X, cl.Bottom - 3 ), + new Point( cl.X + 2, cl.Bottom - 1 ), + new Point( cl.Right - ctrl.combobox_info.button_rect.Width - 3, cl.Bottom - 1 ) + }; + } else { + border_points = new Point[9] { + new Point( cl.X + 2, cl.Y ), + new Point( cl.Right - 3, cl.Y ), + new Point( cl.Right - 1, cl.Y + 2 ), + new Point( cl.Right - 1, cl.Bottom - 3 ), + new Point( cl.Right - 3, cl.Bottom - 1 ), + new Point( cl.X + 2, cl.Bottom - 1 ), + new Point( cl.X, cl.Bottom - 3 ), + new Point( cl.X, cl.Y + 2 ), + new Point( cl.X + 2, cl.Y ) + }; + } + + tmp_pen = ResPool.GetPen( ctrl.Parent.BackColor ); + dc.DrawLine( tmp_pen, cl.X, cl.Y, cl.X, cl.Y + 1 ); + dc.DrawLine( tmp_pen, cl.X, cl.Bottom - 1, cl.X, cl.Bottom - 2 ); + dc.DrawLine( tmp_pen, cl.Right - 1, cl.Y, cl.Right - 1, cl.Y + 1 ); + dc.DrawLine( tmp_pen, cl.Right - 1, cl.Bottom - 1, cl.Right - 1, cl.Bottom - 2 ); + + dc.DrawLines( ResPool.GetPen( border_color ), border_points ); + + tmp_pen = ResPool.GetPen( edge_bottom_inner_color ); + dc.DrawLine( tmp_pen, cl.X, cl.Y + 1, cl.X + 1, cl.Y ); + dc.DrawLine( tmp_pen, cl.X, cl.Bottom - 2, cl.X + 1, cl.Bottom - 1 ); + dc.DrawLine( tmp_pen, cl.Right - 2, cl.Y, cl.Right - 1, cl.Y + 1 ); + dc.DrawLine( tmp_pen, cl.Right - 2, cl.Bottom - 1, cl.Right - 1, cl.Bottom - 2 ); + + // FIXME: + // here we need to draw the combobox button again, + // as DrawComboBoxEditDecorations paints over a fullsize combox button. + // ComboBox code calls CPDrawComboButton first then DrawComboBoxEditDecorations + // It would be better to move that code out of ComboBox + + if ( ctrl.combobox_info.show_button ) + { + control_parent_backcolor = ctrl.Parent.BackColor; + + ButtonState bs = ctrl.Enabled ? ctrl.combobox_info.button_status : ButtonState.Inactive; + + Rectangle crect = new Rectangle( ctrl.combobox_info.button_rect.X, ctrl.combobox_info.button_rect.Y - 2, + ctrl.combobox_info.button_rect.Width + 2, ctrl.combobox_info.button_rect.Height + 4 ); + CPDrawComboButton( dc, crect, bs ); + } + } + + public override void DrawComboListBoxDecorations( Graphics dc, ComboBox ctrl, Rectangle cl ) { + if ( ctrl.DropDownStyle == ComboBoxStyle.Simple ) { + DrawComboBoxEditDecorations( dc, ctrl, cl ); + } else { + dc.DrawRectangle( ResPool.GetPen( combobox_border_color ), cl.X, cl.Y, cl.Width - 1, cl.Height - 1 ); + } + } + #endregion ComboBox + + #region Menus + public override void DrawMenuItem( MenuItem item, DrawItemEventArgs e ) { + StringFormat string_format; + Rectangle rect_text = e.Bounds; + + if ( item.Visible == false ) + return; + + if ( item.MenuBar ) { + string_format = string_format_menu_menubar_text; + } else { + string_format = string_format_menu_text; + } + + if ( item.Separator ) { + e.Graphics.DrawLine( ThemeEngine.Current.ResPool.GetPen( menu_separator_color ), + e.Bounds.X, e.Bounds.Y + 1, e.Bounds.X + e.Bounds.Right - 4, e.Bounds.Y + 1 ); + + e.Graphics.DrawLine( ThemeEngine.Current.ResPool.GetPen( Color.White ), + e.Bounds.X, e.Bounds.Y + 2, e.Bounds.X + e.Bounds.Right - 4, e.Bounds.Y + 2 ); + + return; + } + + if ( !item.MenuBar ) + rect_text.X += ThemeEngine.Current.MenuCheckSize.Width; + + if ( item.BarBreak ) { /* Draw vertical break bar*/ + Rectangle rect = e.Bounds; + rect.Y++; + rect.Width = 3; + rect.Height = item.MenuHeight - 6; + + e.Graphics.DrawLine( ThemeEngine.Current.ResPool.GetPen( menu_separator_color ), + rect.X, rect.Y , rect.X, rect.Y + rect.Height ); + + e.Graphics.DrawLine( ThemeEngine.Current.ResPool.GetPen( ThemeEngine.Current.ColorControlLight ), + rect.X + 1, rect.Y , rect.X + 1, rect.Y + rect.Height ); + } + + Color color_text = ThemeEngine.Current.ColorMenuText; + Color color_back; + + /* Draw background */ + Rectangle rect_back = e.Bounds; + rect_back.X++; + rect_back.Width -= 2; + + if ( ( e.State & DrawItemState.Selected ) == DrawItemState.Selected ) { + color_text = ThemeEngine.Current.ColorHighlightText; + color_back = item.MenuBar ? theme_back_color : menu_background_color; + + using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( rect_back.X, rect_back.Y + 1 ), new Point( rect_back.X, rect_back.Bottom - 1 ), menuitem_gradient_first_color, menuitem_gradient_second_color ) ) { + e.Graphics.FillRectangle( lgbr, rect_back.X + 1, rect_back.Y + 1, rect_back.Width - 1, rect_back.Height - 1 ); + } + + rect_back.Height--; + Pen tmp_pen = ResPool.GetPen( menuitem_border_color ); + e.Graphics.DrawLine( tmp_pen, rect_back.X + 1, rect_back.Y, rect_back.Right - 1, rect_back.Y ); + e.Graphics.DrawLine( tmp_pen, rect_back.Right, rect_back.Y + 1, rect_back.Right, rect_back.Bottom - 1 ); + e.Graphics.DrawLine( tmp_pen, rect_back.Right - 1, rect_back.Bottom, rect_back.X + 1, rect_back.Bottom ); + e.Graphics.DrawLine( tmp_pen, rect_back.X, rect_back.Bottom - 1, rect_back.X, rect_back.Y + 1 ); + } else { + color_text = ThemeEngine.Current.ColorMenuText; + color_back = item.MenuBar ? theme_back_color : menu_background_color; + + e.Graphics.FillRectangle( ThemeEngine.Current.ResPool.GetSolidBrush( color_back ), rect_back ); + } + + if ( item.Enabled ) { + e.Graphics.DrawString( item.Text, e.Font, + ThemeEngine.Current.ResPool.GetSolidBrush( color_text ), + rect_text, string_format ); + + if ( !item.MenuBar && item.Shortcut != Shortcut.None && item.ShowShortcut ) { + string str = item.GetShortCutText( ); + Rectangle rect = rect_text; + rect.X = item.XTab; + rect.Width -= item.XTab; + + e.Graphics.DrawString( str, e.Font, ThemeEngine.Current.ResPool.GetSolidBrush( color_text ), + rect, string_format_menu_shortcut ); + } + } else { + ControlPaint.DrawStringDisabled( e.Graphics, item.Text, e.Font, + Color.Black, rect_text, string_format ); + } + + /* Draw arrow */ + if ( item.MenuBar == false && item.IsPopup ) { + int cx = ThemeEngine.Current.MenuCheckSize.Width; + int cy = ThemeEngine.Current.MenuCheckSize.Height; + using ( Bitmap bmp = new Bitmap( cx, cy ) ) { + using ( Graphics dc = Graphics.FromImage( bmp ) ) { + SmoothingMode old_smoothing_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + + Rectangle rect_arrow = new Rectangle( 0, 0, cx, cy ); + ControlPaint.DrawMenuGlyph( dc, rect_arrow, MenuGlyph.Arrow ); + bmp.MakeTransparent( ); + + if ( item.Enabled ) { + e.Graphics.DrawImage( bmp, e.Bounds.X + e.Bounds.Width - cx, + e.Bounds.Y + ( ( e.Bounds.Height - cy ) / 2 ) ); + } else { + ControlPaint.DrawImageDisabled( e.Graphics, bmp, e.Bounds.X + e.Bounds.Width - cx, + e.Bounds.Y + ( ( e.Bounds.Height - cy ) / 2 ), color_back ); + } + + dc.SmoothingMode = old_smoothing_mode; + } + } + } + + /* Draw checked or radio */ + if ( item.MenuBar == false && item.Checked ) { + + Rectangle area = e.Bounds; + int cx = ThemeEngine.Current.MenuCheckSize.Width; + int cy = ThemeEngine.Current.MenuCheckSize.Height; + using ( Bitmap bmp = new Bitmap( cx, cy ) ) { + using ( Graphics gr = Graphics.FromImage( bmp ) ) { + Rectangle rect_arrow = new Rectangle( 0, 0, cx, cy ); + + if ( item.RadioCheck ) + ControlPaint.DrawMenuGlyph( gr, rect_arrow, MenuGlyph.Bullet ); + else + ControlPaint.DrawMenuGlyph( gr, rect_arrow, MenuGlyph.Checkmark ); + + bmp.MakeTransparent( ); + e.Graphics.DrawImage( bmp, area.X, e.Bounds.Y + ( ( e.Bounds.Height - cy ) / 2 ) ); + } + } + } + } + + public override void DrawPopupMenu( Graphics dc, Menu menu, Rectangle cliparea, Rectangle rect ) { + + dc.FillRectangle( ThemeEngine.Current.ResPool.GetSolidBrush + ( menu_background_color ), cliparea ); + + /* Draw menu borders */ + dc.DrawRectangle( ResPool.GetPen( menu_border_color ), rect.X, rect.Y, rect.Width - 1, rect.Height - 1 ); + + // inner border + Pen tmp_pen = ResPool.GetPen( Color.White ); + dc.DrawLine( tmp_pen, rect.X + 1, rect.Y + 1, rect.Right - 2, rect.Y + 1 ); + dc.DrawLine( tmp_pen, rect.X + 1, rect.Y + 2, rect.X + 1, rect.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( menu_inner_border_color ); + dc.DrawLine( tmp_pen, rect.Right - 2, rect.Y + 2, rect.Right - 2, rect.Bottom - 2 ); + dc.DrawLine( tmp_pen, rect.Right - 3, rect.Bottom - 2, rect.X + 2, rect.Bottom - 2 ); + + for ( int i = 0; i < menu.MenuItems.Count; i++ ) + if ( cliparea.IntersectsWith( menu.MenuItems[ i ].bounds ) ) { + MenuItem item = menu.MenuItems[ i ]; + item.MenuHeight = menu.Height; + item.PerformDrawItem( new DrawItemEventArgs( dc, ThemeEngine.Current.MenuFont, + item.bounds, i, item.Status ) ); + } + } + #endregion // Menus + + #region ProgressBar + public override void DrawProgressBar( Graphics dc, Rectangle clip_rect, ProgressBar ctrl ) { + Rectangle client_area = ctrl.client_area; + int barpos_pixels; + Rectangle bar = ctrl.client_area; + + barpos_pixels = ( ( ctrl.Value - ctrl.Minimum ) * client_area.Width ) / ( ctrl.Maximum - ctrl.Minimum ); + + bar.Width = barpos_pixels + 1; + + // Draw bar background + dc.FillRectangle( ResPool.GetSolidBrush( menu_separator_color ), ctrl.ClientRectangle.X + 1, ctrl.ClientRectangle.Y + 1, ctrl.ClientRectangle.Width - 2, ctrl.ClientRectangle.Height - 2 ); + + /* Draw border */ + Pen tmp_pen = ResPool.GetPen( progressbar_edge_dot_color ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Y, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Y + 1 ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Bottom - 1, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Bottom - 2 ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Y, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Y + 1 ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Bottom - 1, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X + 1, ctrl.ClientRectangle.Y, ctrl.ClientRectangle.Right - 2, ctrl.ClientRectangle.Y ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Y + 1, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Bottom - 2 ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X + 1, ctrl.ClientRectangle.Bottom - 1, ctrl.ClientRectangle.Right - 2, ctrl.ClientRectangle.Bottom - 1 ); + dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Y + 1, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Bottom - 2 ); + + if ( barpos_pixels == 0 ) + return; + + // Draw bar + dc.DrawRectangle( ResPool.GetPen( combobox_focus_border_color ), bar.X - 1, bar.Y - 1, bar.Width, bar.Height + 1 ); + tmp_pen = ResPool.GetPen( progressbar_inner_border_color ); + dc.DrawLine( tmp_pen, bar.X, bar.Y, bar.Right - 2, bar.Y ); + dc.DrawLine( tmp_pen, bar.X, bar.Y, bar.X, bar.Bottom - 1 ); + + using ( Bitmap bmp = new Bitmap( bar.Width - 2, bar.Height - 1 ) ) { + using ( Graphics gr = Graphics.FromImage( bmp ) ) { + gr.FillRectangle( ResPool.GetSolidBrush( tab_focus_color ), 0, 0, bmp.Width, bmp.Height ); + + LinearGradientBrush lgbr = new LinearGradientBrush( new Rectangle( 0, 0, bmp.Height, bmp.Height ), progressbar_first_gradient_color, progressbar_second_gradient_color, 0.0f, true ); + + lgbr.RotateTransform( 45.0f, MatrixOrder.Append ); + + float pen_width = bmp.Height / 2; + + Pen pen = new Pen( lgbr, pen_width ); + + int add = bmp.Height + (int)pen.Width / 2; + + int x_top = 0; + int x_bottom = - bmp.Height; + + while ( x_bottom < bmp.Width ) { + gr.DrawLine( pen, x_top, 0, x_bottom, bmp.Height ); + x_top += add; + x_bottom += add; + } + pen.Dispose( ); + lgbr.Dispose( ); + } + + dc.DrawImage( bmp, bar.X + 1, bar.Y + 1 ); + } + } + #endregion // ProgressBar + + #region RadioButton + protected override void RadioButton_DrawButton( RadioButton radio_button, Graphics dc, ButtonState state, Rectangle radiobutton_rectangle ) { + SolidBrush sb = new SolidBrush( radio_button.BackColor ); + dc.FillRectangle( sb, radio_button.ClientRectangle ); + sb.Dispose( ); + + if ( radio_button.appearance == Appearance.Button ) { + if ( radio_button.FlatStyle == FlatStyle.Flat || radio_button.FlatStyle == FlatStyle.Popup ) { + DrawFlatStyleButton( dc, radio_button.ClientRectangle, radio_button ); + } else { + DrawButtonBase( dc, radio_button.ClientRectangle, radio_button ); + } + } else { + // establish if we are rendering a flat style of some sort + if ( radio_button.FlatStyle == FlatStyle.Flat || radio_button.FlatStyle == FlatStyle.Popup ) { + DrawFlatStyleRadioButton( dc, radiobutton_rectangle, radio_button ); + } else { + ControlPaint.DrawRadioButton( dc, radiobutton_rectangle, state ); + } + } + } + + protected override void RadioButton_DrawFocus( RadioButton radio_button, Graphics dc, Rectangle text_rectangle ) { + if ( radio_button.Focused && radio_button.appearance != Appearance.Button ) { + if ( radio_button.FlatStyle != FlatStyle.Flat && radio_button.FlatStyle != FlatStyle.Popup ) { + DrawInnerFocusRectangle( dc, text_rectangle, radio_button.BackColor ); + } + } + } + + // renders a radio button with the Flat and Popup FlatStyle + protected void DrawFlatStyleRadioButton (Graphics dc, Rectangle rectangle, RadioButton radio_button) + { + if (radio_button.Enabled) { + // draw the outer flatstyle arcs + if (radio_button.FlatStyle == FlatStyle.Flat) { + dc.DrawArc (ResPool.GetPen (radio_button.ForeColor), rectangle, 0, 359); + + // fill in the area depending on whether or not the mouse is hovering + if (radio_button.is_entered && radio_button.Capture) { + dc.FillPie (ResPool.GetSolidBrush (ControlPaint.Light (radio_button.BackColor)), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359); + } else { + dc.FillPie (ResPool.GetSolidBrush (ControlPaint.LightLight (radio_button.BackColor)), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359); + } + } else { + // must be a popup radio button + // fill the control + dc.FillPie (ResPool.GetSolidBrush (ControlPaint.LightLight (radio_button.BackColor)), rectangle, 0, 359); + + if (radio_button.is_entered || radio_button.Capture) { + // draw the popup 3d button knob + dc.DrawArc (ResPool.GetPen (ControlPaint.Light (radio_button.BackColor)), rectangle.X+1, rectangle.Y+1, rectangle.Width-2, rectangle.Height-2, 0, 359); + + dc.DrawArc (ResPool.GetPen (ControlPaint.Dark (radio_button.BackColor)), rectangle, 135, 180); + dc.DrawArc (ResPool.GetPen (ControlPaint.LightLight (radio_button.BackColor)), rectangle, 315, 180); + + } else { + // just draw lighter flatstyle outer circle + dc.DrawArc (ResPool.GetPen (ControlPaint.Dark (this.ColorControl)), rectangle, 0, 359); + } + } + } else { + // disabled + // fill control background color regardless of actual backcolor + dc.FillPie (ResPool.GetSolidBrush (this.ColorControl), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359); + // draw the ark as control dark + dc.DrawArc (ResPool.GetPen (ControlPaint.Dark(this.ColorControl)), rectangle, 0, 359); + } + + // draw the check + if (radio_button.Checked) { + SmoothingMode old_smoothing_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + + CL_Draw_RadioButton_Dot (dc, rectangle, true, false); + + dc.SmoothingMode = old_smoothing_mode; + } + } + #endregion // RadioButton + + #region ScrollBar + public override void DrawScrollBar( Graphics dc, Rectangle clip, ScrollBar bar ) { + int scrollbutton_width = bar.scrollbutton_width; + int scrollbutton_height = bar.scrollbutton_height; + Rectangle first_arrow_area; + Rectangle second_arrow_area; + Rectangle thumb_pos; + + thumb_pos = bar.ThumbPos; + + if ( bar.vert ) { + first_arrow_area = new Rectangle( 0, 0, bar.Width, scrollbutton_height + 1 ); + bar.FirstArrowArea = first_arrow_area; + + second_arrow_area = new Rectangle( 0, bar.ClientRectangle.Height - scrollbutton_height - 1, bar.Width, scrollbutton_height + 1 ); + bar.SecondArrowArea = second_arrow_area; + + thumb_pos.Width = bar.Width; + bar.ThumbPos = thumb_pos; + + /* Background */ + switch ( bar.thumb_moving ) { + case ScrollBar.ThumbMoving.None: { + ScrollBar_Vertical_Draw_ThumbMoving_None( scrollbutton_height, bar, clip, dc ); + break; + } + case ScrollBar.ThumbMoving.Forward: { + ScrollBar_Vertical_Draw_ThumbMoving_Forward( scrollbutton_height, bar, thumb_pos, clip, dc ); + break; + } + + case ScrollBar.ThumbMoving.Backwards: { + ScrollBar_Vertical_Draw_ThumbMoving_Backwards( scrollbutton_height, bar, thumb_pos, clip, dc ); + break; + } + + default: + break; + } + + /* Buttons */ + if ( clip.IntersectsWith( first_arrow_area ) ) + CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Up, bar.firstbutton_state ); + if ( clip.IntersectsWith( second_arrow_area ) ) + CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Down, bar.secondbutton_state ); + } else { + first_arrow_area = new Rectangle( 0, 0, scrollbutton_width + 1, bar.Height ); + bar.FirstArrowArea = first_arrow_area; + + second_arrow_area = new Rectangle( bar.ClientRectangle.Width - scrollbutton_width - 1, 0, scrollbutton_width + 1, bar.Height ); + bar.SecondArrowArea = second_arrow_area; + + thumb_pos.Height = bar.Height; + bar.ThumbPos = thumb_pos; + + /* Background */ + switch ( bar.thumb_moving ) { + case ScrollBar.ThumbMoving.None: { + ScrollBar_Horizontal_Draw_ThumbMoving_None( scrollbutton_width, bar, clip, dc ); + break; + } + + case ScrollBar.ThumbMoving.Forward: { + ScrollBar_Horizontal_Draw_ThumbMoving_Forward( scrollbutton_width, thumb_pos, bar, clip, dc ); + break; + } + + case ScrollBar.ThumbMoving.Backwards: { + ScrollBar_Horizontal_Draw_ThumbMoving_Backwards( scrollbutton_width, thumb_pos, bar, clip, dc ); + break; + } + } + + /* Buttons */ + if ( clip.IntersectsWith( first_arrow_area ) ) + CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Left, bar.firstbutton_state ); + if ( clip.IntersectsWith( second_arrow_area ) ) + CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Right, bar.secondbutton_state ); + } + + /* Thumb */ + ScrollBar_DrawThumb( bar, thumb_pos, clip, dc ); + } + + protected override void ScrollBar_DrawThumb( ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) { + if ( bar.Enabled && thumb_pos.Width > 0 && thumb_pos.Height > 0 && clip.IntersectsWith( thumb_pos ) ) + DrawScrollBarThumb( dc, thumb_pos, bar ); + } + + protected override void ScrollBar_Vertical_Draw_ThumbMoving_None( int scrollbutton_height, ScrollBar bar, Rectangle clip, Graphics dc ) { + Rectangle r = new Rectangle( 0, + scrollbutton_height, bar.ClientRectangle.Width, bar.ClientRectangle.Height - ( scrollbutton_height * 2 ) ); + Rectangle intersect = Rectangle.Intersect( clip, r ); + + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.X, intersect.Bottom - 1 ); + dc.DrawLine( pen, intersect.Right - 1, intersect.Y, intersect.Right - 1, intersect.Bottom - 1 ); + } + } + + protected override void ScrollBar_Vertical_Draw_ThumbMoving_Forward( int scrollbutton_height, ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) { + Rectangle r = new Rectangle( 0, scrollbutton_height, + bar.ClientRectangle.Width, thumb_pos.Y - scrollbutton_height ); + Rectangle intersect = Rectangle.Intersect( clip, r ); + + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.X, intersect.Bottom - 1 ); + dc.DrawLine( pen, intersect.Right - 1, intersect.Y, intersect.Right - 1, intersect.Bottom - 1 ); + } + + r.X = 0; + r.Y = thumb_pos.Y + thumb_pos.Height; + r.Width = bar.ClientRectangle.Width; + r.Height = bar.ClientRectangle.Height - ( thumb_pos.Y + thumb_pos.Height ) - scrollbutton_height; + + intersect = Rectangle.Intersect( clip, r ); + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.X, intersect.Bottom - 1 ); + dc.DrawLine( pen, intersect.Right - 1, intersect.Y, intersect.Right - 1, intersect.Bottom - 1 ); + } + } + + protected override void ScrollBar_Vertical_Draw_ThumbMoving_Backwards( int scrollbutton_height, ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) { + Rectangle r = new Rectangle( 0, scrollbutton_height, + bar.ClientRectangle.Width, thumb_pos.Y - scrollbutton_height ); + Rectangle intersect = Rectangle.Intersect( clip, r ); + + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.X, intersect.Bottom - 1 ); + dc.DrawLine( pen, intersect.Right - 1, intersect.Y, intersect.Right - 1, intersect.Bottom - 1 ); + } + + r.X = 0; + r.Y = thumb_pos.Y + thumb_pos.Height; + r.Width = bar.ClientRectangle.Width; + r.Height = bar.ClientRectangle.Height - ( thumb_pos.Y + thumb_pos.Height ) - scrollbutton_height; + + intersect = Rectangle.Intersect( clip, r ); + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.X, intersect.Bottom - 1 ); + dc.DrawLine( pen, intersect.Right - 1, intersect.Y, intersect.Right - 1, intersect.Bottom - 1 ); + } + } + + protected override void ScrollBar_Horizontal_Draw_ThumbMoving_None( int scrollbutton_width, ScrollBar bar, Rectangle clip, Graphics dc ) { + Rectangle r = new Rectangle( scrollbutton_width, + 0, bar.ClientRectangle.Width - ( scrollbutton_width * 2 ), bar.ClientRectangle.Height ); + Rectangle intersect = Rectangle.Intersect( clip, r ); + + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.Right - 1, intersect.Y ); + dc.DrawLine( pen, intersect.X, intersect.Bottom - 1, intersect.Right - 1, intersect.Bottom - 1 ); + } + } + + protected override void ScrollBar_Horizontal_Draw_ThumbMoving_Forward( int scrollbutton_width, Rectangle thumb_pos, ScrollBar bar, Rectangle clip, Graphics dc ) { + Rectangle r = new Rectangle( scrollbutton_width, 0, + thumb_pos.X - scrollbutton_width, bar.ClientRectangle.Height ); + Rectangle intersect = Rectangle.Intersect( clip, r ); + + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.Right - 1, intersect.Y ); + dc.DrawLine( pen, intersect.X, intersect.Bottom - 1, intersect.Right - 1, intersect.Bottom - 1 ); + } + + r.X = thumb_pos.X + thumb_pos.Width; + r.Y = 0; + r.Width = bar.ClientRectangle.Width - ( thumb_pos.X + thumb_pos.Width ) - scrollbutton_width; + r.Height = bar.ClientRectangle.Height; + + intersect = Rectangle.Intersect( clip, r ); + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.Right - 1, intersect.Y ); + dc.DrawLine( pen, intersect.X, intersect.Bottom - 1, intersect.Right - 1, intersect.Bottom - 1 ); + } + } + + protected override void ScrollBar_Horizontal_Draw_ThumbMoving_Backwards( int scrollbutton_width, Rectangle thumb_pos, ScrollBar bar, Rectangle clip, Graphics dc ) { + Rectangle r = new Rectangle( scrollbutton_width, 0, + thumb_pos.X - scrollbutton_width, bar.ClientRectangle.Height ); + Rectangle intersect = Rectangle.Intersect( clip, r ); + + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.Right - 1, intersect.Y ); + dc.DrawLine( pen, intersect.X, intersect.Bottom - 1, intersect.Right - 1, intersect.Bottom - 1 ); + } + + r.X = thumb_pos.X + thumb_pos.Width; + r.Y = 0; + r.Width = bar.ClientRectangle.Width - ( thumb_pos.X + thumb_pos.Width ) - scrollbutton_width; + r.Height = bar.ClientRectangle.Height; + + intersect = Rectangle.Intersect( clip, r ); + if ( intersect != Rectangle.Empty ) { + dc.FillRectangle( ResPool.GetSolidBrush( scrollbar_background_color ), intersect ); + Pen pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, intersect.X, intersect.Y, intersect.Right - 1, intersect.Y ); + dc.DrawLine( pen, intersect.X, intersect.Bottom - 1, intersect.Right - 1, intersect.Bottom - 1 ); + } + } + #endregion // ScrollBar + + #region StatusBar + protected override void DrawStatusBarPanel( Graphics dc, Rectangle area, int index, + SolidBrush br_forecolor, StatusBarPanel panel ) { + int border_size = 3; // this is actually const, even if the border style is none + + area.Height -= border_size; + if ( panel.BorderStyle != StatusBarPanelBorderStyle.None ) { + dc.DrawRectangle( ResPool.GetPen( pressed_inner_border_dark_color ), area ); + } + + if ( panel.Style == StatusBarPanelStyle.OwnerDraw ) { + StatusBarDrawItemEventArgs e = new StatusBarDrawItemEventArgs( + dc, panel.Parent.Font, area, index, DrawItemState.Default, + panel, panel.Parent.ForeColor, panel.Parent.BackColor ); + panel.Parent.OnDrawItemInternal( e ); + return; + } + + int left = area.Left; + if ( panel.Icon != null ) { + left += 2; + dc.DrawIcon( panel.Icon, left, area.Top ); + left += panel.Icon.Width; + } + + if ( panel.Text == String.Empty ) + return; + + string text = panel.Text; + StringFormat string_format = new StringFormat( ); + string_format.Trimming = StringTrimming.Character; + string_format.FormatFlags = StringFormatFlags.NoWrap; + + if ( text[ 0 ] == '\t' ) { + string_format.Alignment = StringAlignment.Center; + text = text.Substring( 1 ); + if ( text[ 0 ] == '\t' ) { + string_format.Alignment = StringAlignment.Far; + text = text.Substring( 1 ); + } + } + + int x = left + border_size; + int y = border_size + 2; + Rectangle r = new Rectangle( x, y, + area.Right - x - border_size, + area.Bottom - y - border_size ); + + dc.DrawString( text, panel.Parent.Font, br_forecolor, r, string_format ); + } + #endregion // StatusBar + + // FIXME: regions near the borders don't get filled with the correct backcolor + // TODO: TabAlignment.Left and TabAlignment.Bottom + public override void DrawTabControl( Graphics dc, Rectangle area, TabControl tab ) { + if (tab.Parent != null) + dc.FillRectangle( ResPool.GetSolidBrush( tab.Parent.BackColor ), area ); + else + dc.FillRectangle( ResPool.GetSolidBrush( tab.BackColor ), area ); + Rectangle panel_rect = GetTabPanelRectExt( tab ); + + if ( tab.Appearance == TabAppearance.Normal ) { + + switch ( tab.Alignment ) { + case TabAlignment.Top: + // inner border... + Pen pen = ResPool.GetPen( Color.White ); + + dc.DrawLine( pen, panel_rect.Left + 1, panel_rect.Top, panel_rect.Left + 1, panel_rect.Bottom - 1 ); + dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Top , panel_rect.Right - 2, panel_rect.Top ); + + pen = ResPool.GetPen( tab_inner_border_color ); + dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Top + 1, panel_rect.Right - 2, panel_rect.Bottom - 2 ); + dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Bottom - 1, panel_rect.Left + 2, panel_rect.Bottom - 1 ); + + // border + pen = ResPool.GetPen( tab_border_color ); + + dc.DrawLine( pen, panel_rect.Left, panel_rect.Top - 1, panel_rect.Right - 1, panel_rect.Top - 1 ); + dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Top - 1, panel_rect.Right - 1, panel_rect.Bottom - 2 ); + dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Bottom - 2, panel_rect.Right - 3, panel_rect.Bottom ); + dc.DrawLine( pen, panel_rect.Right - 3, panel_rect.Bottom, panel_rect.Left + 2, panel_rect.Bottom ); + dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Bottom, panel_rect.Left, panel_rect.Bottom - 2 ); + dc.DrawLine( pen, panel_rect.Left, panel_rect.Bottom - 2, panel_rect.Left, panel_rect.Top - 1 ); + break; + + // FIXME: the size of the tab page is to big to draw the upper inner white border + case TabAlignment.Right: + // inner border... + pen = ResPool.GetPen( Color.White ); + + dc.DrawLine( pen, panel_rect.Left + 1, panel_rect.Top + 1, panel_rect.Left + 1, panel_rect.Bottom - 1 ); + dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Top + 1 , panel_rect.Right - 2, panel_rect.Top + 1 ); + + pen = ResPool.GetPen( tab_inner_border_color ); + dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Top + 1, panel_rect.Right - 2, panel_rect.Bottom - 2 ); + dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Bottom - 1, panel_rect.Left + 2, panel_rect.Bottom - 1 ); + + // border + pen = ResPool.GetPen( tab_border_color ); + + dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Top, panel_rect.Right - 1, panel_rect.Top ); + dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Top, panel_rect.Right - 1, panel_rect.Bottom ); + dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Bottom, panel_rect.Left + 2, panel_rect.Bottom ); + dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Bottom, panel_rect.Left, panel_rect.Bottom - 2 ); + dc.DrawLine( pen, panel_rect.Left, panel_rect.Bottom - 2, panel_rect.Left, panel_rect.Top + 2 ); + dc.DrawLine( pen, panel_rect.Left, panel_rect.Top + 2, panel_rect.Left + 2, panel_rect.Top ); + break; + } + } + + if (tab.Alignment == TabAlignment.Top) { + for (int r = tab.TabPages.Count; r > 0; r--) { + for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) { + if (i == tab.SelectedIndex) + continue; + if (r != tab.TabPages [i].Row) + continue; + Rectangle rect = tab.GetTabRect (i); + if (!rect.IntersectsWith (area)) + continue; + DrawTab (dc, tab.TabPages [i], tab, rect, false); + } + } + } else { + for (int r = 0; r < tab.TabPages.Count; r++) { + for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) { + if (i == tab.SelectedIndex) + continue; + if (r != 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 = GetTabControlRightScrollRect (tab); + Rectangle left = GetTabControlLeftScrollRect (tab); + CPDrawScrollButton (dc, right, ScrollButton.Right, tab.RightSliderState); + CPDrawScrollButton (dc, left, ScrollButton.Left, tab.LeftSliderState); + } + } + + protected override int DrawTab (Graphics dc, TabPage page, TabControl tab, Rectangle bounds, bool is_selected) + { + int FlatButtonSpacing = 8; + Rectangle interior; + int res = bounds.Width; + + if (page.BackColor != tab_selected_gradient_second_color) + page.BackColor = tab_selected_gradient_second_color; + + // we can't fill the background right away because the bounds might be adjusted if the tab is selected + + StringFormat string_format = new StringFormat (); + + if (tab.Appearance == TabAppearance.Buttons || tab.Appearance == TabAppearance.FlatButtons) { + dc.FillRectangle (ResPool.GetSolidBrush (tab_selected_gradient_second_color), bounds); + + // Separators + if (tab.Appearance == TabAppearance.FlatButtons) { + int width = bounds.Width; + bounds.Width += (FlatButtonSpacing - 2); + res = bounds.Width; + CPDrawBorder3D (dc, bounds, Border3DStyle.Etched, Border3DSide.Right); + bounds.Width = width; + } + + if (is_selected) { + CPDrawBorder3D (dc, bounds, Border3DStyle.Sunken, Border3DSide.All); + } else if (tab.Appearance != TabAppearance.FlatButtons) { + CPDrawBorder3D (dc, bounds, Border3DStyle.Raised, Border3DSide.All); + } + + interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 4, bounds.Height - 4); + + string_format.Alignment = StringAlignment.Center; + string_format.LineAlignment = StringAlignment.Center; + string_format.FormatFlags = StringFormatFlags.NoWrap; + } else { + Color tab_first_color = is_selected ? tab_selected_gradient_first_color : tab_not_selected_gradient_first_color; + Color tab_second_color = is_selected ? tab_selected_gradient_second_color : tab_not_selected_gradient_second_color; + + switch (tab.Alignment) { + case TabAlignment.Top: + + Rectangle tab_interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 2, bounds.Height - 3); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left + 2, bounds.Top + 2), new Point (bounds.Left + 2, bounds.Bottom), tab_first_color, tab_second_color)) { + dc.FillRectangle (lgbr, tab_interior); + } + + // edges + Pen tmp_pen = ResPool.GetPen (tab_edge_color); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 1, bounds.Left + 1, bounds.Top); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Top, bounds.Right, bounds.Top + 1); + + // inner border + tmp_pen = ResPool.GetPen (Color.White); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Left + 1, bounds.Top + 1); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 1, bounds.Right - 1, bounds.Top + 1); + + // border + tmp_pen = ResPool.GetPen (border_pressed_dark_color); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 2, bounds.Left + 2, bounds.Top); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top, bounds.Right - 2, bounds.Top); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top, bounds.Right, bounds.Top + 2); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Left, bounds.Bottom - 1), border_pressed_dark_color, border_pressed_light_color)) { + int diff = is_selected ? 4 : 3; + dc.FillRectangle (lgbr, bounds.Left, bounds.Top + 2, 1, bounds.Height - diff); + dc.FillRectangle (lgbr, bounds.Right, bounds.Top + 2, 1, bounds.Height - diff); + } + + if (page.Focused) { + tmp_pen = ResPool.GetPen (tab_focus_color); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top + 2, bounds.Right - 1, bounds.Top + 2); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 1, bounds.Right - 2, bounds.Top + 1); + + tmp_pen = ResPool.GetPen (tab_top_border_focus_color); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 2, bounds.Left + 2, bounds.Top); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top, bounds.Right - 2, bounds.Top); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top, bounds.Right, bounds.Top + 2); + } + + interior = new Rectangle (bounds.Left + 4, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8); + + string_format.Alignment = StringAlignment.Center; + string_format.LineAlignment = StringAlignment.Center; + string_format.FormatFlags = StringFormatFlags.NoWrap; + + break; + + case TabAlignment.Bottom: + + tab_interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 2, bounds.Height - 3); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left + 2, bounds.Top + 2), new Point (bounds.Left + 2, bounds.Bottom - 1), tab_first_color, tab_second_color)) { + dc.FillRectangle (lgbr, tab_interior); + } + + // edges + tmp_pen = ResPool.GetPen (tab_edge_color); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 1, bounds.Left + 1, bounds.Bottom); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom, bounds.Right, bounds.Bottom - 1); + + // inner border + tmp_pen = ResPool.GetPen (Color.White); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Left + 1, bounds.Top + 2); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1); + + // border + tmp_pen = ResPool.GetPen (border_pressed_dark_color); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom, bounds.Right - 2, bounds.Bottom); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Bottom, bounds.Right, bounds.Bottom - 2); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Left, bounds.Bottom - 1), border_pressed_light_color, border_pressed_dark_color)) { + int diff = is_selected ? 4 : 3; + dc.FillRectangle (lgbr, bounds.Left, bounds.Top + 2, 1, bounds.Height - diff); + dc.FillRectangle (lgbr, bounds.Right, bounds.Top + 2, 1, bounds.Height - diff); + } + + if (page.Focused) { + tmp_pen = ResPool.GetPen (tab_focus_color); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Right - 1, bounds.Bottom - 2); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom - 1); + + tmp_pen = ResPool.GetPen (tab_top_border_focus_color); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom, bounds.Right - 2, bounds.Bottom); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Bottom, bounds.Right, bounds.Bottom - 2); + } + + interior = new Rectangle (bounds.Left + 4, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8); + + string_format.Alignment = StringAlignment.Center; + string_format.LineAlignment = StringAlignment.Center; + string_format.FormatFlags = StringFormatFlags.NoWrap; + + break; + + case TabAlignment.Left: + + int w_diff = is_selected ? 2 : 0; + + tab_interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 2 - w_diff, bounds.Height - 2); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left + 2, bounds.Top + 2), new Point (bounds.Right - w_diff, bounds.Top + 2), tab_first_color, tab_second_color)) { + dc.FillRectangle (lgbr, tab_interior); + } + + // edges + tmp_pen = ResPool.GetPen (tab_edge_color); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top, bounds.Left, bounds.Top + 1); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 1, bounds.Left + 1, bounds.Bottom); + + // inner border + tmp_pen = ResPool.GetPen (Color.White); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 1, bounds.Right - 3, bounds.Top + 1); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top + 2, bounds.Left + 1, bounds.Bottom - 2); + + // border + tmp_pen = ResPool.GetPen (border_pressed_dark_color); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top, bounds.Left, bounds.Top + 2); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 2, bounds.Left, bounds.Bottom - 2); + dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Right - 2, bounds.Top + 2), border_pressed_dark_color, border_pressed_light_color)) { + int diff = is_selected ? 4 : 2; + + dc.FillRectangle (lgbr, bounds.Left + 2, bounds.Top, bounds.Width - diff, 1); + dc.FillRectangle (lgbr, bounds.Left + 2, bounds.Bottom, bounds.Width - diff, 1); + } + + if (page.Focused) { + tmp_pen = ResPool.GetPen (tab_focus_color); + dc.DrawLine (tmp_pen, bounds.Left + 3, bounds.Top + 1, bounds.Left + 3, bounds.Bottom - 1); + dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 2, bounds.Left + 2, bounds.Bottom - 2); + + tmp_pen = ResPool.GetPen (tab_top_border_focus_color); + dc.DrawLine (tmp_pen, bounds.Left + 3, bounds.Top, bounds.Left + 1, bounds.Top + 2); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top + 2, bounds.Left + 1, bounds.Bottom - 2); + dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Left + 3, bounds.Bottom); + } + + interior = new Rectangle (bounds.Left + 2, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8); + + string_format.Alignment = StringAlignment.Center; + string_format.LineAlignment = StringAlignment.Center; + string_format.FormatFlags = StringFormatFlags.NoWrap; + string_format.FormatFlags = StringFormatFlags.DirectionVertical; + + break; + + default: + // TabAlignment.Right + + tab_interior = new Rectangle (bounds.Left, bounds.Top + 2, bounds.Width - 2, bounds.Height - 2); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Right, bounds.Top + 2), tab_second_color, tab_first_color)) { + dc.FillRectangle (lgbr, tab_interior); + } + + int l_diff = is_selected ? 2 : 0; + + // edges + tmp_pen = ResPool.GetPen (tab_edge_color); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top, bounds.Right - 1, bounds.Top + 1); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom); + + // inner border + tmp_pen = ResPool.GetPen (Color.White); + dc.DrawLine (tmp_pen, bounds.Left + l_diff, bounds.Top + 1, bounds.Right - 2, bounds.Top + 1); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2); + + // border + tmp_pen = ResPool.GetPen (border_pressed_dark_color); + dc.DrawLine (tmp_pen, bounds.Right - 3, bounds.Top, bounds.Right - 1, bounds.Top + 2); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Top + 2, bounds.Right - 1, bounds.Bottom - 2); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom - 2, bounds.Right - 3, bounds.Bottom); + + using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Right - 2, bounds.Top + 2), border_pressed_light_color, border_pressed_dark_color)) { + int diff = is_selected ? 4 : 2; + + dc.FillRectangle (lgbr, bounds.Left + l_diff, bounds.Top, bounds.Width - diff, 1); + dc.FillRectangle (lgbr, bounds.Left + l_diff, bounds.Bottom, bounds.Width - diff, 1); + } + + if (page.Focused) { + tmp_pen = ResPool.GetPen (tab_focus_color); + dc.DrawLine (tmp_pen, bounds.Right - 3, bounds.Top + 1, bounds.Right - 3, bounds.Bottom - 1); + dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2); + + tmp_pen = ResPool.GetPen (tab_top_border_focus_color); + dc.DrawLine (tmp_pen, bounds.Right - 3, bounds.Top, bounds.Right - 1, bounds.Top + 2); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Top + 2, bounds.Right - 1, bounds.Bottom - 2); + dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom - 2, bounds.Right - 3, bounds.Bottom); + } + + interior = new Rectangle (bounds.Left + 4, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8); + + string_format.Alignment = StringAlignment.Center; + string_format.LineAlignment = StringAlignment.Center; + string_format.FormatFlags = StringFormatFlags.NoWrap; + string_format.FormatFlags = StringFormatFlags.DirectionVertical; + + break; + } + } + + if (tab.DrawMode == TabDrawMode.Normal && page.Text != null) { + if (tab.Alignment == TabAlignment.Left) { + int wo = interior.Width / 2; + int ho = interior.Height / 2; + dc.TranslateTransform (interior.X + wo, interior.Y + ho); + dc.RotateTransform (180); + dc.DrawString (page.Text, page.Font, ThemeEngine.Current.ResPool.GetSolidBrush (SystemColors.ControlText), 0, 0, string_format); + dc.ResetTransform (); + } else { + dc.DrawString (page.Text, page.Font, + ThemeEngine.Current.ResPool.GetSolidBrush (SystemColors.ControlText), + interior, string_format); + } + } 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; + } + + return res; + } + + public override void CPDrawComboButton( Graphics dc, Rectangle rectangle, ButtonState state ) { + Point[] arrow = new Point[ 3 ]; + Point P1; + Point P2; + Point P3; + int centerX; + int centerY; + int shiftX; + int shiftY; + Rectangle rect; + + bool pushed = false; + + Color first_color = Color.White; + Color second_color = combobox_button_second_gradient_color; + + dc.FillRectangle( ResPool.GetSolidBrush( Color.White ), rectangle ); + + if ( state == ButtonState.Pushed ) { + first_color = pressed_gradient_first_color; + second_color = pressed_gradient_second_color; + pushed = true; + } + + using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( rectangle.X, rectangle.Y + 2 ), new Point( rectangle.X, rectangle.Bottom - 2 ), first_color, second_color ) ) { + dc.FillRectangle( lgbr, rectangle.X + 2, rectangle.Y + 2, rectangle.Width - 4, rectangle.Height - 4 ); + } + + // inner borders + Pen tmp_pen = ResPool.GetPen( !pushed ? Color.White : pressed_inner_border_dark_color ); + dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 1, rectangle.Right - 2, rectangle.Y + 1 ); + dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 1, rectangle.X + 1, rectangle.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( !pushed ? inner_border_dark_color : pressed_inner_border_dark_color ); + dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Y + 2, rectangle.Right - 2, rectangle.Bottom - 2 ); + dc.DrawLine( tmp_pen, rectangle.X + 2, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 2 ); + + // border + Point[] points = new Point[] { + new Point( rectangle.X, rectangle.Y ), + new Point( rectangle.Right - 3, rectangle.Y ), + new Point( rectangle.Right - 1, rectangle.Y + 2 ), + new Point( rectangle.Right - 1, rectangle.Bottom - 3 ), + new Point( rectangle.Right - 3, rectangle.Bottom - 1 ), + new Point( rectangle.X, rectangle.Bottom - 1 ), + new Point( rectangle.X, rectangle.Y ) + }; + + dc.DrawPolygon( ResPool.GetPen( pushed ? border_pressed_dark_color : border_normal_dark_color ), points ); + + // edges on right side + tmp_pen = ResPool.GetPen( control_parent_backcolor ); + dc.DrawLine( tmp_pen, rectangle.Right - 1, rectangle.Y, rectangle.Right - 1, rectangle.Y + 1 ); + dc.DrawLine( tmp_pen, rectangle.Right - 1, rectangle.Bottom - 1, rectangle.Right - 1, rectangle.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( edge_bottom_inner_color ); + dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Y, rectangle.Right - 1, rectangle.Y + 1 ); + dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Bottom - 1, rectangle.Right - 1, rectangle.Bottom - 2 ); + + rect = new Rectangle( rectangle.X + 1 + rectangle.Width / 4, rectangle.Y + rectangle.Height / 4, rectangle.Width / 2 - 1, rectangle.Height / 2 ); + centerX = rect.Left + rect.Width / 2; + centerY = rect.Top + rect.Height / 2; + shiftX = Math.Max( 1, rect.Width / 8 ); + shiftY = Math.Max( 1, rect.Height / 8 ); + + if ( ( state & ButtonState.Pushed ) != 0 ) { + shiftX--; + shiftY--; + } + + rect.Y -= shiftY; + centerY -= shiftY; + + P1 = new Point( rect.Left, centerY ); + P2 = new Point( centerX, rect.Bottom ); + P3 = new Point( rect.Right, centerY ); + + arrow[ 0 ] = P1; + arrow[ 1 ] = P2; + arrow[ 2 ] = P3; + + SmoothingMode old_smoothing_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + + /* Draw the arrow */ + if ( state == ButtonState.Inactive ) { + /* Move away from the shadow */ + P1.X += 1; P1.Y += 1; + P2.X += 1; P2.Y += 1; + P3.X += 1; P3.Y += 1; + + arrow[ 0 ] = P1; + arrow[ 1 ] = P2; + arrow[ 2 ] = P3; + + using ( Pen pen = new Pen( SystemColors.ControlLightLight, 2 ) ) { + dc.DrawLines( pen, arrow ); + } + + P1 = new Point( rect.Left, centerY ); + P2 = new Point( centerX, rect.Bottom ); + P3 = new Point( rect.Right, centerY ); + + arrow[ 0 ] = P1; + arrow[ 1 ] = P2; + arrow[ 2 ] = P3; + + using ( Pen pen = new Pen( SystemColors.ControlDark, 2 ) ) { + dc.DrawLines( pen, arrow ); + } + } else { + using ( Pen pen = new Pen( SystemColors.ControlText, 2 ) ) { + dc.DrawLines( pen, arrow ); + } + } + + dc.SmoothingMode = old_smoothing_mode; + } + + /* Scroll button: regular button + direction arrow */ + public override void CPDrawScrollButton( Graphics dc, Rectangle area, ScrollButton scroll_button_type, ButtonState state ) { + bool enabled = ( state == ButtonState.Inactive ) ? false: true; + + DrawScrollButtonPrimitive( dc, area, state, scroll_button_type ); + + if ( area.Width < 12 || area.Height < 12 ) /* Cannot see a thing at smaller sizes */ + return; + + Color color_arrow; + + if ( enabled ) + color_arrow = arrow_color; + else + color_arrow = ColorGrayText; + + /* Paint arrows */ + + int centerX = area.Left + area.Width / 2; + int centerY = area.Top + area.Height / 2; + + int shift = 0; + + if ( ( state & ButtonState.Pushed ) != 0 ) + shift = 1; + + Point[] arrow = new Point[ 4 ]; + + switch ( scroll_button_type ) { + case ScrollButton.Down: + centerY += shift + 1; + arrow[ 0 ] = new Point( centerX - 4, centerY - 2 ); + arrow[ 1 ] = new Point( centerX, centerY + 2 ); + arrow[ 2 ] = new Point( centerX + 4, centerY - 2 ); + arrow[ 3 ] = new Point( centerX - 4, centerY - 2 ); + break; + case ScrollButton.Up: + centerY -= shift; + arrow[ 0 ] = new Point( centerX - 4, centerY + 2 ); + arrow[ 1 ] = new Point( centerX, centerY - 2 ); + arrow[ 2 ] = new Point( centerX + 4, centerY + 2 ); + arrow[ 3 ] = new Point( centerX - 4, centerY + 2 ); + break; + case ScrollButton.Left: + centerX -= shift; + arrow[ 0 ] = new Point( centerX + 2, centerY - 4 ); + arrow[ 1 ] = new Point( centerX + 2, centerY + 4 ); + arrow[ 2 ] = new Point( centerX - 2, centerY ); + arrow[ 3 ] = new Point( centerX + 2, centerY - 4 ); + break; + case ScrollButton.Right: + centerX += shift + 1; + arrow[ 0 ] = new Point( centerX - 2, centerY - 4 ); + arrow[ 1 ] = new Point( centerX + 2, centerY ); + arrow[ 2 ] = new Point( centerX - 2, centerY + 4 ); + arrow[ 3 ] = new Point( centerX - 2, centerY - 4 ); + break; + default: + break; + } + + SmoothingMode old_smoothing_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + dc.FillPolygon( ResPool.GetSolidBrush( color_arrow ), arrow ); + dc.SmoothingMode = old_smoothing_mode; + } + + public override void CPDrawSizeGrip( Graphics dc, Color backColor, Rectangle bounds ) { + Point pt1 = new Point( bounds.Right - 3, bounds.Bottom ); + Point pt2 = new Point( bounds.Right, bounds.Bottom - 3 ); + + // diagonals + Pen tmp_pen = ResPool.GetPen( Color.White ); + for ( int i = 0; i < 4; i++ ) { + dc.DrawLine( tmp_pen, pt1.X - i * 4, pt1.Y, pt2.X, pt2.Y - i * 4 ); + } + + pt1.X += 1; + pt2.Y += 1; + + tmp_pen = ResPool.GetPen( pressed_inner_border_dark_color ); + for ( int i = 0; i < 4; i++ ) { + dc.DrawLine( tmp_pen, pt1.X - i * 4, pt1.Y, pt2.X, pt2.Y - i * 4 ); + } + } + + private void DrawScrollBarThumb( Graphics dc, Rectangle area, ScrollBar bar ) { + LinearGradientBrush lgbr = null; + + if ( bar.vert ) + lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.Right - 2, area.Y + 2 ), scrollbar_gradient_first_color, scrollbar_gradient_second_color ); + else + lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.X + 2, area.Bottom - 2 ), scrollbar_gradient_first_color, scrollbar_gradient_second_color ); + + dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 4 ); + + lgbr.Dispose( ); + + // outer border + Pen pen = ResPool.GetPen( border_normal_dark_color ); + + dc.DrawRectangle( pen, area.X, area.Y, area.Width - 1, area.Height - 1 ); + + // inner border + pen = ResPool.GetPen( Color.White ); + dc.DrawLine( pen, area.X + 1, area.Bottom - 2, area.X + 1, area.Y + 1 ); + dc.DrawLine( pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 ); + + pen = ResPool.GetPen( inner_border_dark_color ); + dc.DrawLine( pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 ); + dc.DrawLine( pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 ); + + if ( bar.vert ) { + if ( area.Height > 12 ) { + int mid_y = area.Y + ( area.Height / 2 ); + int mid_x = area.X + ( area.Width / 2 ); + + pen = ResPool.GetPen( pressed_inner_border_dark_color ); + dc.DrawLine( pen, mid_x - 3, mid_y, mid_x + 3, mid_y ); + dc.DrawLine( pen, mid_x - 3, mid_y - 3, mid_x + 3, mid_y - 3 ); + dc.DrawLine( pen, mid_x - 3, mid_y + 3, mid_x + 3, mid_y + 3 ); + + Pen spen = ResPool.GetPen( Color.White ); + dc.DrawLine( spen, mid_x - 3, mid_y + 1, mid_x + 3, mid_y + 1 ); + dc.DrawLine( spen, mid_x - 3, mid_y - 2, mid_x + 3, mid_y - 2 ); + dc.DrawLine( spen, mid_x - 3, mid_y + 4, mid_x + 3, mid_y + 4 ); + } + } else { + // draw grip lines only if there is enough space + if ( area.Width > 12 ) { + int mid_x = area.X + ( area.Width / 2 ); + int mid_y = area.Y + ( area.Height / 2 ); + + pen = ResPool.GetPen( pressed_inner_border_dark_color ); + dc.DrawLine( pen, mid_x, mid_y - 3, mid_x, mid_y + 3 ); + dc.DrawLine( pen, mid_x - 3, mid_y - 3, mid_x - 3, mid_y + 3 ); + dc.DrawLine( pen, mid_x + 3, mid_y - 3, mid_x + 3, mid_y + 3 ); + + Pen spen = ResPool.GetPen( Color.White ); + dc.DrawLine( spen, mid_x + 1, mid_y - 3, mid_x + 1, mid_y + 3 ); + dc.DrawLine( spen, mid_x - 2, mid_y - 3, mid_x - 2, mid_y + 3 ); + dc.DrawLine( spen, mid_x + 4, mid_y - 3, mid_x + 4, mid_y + 3 ); + } + } + } + + public void DrawScrollButtonPrimitive( Graphics dc, Rectangle area, ButtonState state, ScrollButton scroll_button_type ) { + Pen pen = ResPool.GetPen( border_normal_dark_color ); + + Color first_gradient_color = gradient_first_color; + Color second_gradient_color = gradient_second_color_nr2; + + bool pushed = false; + + if ( ( state & ButtonState.Pushed ) == ButtonState.Pushed ) { + first_gradient_color = pressed_gradient_first_color; + second_gradient_color = pressed_gradient_second_color; + pushed = true; + } + + Point[] points = null; + + LinearGradientBrush lgbr = null; + + switch ( scroll_button_type ) { + case ScrollButton.Left: + // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control + dc.DrawLine( ResPool.GetPen( ColorControl ), area.X, area.Y, area.X, area.Bottom - 1 ); + + lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.X + 2, area.Bottom - 2 ), first_gradient_color, second_gradient_color ); + dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 2 ); + + Pen tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White ); + dc.DrawLine( tmp_pen, area.X + 1, area.Y + 2, area.X + 1, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( edge_top_inner_color ); + dc.DrawLine( tmp_pen, area.X, area.Y + 1, area.X + 1, area.Y ); + dc.DrawLine( tmp_pen, area.X, area.Bottom - 2, area.X + 1, area.Bottom - 1 ); + + points = new Point[] { + new Point( area.X + 2, area.Y ), + new Point( area.Right - 1, area.Y ), + new Point( area.Right - 1, area.Bottom - 1 ), + new Point( area.X + 2, area.Bottom - 1 ), + new Point( area.X, area.Bottom - 3 ), + new Point( area.X, area.Y + 2 ), + new Point( area.X + 2, area.Y ) + }; + dc.DrawPolygon( pen, points ); + break; + case ScrollButton.Right: + // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control + dc.DrawLine( ResPool.GetPen( ColorControl ), area.Right - 1, area.Y, area.Right - 1, area.Bottom - 1 ); + + lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.X + 2, area.Bottom - 2 ), first_gradient_color, second_gradient_color ); + dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 2 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White ); + dc.DrawLine( tmp_pen, area.X + 1, area.Y + 1, area.X + 1, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( edge_top_inner_color ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Y, area.Right - 1, area.Y + 1 ); + dc.DrawLine( tmp_pen, area.Right - 1, area.Bottom - 2, area.Right - 2, area.Bottom - 1 ); + + points = new Point[] { + new Point( area.X, area.Y ), + new Point( area.Right - 3, area.Y ), + new Point( area.Right - 1, area.Y + 2 ), + new Point( area.Right - 1, area.Bottom - 3 ), + new Point( area.Right - 3, area.Bottom - 1 ), + new Point( area.X, area.Bottom - 1 ), + new Point( area.X, area.Y ), + }; + dc.DrawPolygon( pen, points ); + break; + case ScrollButton.Up: + // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control + dc.DrawLine( ResPool.GetPen( ColorControl ), area.X, area.Y, area.Right - 1, area.Y ); + + lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y ), new Point( area.Right - 2, area.Y ), first_gradient_color, second_gradient_color ); + dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 4 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White ); + dc.DrawLine( tmp_pen, area.X + 1, area.Y + 1, area.X + 1, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( edge_top_inner_color ); + dc.DrawLine( tmp_pen, area.X, area.Y + 1, area.X + 1, area.Y ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Y, area.Right - 1, area.Y + 1 ); + + points = new Point[] { + new Point( area.X + 2, area.Y ), + new Point( area.Right - 3, area.Y ), + new Point( area.Right - 1, area.Y + 2 ), + new Point( area.Right - 1, area.Bottom - 1 ), + new Point( area.X, area.Bottom - 1 ), + new Point( area.X, area.Y + 2 ), + new Point( area.X + 2, area.Y ) + }; + dc.DrawPolygon( pen, points ); + break; + case ScrollButton.Down: + // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control + dc.DrawLine( ResPool.GetPen( ColorControl ), area.X, area.Bottom - 1, area.Right - 1, area.Bottom - 1 ); + + lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y ), new Point( area.Right - 2, area.Y ), first_gradient_color, second_gradient_color ); + dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 4 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White ); + dc.DrawLine( tmp_pen, area.X + 1, area.Y + 1, area.X + 1, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 ); + + tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 ); + dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( edge_top_inner_color ); + dc.DrawLine( tmp_pen, area.X, area.Bottom - 2, area.X + 1, area.Bottom - 1 ); + dc.DrawLine( tmp_pen, area.Right - 2, area.Bottom - 1, area.Right - 1, area.Bottom - 2 ); + + points = new Point[] { + new Point( area.X, area.Y ), + new Point( area.Right - 1, area.Y ), + new Point( area.Right - 1, area.Bottom - 3 ), + new Point( area.Right - 3, area.Bottom - 1 ), + new Point( area.X + 2, area.Bottom - 1 ), + new Point( area.X, area.Bottom - 3 ), + new Point( area.X, area.Y ) + }; + dc.DrawPolygon( pen, points ); + break; + } + + lgbr.Dispose( ); + } + + #region GroupBox + public override void DrawGroupBox( Graphics dc, Rectangle area, GroupBox box ) { + StringFormat text_format; + SizeF size; + int width; + int y; + Rectangle rect; + + rect = box.ClientRectangle; + + dc.FillRectangle( ResPool.GetSolidBrush( box.BackColor ), rect ); + + text_format = new StringFormat( ); + text_format.HotkeyPrefix = HotkeyPrefix.Show; + + size = dc.MeasureString( box.Text, box.Font ); + width = (int) size.Width; + + if ( width > box.Width - 16 ) + width = box.Width - 16; + + y = box.Font.Height / 2; + + Pen pen = ResPool.GetPen( pressed_inner_border_dark_color ); + + /* Draw group box*/ + Point[] points = { + new Point( 8 + width, y ), + new Point( box.Width - 3, y ), + new Point( box.Width - 1, y + 2 ), + new Point( box.Width - 1, box.Height - 3 ), + new Point( box.Width - 3, box.Height - 1 ), + new Point( 2, box.Height - 1 ), + new Point( 0, box.Height - 3 ), + new Point( 0, y + 2 ), + new Point( 2, y ), + new Point( 8, y ) + }; + dc.DrawLines( pen, points ); + + /* Text */ + if ( box.Enabled ) { + dc.DrawString( box.Text, box.Font, ResPool.GetSolidBrush( box.ForeColor ), 10, 0, text_format ); + } else { + CPDrawStringDisabled( dc, box.Text, box.Font, box.ForeColor, + new RectangleF( 10, 0, width, box.Font.Height ), text_format ); + } + text_format.Dispose( ); + } + #endregion + + #region TrackBar + private void DrawTrackBar_Vertical( Graphics dc, Rectangle clip_rectangle, TrackBar tb, + ref Rectangle thumb_pos, ref Rectangle thumb_area, + float ticks, int value_pos, bool mouse_value ) { + + Point toptick_startpoint = new Point( ); + Point bottomtick_startpoint = new Point( ); + Point channel_startpoint = new Point( ); + float pixel_len; + float pixels_betweenticks; + const int space_from_right = 8; + const int space_from_left = 8; + Rectangle area = tb.ClientRectangle; + + switch ( tb.TickStyle ) { + case TickStyle.BottomRight: + case TickStyle.None: + channel_startpoint.Y = 8; + channel_startpoint.X = 9; + bottomtick_startpoint.Y = 13; + bottomtick_startpoint.X = 24; + break; + case TickStyle.TopLeft: + channel_startpoint.Y = 8; + channel_startpoint.X = 19; + toptick_startpoint.Y = 13; + toptick_startpoint.X = 8; + break; + case TickStyle.Both: + channel_startpoint.Y = 8; + channel_startpoint.X = 18; + bottomtick_startpoint.Y = 13; + bottomtick_startpoint.X = 32; + toptick_startpoint.Y = 13; + toptick_startpoint.X = 8; + break; + default: + break; + } + + thumb_area.X = area.X + channel_startpoint.X; + thumb_area.Y = area.Y + channel_startpoint.Y; + thumb_area.Height = area.Height - space_from_right - space_from_left; + thumb_area.Width = 4; + + pixel_len = thumb_area.Height - 11; + pixels_betweenticks = pixel_len / ( tb.Maximum - tb.Minimum ); + + /* Convert thumb position from mouse position to value*/ + if ( mouse_value ) { + + if ( value_pos >= channel_startpoint.Y ) + value_pos = (int)( ( (float) ( value_pos - channel_startpoint.Y ) ) / pixels_betweenticks ); + else + value_pos = 0; + + if ( value_pos + tb.Minimum > tb.Maximum ) + value_pos = tb.Maximum - tb.Minimum; + + tb.Value = value_pos + tb.Minimum; + } + + thumb_pos.Width = 13; + thumb_pos.Height = 29; + + thumb_pos.Y = channel_startpoint.Y + (int) ( pixels_betweenticks * (float) value_pos ) - ( thumb_pos.Height / 3 ); + + if ( thumb_pos.Y < channel_startpoint.Y ) + thumb_pos.Y = channel_startpoint.Y; + + if ( thumb_pos.Y > thumb_area.Bottom - 29 ) + thumb_pos.Y = thumb_area.Bottom - 29; + + /* Draw channel */ + // bottom + Pen pen = ResPool.GetPen( tab_top_border_focus_color ); + dc.DrawLine( pen, channel_startpoint.X, thumb_pos.Y + 29, channel_startpoint.X, thumb_area.Bottom ); + dc.DrawLine( pen, channel_startpoint.X, thumb_area.Bottom, channel_startpoint.X + 4, thumb_area.Bottom ); + dc.DrawLine( pen, channel_startpoint.X + 4, thumb_pos.Y + 29, channel_startpoint.X + 4, thumb_area.Bottom ); + + pen = ResPool.GetPen( menuitem_gradient_first_color ); + dc.DrawLine( pen, channel_startpoint.X + 1, thumb_pos.Y + 28, channel_startpoint.X + 1, thumb_area.Bottom - 1 ); + pen = ResPool.GetPen( trackbar_second_gradient_color ); + dc.DrawLine( pen, channel_startpoint.X + 2, thumb_pos.Y + 28, channel_startpoint.X + 2, thumb_area.Bottom - 1 ); + pen = ResPool.GetPen( trackbar_third_gradient_color ); + dc.DrawLine( pen, channel_startpoint.X + 3, thumb_pos.Y + 28, channel_startpoint.X + 3, thumb_area.Bottom - 1 ); + + // top + pen = ResPool.GetPen( pressed_inner_border_dark_color ); + dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 1, channel_startpoint.X + 1, thumb_pos.Y ); + dc.DrawRectangle( ResPool.GetPen( scrollbar_background_color ), channel_startpoint.X + 2, channel_startpoint.Y + 1, 1, thumb_pos.Y ); + + pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, channel_startpoint.X, thumb_pos.Y ); + dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, channel_startpoint.X + 4, channel_startpoint.Y ); + dc.DrawLine( pen, channel_startpoint.X + 4, channel_startpoint.Y, channel_startpoint.X + 4, thumb_pos.Y ); + + /* Draw thumb */ + thumb_pos.X = channel_startpoint.X - 4; + + // inner border + pen = ResPool.GetPen( Color.White ); + dc.DrawLine( pen, thumb_pos.X + 1, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Bottom - 2 ); + dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Y + 1, thumb_pos.Right - 2, thumb_pos.Y + 1 ); + + pen = ResPool.GetPen( menu_separator_color ); + dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 ); + dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y + 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 ); + + // outer border + Point[] points = { + new Point( thumb_pos.X + 2, thumb_pos.Y ), + new Point( thumb_pos.Right - 3 , thumb_pos.Y ), + new Point( thumb_pos.Right - 1, thumb_pos.Y + 2 ), + new Point( thumb_pos.Right - 1, thumb_pos.Bottom - 3 ), + new Point( thumb_pos.Right - 3, thumb_pos.Bottom - 1 ), + new Point( thumb_pos.X + 2, thumb_pos.Bottom - 1 ), + new Point( thumb_pos.X, thumb_pos.Bottom - 3 ), + new Point( thumb_pos.X, thumb_pos.Y + 2 ), + new Point( thumb_pos.X + 2, thumb_pos.Y ) + }; + + dc.DrawLines( ResPool.GetPen( border_normal_dark_color ), points ); + + Color first_gradient_color = mouse_value ? button_edge_bottom_outer_color : trackbar_inner_first_gradient_color; + Color second_gradient_color = mouse_value ? trackbar_inner_pressed_second_gradient_color : trackbar_inner_second_gradient_color; + + using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( thumb_pos.X, thumb_pos.Y + 2 ), new Point( thumb_pos.X, thumb_pos.Bottom - 2 ), first_gradient_color, second_gradient_color ) ) { + dc.FillRectangle( lgbr, thumb_pos.X + 2, thumb_pos.Y + 2, thumb_pos.Width - 4, thumb_pos.Height - 4 ); + } + + // outer egdes + pen = ResPool.GetPen( edge_top_inner_color ); + dc.DrawLine( pen, thumb_pos.X, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Y ); + dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y, thumb_pos.Right - 1, thumb_pos.Y + 1 ); + + pen = ResPool.GetPen( edge_bottom_inner_color ); + dc.DrawLine( pen, thumb_pos.X, thumb_pos.Bottom - 2, thumb_pos.X + 1, thumb_pos.Bottom - 1 ); + dc.DrawLine( pen, thumb_pos.Right - 1, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 1 ); + + // draw grip lines + pen = ResPool.GetPen( pressed_inner_border_dark_color ); + dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 11, thumb_pos.X + 8, thumb_pos.Y + 11 ); + dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 14, thumb_pos.X + 8, thumb_pos.Y + 14 ); + dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 17, thumb_pos.X + 8, thumb_pos.Y + 17 ); + + pen = ResPool.GetPen( Color.White ); + dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 12, thumb_pos.X + 8, thumb_pos.Y + 12 ); + dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 15, thumb_pos.X + 8, thumb_pos.Y + 15 ); + dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 18, thumb_pos.X + 8, thumb_pos.Y + 18 ); + + pixel_len = thumb_area.Height - 11; + pixels_betweenticks = pixel_len / ticks; + + /* Draw ticks*/ + thumb_area.X = thumb_pos.X; + thumb_area.Y = channel_startpoint.Y; + thumb_area.Width = thumb_pos.Width; + + Region outside = new Region( area ); + outside.Exclude( thumb_area ); + + if ( outside.IsVisible( clip_rectangle ) ) { + if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.BottomRight ) == TickStyle.BottomRight || + ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) { + + for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) { + if ( inc == 0 || ( inc + pixels_betweenticks ) >= pixel_len + 1 ) + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X , area.Y + bottomtick_startpoint.Y + inc, + area.X + bottomtick_startpoint.X + 3, area.Y + bottomtick_startpoint.Y + inc ); + else + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X, area.Y + bottomtick_startpoint.Y + inc, + area.X + bottomtick_startpoint.X + 2, area.Y + bottomtick_startpoint.Y + inc ); + } + } + + if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.TopLeft ) == TickStyle.TopLeft || + ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) { + + pixel_len = thumb_area.Height - 11; + pixels_betweenticks = pixel_len / ticks; + + for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) { + if ( inc == 0 || ( inc + pixels_betweenticks ) >= pixel_len + 1 ) + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X - 3 , area.Y + toptick_startpoint.Y + inc, + area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y + inc ); + else + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X - 2, area.Y + toptick_startpoint.Y + inc, + area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y + inc ); + } + } + } + + outside.Dispose( ); + + } + + private void DrawTrackBar_Horizontal( Graphics dc, Rectangle clip_rectangle, TrackBar tb, + ref Rectangle thumb_pos, ref Rectangle thumb_area, + float ticks, int value_pos, bool mouse_value ) { + Point toptick_startpoint = new Point( ); + Point bottomtick_startpoint = new Point( ); + Point channel_startpoint = new Point( ); + float pixel_len; + float pixels_betweenticks; + const int space_from_right = 8; + const int space_from_left = 8; + Rectangle area = tb.ClientRectangle; + + switch ( tb.TickStyle ) { + case TickStyle.BottomRight: + case TickStyle.None: + channel_startpoint.X = 8; + channel_startpoint.Y = 9; + bottomtick_startpoint.X = 13; + bottomtick_startpoint.Y = 24; + break; + case TickStyle.TopLeft: + channel_startpoint.X = 8; + channel_startpoint.Y = 19; + toptick_startpoint.X = 13; + toptick_startpoint.Y = 8; + break; + case TickStyle.Both: + channel_startpoint.X = 8; + channel_startpoint.Y = 18; + bottomtick_startpoint.X = 13; + bottomtick_startpoint.Y = 32; + toptick_startpoint.X = 13; + toptick_startpoint.Y = 8; + break; + default: + break; + } + + thumb_area.X = area.X + channel_startpoint.X; + thumb_area.Y = area.Y + channel_startpoint.Y; + thumb_area.Width = area.Width - space_from_right - space_from_left; + thumb_area.Height = 4; + + pixel_len = thumb_area.Width - 11; + pixels_betweenticks = pixel_len / ( tb.Maximum - tb.Minimum ); + + /* Convert thumb position from mouse position to value*/ + if ( mouse_value ) { + if ( value_pos >= channel_startpoint.X ) + value_pos = (int)( ( (float) ( value_pos - channel_startpoint.X ) ) / pixels_betweenticks ); + else + value_pos = 0; + + if ( value_pos + tb.Minimum > tb.Maximum ) + value_pos = tb.Maximum - tb.Minimum; + + tb.Value = value_pos + tb.Minimum; + } + + thumb_pos.Width = 29; + thumb_pos.Height = 13; + + thumb_pos.X = channel_startpoint.X + (int) ( pixels_betweenticks * (float) value_pos ) - ( thumb_pos.Width / 3 ); + + if ( thumb_pos.X < channel_startpoint.X ) + thumb_pos.X = channel_startpoint.X; + + if ( thumb_pos.X > thumb_area.Right - 29 ) + thumb_pos.X = thumb_area.Right - 29; + + /* Draw channel */ + // left side + Pen pen = ResPool.GetPen( tab_top_border_focus_color ); + dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, thumb_pos.X, channel_startpoint.Y ); + dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, channel_startpoint.X, channel_startpoint.Y + 4 ); + dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y + 4, thumb_pos.X, channel_startpoint.Y + 4 ); + + pen = ResPool.GetPen( menuitem_gradient_first_color ); + dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 1, thumb_pos.X, channel_startpoint.Y + 1 ); + pen = ResPool.GetPen( trackbar_second_gradient_color ); + dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 2, thumb_pos.X, channel_startpoint.Y + 2 ); + pen = ResPool.GetPen( trackbar_third_gradient_color ); + dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 3, thumb_pos.X, channel_startpoint.Y + 3 ); + + // right side + pen = ResPool.GetPen( pressed_inner_border_dark_color ); + dc.DrawLine( pen, thumb_pos.X + 29, channel_startpoint.Y + 1, thumb_area.Right - 1, channel_startpoint.Y + 1 ); + dc.DrawRectangle( ResPool.GetPen( scrollbar_background_color ), thumb_pos.X + 29, channel_startpoint.Y + 2, thumb_area.Right - thumb_pos.X - 30, 1 ); + + pen = ResPool.GetPen( scrollbar_border_color ); + dc.DrawLine( pen, thumb_pos.X + 29, channel_startpoint.Y, thumb_area.Right, channel_startpoint.Y ); + dc.DrawLine( pen, thumb_area.Right, channel_startpoint.Y, thumb_area.Right, channel_startpoint.Y + 4 ); + dc.DrawLine( pen, thumb_pos.X + 29, channel_startpoint.Y + 4, thumb_area.Right, channel_startpoint.Y + 4 ); + + /* Draw thumb */ + + thumb_pos.Y = channel_startpoint.Y - 4; + + // inner border + pen = ResPool.GetPen( Color.White ); + dc.DrawLine( pen, thumb_pos.X + 1, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Bottom - 2 ); + dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Y + 1, thumb_pos.Right - 2, thumb_pos.Y + 1 ); + + pen = ResPool.GetPen( menu_separator_color ); + dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 ); + dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y + 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 ); + + // outer border + Point[] points = { + new Point( thumb_pos.X + 2, thumb_pos.Y ), + new Point( thumb_pos.Right - 3 , thumb_pos.Y ), + new Point( thumb_pos.Right - 1, thumb_pos.Y + 2 ), + new Point( thumb_pos.Right - 1, thumb_pos.Bottom - 3 ), + new Point( thumb_pos.Right - 3, thumb_pos.Bottom - 1 ), + new Point( thumb_pos.X + 2, thumb_pos.Bottom - 1 ), + new Point( thumb_pos.X, thumb_pos.Bottom - 3 ), + new Point( thumb_pos.X, thumb_pos.Y + 2 ), + new Point( thumb_pos.X + 2, thumb_pos.Y ) + }; + + dc.DrawLines( ResPool.GetPen( border_normal_dark_color ), points ); + + Color first_gradient_color = mouse_value ? button_edge_bottom_outer_color : trackbar_inner_first_gradient_color; + Color second_gradient_color = mouse_value ? trackbar_inner_pressed_second_gradient_color : trackbar_inner_second_gradient_color; + + using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( thumb_pos.X, thumb_pos.Y + 2 ), new Point( thumb_pos.X, thumb_pos.Bottom - 2 ), first_gradient_color, second_gradient_color ) ) { + dc.FillRectangle( lgbr, thumb_pos.X + 2, thumb_pos.Y + 2, thumb_pos.Width - 4, thumb_pos.Height - 4 ); + } + + // outer egdes + pen = ResPool.GetPen( edge_top_inner_color ); + dc.DrawLine( pen, thumb_pos.X, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Y ); + dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y, thumb_pos.Right - 1, thumb_pos.Y + 1 ); + + pen = ResPool.GetPen( edge_bottom_inner_color ); + dc.DrawLine( pen, thumb_pos.X, thumb_pos.Bottom - 2, thumb_pos.X + 1, thumb_pos.Bottom - 1 ); + dc.DrawLine( pen, thumb_pos.Right - 1, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 1 ); + + // draw grip lines + pen = ResPool.GetPen( pressed_inner_border_dark_color ); + dc.DrawLine( pen, thumb_pos.X + 11, thumb_pos.Y + 4, thumb_pos.X + 11, thumb_pos.Y + 8 ); + dc.DrawLine( pen, thumb_pos.X + 14, thumb_pos.Y + 4, thumb_pos.X + 14, thumb_pos.Y + 8 ); + dc.DrawLine( pen, thumb_pos.X + 17, thumb_pos.Y + 4, thumb_pos.X + 17, thumb_pos.Y + 8 ); + + pen = ResPool.GetPen( Color.White ); + dc.DrawLine( pen, thumb_pos.X + 12, thumb_pos.Y + 4, thumb_pos.X + 12, thumb_pos.Y + 8 ); + dc.DrawLine( pen, thumb_pos.X + 15, thumb_pos.Y + 4, thumb_pos.X + 15, thumb_pos.Y + 8 ); + dc.DrawLine( pen, thumb_pos.X + 18, thumb_pos.Y + 4, thumb_pos.X + 18, thumb_pos.Y + 8 ); + + pixel_len = thumb_area.Width - 11; + pixels_betweenticks = pixel_len / ticks; + + /* Draw ticks*/ + thumb_area.Y = thumb_pos.Y; + thumb_area.X = channel_startpoint.X; + thumb_area.Height = thumb_pos.Height; + Region outside = new Region( area ); + outside.Exclude( thumb_area ); + + if ( outside.IsVisible( clip_rectangle ) ) { + if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.BottomRight ) == TickStyle.BottomRight || + ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) { + + for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) { + if ( inc == 0 || ( inc + pixels_betweenticks ) >= pixel_len + 1 ) + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y, + area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y + 3 ); + else + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y, + area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y + 2 ); + } + } + + if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.TopLeft ) == TickStyle.TopLeft || + ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) { + + for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) { + if ( inc == 0 || ( inc + pixels_betweenticks ) >= pixel_len + 1 ) + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y - 3, + area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y ); + else + dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y - 2, + area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y ); + } + } + } + + outside.Dispose( ); + } + + public override void DrawTrackBar( Graphics dc, Rectangle clip_rectangle, TrackBar tb ) { + int value_pos; + bool mouse_value; + float ticks = ( tb.Maximum - tb.Minimum ) / tb.tickFrequency; /* N of ticks draw*/ + Rectangle area; + Rectangle thumb_pos = tb.ThumbPos; + Rectangle thumb_area = tb.ThumbArea; + + if ( tb.thumb_pressed ) { + value_pos = tb.thumb_mouseclick; + mouse_value = true; + } else { + value_pos = tb.Value - tb.Minimum; + mouse_value = false; + } + + area = tb.ClientRectangle; + + /* Control Background */ + if ( tb.BackColor == DefaultControlBackColor ) { + dc.FillRectangle( ResPool.GetSolidBrush( ColorControl ), clip_rectangle ); + } else { + dc.FillRectangle( ResPool.GetSolidBrush( tb.BackColor ), clip_rectangle ); + } + + if ( tb.Orientation == Orientation.Vertical ) { + DrawTrackBar_Vertical( dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area, + ticks, value_pos, mouse_value ); + + } else { + DrawTrackBar_Horizontal( dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area, + ticks, value_pos, mouse_value ); + } + + // TODO: draw better focus rectangle + if ( tb.Focused ) { + dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X, area.Y, area.Width - 1, 1 ); + dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X, area.Y + area.Height - 1, area.Width - 1, 1 ); + dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X, area.Y, 1, area.Height - 1 ); + dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X + area.Width - 1, area.Y, 1, area.Height - 1 ); + } + + tb.ThumbPos = thumb_pos; + tb.ThumbArea = thumb_area; + } + #endregion // TrackBar + + #region ListView + // draws the ListViewItem of the given index + protected override void DrawListViewItem( Graphics dc, ListView control, ListViewItem item ) { + Rectangle rect_checkrect = item.CheckRectReal; + Rectangle rect_iconrect = item.GetBounds( ItemBoundsPortion.Icon ); + Rectangle full_rect = item.GetBounds( ItemBoundsPortion.Entire ); + Rectangle text_rect = item.GetBounds( ItemBoundsPortion.Label ); + + if ( control.CheckBoxes ) { + if ( control.StateImageList == null ) { + // Make sure we've got at least a line width of 1 + int check_wd = Math.Max( 3, rect_checkrect.Width / 6 ); + int scale = Math.Max( 1, rect_checkrect.Width / 12 ); + + // set the checkbox background + dc.FillRectangle( this.ResPool.GetSolidBrush( this.ColorWindow ), + rect_checkrect ); + // define a rectangle inside the border area + Rectangle rect = new Rectangle( rect_checkrect.X + 2, + rect_checkrect.Y + 2, + rect_checkrect.Width - 4, + rect_checkrect.Height - 4 ); + Pen pen = new Pen( this.ColorWindowText, 2 ); + dc.DrawRectangle( pen, rect ); + + // Need to draw a check-mark + if ( item.Checked ) { + pen.Width = 1; + // adjustments to get the check-mark at the right place + rect.X ++; rect.Y ++; + // following logic is taken from DrawFrameControl method + for ( int i = 0; i < check_wd; i++ ) { + dc.DrawLine( pen, rect.Left + check_wd / 2, + rect.Top + check_wd + i, + rect.Left + check_wd / 2 + 2 * scale, + rect.Top + check_wd + 2 * scale + i ); + dc.DrawLine( pen, + rect.Left + check_wd / 2 + 2 * scale, + rect.Top + check_wd + 2 * scale + i, + rect.Left + check_wd / 2 + 6 * scale, + rect.Top + check_wd - 2 * scale + i ); + } + } + } else { + if ( item.Checked && control.StateImageList.Images.Count > 1 ) + control.StateImageList.Draw( dc, + rect_checkrect.Location, 1 ); + else if ( ! item.Checked && control.StateImageList.Images.Count > 0 ) + control.StateImageList.Draw( dc, + rect_checkrect.Location, 0 ); + } + } + + // Item is drawn as a special case, as it is not just text + if ( control.View == View.LargeIcon ) { + if ( item.ImageIndex > -1 && + control.LargeImageList != null && + item.ImageIndex < control.LargeImageList.Images.Count ) { + // center image + Point image_location = rect_iconrect.Location; + Image image = control.LargeImageList.Images[ item.ImageIndex ]; + if ( image.Width < rect_iconrect.Width ) { + int icon_rect_middle = rect_iconrect.Width / 2; + int image_middle = image.Width / 2; + image_location.X = image_location.X + icon_rect_middle - image_middle; + } + control.LargeImageList.Draw( dc, image_location, + item.ImageIndex ); + } + } else { + if ( item.ImageIndex > -1 && + control.SmallImageList != null && + item.ImageIndex < control.SmallImageList.Images.Count ) + control.SmallImageList.Draw( dc, rect_iconrect.Location, + item.ImageIndex ); + } + + // draw the item text + // format for the item text + StringFormat format = new StringFormat( ); + format.LineAlignment = StringAlignment.Center; + if ( control.View == View.LargeIcon ) + format.Alignment = StringAlignment.Center; + else + format.Alignment = StringAlignment.Near; + + if ( !control.LabelWrap ) + format.FormatFlags = StringFormatFlags.NoWrap; + + if ( item.Selected ) { + if ( control.View == View.Details ) { + if ( control.FullRowSelect ) { + // fill the entire rect excluding the checkbox + full_rect.Location = item.LabelRect.Location; + dc.FillRectangle( this.ResPool.GetSolidBrush + ( this.ColorHighlight ), full_rect ); + } else { + Size text_size = Size.Ceiling( dc.MeasureString( item.Text, + item.Font ) ); + text_rect.Width = text_size.Width; + dc.FillRectangle( this.ResPool.GetSolidBrush + ( this.ColorHighlight ), text_rect ); + } + } else { + /*Size text_size = Size.Ceiling (dc.MeasureString (item.Text, + item.Font)); + Point loc = text_rect.Location; + loc.X += (text_rect.Width - text_size.Width) / 2; + text_rect.Width = text_size.Width;*/ + dc.FillRectangle( this.ResPool.GetSolidBrush( this.ColorHighlight ), + text_rect ); + } + } else + dc.FillRectangle( ResPool.GetSolidBrush( item.BackColor ), text_rect ); + + if ( item.Text != null && item.Text.Length > 0 ) { + + if ( control.View != View.LargeIcon ) { + if ( item.Selected ) + dc.DrawString( item.Text, item.Font, this.ResPool.GetSolidBrush + ( this.ColorHighlightText ), text_rect, format ); + else + dc.DrawString( item.Text, item.Font, this.ResPool.GetSolidBrush + ( item.ForeColor ), text_rect, format ); + } else { + // ListView CalcTextSize says wrapping is done for two lines only !?! + // text is centered for the complete text_rect but it should be centered per available row/line + + // calculate how much lines we get out of text_rect and current item.Font + int nr_lines = text_rect.Height / item.Font.Height; + int rest = text_rect.Height % item.Font.Height; + int line_height = item.Font.Height + ( rest > 1 ? 2 : 0 ); + + Rectangle[] text_rects = new Rectangle[ nr_lines ]; + + for ( int i = 0; i < nr_lines; i++ ) { + text_rects[ i ].X = text_rect.X; + text_rects[ i ].Y = text_rect.Y + i * line_height; + text_rects[ i ].Width = text_rect.Width; + text_rects[ i ].Height = line_height; + } + + string[] lines = new string[ nr_lines ]; + + string text = item.Text; + + int line_nr = 0; + int current_pos = 0; + for ( int k = 1; k <= text.Length; k++ ) { + lines[ line_nr ] = text.Substring( current_pos, k - current_pos ); + + // FIXME: Graphics.MeasureString returns wrong results if there is a + // space char in the string + SizeF sizef = dc.MeasureString( lines[ line_nr ], item.Font, text_rect.Width, format ); + + if ( (int)sizef.Width > text_rect.Width - 3 ) { + lines[ line_nr ] = lines[ line_nr ].Remove( lines[ line_nr ].Length - 1, 1 ); + k--; + current_pos = k; + line_nr++; + if ( line_nr == nr_lines ) + break; + } + } + + int j = 0; + foreach ( Rectangle t_rect in text_rects ) { + if ( item.Selected ) + dc.DrawString( lines[ j ], item.Font, this.ResPool.GetSolidBrush + ( this.ColorHighlightText ), t_rect, format ); + else + dc.DrawString( lines[ j ], item.Font, this.ResPool.GetSolidBrush + ( item.ForeColor ), t_rect, format ); + j++; + } + } + } + + if ( control.View == View.Details && control.Columns.Count > 0 ) { + // draw subitems for details view + ListViewItem.ListViewSubItemCollection subItems = item.SubItems; + int count = ( control.Columns.Count < subItems.Count ? + control.Columns.Count : subItems.Count ); + + if ( count > 0 ) { + ColumnHeader col; + ListViewItem.ListViewSubItem subItem; + Rectangle sub_item_rect = text_rect; + + // set the format for subitems + format.FormatFlags = StringFormatFlags.NoWrap; + format.Alignment = StringAlignment.Near; + + // 0th subitem is the item already drawn + for ( int index = 1; index < count; index++ ) { + subItem = subItems[ index ]; + col = control.Columns[ index ]; + sub_item_rect.X = col.Rect.Left; + sub_item_rect.Width = col.Wd; + sub_item_rect.X -= control.h_marker; + + SolidBrush sub_item_back_br = null; + SolidBrush sub_item_fore_br = null; + Font sub_item_font = null; + + if ( item.UseItemStyleForSubItems ) { + sub_item_back_br = this.ResPool.GetSolidBrush + ( item.BackColor ); + sub_item_fore_br = this.ResPool.GetSolidBrush + ( item.ForeColor ); + sub_item_font = item.Font; + } else { + sub_item_back_br = this.ResPool.GetSolidBrush + ( subItem.BackColor ); + sub_item_fore_br = this.ResPool.GetSolidBrush + ( subItem.ForeColor ); + sub_item_font = subItem.Font; + } + + // In case of fullrowselect, background is filled + // for the entire rect above + if ( item.Selected && control.FullRowSelect ) { + if ( subItem.Text != null && subItem.Text.Length > 0 ) + dc.DrawString( subItem.Text, sub_item_font, + this.ResPool.GetSolidBrush + ( this.ColorHighlightText ), + sub_item_rect, format ); + } else { + dc.FillRectangle( sub_item_back_br, sub_item_rect ); + if ( subItem.Text != null && subItem.Text.Length > 0 ) + dc.DrawString( subItem.Text, sub_item_font, + sub_item_fore_br, + sub_item_rect, format ); + } + sub_item_rect.X += col.Wd; + } + } + } + + if ( item.Focused ) { + if ( item.Selected ) + CPDrawFocusRectangle( dc, text_rect, ColorHighlightText, ColorHighlight ); + else + CPDrawFocusRectangle( dc, text_rect, control.ForeColor, control.BackColor ); + } + + format.Dispose( ); + } + #endregion ListView + + #region DateTimePicker + public override void DrawDateTimePicker (Graphics dc, Rectangle clip_rectangle, DateTimePicker dtp) { + // if not showing the numeric updown control then render border + if (!dtp.ShowUpDown && clip_rectangle.IntersectsWith (dtp.ClientRectangle)) { + // draw the outer border + Rectangle button_bounds = dtp.ClientRectangle; + CPDrawBorder3D (dc, button_bounds, Border3DStyle.Sunken, Border3DSide.All, dtp.BackColor); + + // deflate by the border width + if (clip_rectangle.IntersectsWith (dtp.drop_down_arrow_rect)) { + button_bounds.Inflate (-2,-2); + ButtonState state = dtp.is_drop_down_visible ? ButtonState.Pushed : ButtonState.Normal; + Rectangle button_rect = new Rectangle(dtp.drop_down_arrow_rect.X, dtp.drop_down_arrow_rect.Y + 1, + dtp.drop_down_arrow_rect.Width - 1, dtp.drop_down_arrow_rect.Height - 2); + this.CPDrawComboButton ( + dc, + button_rect, + state); + } + } + + // render the date part + if (clip_rectangle.IntersectsWith (dtp.date_area_rect)) { + // fill the background + Rectangle date_area_rect = new Rectangle( dtp.date_area_rect.X + 1, dtp.date_area_rect.Y + 1, + dtp.date_area_rect.Width - 2, dtp.date_area_rect.Height - 2); + dc.FillRectangle (ResPool.GetSolidBrush (ThemeEngine.Current.ColorWindow), date_area_rect); + + // fill the currently highlighted area + if (dtp.hilight_date_area != Rectangle.Empty) { + dc.FillRectangle (ResPool.GetSolidBrush (ThemeEngine.Current.ColorHighlight), dtp.hilight_date_area); + } + + // draw the text part + // TODO: if date format is CUstom then we need to draw the dates as separate parts + StringFormat text_format = new StringFormat(); + text_format.LineAlignment = StringAlignment.Center; + text_format.Alignment = StringAlignment.Near; + dc.DrawString (dtp.Text, dtp.Font, ResPool.GetSolidBrush (dtp.ForeColor), Rectangle.Inflate(dtp.date_area_rect, -1, -1), text_format); + text_format.Dispose (); + } + } + #endregion // DateTimePicker + + #region MonthCalendar + // draw the month calendar + public override void DrawMonthCalendar(Graphics dc, Rectangle clip_rectangle, MonthCalendar mc) + { + Rectangle client_rectangle = mc.ClientRectangle; + Size month_size = mc.SingleMonthSize; + // cache local copies of Marshal-by-ref internal members (gets around error CS0197) + Size calendar_spacing = (Size)((object)mc.calendar_spacing); + Size date_cell_size = (Size)((object)mc.date_cell_size); + + // draw the singlecalendars + int x_offset = 1; + int y_offset = 1; + // adjust for the position of the specific month + for (int i=0; i < mc.CalendarDimensions.Height; i++) + { + if (i > 0) + { + y_offset += month_size.Height + calendar_spacing.Height; + } + // now adjust for x position + for (int j=0; j < mc.CalendarDimensions.Width; j++) + { + if (j > 0) + { + x_offset += month_size.Width + calendar_spacing.Width; + } + else + { + x_offset = 1; + } + + Rectangle month_rect = new Rectangle (x_offset, y_offset, month_size.Width, month_size.Height); + if (month_rect.IntersectsWith (clip_rectangle)) { + DrawSingleMonth ( + dc, + clip_rectangle, + month_rect, + mc, + i, + j); + } + } + } + + Rectangle bottom_rect = new Rectangle ( + client_rectangle.X, + Math.Max(client_rectangle.Bottom - date_cell_size.Height - 3, 0), + client_rectangle.Width, + date_cell_size.Height + 2); + // draw the today date if it's set + if (mc.ShowToday && bottom_rect.IntersectsWith (clip_rectangle)) + { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), bottom_rect); + if (mc.ShowToday) { + int today_offset = 5; + if (mc.ShowTodayCircle) + { + Rectangle today_circle_rect = new Rectangle ( + client_rectangle.X + 5, + Math.Max(client_rectangle.Bottom - date_cell_size.Height - 2, 0), + date_cell_size.Width, + date_cell_size.Height); + DrawTodayCircle (dc, today_circle_rect); + today_offset += date_cell_size.Width + 5; + } + // draw today's date + StringFormat text_format = new StringFormat(); + text_format.LineAlignment = StringAlignment.Center; + text_format.Alignment = StringAlignment.Near; + Font bold_font = new Font (mc.Font.FontFamily, mc.Font.Size, mc.Font.Style | FontStyle.Bold); + Rectangle today_rect = new Rectangle ( + today_offset + client_rectangle.X, + Math.Max(client_rectangle.Bottom - date_cell_size.Height, 0), + Math.Max(client_rectangle.Width - today_offset, 0), + date_cell_size.Height); + dc.DrawString ("Today: " + DateTime.Now.ToShortDateString(), bold_font, ResPool.GetSolidBrush (mc.ForeColor), today_rect, text_format); + text_format.Dispose (); + bold_font.Dispose (); + } + } + + // finally paint the borders of the calendars as required + for (int i = 0; i <= mc.CalendarDimensions.Width; i++) { + if (i == 0 && clip_rectangle.X == client_rectangle.X) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.X, client_rectangle.Y, 1, client_rectangle.Height)); + } else if (i == mc.CalendarDimensions.Width && clip_rectangle.Right == client_rectangle.Right) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.Right-1, client_rectangle.Y, 1, client_rectangle.Height)); + } else { + Rectangle rect = new Rectangle ( + client_rectangle.X + (month_size.Width*i) + (calendar_spacing.Width * (i-1)) + 1, + client_rectangle.Y, + calendar_spacing.Width, + client_rectangle.Height); + if (i < mc.CalendarDimensions.Width && i > 0 && clip_rectangle.IntersectsWith (rect)) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), rect); + } + } + } + for (int i = 0; i <= mc.CalendarDimensions.Height; i++) { + if (i == 0 && clip_rectangle.Y == client_rectangle.Y) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.X, client_rectangle.Y, client_rectangle.Width, 1)); + } else if (i == mc.CalendarDimensions.Height && clip_rectangle.Bottom == client_rectangle.Bottom) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.X, client_rectangle.Bottom-1, client_rectangle.Width, 1)); + } else { + Rectangle rect = new Rectangle ( + client_rectangle.X, + client_rectangle.Y + (month_size.Height*i) + (calendar_spacing.Height*(i-1)) + 1, + client_rectangle.Width, + calendar_spacing.Height); + if (i < mc.CalendarDimensions.Height && i > 0 && clip_rectangle.IntersectsWith (rect)) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), rect); + } + } + } + + // draw the drop down border if need + if (mc.owner != null) { + Rectangle bounds = mc.ClientRectangle; + if (clip_rectangle.Contains (mc.Location)) { + // find out if top or left line to draw + if(clip_rectangle.Contains (new Point (bounds.Left, bounds.Bottom))) { + + dc.DrawLine (SystemPens.ControlText, bounds.X, bounds.Y, bounds.X, bounds.Bottom-1); + } + if(clip_rectangle.Contains (new Point (bounds.Right, bounds.Y))) { + dc.DrawLine (SystemPens.ControlText, bounds.X, bounds.Y, bounds.Right-1, bounds.Y); + } + } + if (clip_rectangle.Contains (new Point(bounds.Right, bounds.Bottom))) { + // find out if bottom or right line to draw + if(clip_rectangle.Contains (new Point (bounds.Left, bounds.Bottom))) { + dc.DrawLine (SystemPens.ControlText, bounds.X, bounds.Bottom-1, bounds.Right-1, bounds.Bottom-1); + } + if(clip_rectangle.Contains (new Point (bounds.Right, bounds.Y))) { + dc.DrawLine (SystemPens.ControlText, bounds.Right-1, bounds.Y, bounds.Right-1, bounds.Bottom-1); + } + } + } + } + + // darws a single part of the month calendar (with one month) + private void DrawSingleMonth(Graphics dc, Rectangle clip_rectangle, Rectangle rectangle, MonthCalendar mc, int row, int col) + { + // cache local copies of Marshal-by-ref internal members (gets around error CS0197) + Size title_size = (Size)((object)mc.title_size); + Size date_cell_size = (Size)((object)mc.date_cell_size); + DateTime current_month = (DateTime)((object)mc.current_month); + + // set up some standard string formating variables + StringFormat text_format = new StringFormat(); + text_format.LineAlignment = StringAlignment.Center; + text_format.Alignment = StringAlignment.Center; + + + // draw the title back ground + DateTime this_month = current_month.AddMonths (row*mc.CalendarDimensions.Width+col); + Rectangle title_rect = new Rectangle(rectangle.X, rectangle.Y, title_size.Width, title_size.Height); + if (title_rect.IntersectsWith (clip_rectangle)) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), title_rect); + // draw the title + string title_text = this_month.ToString ("MMMM yyyy"); + dc.DrawString (title_text, mc.Font, ResPool.GetSolidBrush (mc.TitleForeColor), title_rect, text_format); + + // draw previous and next buttons if it's time + if (row == 0 && col == 0) + { + // draw previous button + DrawMonthCalendarButton ( + dc, + rectangle, + mc, + title_size, + mc.button_x_offset, + (System.Drawing.Size)((object)mc.button_size), + true); + } + if (row == 0 && col == mc.CalendarDimensions.Width-1) + { + // draw next button + DrawMonthCalendarButton ( + dc, + rectangle, + mc, + title_size, + mc.button_x_offset, + (System.Drawing.Size)((object)mc.button_size), + false); + } + } + + // set the week offset and draw week nums if needed + int col_offset = (mc.ShowWeekNumbers) ? 1 : 0; + Rectangle day_name_rect = new Rectangle( + rectangle.X, + rectangle.Y + title_size.Height, + (7 + col_offset) * date_cell_size.Width, + date_cell_size.Height); + if (day_name_rect.IntersectsWith (clip_rectangle)) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), day_name_rect); + // draw the day names + DayOfWeek first_day_of_week = mc.GetDayOfWeek(mc.FirstDayOfWeek); + for (int i=0; i < 7; i++) + { + int position = i - (int) first_day_of_week; + if (position < 0) + { + position = 7 + position; + } + // draw it + Rectangle day_rect = new Rectangle( + day_name_rect.X + ((i + col_offset)* date_cell_size.Width), + day_name_rect.Y, + date_cell_size.Width, + date_cell_size.Height); + dc.DrawString (((DayOfWeek)i).ToString().Substring(0, 3), mc.Font, ResPool.GetSolidBrush (mc.TitleBackColor), day_rect, text_format); + } + + // draw the vertical divider + int vert_divider_y = Math.Max(title_size.Height+ date_cell_size.Height-1, 0); + dc.DrawLine ( + ResPool.GetPen (mc.ForeColor), + rectangle.X + (col_offset * date_cell_size.Width) + mc.divider_line_offset, + rectangle.Y + vert_divider_y, + rectangle.Right - mc.divider_line_offset, + rectangle.Y + vert_divider_y); + } + + + // draw the actual date items in the grid (including the week numbers) + Rectangle date_rect = new Rectangle ( + rectangle.X, + rectangle.Y + title_size.Height + date_cell_size.Height, + date_cell_size.Width, + date_cell_size.Height); + int month_row_count = 0; + bool draw_week_num_divider = false; + DateTime current_date = mc.GetFirstDateInMonthGrid ( new DateTime (this_month.Year, this_month.Month, 1)); + for (int i=0; i < 6; i++) + { + // establish if this row is in our clip_area + Rectangle row_rect = new Rectangle ( + rectangle.X, + rectangle.Y + title_size.Height + (date_cell_size.Height * (i+1)), + date_cell_size.Width * 7, + date_cell_size.Height); + if (mc.ShowWeekNumbers) { + row_rect.Width += date_cell_size.Width; + } + + bool draw_row = row_rect.IntersectsWith (clip_rectangle); + if (draw_row) { + dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), row_rect); + } + // establish if this is a valid week to draw + if (mc.IsValidWeekToDraw (this_month, current_date, row, col)) { + month_row_count = i; + } + + // draw the week number if required + if (mc.ShowWeekNumbers && month_row_count == i) { + if (!draw_week_num_divider) { + draw_week_num_divider = draw_row; + } + // get the week for this row + int week = mc.GetWeekOfYear (current_date); + + if (draw_row) { + dc.DrawString ( + week.ToString(), + mc.Font, + ResPool.GetSolidBrush (mc.TitleBackColor), + date_rect, + text_format); + } + date_rect.Offset(date_cell_size.Width, 0); + } + + // only draw the days if we have to + if(month_row_count == i) { + for (int j=0; j < 7; j++) + { + if (draw_row) { + DrawMonthCalendarDate ( + dc, + date_rect, + mc, + current_date, + this_month, + row, + col); + } + + // move the day on + current_date = current_date.AddDays(1); + date_rect.Offset(date_cell_size.Width, 0); + } + + // shift the rectangle down one row + int offset = (mc.ShowWeekNumbers) ? -8 : -7; + date_rect.Offset(offset*date_cell_size.Width, date_cell_size.Height); + } + } + + // month_row_count is zero based, so add one + month_row_count++; + + // draw week numbers if required + if (draw_week_num_divider) { + col_offset = 1; + dc.DrawLine ( + ResPool.GetPen (mc.ForeColor), + rectangle.X + date_cell_size.Width - 1, + rectangle.Y + title_size.Height + date_cell_size.Height + mc.divider_line_offset, + rectangle.X + date_cell_size.Width - 1, + rectangle.Y + title_size.Height + date_cell_size.Height + (month_row_count * date_cell_size.Height) - mc.divider_line_offset); + } + text_format.Dispose (); + } + + // draws the pervious or next button + private void DrawMonthCalendarButton (Graphics dc, Rectangle rectangle, MonthCalendar mc, Size title_size, int x_offset, Size button_size, bool is_previous) + { + bool is_clicked = false; + Rectangle button_rect; + Rectangle arrow_rect = new Rectangle (rectangle.X, rectangle.Y, 4, 7); + Point[] arrow_path = new Point[3]; + // prepare the button + if (is_previous) + { + is_clicked = mc.is_previous_clicked; + button_rect = new Rectangle ( + rectangle.X + 1 + x_offset, + rectangle.Y + 1 + ((title_size.Height - button_size.Height)/2), + Math.Max(button_size.Width - 1, 0), + Math.Max(button_size.Height - 1, 0)); + arrow_rect.X = button_rect.X + ((button_rect.Width - arrow_rect.Width)/2); + arrow_rect.Y = button_rect.Y + ((button_rect.Height - arrow_rect.Height)/2); + if (is_clicked) { + arrow_rect.Offset(1,1); + } + arrow_path[0] = new Point (arrow_rect.Right, arrow_rect.Y); + arrow_path[1] = new Point (arrow_rect.X, arrow_rect.Y + arrow_rect.Height/2); + arrow_path[2] = new Point (arrow_rect.Right, arrow_rect.Bottom); + } + else + { + is_clicked = mc.is_next_clicked; + button_rect = new Rectangle ( + rectangle.Right - 1 - x_offset - button_size.Width, + rectangle.Y + 1 + ((title_size.Height - button_size.Height)/2), + Math.Max(button_size.Width - 1, 0), + Math.Max(button_size.Height - 1, 0)); + arrow_rect.X = button_rect.X + ((button_rect.Width - arrow_rect.Width)/2); + arrow_rect.Y = button_rect.Y + ((button_rect.Height - arrow_rect.Height)/2); + if (is_clicked) { + arrow_rect.Offset(1,1); + } + arrow_path[0] = new Point (arrow_rect.X, arrow_rect.Y); + arrow_path[1] = new Point (arrow_rect.Right, arrow_rect.Y + arrow_rect.Height/2); + arrow_path[2] = new Point (arrow_rect.X, arrow_rect.Bottom); + } + + // fill the background + dc.FillRectangle (ResPool.GetSolidBrush(mc.TitleBackColor), button_rect); + + // draw the button + Color first_gradient_color = is_clicked ? pressed_gradient_first_color : gradient_first_color; + Color second_gradient_color = is_clicked ? pressed_gradient_second_color : gradient_second_color; + + CL_Draw_Button (dc, button_rect, FlatStyle.Standard, + false, true, is_clicked, + first_gradient_color, second_gradient_color, + false); + + // draw the arrow + SmoothingMode old_smooting_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + dc.FillPolygon (SystemBrushes.ControlText, arrow_path); + dc.SmoothingMode = old_smooting_mode; + } + + + // draws one day in the calendar grid + private void DrawMonthCalendarDate (Graphics dc, Rectangle rectangle, MonthCalendar mc, DateTime date, DateTime month, int row, int col) { + Color date_color = mc.ForeColor; + Rectangle interior = new Rectangle (rectangle.X, rectangle.Y, Math.Max(rectangle.Width - 1, 0), Math.Max(rectangle.Height - 1, 0)); + + // find out if we are the lead of the first calendar or the trail of the last calendar + if (date.Year != month.Year || date.Month != month.Month) { + DateTime check_date = month.AddMonths (-1); + // check if it's the month before + if (check_date.Year == date.Year && check_date.Month == date.Month && row == 0 && col == 0) { + date_color = mc.TrailingForeColor; + } else { + // check if it's the month after + check_date = month.AddMonths (1); + if (check_date.Year == date.Year && check_date.Month == date.Month && row == mc.CalendarDimensions.Height-1 && col == mc.CalendarDimensions.Width-1) { + date_color = mc.TrailingForeColor; + } else { + return; + } + } + } else { + date_color = mc.ForeColor; + } + + + if (date == mc.SelectionStart && date == mc.SelectionEnd) { + // see if the date is in the start of selection + date_color = mc.BackColor; + // draw the left hand of the back ground + Rectangle selection_rect = Rectangle.Inflate(rectangle, -3, -3); + dc.FillPie (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect, 0, 359); + } else if (date == mc.SelectionStart) { + // see if the date is in the start of selection + date_color = mc.BackColor; + // draw the left hand of the back ground + Rectangle selection_rect = Rectangle.Inflate(rectangle, -3, -3); + dc.FillPie (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect, 90, 180); + // fill the other side as a straight rect + if (date < mc.SelectionEnd) + { + // use rectangle instead of rectangle to go all the way to edge of rect + selection_rect.X = (int) Math.Floor((double)(rectangle.X + rectangle.Width / 2)); + selection_rect.Width = Math.Max(rectangle.Right - selection_rect.X, 0); + dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect); + } + } else if (date == mc.SelectionEnd) { + // see if it is the end of selection + date_color = mc.BackColor; + // draw the left hand of the back ground + Rectangle selection_rect = Rectangle.Inflate(rectangle, -3, -3); + dc.FillPie (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect, 270, 180); + // fill the other side as a straight rect + if (date > mc.SelectionStart) { + selection_rect.X = rectangle.X; + selection_rect.Width = rectangle.Width - (rectangle.Width / 2); + dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect); + } + } else if (date > mc.SelectionStart && date < mc.SelectionEnd) { + // now see if it's in the middle + date_color = mc.BackColor; + // draw the left hand of the back ground + Rectangle selection_rect = Rectangle.Inflate(rectangle, 0, -3); + dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect); + } + + // set up some standard string formating variables + StringFormat text_format = new StringFormat(); + text_format.LineAlignment = StringAlignment.Center; + text_format.Alignment = StringAlignment.Center; + + + // establish if it's a bolded font + Font font; + if (mc.IsBoldedDate (date)) { + font = new Font (mc.Font.FontFamily, mc.Font.Size, mc.Font.Style | FontStyle.Bold); + } else { + font = mc.Font; + } + + // just draw the date now + dc.DrawString (date.Day.ToString(), font, ResPool.GetSolidBrush (date_color), rectangle, text_format); + + // today circle if needed + if (mc.ShowTodayCircle && date == DateTime.Now.Date) { + DrawTodayCircle (dc, interior); + } + + // draw the selection grid + if (mc.is_date_clicked && mc.clicked_date == date) { + using (Pen pen = new Pen (Color.Black, 1) ) { + pen.DashStyle = DashStyle.Dot; + dc.DrawRectangle (pen, interior); + } + } + text_format.Dispose (); + } + + private void DrawTodayCircle (Graphics dc, Rectangle rectangle) { + Color circle_color = Color.FromArgb (248, 0, 0); + // draw the left hand of the circle + Rectangle lhs_circle_rect = new Rectangle (rectangle.X + 1, rectangle.Y + 4, Math.Max(rectangle.Width - 2, 0), Math.Max(rectangle.Height - 5, 0)); + Rectangle rhs_circle_rect = new Rectangle (rectangle.X + 1, rectangle.Y + 1, Math.Max(rectangle.Width - 2, 0), Math.Max(rectangle.Height - 2, 0)); + Point [] curve_points = new Point [3]; + curve_points [0] = new Point (lhs_circle_rect.X, rhs_circle_rect.Y + rhs_circle_rect.Height/12); + curve_points [1] = new Point (lhs_circle_rect.X + lhs_circle_rect.Width/9, rhs_circle_rect.Y); + curve_points [2] = new Point (lhs_circle_rect.X + lhs_circle_rect.Width/2 + 1, rhs_circle_rect.Y); + + SmoothingMode old_smoothing_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + + using (Pen pen = new Pen (circle_color, 2)) { + dc.DrawArc (pen, lhs_circle_rect, 90, 180); + dc.DrawArc (pen, rhs_circle_rect, 270, 180); + dc.DrawCurve (pen, curve_points); + dc.DrawLine (ResPool.GetPen (circle_color), curve_points [2], new Point (curve_points [2].X, lhs_circle_rect.Y)); + } + + dc.SmoothingMode = old_smoothing_mode; + } + #endregion // MonthCalendar + + public override void CPDrawBorder3D( Graphics graphics, Rectangle rectangle, Border3DStyle style, Border3DSide sides ) { + CPDrawBorder3D( graphics, rectangle, style, sides, ColorControl ); + } + + private void CPDrawBorder3D( Graphics dc, Rectangle rectangle, Border3DStyle style, Border3DSide sides, Color control_color ) { + // currently we don't take care of Border3DStyle or Border3DSide + + // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control + dc.DrawLine( ResPool.GetPen( ColorControl ), rectangle.X, rectangle.Y, rectangle.X, rectangle.Bottom - 1 ); + dc.DrawLine( ResPool.GetPen( ColorControl ), rectangle.Right - 1, rectangle.Y, rectangle.Right - 1, rectangle.Bottom - 1 ); + + Pen tmp_pen = ResPool.GetPen( edge_bottom_inner_color ); + dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 2, rectangle.X + 2, rectangle.Y + 1 ); + dc.DrawLine( tmp_pen, rectangle.Right - 3, rectangle.Y + 1, rectangle.Right - 2, rectangle.Y + 2 ); + dc.DrawLine( tmp_pen, rectangle.Right - 3, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 3 ); + dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Bottom - 3, rectangle.X + 2, rectangle.Bottom - 2 ); + + tmp_pen = ResPool.GetPen( theme_back_color ); + dc.DrawLine( tmp_pen, rectangle.X + 2, rectangle.Y + 2, rectangle.Right - 3, rectangle.Y + 2 ); + dc.DrawLine( tmp_pen, rectangle.X + 2, rectangle.Y + 3, rectangle.X + 2, rectangle.Bottom - 3 ); + + tmp_pen = ResPool.GetPen( Color.White ); + dc.DrawLine( tmp_pen, rectangle.X + 3, rectangle.Bottom - 3, rectangle.Right - 3, rectangle.Bottom - 3 ); + dc.DrawLine( tmp_pen, rectangle.Right - 3, rectangle.Y + 3, rectangle.Right - 3, rectangle.Bottom - 3 ); + + Point[] points = { + new Point( rectangle.X + 3, rectangle.Y + 1 ), + new Point( rectangle.Right - 4, rectangle.Y + 1 ), + new Point( rectangle.Right - 2, rectangle.Y + 3 ), + new Point( rectangle.Right - 2, rectangle.Bottom - 4 ), + new Point( rectangle.Right - 4, rectangle.Bottom - 2 ), + new Point( rectangle.X + 3, rectangle.Bottom - 2 ), + new Point( rectangle.X + 1, rectangle.Bottom - 4 ), + new Point( rectangle.X + 1, rectangle.Y + 3 ), + new Point( rectangle.X + 3, rectangle.Y + 1 ) + }; + + dc.DrawLines( ResPool.GetPen( combobox_border_color ), points ); + + Point[] points_top_outer = { + new Point( rectangle.X + 1, rectangle.Y + 1 ), + new Point( rectangle.X + 2, rectangle.Y ), + new Point( rectangle.Right - 3, rectangle.Y ), + new Point( rectangle.Right - 2 , rectangle.Y + 1 ) + }; + + Point[] points_bottom_outer = { + new Point( rectangle.X + 1, rectangle.Bottom - 2 ), + new Point( rectangle.X + 2, rectangle.Bottom - 1 ), + new Point( rectangle.Right - 3, rectangle.Bottom - 1 ), + new Point( rectangle.Right - 2, rectangle.Bottom - 2 ) + }; + + // outer border + tmp_pen = ResPool.GetPen( button_outer_border_dark_color ); + dc.DrawLines( tmp_pen, points_top_outer ); + tmp_pen = ResPool.GetPen( button_outer_border_light_color ); + dc.DrawLines( tmp_pen, points_bottom_outer ); + + using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( 0, 2 ), new Point( 0, rectangle.Height - 1 ), button_outer_border_dark_color, button_outer_border_light_color ) ) { + dc.FillRectangle( lgbr, rectangle.X, rectangle.Y + 2, 1, rectangle.Height - 4 ); + dc.FillRectangle( lgbr, rectangle.Right - 1, rectangle.Y + 2, 1, rectangle.Height - 4 ); + } + + tmp_pen = ResPool.GetPen( button_edge_top_outer_color ); + dc.DrawLine( tmp_pen, rectangle.X, rectangle.Y + 1, rectangle.X + 1, rectangle.Y ); + dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Y, rectangle.Right - 1, rectangle.Y + 1 ); + + tmp_pen = ResPool.GetPen( button_edge_bottom_outer_color ); + dc.DrawLine( tmp_pen, rectangle.X, rectangle.Bottom - 2, rectangle.X + 1, rectangle.Bottom - 1 ); + dc.DrawLine( tmp_pen, rectangle.Right - 1, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 1 ); + } + + public override void CPDrawBorder( Graphics dc, Rectangle bounds, Color leftColor, int leftWidth, + ButtonBorderStyle leftStyle, Color topColor, int topWidth, ButtonBorderStyle topStyle, + Color rightColor, int rightWidth, ButtonBorderStyle rightStyle, Color bottomColor, + int bottomWidth, ButtonBorderStyle bottomStyle ) { + dc.DrawRectangle( ResPool.GetPen( combobox_border_color ), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1 ); + } + + // TODO: inactive... + public override void CPDrawCheckBox( Graphics dc, Rectangle rectangle, ButtonState state ) { + + bool pushed = ( state & ButtonState.Pushed ) != 0; + + int lineWidth; + Rectangle rect; + int scale; + + // background + dc.FillRectangle( ResPool.GetSolidBrush( pushed ? checkbox_pressed_backcolor : Color.White ), rectangle ); + + // border + dc.DrawRectangle( ResPool.GetPen( scrollbar_border_color ), rectangle ); + + Color inner_border_color = pushed ? checkbox_pressed_inner_boder_color : checkbox_inner_boder_color; + + Pen tmp_pen = ResPool.GetPen( inner_border_color ); + dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 1, rectangle.Right - 1, rectangle.Y + 1 ); + dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 2, rectangle.X + 1, rectangle.Bottom - 1 ); + + /* Make sure we've got at least a line width of 1 */ + lineWidth = Math.Max( 3, rectangle.Width / 6 ); + scale = Math.Max( 1, rectangle.Width / 12 ); + + // define a rectangle inside the border area + rect = new Rectangle( rectangle.X + 2, rectangle.Y + 2, rectangle.Width - 4, rectangle.Height - 4 ); + if ( ( state & ButtonState.Inactive ) != 0 ) { + tmp_pen = SystemPens.ControlDark; + } else { + tmp_pen = SystemPens.ControlText; + } + + if ( ( state & ButtonState.Checked ) != 0 ) { + /* Need to draw a check-mark */ + for ( int i=0; i < lineWidth; i++ ) { + dc.DrawLine( tmp_pen, rect.Left + lineWidth / 2, rect.Top + lineWidth + i, rect.Left + lineWidth / 2 + 2 * scale, rect.Top + lineWidth + 2 * scale + i ); + dc.DrawLine( tmp_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 ); + } + } + } + + public override void CPDrawStringDisabled( Graphics graphics, string s, Font font, Color color, RectangleF layoutRectangle, + StringFormat format ) { + + graphics.DrawString( s, font, ResPool.GetSolidBrush( ThemeEngine.Current.ColorGrayText), layoutRectangle, format ); + + } + + public override void CPDrawButton (Graphics dc, Rectangle buttonRectangle, ButtonState state) + { + bool is_enabled = true; + FlatStyle flat_style = FlatStyle.Standard; + bool is_pressed = false; + + if ((state & ButtonState.Pushed) != 0) { + is_pressed = true; + } + +// if ((state & ButtonState.Checked)!=0) { +// dfcs |= DrawFrameControlStates.Checked; +// } + + if ((state & ButtonState.Flat) != 0) { + flat_style = FlatStyle.Flat; + } + + if ((state & ButtonState.Inactive) != 0) { + is_enabled = false; + } + + Color first_gradient_color = gradient_first_color; + Color second_gradient_color = gradient_second_color; + + if (is_pressed) { + first_gradient_color = pressed_gradient_first_color; + second_gradient_color = pressed_gradient_second_color; + } + + CL_Draw_Button (dc, buttonRectangle, flat_style, + false, is_enabled, is_pressed, + first_gradient_color, second_gradient_color, + false); + } + + public override void CPDrawRadioButton (Graphics dc, Rectangle rectangle, ButtonState state) + { + bool is_checked = false; + bool is_inactive = false; + + if ((state & ButtonState.Checked) != 0) { + is_checked = true; + } + + if ((state & ButtonState.Inactive) != 0) { + is_inactive = true; + } + + SmoothingMode old_smooting_mode = dc.SmoothingMode; + dc.SmoothingMode = SmoothingMode.AntiAlias; + + dc.FillPie (ResPool.GetSolidBrush (this.ColorWindow), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359); + + dc.DrawArc (ResPool.GetPen (radio_button_border_circle_color), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359); + + CL_Draw_RadioButton_Dot (dc, rectangle, is_checked, is_inactive); + + dc.SmoothingMode = old_smooting_mode; + } + + private void CL_Draw_RadioButton_Dot (Graphics dc, Rectangle rectangle, bool is_checked, bool is_inactive) + { + if (is_checked) { + int lineWidth = Math.Max (1, Math.Min (rectangle.Width, rectangle.Height) / 4); + + SolidBrush buttonBrush; + + if (is_inactive) { + buttonBrush = SystemBrushes.ControlDark as SolidBrush; + } else { + buttonBrush = ResPool.GetSolidBrush (radio_button_dot_color); + } + dc.FillPie (buttonBrush, rectangle.X + lineWidth, rectangle.Y + lineWidth, rectangle.Width - lineWidth * 2, rectangle.Height - lineWidth * 2, 0, 359); + + // the white shiny dott + buttonBrush = ResPool.GetSolidBrush (ColorWindow); + dc.FillPie (buttonBrush, rectangle.X + lineWidth + lineWidth / 2, rectangle.Y + lineWidth + lineWidth / 2, (rectangle.Width - lineWidth * 2) / 3, (rectangle.Height - lineWidth * 2) / 3, 0, 359); + } + } + } //class +} + |