Hey everyone,

I've finished up an initial implementation of all the new layout changes to Button 2.0. Since the method I ended up going with is a departure from what we had, I thought I would run it by people before I commit.

In the current way our theming works for Button, drawing is done by one call from ButtonBase: DrawButtonBase, which calculates and draws every permutation of FlatStyle [4 options] for Button, CheckBox, and RadioButton. Each theme must fully reimplement this do-all function to draw a button. For 2.0, there are many more permutations: AutoEllipsis [2 options], TextImageRelation [5 options], UseMnemonic [2 options], and UseCompatibleTextRendering [2 options]. Also, there are 5 new options in FlatAppearance used when FlatStyle = Flat.

Therefore, I have tried to break it down a bit. There is a new class called ThemeElements that solely handles painting an element, such as a standard button or a checkbox. The elements will be broken down along roughly the same lines as what is used in the VisualStyle namespace, as it is extremely granular. Additionally, it should make a XP/Vista Theme trivial to implement, and make it easy for the VisualStyle namespace to support drawing on other platforms.

For example, here are the 3 functions currently in ThemeElements:
public static void DrawButton (Graphics g, Rectangle bounds, ButtonThemeState state, Color backColor, Color foreColor) public static void DrawFlatButton (Graphics g, Rectangle bounds, ButtonThemeState state, Color backColor, Color foreColor, FlatButtonAppearance appearance) public static void DrawPopupButton (Graphics g, Rectangle bounds, ButtonThemeState state, Color backColor, Color foreColor)

(state is an enum of Normal, Entered, Pressed, Disabled, Default)

These functions ONLY draw the button graphic in a given rectangle. Things like text and image layout and drawing is still handled in Theme, as it is much more likely to be reused across all themes, though it is overridable as well.

By breaking things down this way, it should greatly reduce the work required for each theme. Each theme will generally need to override a function that simply draws the button graphic in a rectangle, instead of calculate and draw every permutation of button.

I made the changes for Win32. It's backwards compatibile, so Nice and Clearlooks will draw the 1.1 button still, ignoring the 2.0 options. Also, only Button will currently draw the 2.0 features, RadioButton and CheckBox are not updated even though the properties will be settable in ButtonBase.

Thoughts?  Concerns?  Suggestions?  Anyone read past the first paragraph?
Jon
Index: System.Windows.Forms.dll.sources
===================================================================
--- System.Windows.Forms.dll.sources    (revision 73495)
+++ System.Windows.Forms.dll.sources    (working copy)
@@ -613,6 +613,8 @@
 System.Windows.Forms/Theme.cs
 System.Windows.Forms/ThemeClearlooks.cs
 System.Windows.Forms/ThemeEngine.cs
+System.Windows.Forms/ThemeElements.cs
+System.Windows.Forms/ThemeElementsDefault.cs
 System.Windows.Forms/ThemeGtk.cs
 System.Windows.Forms/ThemeNice.cs
 System.Windows.Forms/ThemeWin32Classic.cs
Index: System.Windows.Forms/Button.cs
===================================================================
--- System.Windows.Forms/Button.cs      (revision 73495)
+++ System.Windows.Forms/Button.cs      (working copy)
@@ -54,6 +54,34 @@
                        if (eh != null)
                                eh (this, EventArgs.Empty);
                }
+               
+#if NET_2_0
+               internal override void Draw (PaintEventArgs pevent)
+               {
+                       // System style does not use any of the new 2.0 stuff
+                       if (this.FlatStyle == FlatStyle.System) {
+                               base.Draw (pevent);
+                               return;
+                       }
+
+                       // FIXME: This should be called every time something 
that can affect it
+                       // is changed, not every paint.  Can only change so 
many things at a time.
+
+                       // Figure out where our text and image should go
+                       Rectangle text_rectangle;
+                       Rectangle image_rectangle;
+
+                       ThemeEngine.Current.CalculateButtonTextAndImageLayout 
(this, out text_rectangle, out image_rectangle);
+
+                       // Draw our button
+                       if (this.FlatStyle == FlatStyle.Standard)
+                               ThemeEngine.Current.DrawButton 
(pevent.Graphics, this, text_rectangle, image_rectangle, pevent.ClipRectangle);
+                       else if (this.FlatStyle == FlatStyle.Flat)
+                               ThemeEngine.Current.DrawFlatButton 
(pevent.Graphics, this, text_rectangle, image_rectangle, pevent.ClipRectangle);
+                       else if (this.FlatStyle == FlatStyle.Popup)
+                               ThemeEngine.Current.DrawPopupButton 
(pevent.Graphics, this, text_rectangle, image_rectangle, pevent.ClipRectangle);
+               }
+#endif
                #endregion      // Internal methods
 
                #region Public Instance Properties
@@ -108,7 +136,7 @@
                }
 
                protected override bool ProcessMnemonic(char charCode) {
-                       if (IsMnemonic(charCode, Text) == true) {
+                       if (this.UseMnemonic && IsMnemonic(charCode, Text) == 
true) {
                                PerformClick();
                                return true;
                        }
Index: System.Windows.Forms/ButtonBase.cs
===================================================================
--- System.Windows.Forms/ButtonBase.cs  (revision 73495)
+++ System.Windows.Forms/ButtonBase.cs  (working copy)
@@ -39,21 +39,26 @@
        public abstract class ButtonBase : Control
        {
                #region Local Variables
-               FlatStyle flat_style;
-               internal int                    image_index;
+               private FlatStyle               flat_style;
+               private int                     image_index;
                internal Image                  image;
                internal ImageList              image_list;
-               internal ContentAlignment       image_alignment;
+               private ContentAlignment        image_alignment;
                internal ContentAlignment       text_alignment;
                private bool                    is_default;
                internal bool                   is_pressed;
-               internal bool                   enter_state;
+               private bool                    enter_state;
                internal StringFormat           text_format;
                internal bool                   paint_as_acceptbutton;
-#if NET_2_0
+               
+               // Properties are 2.0, but variables used in 1.1 for common 
drawing code
+               private bool                    auto_ellipsis;
+               private FlatButtonAppearance    flat_button_appearance;
+               private string                  image_key;
+               private TextImageRelation       text_image_relation;
+               private TextFormatFlags         text_format_flags;
+               private bool                    use_mnemonic;
                private bool                    use_visual_style_back_color;
-               private FlatButtonAppearance flat_button_appearance;
-#endif
                #endregion      // Local Variables
 
                #region ButtonBaseAccessibleObject sub-class
@@ -139,6 +144,9 @@
                        flat_style      = FlatStyle.Standard;
 #if NET_2_0
                        flat_button_appearance = new FlatButtonAppearance 
(this);
+                       this.image_key = string.Empty;
+                       this.text_image_relation = TextImageRelation.Overlay;
+                       this.use_mnemonic = true;
 #endif
                        image_index     = -1;
                        image           = null;
@@ -153,6 +161,10 @@
                        text_format.LineAlignment = StringAlignment.Center;
                        text_format.HotkeyPrefix = HotkeyPrefix.Show;
 
+                       text_format_flags = TextFormatFlags.HorizontalCenter;
+                       text_format_flags |= TextFormatFlags.VerticalCenter;
+                       text_format_flags |= TextFormatFlags.WordBreak;
+               
                        TextChanged+=new System.EventHandler(RedrawEvent);
                        SizeChanged+=new EventHandler(RedrawEvent);
 
@@ -184,25 +196,45 @@
                                Invalidate();
                        }
                }
-#if NET_2_0
-               [MonoTODO("FlatAppearance is currently ignored on drawing.")]
+
                
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
                [Browsable(true)]
-               public FlatButtonAppearance FlatAppearance
+#if NET_2_0
+               public 
+#else
+               internal
+#endif
+               FlatButtonAppearance FlatAppearance
                {
                        get { return flat_button_appearance; }
                }
-#endif         
+
                [Localizable(true)]
                [MWFDescription("Sets image to be displayed on button face"), 
MWFCategory("Appearance")]
                public Image Image {
                        get {
-                               return image;
+                               if (this.image != null)
+                                       return this.image;
+
+                               if (this.image_index >= 0)
+                                       if (this.image_list != null)
+                                               return 
this.image_list.Images[this.image_index];
+
+#if NET_2_0
+                               if (!string.IsNullOrEmpty (this.image_key))
+                                       if (this.image_list != null)
+                                               return 
this.image_list.Images[this.image_key];
+#endif
+                               return null;
                        }
-
                        set {
-                               image = value;
-                               Invalidate();
+                               if (this.image != value) {
+                                       this.image = value;
+                                       this.image_index = -1;
+                                       this.image_key = string.Empty;
+                                       this.image_list = null;
+                                       Invalidate();
+                               }
                        }
                }
 
@@ -237,8 +269,12 @@
                        }
 
                        set {
-                               image_index=value;
-                               Invalidate();
+                               if (this.image_index != value) {
+                                       this.image_index = value;
+                                       this.image = null;
+                                       this.image_key = string.Empty;
+                                       Invalidate();
+                               }
                        }
                }
 
@@ -281,6 +317,14 @@
                        set {
                                if (text_alignment != value) {
                                        text_alignment = value;
+
+                                       text_format_flags &= 
~TextFormatFlags.Bottom;
+                                       text_format_flags &= 
~TextFormatFlags.Top;
+                                       text_format_flags &= 
~TextFormatFlags.Left;
+                                       text_format_flags &= 
~TextFormatFlags.Right;
+                                       text_format_flags &= 
~TextFormatFlags.HorizontalCenter;
+                                       text_format_flags &= 
~TextFormatFlags.VerticalCenter;
+                                       
                                        switch(text_alignment) {
                                        case ContentAlignment.TopLeft:
                                                
text_format.Alignment=StringAlignment.Near;
@@ -290,41 +334,49 @@
                                        case ContentAlignment.TopCenter:
                                                
text_format.Alignment=StringAlignment.Center;
                                                
text_format.LineAlignment=StringAlignment.Near;
+                                               text_format_flags |= 
TextFormatFlags.HorizontalCenter;
                                                break;
 
                                        case ContentAlignment.TopRight:
                                                
text_format.Alignment=StringAlignment.Far;
                                                
text_format.LineAlignment=StringAlignment.Near;
+                                               text_format_flags |= 
TextFormatFlags.Right;
                                                break;
 
                                        case ContentAlignment.MiddleLeft:
                                                
text_format.Alignment=StringAlignment.Near;
                                                
text_format.LineAlignment=StringAlignment.Center;
+                                               text_format_flags |= 
TextFormatFlags.VerticalCenter;
                                                break;
 
                                        case ContentAlignment.MiddleCenter:
                                                
text_format.Alignment=StringAlignment.Center;
                                                
text_format.LineAlignment=StringAlignment.Center;
+                                               text_format_flags |= 
TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter;
                                                break;
 
                                        case ContentAlignment.MiddleRight:
                                                
text_format.Alignment=StringAlignment.Far;
                                                
text_format.LineAlignment=StringAlignment.Center;
+                                               text_format_flags |= 
TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
                                                break;
 
                                        case ContentAlignment.BottomLeft:
                                                
text_format.Alignment=StringAlignment.Near;
                                                
text_format.LineAlignment=StringAlignment.Far;
+                                               text_format_flags |= 
TextFormatFlags.Bottom;
                                                break;
 
                                        case ContentAlignment.BottomCenter:
                                                
text_format.Alignment=StringAlignment.Center;
                                                
text_format.LineAlignment=StringAlignment.Far;
+                                               text_format_flags |= 
TextFormatFlags.HorizontalCenter | TextFormatFlags.Bottom;
                                                break;
 
                                        case ContentAlignment.BottomRight:
                                                
text_format.Alignment=StringAlignment.Far;
                                                
text_format.LineAlignment=StringAlignment.Far;
+                                               text_format_flags |= 
TextFormatFlags.Bottom | TextFormatFlags.Right;
                                                break;
                                        }
                                        Invalidate();
@@ -531,7 +583,17 @@
                }
                #endregion      // Public Instance Properties
 
-
+               #region Internal Instance Properties
+               internal bool Pressed {
+                       get { return this.is_pressed; }
+               }
+               
+               // The flags to be used for MeasureText and DrawText
+               internal TextFormatFlags TextFormatFlags {
+                       get { return this.text_format_flags; }
+               }
+               #endregion
+               
                #region Internal Methods
                private void PerformClick() {
                        OnClick(EventArgs.Empty);
@@ -539,6 +601,13 @@
                #endregion      // Internal Methods
 
                #region Events
+#if NET_2_0
+               public new event EventHandler AutoSizeChanged {
+                       add { base.AutoSizeChanged += value; }
+                       remove { base.AutoSizeChanged -= value; }
+               }
+#endif
+
                [Browsable(false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public new event EventHandler ImeModeChanged {
@@ -549,23 +618,120 @@
 
 
                #region .NET 2.0 Public Instance Properties
+               [DefaultValue (false)]
 #if NET_2_0
-               public bool UseVisualStyleBackColor {
-                       get { return use_visual_style_back_color; }
-                       set { use_visual_style_back_color = value; }
+               public 
+#else
+               internal
+#endif
+               bool AutoEllipsis {
+                       get { return this.auto_ellipsis; }
+                       set {
+                               if (this.auto_ellipsis != value) {
+                                       this.auto_ellipsis = value;
+                                       
+                                       if (this.auto_ellipsis) {
+                                               text_format_flags |= 
TextFormatFlags.EndEllipsis;
+                                               text_format_flags &= 
~TextFormatFlags.WordBreak;
+                                       }
+                                       else {
+                                               text_format_flags &= 
~TextFormatFlags.EndEllipsis;
+                                               text_format_flags |= 
TextFormatFlags.WordBreak;
+                                       }
+                                               
+                                       this.Invalidate ();
+                               }
+                       }
                }
 
-               [DefaultValue (false)]
-               public bool UseCompatibleTextRendering {
-                       get {
-                               return use_compatible_text_rendering;
+#if NET_2_0
+               [DefaultValue (true)]
+               public override bool AutoSize {
+                       get { return base.AutoSize; }
+                       set { base.AutoSize = value; }
+               }
+
+               public override Color BackColor {
+                       get { return base.BackColor; }
+                       set { base.BackColor = value; }
+               }
+               
+               [Localizable (true)]
+               public string ImageKey {
+                       get { return this.image_key; }
+                       set {
+                               if (this.image_key != value) {
+                                       this.image = null;
+                                       this.image_index = -1;
+                                       this.image_key = value;
+                                       this.Invalidate ();
+                               }
                        }
+               }
+               
+               [Localizable (true)]
+               [DefaultValue (TextImageRelation.Overlay)]
+               public 
+#else
+               internal
+#endif
+               TextImageRelation TextImageRelation {
+                       get { return this.text_image_relation; }
+                       set {
+                               if (!Enum.IsDefined (typeof 
(TextImageRelation), value))
+                                       throw new InvalidEnumArgumentException 
(string.Format ("Enum argument value '{0}' is not valid for TextImageRelation", 
value));
 
+                               if (this.text_image_relation != value) {
+                                       this.text_image_relation = value;
+                                       this.Invalidate ();
+                               }
+                       }
+               }
+               
+               [DefaultValue (true)]
+#if NET_2_0
+               public 
+#else
+               internal
+#endif
+               bool UseMnemonic {
+                       get { return this.use_mnemonic; }
                        set {
-                               use_compatible_text_rendering = value;
+                               if (this.use_mnemonic != value) {
+                                       this.use_mnemonic = value;
+
+                                       if (this.use_mnemonic)
+                                               text_format_flags &= 
~TextFormatFlags.NoPrefix;
+                                       else
+                                               text_format_flags |= 
TextFormatFlags.NoPrefix;
+                                       
+                                       this.Invalidate ();
+                               }
                        }
                }
 
+#if NET_2_0
+               public 
+#else
+               internal
+#endif
+               bool UseVisualStyleBackColor {
+                       get { return use_visual_style_back_color; }
+                       set { use_visual_style_back_color = value; }
+               }
+
+               [DefaultValue (false)]
+#if NET_2_0
+               public 
+#else
+               internal
+#endif
+               bool UseCompatibleTextRendering {
+                       get { return use_compatible_text_rendering; }
+                       set { use_compatible_text_rendering = value; }
+               }
+
+#if NET_2_0
                [SettingsBindable (true)]
                [Editor ("System.ComponentModel.Design.MultilineStringEditor, " 
+ Consts.AssemblySystem_Design,
                         "System.Drawing.Design.UITypeEditor, " + 
Consts.AssemblySystem_Drawing)]
Index: System.Windows.Forms/ChangeLog
===================================================================
--- System.Windows.Forms/ChangeLog      (revision 73495)
+++ System.Windows.Forms/ChangeLog      (working copy)
@@ -1,3 +1,18 @@
+2007-02-27  Jonathan Pobst  <[EMAIL PROTECTED]>
+
+       * ButtonBase.cs: Add 2.0 properties.
+       * Button.cs: Override Draw for 2.0.
+       * Control.cs: Add Entered and Selected properties.
+       * FlatButtonAppearance.cs, TextFormatFlags.cs, TextImageRelation.cs,
+       TextRenderer.cs: Make internal for 1.1 to unify drawing code.
+       * Theme.cs: New abstract functions for drawing Standard, Flat, Popup
+       buttons.
+       * ThemeWin32Classic.cs: Implement layout calculations for 2.0 buttons.
+       * ThemeElements.cs: Driver code to theme class that actually draws 
+       theme elements.
+       * ThemeElementsDefault.cs: Default [win32 style] implementation of 
+       Standard, Flat, Popup buttons.
+
 2007-02-26  Jonathan Pobst  <[EMAIL PROTECTED]>
 
        * XplatUIStructs.cs: Add some convenience methods for POINT structure.
Index: System.Windows.Forms/Control.cs
===================================================================
--- System.Windows.Forms/Control.cs     (revision 73495)
+++ System.Windows.Forms/Control.cs     (working copy)
@@ -127,6 +127,7 @@
                BindingContext          binding_context;
                RightToLeft             right_to_left; // drawing direction for 
control
                ContextMenu             context_menu; // Context menu 
associated with the control
+               internal bool           use_compatible_text_rendering;
 
                // double buffering
                DoubleBuffer            backbuffer;
@@ -138,7 +139,6 @@
                ControlBindingsCollection data_bindings;
 
 #if NET_2_0
-               internal bool use_compatible_text_rendering;
                static bool verify_thread_handle;
                Padding padding;
                ImageLayout backgroundimage_layout;
@@ -936,6 +936,7 @@
                        dist_bottom = 0;
                        tab_stop = true;
                        ime_mode = ImeMode.Inherit;
+                       use_compatible_text_rendering = true;
 
 #if NET_2_0
                        backgroundimage_layout = ImageLayout.Tile;
@@ -1036,6 +1037,26 @@
                #endregion      // Public Constructors
 
                #region Internal Properties
+               // Control is currently selected, like Focused, except 
maintains state
+               // when Form loses focus
+               internal bool Selected {
+                       get {
+                               IContainerControl container;
+                       
+                               container = GetContainerControl();
+                               
+                               if (container != null && 
container.ActiveControl == this)
+                                       return true;
+                                       
+                               return false;
+                       }
+               }
+               
+               // Mouse is currently within the control's bounds
+               internal bool Entered {
+                       get { return this.is_entered; }
+               }
+
                internal bool VisibleInternal {
                        get { return is_visible; }
                }
Index: System.Windows.Forms/FlatButtonAppearance.cs
===================================================================
--- System.Windows.Forms/FlatButtonAppearance.cs        (revision 73495)
+++ System.Windows.Forms/FlatButtonAppearance.cs        (working copy)
@@ -25,7 +25,6 @@
 // Author:
 //      Daniel Nauck    (dna(at)mono-project(dot)de)
 
-#if NET_2_0
 
 using System;
 using System.ComponentModel;
@@ -34,7 +33,10 @@
 
 namespace System.Windows.Forms
 {
-       public class FlatButtonAppearance
+#if NET_2_0
+       public 
+#endif
+       class FlatButtonAppearance
        {
                private Color borderColor = Color.Empty;
                private int borderSize = 1;
@@ -141,5 +143,4 @@
                        }
                }
        }
-}
-#endif
\ No newline at end of file
+}
\ No newline at end of file
Index: System.Windows.Forms/TextFormatFlags.cs
===================================================================
--- System.Windows.Forms/TextFormatFlags.cs     (revision 73495)
+++ System.Windows.Forms/TextFormatFlags.cs     (working copy)
@@ -24,12 +24,14 @@
 //
 
 
-#if NET_2_0
 
 namespace System.Windows.Forms {
        
        [FlagsAttribute()]
-       public enum TextFormatFlags {
+#if NET_2_0
+       public 
+#endif
+       enum TextFormatFlags {
                Left = 0,
                Top = 0,
                Default = 0,
@@ -59,7 +61,4 @@
                NoPadding = 268435456,
                LeftAndRightPadding = 536870912
        }
-
-}
-
-#endif
+}
\ No newline at end of file
Index: System.Windows.Forms/TextImageRelation.cs
===================================================================
--- System.Windows.Forms/TextImageRelation.cs   (revision 73495)
+++ System.Windows.Forms/TextImageRelation.cs   (working copy)
@@ -27,10 +27,12 @@
 //
 
 
-#if NET_2_0
 namespace System.Windows.Forms
 {
-       public enum TextImageRelation
+#if NET_2_0
+       public 
+#endif
+       enum TextImageRelation
        {
                Overlay = 0,
                ImageAboveText = 1,
@@ -39,4 +41,3 @@
                TextBeforeImage = 8
        }
 }
-#endif
\ No newline at end of file
Index: System.Windows.Forms/TextRenderer.cs
===================================================================
--- System.Windows.Forms/TextRenderer.cs        (revision 73495)
+++ System.Windows.Forms/TextRenderer.cs        (working copy)
@@ -26,16 +26,17 @@
 //     Jonathan Pobst ([EMAIL PROTECTED])
 //
 
-#if NET_2_0
 using System.Drawing;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Drawing.Text;
-using System.Windows.Forms.VisualStyles;
 
 namespace System.Windows.Forms
 {
-       public sealed class TextRenderer
+#if NET_2_0
+       public sealed 
+#endif
+       class TextRenderer
        {
                private static Bitmap measure_bitmap = new Bitmap (1, 1);
 
@@ -44,6 +45,7 @@
                }
 
                #region Public Methods
+#if NET_2_0
                public static void DrawText (IDeviceContext dc, string text, 
Font font, Point pt, Color foreColor)
                {
                        DrawTextInternal (dc, text, font, pt, foreColor, 
Color.Transparent, TextFormatFlags.Default, false);
@@ -113,11 +115,17 @@
                {
                        return MeasureTextInternal (dc, text, font, 
proposedSize, flags, false);
                }
+#endif
                #endregion
 
                #region Internal Methods That Do Stuff
+#if NET_2_0
                internal static void DrawTextInternal (IDeviceContext dc, 
string text, Font font, Rectangle bounds, Color foreColor, Color backColor, 
TextFormatFlags flags, bool useDrawString)
+#else
+               internal static void DrawTextInternal (Graphics dc, string 
text, Font font, Rectangle bounds, Color foreColor, Color backColor, 
TextFormatFlags flags, bool useDrawString)
+#endif
                {
+#if NET_2_0
                        if (dc == null)
                                throw new ArgumentNullException ("dc");
 
@@ -187,13 +195,19 @@
                        }
                        // Use Graphics.DrawString as a fallback method
                        else {
+#endif
                                Graphics g;
 
+#if NET_2_0
                                if (dc is Graphics)
                                        g = (Graphics)dc;
                                else
                                        g = Graphics.FromHdc (dc.GetHdc ());
+#else
+                                       g = (Graphics)dc;
 
+#endif
+
                                StringFormat sf = FlagsToStringFormat (flags);
 
                                Rectangle new_bounds = PadDrawStringRectangle 
(bounds, flags);
@@ -201,15 +215,22 @@
                                using (Brush b = new SolidBrush (foreColor))
                                        g.DrawString (text, font, b, 
new_bounds, sf);
 
+#if NET_2_0
                                if (!(dc is Graphics)) {
                                        g.Dispose ();
                                        dc.ReleaseHdc ();
                                }
                        }
+#endif
                }
 
+#if NET_2_0
                internal static Size MeasureTextInternal (IDeviceContext dc, 
string text, Font font, Size proposedSize, TextFormatFlags flags, bool 
useMeasureString)
+#else
+               internal static Size MeasureTextInternal (Graphics dc, string 
text, Font font, Size proposedSize, TextFormatFlags flags, bool 
useMeasureString)
+#endif
                {
+#if NET_2_0
                        if (!useMeasureString && 
(Environment.OSVersion.Platform == PlatformID.Win32NT || 
Environment.OSVersion.Platform == PlatformID.Win32Windows)) {
                                // Tell DrawText to calculate size instead of 
draw
                                flags |= (TextFormatFlags)1024;         // 
DT_CALCRECT
@@ -244,6 +265,7 @@
                                return retval;
                        }
                        else {
+#endif
                                Graphics g = Graphics.FromImage 
(measure_bitmap);
 
                                Size retval = g.MeasureString (text, 
font).ToSize ();
@@ -253,10 +275,13 @@
 
                                return retval;
                        }
+#if NET_2_0
                }
+#endif
                #endregion
 
 #region Internal Methods That Are Just Overloads
+#if NET_2_0
                internal static void DrawTextInternal (IDeviceContext dc, 
string text, Font font, Point pt, Color foreColor, bool useDrawString)
                {
                        DrawTextInternal (dc, text, font, pt, foreColor, 
Color.Transparent, TextFormatFlags.Default, useDrawString);
@@ -283,10 +308,14 @@
                }
 
                internal static void DrawTextInternal (IDeviceContext dc, 
string text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags 
flags, bool useDrawString)
+#else
+               internal static void DrawTextInternal (Graphics dc, string 
text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags, bool 
useDrawString)
+#endif
                {
                        DrawTextInternal (dc, text, font, bounds, foreColor, 
Color.Transparent, flags, useDrawString);
                }
 
+#if NET_2_0
                internal static void DrawTextInternal (IDeviceContext dc, 
string text, Font font, Point pt, Color foreColor, Color backColor, 
TextFormatFlags flags, bool useDrawString)
                {
                        Size sz = MeasureTextInternal (dc, text, font, 
useDrawString);
@@ -313,6 +342,7 @@
                        return MeasureTextInternal (dc, text, font, 
proposedSize, TextFormatFlags.Default, useMeasureString);
                }
 
+#endif
                internal static Size MeasureTextInternal (string text, Font 
font, Size proposedSize, TextFormatFlags flags, bool useMeasureString)
                {
                        return MeasureTextInternal (Graphics.FromImage 
(measure_bitmap), text, font, proposedSize, flags, useMeasureString);
@@ -459,5 +489,4 @@
                static extern bool SelectClipRgn(IntPtr hdc, IntPtr hrgn);
 #endregion
        }
-}
-#endif
+}
\ No newline at end of file
Index: System.Windows.Forms/Theme.cs
===================================================================
--- System.Windows.Forms/Theme.cs       (revision 73495)
+++ System.Windows.Forms/Theme.cs       (working copy)
@@ -692,6 +692,10 @@
                #endregion      // OwnerDraw Support
 
                #region Button
+               public abstract void CalculateButtonTextAndImageLayout (Button 
b, out Rectangle textRectangle, out Rectangle imageRectangle);
+               public abstract void DrawButton (Graphics g, Button b, 
Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle);
+               public abstract void DrawFlatButton (Graphics g, Button b, 
Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle);
+               public abstract void DrawPopupButton (Graphics g, Button b, 
Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle);
                #endregion      // Button
 
                #region ButtonBase
Index: System.Windows.Forms/ThemeElements.cs
===================================================================
--- System.Windows.Forms/ThemeElements.cs       (revision 0)
+++ System.Windows.Forms/ThemeElements.cs       (revision 0)
@@ -0,0 +1,51 @@
+using System;
+using System.Drawing;
+
+namespace System.Windows.Forms
+{
+       internal class ThemeElements
+       {
+               private static ThemeElementsDefault theme;
+
+               static ThemeElements ()
+               {
+                       string theme_var;
+
+                       theme_var = Environment.GetEnvironmentVariable 
("MONO_THEME");
+
+                       if (theme_var == null)
+                               theme_var = "win32";
+                       else
+                               theme_var = theme_var.ToLower ();
+
+                       theme = new ThemeElementsDefault ();
+               }
+               
+               public static void DrawButton (Graphics g, Rectangle bounds, 
ButtonThemeState state, Color backColor, Color foreColor)
+               {
+                       theme.DrawButton (g, bounds, state, backColor, 
foreColor);
+               }
+
+               public static void DrawFlatButton (Graphics g, Rectangle 
bounds, ButtonThemeState state, Color backColor, Color foreColor, 
FlatButtonAppearance appearance)
+               {
+                       theme.DrawFlatButton (g, bounds, state, backColor, 
foreColor, appearance);
+               }
+
+               public static void DrawPopupButton (Graphics g, Rectangle 
bounds, ButtonThemeState state, Color backColor, Color foreColor)
+               {
+                       theme.DrawPopupButton (g, bounds, state, backColor, 
foreColor);
+               }
+       }
+
+       #region Internal Enums
+       [Flags]
+       internal enum ButtonThemeState
+       {
+               Normal = 1,
+               Entered = 2,
+               Pressed = 4,
+               Disabled = 8,
+               Default = 16
+       }
+       #endregion
+}
Index: System.Windows.Forms/ThemeElementsDefault.cs
===================================================================
--- System.Windows.Forms/ThemeElementsDefault.cs        (revision 0)
+++ System.Windows.Forms/ThemeElementsDefault.cs        (revision 0)
@@ -0,0 +1,152 @@
+using System;
+using System.Drawing;
+
+namespace System.Windows.Forms
+{
+       internal class ThemeElementsDefault
+       {
+               public ThemeElementsDefault ()
+               {
+               }
+
+               protected SystemResPool ResPool { get { return 
ThemeEngine.Current.ResPool; } }
+               
+               #region Buttons
+               #region Standard Button
+               public virtual void DrawButton (Graphics g, Rectangle bounds, 
ButtonThemeState state, Color backColor, Color foreColor)
+               {
+                       bool is_themecolor = backColor.ToArgb () == 
ThemeEngine.Current.ColorControl.ToArgb () || backColor == Color.Empty ? true : 
false;
+                       CPColor cpcolor = is_themecolor ? CPColor.Empty : 
ResPool.GetCPColor (backColor);
+                       Pen pen;
+                       
+                       switch (state) {
+                               case ButtonThemeState.Normal:
+                               case ButtonThemeState.Entered:
+                               case ButtonThemeState.Disabled:
+                                       pen = is_themecolor ? 
SystemPens.ControlLightLight : ResPool.GetPen (cpcolor.LightLight);
+                                       g.DrawLine (pen, bounds.X, bounds.Y, 
bounds.X, bounds.Bottom - 2);
+                                       g.DrawLine (pen, bounds.X + 1, 
bounds.Y, bounds.Right - 2, bounds.Y);
+
+                                       pen = is_themecolor ? 
SystemPens.Control : ResPool.GetPen (backColor);
+                                       g.DrawLine (pen, bounds.X + 1, bounds.Y 
+ 1, bounds.X + 1, bounds.Bottom - 3);
+                                       g.DrawLine (pen, bounds.X + 2, bounds.Y 
+ 1, bounds.Right - 3, bounds.Y + 1);
+
+                                       pen = is_themecolor ? 
SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark);
+                                       g.DrawLine (pen, bounds.X + 1, 
bounds.Bottom - 2, bounds.Right - 2, bounds.Bottom - 2);
+                                       g.DrawLine (pen, bounds.Right - 2, 
bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 3);
+
+                                       pen = is_themecolor ? 
SystemPens.ControlDarkDark : ResPool.GetPen (cpcolor.DarkDark);
+                                       g.DrawLine (pen, bounds.X, 
bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1);
+                                       g.DrawLine (pen, bounds.Right - 1, 
bounds.Y, bounds.Right - 1, bounds.Bottom - 2);
+                                       break;
+                               case ButtonThemeState.Pressed:
+                                       g.DrawRectangle (ResPool.GetPen 
(foreColor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
+
+                                       bounds.Inflate (-1, -1);
+                                       pen = is_themecolor ? 
SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark);
+                                       g.DrawRectangle (pen, bounds.X, 
bounds.Y, bounds.Width - 1, bounds.Height - 1);
+                                       break;
+                               case ButtonThemeState.Default:
+                                       g.DrawRectangle (ResPool.GetPen 
(foreColor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
+
+                                       bounds.Inflate (-1, -1);
+                                       pen = is_themecolor ? 
SystemPens.ControlLightLight : ResPool.GetPen (cpcolor.LightLight);
+                                       g.DrawLine (pen, bounds.X, bounds.Y, 
bounds.X, bounds.Bottom - 2);
+                                       g.DrawLine (pen, bounds.X + 1, 
bounds.Y, bounds.Right - 2, bounds.Y);
+
+                                       pen = is_themecolor ? 
SystemPens.Control : ResPool.GetPen (backColor);
+                                       g.DrawLine (pen, bounds.X + 1, bounds.Y 
+ 1, bounds.X + 1, bounds.Bottom - 3);
+                                       g.DrawLine (pen, bounds.X + 2, bounds.Y 
+ 1, bounds.Right - 3, bounds.Y + 1);
+
+                                       pen = is_themecolor ? 
SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark);
+                                       g.DrawLine (pen, bounds.X + 1, 
bounds.Bottom - 2, bounds.Right - 2, bounds.Bottom - 2);
+                                       g.DrawLine (pen, bounds.Right - 2, 
bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 3);
+
+                                       pen = is_themecolor ? 
SystemPens.ControlDarkDark : ResPool.GetPen (cpcolor.DarkDark);
+                                       g.DrawLine (pen, bounds.X, 
bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1);
+                                       g.DrawLine (pen, bounds.Right - 1, 
bounds.Y, bounds.Right - 1, bounds.Bottom - 2);
+                                       break;
+                       }
+               }
+               #endregion
+
+               #region FlatStyle Button
+               public virtual void DrawFlatButton (Graphics g, Rectangle 
bounds, ButtonThemeState state, Color backColor, Color foreColor, 
FlatButtonAppearance appearance)
+               {
+                       bool is_themecolor = backColor.ToArgb () == 
ThemeEngine.Current.ColorControl.ToArgb () || backColor == Color.Empty ? true : 
false;
+                       CPColor cpcolor = is_themecolor ? CPColor.Empty : 
ResPool.GetCPColor (backColor);
+                       Pen pen;
+                       
+                       switch (state) {
+                               case ButtonThemeState.Normal:
+                               case ButtonThemeState.Disabled:
+                                       // This will just use the BackColor
+                                       break;
+                               case ButtonThemeState.Entered:
+                                       if (appearance.MouseOverBackColor != 
Color.Empty)
+                                               g.FillRectangle 
(ResPool.GetSolidBrush (appearance.MouseOverBackColor), bounds);
+                                       break;
+                               case ButtonThemeState.Pressed:
+                                       if (appearance.MouseDownBackColor != 
Color.Empty)
+                                               g.FillRectangle 
(ResPool.GetSolidBrush (appearance.MouseDownBackColor), bounds);
+                                       break;
+                               case ButtonThemeState.Default:
+                                       if (appearance.CheckedBackColor != 
Color.Empty)
+                                               g.FillRectangle 
(ResPool.GetSolidBrush (appearance.CheckedBackColor), bounds);
+                                       break;
+                       }
+                       
+                       if (appearance.BorderColor == Color.Empty)
+                               pen = is_themecolor ? 
SystemPens.ControlDarkDark : ResPool.GetSizedPen (cpcolor.DarkDark, 
appearance.BorderSize);
+                       else
+                               pen = ResPool.GetSizedPen 
(appearance.BorderColor, appearance.BorderSize);
+                               
+                       bounds.Width -= 1;
+                       bounds.Height -= 1;
+                       g.DrawRectangle (pen, bounds);
+
+                       if (state == ButtonThemeState.Default || state == 
ButtonThemeState.Pressed) {
+                               bounds.Inflate (-1, -1);
+                               g.DrawRectangle (pen, bounds);
+                       }
+               }
+               #endregion
+
+               #region Popup Button
+               public virtual void DrawPopupButton (Graphics g, Rectangle 
bounds, ButtonThemeState state, Color backColor, Color foreColor)
+               {
+                       bool is_themecolor = backColor.ToArgb () == 
ThemeEngine.Current.ColorControl.ToArgb () || backColor == Color.Empty ? true : 
false;
+                       CPColor cpcolor = is_themecolor ? CPColor.Empty : 
ResPool.GetCPColor (backColor);
+                       Pen pen;
+
+                       switch (state) {
+                               case ButtonThemeState.Normal:
+                               case ButtonThemeState.Disabled:
+                               case ButtonThemeState.Pressed:
+                               case ButtonThemeState.Default:
+                                       pen = is_themecolor ? 
SystemPens.ControlDarkDark : ResPool.GetPen (cpcolor.DarkDark);
+
+                                       bounds.Width -= 1;
+                                       bounds.Height -= 1;
+                                       g.DrawRectangle (pen, bounds);
+
+                                       if (state == ButtonThemeState.Default 
|| state == ButtonThemeState.Pressed) {
+                                               bounds.Inflate (-1, -1);
+                                               g.DrawRectangle (pen, bounds);
+                                       }
+                                       break;
+                               case ButtonThemeState.Entered:
+                                       pen = is_themecolor ? 
SystemPens.ControlLightLight : ResPool.GetPen (cpcolor.LightLight);
+                                       g.DrawLine (pen, bounds.X, bounds.Y, 
bounds.X, bounds.Bottom - 2);
+                                       g.DrawLine (pen, bounds.X + 1, 
bounds.Y, bounds.Right - 2, bounds.Y);
+
+                                       pen = is_themecolor ? 
SystemPens.ControlDark : ResPool.GetPen (cpcolor.Dark);
+                                       g.DrawLine (pen, bounds.X, 
bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1);
+                                       g.DrawLine (pen, bounds.Right - 1, 
bounds.Y, bounds.Right - 1, bounds.Bottom - 2);
+                                       break;
+                       }
+               }
+               #endregion
+               #endregion
+       }
+}
Index: System.Windows.Forms/ThemeWin32Classic.cs
===================================================================
--- System.Windows.Forms/ThemeWin32Classic.cs   (revision 73495)
+++ System.Windows.Forms/ThemeWin32Classic.cs   (working copy)
@@ -140,6 +140,430 @@
                }
                #endregion      // OwnerDraw Support
 
+               #region Button
+               #region Standard Button Style
+               public override void DrawButton (Graphics g, Button b, 
Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle)
+               {
+                       // Draw Button Background
+                       DrawButtonBackground (g, b, clipRectangle);
+
+                       // If we have an image, draw it
+                       if (imageBounds.Size != Size.Empty)
+                               DrawButtonImage (g, b, imageBounds);
+
+                       // If we're focused, draw a focus rectangle
+                       if (b.Focused && b.Enabled)
+                               DrawButtonFocus (g, b);
+
+                       // If we have text, draw it
+                       if (textBounds != Rectangle.Empty)
+                               DrawButtonText (g, b, textBounds);
+               }
+
+               public virtual void DrawButtonBackground (Graphics g, Button 
button, Rectangle clipArea) 
+               {
+                       if (button.Pressed)
+                               ThemeElements.DrawButton (g, 
button.ClientRectangle, ButtonThemeState.Pressed, button.BackColor, 
button.ForeColor);
+                       else if (button.Selected)
+                               ThemeElements.DrawButton (g, 
button.ClientRectangle, ButtonThemeState.Default, button.BackColor, 
button.ForeColor);
+                       else if (button.Entered)
+                               ThemeElements.DrawButton (g, 
button.ClientRectangle, ButtonThemeState.Entered, button.BackColor, 
button.ForeColor);
+                       else if (!button.Enabled)
+                               ThemeElements.DrawButton (g, 
button.ClientRectangle, ButtonThemeState.Disabled, button.BackColor, 
button.ForeColor);
+                       else
+                               ThemeElements.DrawButton (g, 
button.ClientRectangle, ButtonThemeState.Normal, button.BackColor, 
button.ForeColor);
+               }
+
+               public virtual void DrawButtonFocus (Graphics g, Button button)
+               {
+                       ControlPaint.DrawFocusRectangle (g, Rectangle.Inflate 
(button.ClientRectangle, -4, -4));
+               }
+
+               public virtual void DrawButtonImage (Graphics g, Button button, 
Rectangle imageBounds)
+               {
+                       if (button.Enabled)
+                               g.DrawImage (button.Image, imageBounds);
+                       else
+                               CPDrawImageDisabled (g, button.Image, 
imageBounds.Left, imageBounds.Top, ColorControl);
+               }
+
+               public virtual void DrawButtonText (Graphics g, Button button, 
Rectangle textBounds)
+               {
+                       if (button.Pressed)
+                               textBounds.Offset (1, 1);
+                                                       
+                       if (button.Enabled)
+                               TextRenderer.DrawTextInternal (g, button.Text, 
button.Font, textBounds, button.ForeColor, button.TextFormatFlags, 
button.UseCompatibleTextRendering);
+                       else
+                               DrawStringDisabled20 (g, button.Text, 
button.Font, textBounds, button.BackColor, button.TextFormatFlags, 
button.UseCompatibleTextRendering);
+               }
+               #endregion
+
+               #region FlatStyle Button Style
+               public override void DrawFlatButton (Graphics g, Button b, 
Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle)
+               {
+                       // Draw Button Background
+                       DrawFlatButtonBackground (g, b, clipRectangle);
+
+                       // If we have an image, draw it
+                       if (imageBounds.Size != Size.Empty)
+                               DrawFlatButtonImage (g, b, imageBounds);
+
+                       // If we're focused, draw a focus rectangle
+                       if (b.Focused && b.Enabled)
+                               DrawFlatButtonFocus (g, b);
+
+                       // If we have text, draw it
+                       if (textBounds != Rectangle.Empty)
+                               DrawFlatButtonText (g, b, textBounds);
+               }
+
+               public virtual void DrawFlatButtonBackground (Graphics g, 
Button button, Rectangle clipArea)
+               {
+                       if (button.Pressed)
+                               ThemeElements.DrawFlatButton (g, 
button.ClientRectangle, ButtonThemeState.Pressed, button.BackColor, 
button.ForeColor, button.FlatAppearance);
+                       else if (button.Selected)
+                               ThemeElements.DrawFlatButton (g, 
button.ClientRectangle, ButtonThemeState.Default, button.BackColor, 
button.ForeColor, button.FlatAppearance);
+                       else if (button.Entered)
+                               ThemeElements.DrawFlatButton (g, 
button.ClientRectangle, ButtonThemeState.Entered, button.BackColor, 
button.ForeColor, button.FlatAppearance);
+                       else if (!button.Enabled)
+                               ThemeElements.DrawFlatButton (g, 
button.ClientRectangle, ButtonThemeState.Disabled, button.BackColor, 
button.ForeColor, button.FlatAppearance);
+                       else
+                               ThemeElements.DrawFlatButton (g, 
button.ClientRectangle, ButtonThemeState.Normal, button.BackColor, 
button.ForeColor, button.FlatAppearance);
+               }
+
+               public virtual void DrawFlatButtonFocus (Graphics g, Button 
button)
+               {
+                       if (!button.Pressed) {
+                               Color focus_color = 
ControlPaint.Light(button.BackColor);
+                               g.DrawRectangle (ResPool.GetPen (focus_color), 
new Rectangle (button.ClientRectangle.Left + 4, button.ClientRectangle.Top + 4, 
button.ClientRectangle.Width - 9, button.ClientRectangle.Height - 9));
+                       }
+               }
+
+               public virtual void DrawFlatButtonImage (Graphics g, Button 
button, Rectangle imageBounds)
+               {
+                       // No changes from Standard for image for this theme
+                       DrawButtonImage (g, button, imageBounds);
+               }
+
+               public virtual void DrawFlatButtonText (Graphics g, Button 
button, Rectangle textBounds)
+               {
+                       // No changes from Standard for image for this theme
+                       DrawButtonText (g, button, textBounds);
+               }
+               #endregion
+
+               #region Popup Button Style
+               public override void DrawPopupButton (Graphics g, Button b, 
Rectangle textBounds, Rectangle imageBounds, Rectangle clipRectangle)
+               {
+                       // Draw Button Background
+                       DrawPopupButtonBackground (g, b, clipRectangle);
+
+                       // If we have an image, draw it
+                       if (imageBounds.Size != Size.Empty)
+                               DrawPopupButtonImage (g, b, imageBounds);
+
+                       // If we're focused, draw a focus rectangle
+                       if (b.Focused && b.Enabled)
+                               DrawPopupButtonFocus (g, b);
+
+                       // If we have text, draw it
+                       if (textBounds != Rectangle.Empty)
+                               DrawPopupButtonText (g, b, textBounds);
+               }
+
+               public virtual void DrawPopupButtonBackground (Graphics g, 
Button button, Rectangle clipArea)
+               {
+                       if (button.Pressed)
+                               ThemeElements.DrawPopupButton (g, 
button.ClientRectangle, ButtonThemeState.Pressed, button.BackColor, 
button.ForeColor);
+                       else if (button.Entered)
+                               ThemeElements.DrawPopupButton (g, 
button.ClientRectangle, ButtonThemeState.Entered, button.BackColor, 
button.ForeColor);
+                       else if (button.Selected)
+                               ThemeElements.DrawPopupButton (g, 
button.ClientRectangle, ButtonThemeState.Default, button.BackColor, 
button.ForeColor);
+                       else if (!button.Enabled)
+                               ThemeElements.DrawPopupButton (g, 
button.ClientRectangle, ButtonThemeState.Disabled, button.BackColor, 
button.ForeColor);
+                       else
+                               ThemeElements.DrawPopupButton (g, 
button.ClientRectangle, ButtonThemeState.Normal, button.BackColor, 
button.ForeColor);
+               }
+
+               public virtual void DrawPopupButtonFocus (Graphics g, Button 
button)
+               {
+                       // No changes from Standard for image for this theme
+                       DrawButtonFocus (g, button);
+               }
+
+               public virtual void DrawPopupButtonImage (Graphics g, Button 
button, Rectangle imageBounds)
+               {
+                       // No changes from Standard for image for this theme
+                       DrawButtonImage (g, button, imageBounds);
+               }
+
+               public virtual void DrawPopupButtonText (Graphics g, Button 
button, Rectangle textBounds)
+               {
+                       // No changes from Standard for image for this theme
+                       DrawButtonText (g, button, textBounds);
+               }
+               #endregion
+
+               #region Button Layout Calculations
+               public override void CalculateButtonTextAndImageLayout (Button 
button, out Rectangle textRectangle, out Rectangle imageRectangle)
+               {
+                       Image image = button.Image;
+                       string text = button.Text;
+                       Rectangle content_rect = button.ClientRectangle;
+                       Size text_size = TextRenderer.MeasureTextInternal 
(text, button.Font, content_rect.Size, button.TextFormatFlags, 
button.UseCompatibleTextRendering);
+                       Size image_size = image == null ? Size.Empty : 
image.Size;
+
+                       textRectangle = Rectangle.Empty;
+                       imageRectangle = Rectangle.Empty;
+                       
+                       switch (button.TextImageRelation) {
+                               case TextImageRelation.Overlay:
+                                       // Overlay is easy, text always goes 
here
+                                       textRectangle = Rectangle.Inflate 
(content_rect, -4, -4);
+
+                                       if (button.Pressed)
+                                               textRectangle.Offset (1, 1);
+                                               
+                                       // Image is dependent on ImageAlign
+                                       if (image == null)
+                                               return;
+                                               
+                                       int image_x = 0;
+                                       int image_y = 0;
+                                       int image_height = image.Height;
+                                       int image_width = image.Width;
+                                       
+                                       switch (button.ImageAlign) {
+                                               case 
System.Drawing.ContentAlignment.TopLeft:
+                                                       image_x = 5;
+                                                       image_y = 5;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.TopCenter:
+                                                       image_x = 
(content_rect.Width - image_width) / 2;
+                                                       image_y = 5;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.TopRight:
+                                                       image_x = 
content_rect.Width - image_width - 5;
+                                                       image_y = 5;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.MiddleLeft:
+                                                       image_x = 5;
+                                                       image_y = 
(content_rect.Height - image_height) / 2;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.MiddleCenter:
+                                                       image_x = 
(content_rect.Width - image_width) / 2;
+                                                       image_y = 
(content_rect.Height - image_height) / 2;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.MiddleRight:
+                                                       image_x = 
content_rect.Width - image_width - 4;
+                                                       image_y = 
(content_rect.Height - image_height) / 2;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.BottomLeft:
+                                                       image_x = 5;
+                                                       image_y = 
content_rect.Height - image_height - 4;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.BottomCenter:
+                                                       image_x = 
(content_rect.Width - image_width) / 2;
+                                                       image_y = 
content_rect.Height - image_height - 4;
+                                                       break;
+                                               case 
System.Drawing.ContentAlignment.BottomRight:
+                                                       image_x = 
content_rect.Width - image_width - 4;
+                                                       image_y = 
content_rect.Height - image_height - 4;
+                                                       break;
+                                               default:
+                                                       image_x = 5;
+                                                       image_y = 5;
+                                                       break;
+                                       }
+                                       
+                                       imageRectangle = new Rectangle 
(image_x, image_y, image_width, image_height);
+                                       break;
+                               case TextImageRelation.ImageAboveText:
+                                       content_rect.Inflate (-4, -4);
+                                       LayoutTextAboveOrBelowImage 
(content_rect, false, text_size, image_size, button.TextAlign, 
button.ImageAlign, out textRectangle, out imageRectangle);
+                                       break;
+                               case TextImageRelation.TextAboveImage:
+                                       content_rect.Inflate (-4, -4);
+                                       LayoutTextAboveOrBelowImage 
(content_rect, true, text_size, image_size, button.TextAlign, 
button.ImageAlign, out textRectangle, out imageRectangle);
+                                       break;
+                               case TextImageRelation.ImageBeforeText:
+                                       content_rect.Inflate (-4, -4);
+                                       LayoutTextBeforeOrAfterImage 
(content_rect, false, text_size, image_size, button.TextAlign, 
button.ImageAlign, out textRectangle, out imageRectangle);
+                                       break;
+                               case TextImageRelation.TextBeforeImage:
+                                       content_rect.Inflate (-4, -4);
+                                       LayoutTextBeforeOrAfterImage 
(content_rect, true, text_size, image_size, button.TextAlign, 
button.ImageAlign, out textRectangle, out imageRectangle);
+                                       break;
+                       }
+               }
+
+               private void LayoutTextBeforeOrAfterImage (Rectangle totalArea, 
bool textFirst, Size textSize, Size imageSize, System.Drawing.ContentAlignment 
textAlign, System.Drawing.ContentAlignment imageAlign, out Rectangle textRect, 
out Rectangle imageRect)
+               {
+                       int element_spacing = 0;        // Spacing between the 
Text and the Image
+                       int total_width = textSize.Width + element_spacing + 
imageSize.Width;
+                       
+                       if (!textFirst)
+                               element_spacing += 2;
+                               
+                       // If the text is too big, chop it down to the size we 
have available to it
+                       if (total_width > totalArea.Width) {
+                               textSize.Width = totalArea.Width - 
element_spacing - imageSize.Width;
+                               total_width = totalArea.Width;
+                       }
+                       
+                       int excess_width = totalArea.Width - total_width;
+                       int offset = 0;
+
+                       Rectangle final_text_rect;
+                       Rectangle final_image_rect;
+
+                       HorizontalAlignment h_text = GetHorizontalAlignment 
(textAlign);
+                       HorizontalAlignment h_image = GetHorizontalAlignment 
(imageAlign);
+
+                       if (h_image == HorizontalAlignment.Left)
+                               offset = 0;
+                       else if (h_image == HorizontalAlignment.Right && h_text 
== HorizontalAlignment.Right)
+                               offset = excess_width;
+                       else if (h_image == HorizontalAlignment.Center && 
(h_text == HorizontalAlignment.Left || h_text == HorizontalAlignment.Center))
+                               offset += (int)(excess_width / 3);
+                       else
+                               offset += (int)(2 * (excess_width / 3));
+
+                       if (textFirst) {
+                               final_text_rect = new Rectangle (totalArea.Left 
+ offset, AlignInRectangle (totalArea, textSize, textAlign).Top, 
textSize.Width, textSize.Height);
+                               final_image_rect = new Rectangle 
(final_text_rect.Right + element_spacing, AlignInRectangle (totalArea, 
imageSize, imageAlign).Top, imageSize.Width, imageSize.Height);
+                       }
+                       else {
+                               final_image_rect = new Rectangle 
(totalArea.Left + offset, AlignInRectangle (totalArea, imageSize, 
imageAlign).Top, imageSize.Width, imageSize.Height);
+                               final_text_rect = new Rectangle 
(final_image_rect.Right + element_spacing, AlignInRectangle (totalArea, 
textSize, textAlign).Top, textSize.Width, textSize.Height);
+                       }
+
+                       textRect = final_text_rect;
+                       imageRect = final_image_rect;
+               }
+
+               private void LayoutTextAboveOrBelowImage (Rectangle totalArea, 
bool textFirst, Size textSize, Size imageSize, System.Drawing.ContentAlignment 
textAlign, System.Drawing.ContentAlignment imageAlign, out Rectangle textRect, 
out Rectangle imageRect)
+               {
+                       int element_spacing = 0;        // Spacing between the 
Text and the Image
+                       int total_height = textSize.Height + element_spacing + 
imageSize.Height;
+
+                       if (textFirst)
+                               element_spacing += 2;
+
+                       if (textSize.Width > totalArea.Width)
+                               textSize.Width = totalArea.Width;
+                               
+                       // If the there isn't enough room and we're text first, 
cut out the image
+                       if (total_height > totalArea.Height && textFirst) {
+                               imageSize = Size.Empty;
+                               total_height = totalArea.Height;
+                       }
+
+                       int excess_height = totalArea.Height - total_height;
+                       int offset = 0;
+
+                       Rectangle final_text_rect;
+                       Rectangle final_image_rect;
+
+                       VerticalAlignment v_text = GetVerticalAlignment 
(textAlign);
+                       VerticalAlignment v_image = GetVerticalAlignment 
(imageAlign);
+
+                       if (v_image == VerticalAlignment.Top)
+                               offset = 0;
+                       else if (v_image == VerticalAlignment.Bottom && v_text 
== VerticalAlignment.Bottom)
+                               offset = excess_height;
+                       else if (v_image == VerticalAlignment.Center && (v_text 
== VerticalAlignment.Top || v_text == VerticalAlignment.Center))
+                               offset += (int)(excess_height / 3);
+                       else
+                               offset += (int)(2 * (excess_height / 3));
+
+                       if (textFirst) {
+                               final_text_rect = new Rectangle 
(AlignInRectangle (totalArea, textSize, textAlign).Left, totalArea.Top + 
offset, textSize.Width, textSize.Height);
+                               final_image_rect = new Rectangle 
(AlignInRectangle (totalArea, imageSize, imageAlign).Left, 
final_text_rect.Bottom + element_spacing, imageSize.Width, imageSize.Height);
+                       }
+                       else {
+                               final_image_rect = new Rectangle 
(AlignInRectangle (totalArea, imageSize, imageAlign).Left, totalArea.Top + 
offset, imageSize.Width, imageSize.Height);
+                               final_text_rect = new Rectangle 
(AlignInRectangle (totalArea, textSize, textAlign).Left, 
final_image_rect.Bottom + element_spacing, textSize.Width, textSize.Height);
+                               
+                               if (final_text_rect.Bottom > totalArea.Bottom)
+                                       final_text_rect.Y = totalArea.Top;
+                       }
+
+                       textRect = final_text_rect;
+                       imageRect = final_image_rect;
+               }
+               
+               private HorizontalAlignment GetHorizontalAlignment 
(System.Drawing.ContentAlignment align)
+               {
+                       switch (align) {
+                               case System.Drawing.ContentAlignment.BottomLeft:
+                               case System.Drawing.ContentAlignment.MiddleLeft:
+                               case System.Drawing.ContentAlignment.TopLeft:
+                                       return HorizontalAlignment.Left;
+                               case 
System.Drawing.ContentAlignment.BottomCenter:
+                               case 
System.Drawing.ContentAlignment.MiddleCenter:
+                               case System.Drawing.ContentAlignment.TopCenter:
+                                       return HorizontalAlignment.Center;
+                               case 
System.Drawing.ContentAlignment.BottomRight:
+                               case 
System.Drawing.ContentAlignment.MiddleRight:
+                               case System.Drawing.ContentAlignment.TopRight:
+                                       return HorizontalAlignment.Right;
+                       }
+
+                       return HorizontalAlignment.Left;
+               }
+
+               private enum VerticalAlignment
+               {
+                       Top = 0,
+                       Center = 1,
+                       Bottom = 2
+               }
+               
+               private VerticalAlignment GetVerticalAlignment 
(System.Drawing.ContentAlignment align)
+               {
+                       switch (align) {
+                               case System.Drawing.ContentAlignment.TopLeft:
+                               case System.Drawing.ContentAlignment.TopCenter:
+                               case System.Drawing.ContentAlignment.TopRight:
+                                       return VerticalAlignment.Top;
+                               case System.Drawing.ContentAlignment.MiddleLeft:
+                               case 
System.Drawing.ContentAlignment.MiddleCenter:
+                               case 
System.Drawing.ContentAlignment.MiddleRight:
+                                       return VerticalAlignment.Center;
+                               case System.Drawing.ContentAlignment.BottomLeft:
+                               case 
System.Drawing.ContentAlignment.BottomCenter:
+                               case 
System.Drawing.ContentAlignment.BottomRight:
+                                       return VerticalAlignment.Bottom;
+                       }
+
+                       return VerticalAlignment.Top;
+               }
+
+               internal Rectangle AlignInRectangle (Rectangle outer, Size 
inner, System.Drawing.ContentAlignment align)
+               {
+                       int x = 0;
+                       int y = 0;
+
+                       if (align == System.Drawing.ContentAlignment.BottomLeft 
|| align == System.Drawing.ContentAlignment.MiddleLeft || align == 
System.Drawing.ContentAlignment.TopLeft)
+                               x = outer.X;
+                       else if (align == 
System.Drawing.ContentAlignment.BottomCenter || align == 
System.Drawing.ContentAlignment.MiddleCenter || align == 
System.Drawing.ContentAlignment.TopCenter)
+                               x = Math.Max (outer.X + ((outer.Width - 
inner.Width) / 2), outer.Left);
+                       else if (align == 
System.Drawing.ContentAlignment.BottomRight || align == 
System.Drawing.ContentAlignment.MiddleRight || align == 
System.Drawing.ContentAlignment.TopRight)
+                               x = outer.Right - inner.Width;
+                       if (align == System.Drawing.ContentAlignment.TopCenter 
|| align == System.Drawing.ContentAlignment.TopLeft || align == 
System.Drawing.ContentAlignment.TopRight)
+                               y = outer.Y;
+                       else if (align == 
System.Drawing.ContentAlignment.MiddleCenter || align == 
System.Drawing.ContentAlignment.MiddleLeft || align == 
System.Drawing.ContentAlignment.MiddleRight)
+                               y = outer.Y + (outer.Height - inner.Height) / 2;
+                       else if (align == 
System.Drawing.ContentAlignment.BottomCenter || align == 
System.Drawing.ContentAlignment.BottomRight || align == 
System.Drawing.ContentAlignment.BottomLeft)
+                               y = outer.Bottom - inner.Height;
+
+                       return new Rectangle (x, y, Math.Min (inner.Width, 
outer.Width), Math.Min (inner.Height, outer.Height));
+               }
+               #endregion
+               #endregion
+
                #region ButtonBase
                public override void DrawButtonBase(Graphics dc, Rectangle 
clip_area, ButtonBase button)
                {
@@ -272,7 +696,7 @@
                        int height = button.ClientSize.Height;
 
                        if (button.ImageIndex != -1) {   // We use ImageIndex 
instead of image_index since it will return -1 if image_list is null
-                               i = 
button.image_list.Images[button.image_index];
+                               i = button.image_list.Images[button.ImageIndex];
                        } else {
                                i = button.image;
                        }
@@ -280,7 +704,7 @@
                        image_width = i.Width;
                        image_height = i.Height;
                        
-                       switch (button.image_alignment) {
+                       switch (button.ImageAlign) {
                                case ContentAlignment.TopLeft: {
                                        image_x = 5;
                                        image_y = 5;
@@ -5927,6 +6351,17 @@
                        }
                }
 
+               private void DrawStringDisabled20 (Graphics g, string s, Font 
font, Rectangle layoutRectangle, Color color, TextFormatFlags flags, bool 
useDrawString)
+               {
+                       CPColor cpcolor = ResPool.GetCPColor (color);
+
+                       layoutRectangle.Offset (1, 1);
+                       TextRenderer.DrawTextInternal (g, s, font, 
layoutRectangle, cpcolor.LightLight, flags, useDrawString);
+
+                       layoutRectangle.Offset (-1, -1);
+                       TextRenderer.DrawTextInternal (g, s, font, 
layoutRectangle, cpcolor.Dark, flags, useDrawString);
+               }
+
                public  override void CPDrawStringDisabled (Graphics dc, string 
s, Font font, Color color, RectangleF layoutRectangle, StringFormat format)
                {
                        CPColor cpcolor = ResPool.GetCPColor (color);
_______________________________________________
Mono-winforms-list maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list

Reply via email to