[Mono-winforms-list] Patch: Button Fixes PartIII -> Final Fix

John BouAntoun jba-mono@optusnet.com.au
Thu, 04 Nov 2004 00:52:24 +1100


--=-jxf9CCTHgOs9pBaO3wsn
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Apologies for the resend:

On Thu, 2004-11-04 at 00:50 +1100, John BouAntoun wrote:
> Okay guys,
> 
> This patch does it all.
> 
> Everything listed below and corrections to the DrawBorder3D to make sure
> it renders on the control (not outside it) and also tested corrections
> to the Focus Rectangle drawing for Button, CheckBox and RadioButton.
> 
> The problem with the last patch was that I inadvertantly changed
> DrawBorder3D to draw a rectangle that was 1 pixel larger to the right
> and left (thinking i was fixing an off by one error). Reverting the
> changes made it work properly again.
> 
> Please check and apply asap. :D
> 
> Regards,
> 
> JBA
> 
> 
> 
> On Mon, 2004-11-01 at 15:58 -0700, Peter Dennis Bartok wrote:
> > -----Original Message-----
> > From: "John BouAntoun" <jba-mono@optusnet.com.au>
> > To: "Mono-Winforms-List (E-mail)" <mono-winforms-list@ximian.com>
> > Date: 30 October, 2004 23:52
> > Subject: [Mono-winforms-list] Patch: Button Fixes PartII -> FlatStyle fixes
> > 
> > 
> > >Hi guys,
> > >
> > >I've managed to finally complete my journey of correcting flatstyle
> > >rendering and behaviour for the button, radiobutton and checkbox.
> > >
> > >I have already sent in two other patches that were meant to help
> > >progress to this point (my last two patches to the list) but they
> > >haven't been checked in yet. Unfortunately because they haven't been
> > >checked in yet, this diff is very large and includes those previous
> > >patches (and edit's i've made to the patch sections since sending them
> > >in).
> > >
> > >The changes since the last patch are as follows:
> > >
> > >- Fix Button rendering for FlatStyle = Flat or Popup
> > >- Fix RadioButton and CheckBox rendering when Appearance = Button
> > >(normal and flatstyle).
> > >
> > >However the other fixes that this patch includes (i.e. from my last two
> > >patches) are:
> > >
> > >        Last patch:
> > >        1) Correct outer rectangle color when drawing focus rectangle
> > >        2) Adjust button bounds to be 1 px smaller when focused
> > >        3) Make button not draw sunken 3d border when pushed (windows
> > >        compat)
> > >        4) Fix CPDrawBorder3D to not make bottom right hand corner
> > >        rounded
> > >        (extend border right to corner)
> > >        5) Offset the text in RadioButton and Checkbox when being
> > >        rendered as a
> > >        button.
> > >        
> > >        Patch Before that:
> > >        1) Hover and Click behaviour for Colored FlatStyle.Flat
> > >        radiobuttons
> > >        2) Hover and click behaviour for Colored FlatStyle.Popup
> > >        radiobuttons
> > >        3) Disabled rendering fixes for colored flatstyle radiobuttons
> > >        (both)
> > >        4) Disabled text rendering for all radiobuttons
> > >        
> > >Enjoy the button flat style goodness!!
> > >
> > >There is only one more thing left to do for button rendering, and that
> > >is to render the dashed focus rectangle, but I have a few issues with
> > >that one waiting on a response (in the mailing list).
> > >
> > >JBA
> > >
> > >

--=-jxf9CCTHgOs9pBaO3wsn
Content-Disposition: attachment; filename=ButtonRenderingFixes.patch
Content-Type: text/x-patch; name=ButtonRenderingFixes.patch; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

? ButtonRenderingFixes.patch
? Makefile.SWF
? Makefile.solution.SWF
? SWF.cmbx
? SWF.mdsx
? SWF.pidb
? SWF.prjx
? make.sh
Index: System.Windows.Forms/ThemeWin32Classic.cs
===================================================================
RCS file: /cvs/public/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs,v
retrieving revision 1.52
diff -u -r1.52 ThemeWin32Classic.cs
--- System.Windows.Forms/ThemeWin32Classic.cs	30 Oct 2004 10:23:02 -0000	1.52
+++ System.Windows.Forms/ThemeWin32Classic.cs	3 Nov 2004 12:17:16 -0000
@@ -320,6 +320,7 @@
 		public override void DrawButtonBase(Graphics dc, Rectangle clip_area, ButtonBase button) {
 			int		width;
 			int		height;
+			Rectangle buttonRectangle;
 
 			width = button.ClientSize.Width;
 			height = button.ClientSize.Height;
@@ -327,13 +328,20 @@
 			SolidBrush	sb = new SolidBrush(button.BackColor);
 			dc.FillRectangle(sb, button.ClientRectangle);
 			sb.Dispose();
-
-			CPDrawButton(dc, button.ClientRectangle, button.ButtonState);
-
+			
+			// set up the button rectangle
+			buttonRectangle = clip_area;
 			if (button.has_focus) {
-				CPDrawFocusRectangle(dc, button.ClientRectangle, ColorButtonText, ColorButtonFace);
+				// shrink the rectangle for the normal button drawing inside the focus rectangle
+				buttonRectangle.Inflate(-1,-1);
 			}
 
+			if (button.FlatStyle == FlatStyle.Flat || button.FlatStyle == FlatStyle.Popup) {
+				DrawFlatStyleButton (dc, buttonRectangle, button);
+			} else {
+				CPDrawButton(dc, buttonRectangle, button.ButtonState);
+			}
+			
 			// First, draw the image
 			if ((button.image != null) || (button.image_list != null)) {
 				// Need to draw a picture
@@ -425,10 +433,19 @@
 					CPDrawImageDisabled(dc, i, image_x, image_y, ColorButtonFace);
 				}
 			}
-
+			
+			// Draw the focus rectangle
+			if (button.has_focus) {
+				if (button.FlatStyle == FlatStyle.Flat || button.FlatStyle == FlatStyle.Popup) {
+					DrawFlatStyleFocusRectangle (dc, clip_area, button, button.ForeColor, button.BackColor);
+				} else { 
+					CPDrawFocusRectangle(dc, clip_area, button.ForeColor, button.BackColor);
+				}
+			}
+			
 			// Now the text
 			if (button.text != null && button.text != String.Empty) {
-				Rectangle	text_rect = new Rectangle(3, 3, button.ClientSize.Width-6, button.ClientSize.Height-6); // FIXME; calculate rect properly
+				Rectangle text_rect = new Rectangle(6, 6, button.ClientSize.Width-12, button.ClientSize.Height-12);
 
 				if (button.is_pressed) {
 					text_rect.X++;
@@ -440,7 +457,100 @@
 					dc.DrawString(button.text, button.Font, b, text_rect, button.text_format);
 					b.Dispose();
 				} else {
-					CPDrawStringDisabled(dc, button.text, button.Font, ColorButtonText, text_rect, button.text_format);
+					if (button.FlatStyle == FlatStyle.Flat || button.FlatStyle == FlatStyle.Popup) {
+						dc.DrawString(button.text, button.Font, ResPool.GetSolidBrush (ControlPaint.DarkDark (this.ColorButtonFace)), text_rect, button.text_format);
+					} else {
+						CPDrawStringDisabled(dc, button.text, button.Font, ColorButtonText, text_rect, button.text_format);
+					}
+				}
+			}
+		}
+		
+		// draw the flat style part of the rectangle
+		public void DrawFlatStyleButton (Graphics graphics, Rectangle rectangle, ButtonBase button) {
+			Color rect_back_color = button.BackColor;
+			Color rect_fore_color = button.ForeColor;
+				
+			if (button.Enabled) {
+				if (button.Capture || button.is_entered) {
+					if (button.FlatStyle == FlatStyle.Flat) {
+						// fill the rectangle
+						graphics.FillRectangle (ResPool.GetSolidBrush (rect_back_color), rectangle);
+						
+						// now draw the outer border
+						if (button.Capture && button.is_entered) {
+							rect_back_color = ControlPaint.LightLight (rect_back_color);
+						} else {
+							rect_back_color = ControlPaint.Light (rect_back_color);
+						}
+						
+						// draw rectangle and fill it
+						graphics.FillRectangle (ResPool.GetSolidBrush (rect_back_color), rectangle);
+						graphics.DrawRectangle(ResPool.GetPen (rect_fore_color), rectangle);
+					} else {
+						// else it must be a popup button
+						
+						if (button.Capture && button.is_entered) {
+							graphics.DrawRectangle(ResPool.GetPen (this.ColorButtonText), rectangle);
+						} else {
+							// draw a 3d border
+							graphics.DrawLine ( ResPool.GetPen (ControlPaint.LightLight (rect_back_color)), rectangle.X, rectangle.Y, rectangle.Right-1, rectangle.Y);
+							graphics.DrawLine ( ResPool.GetPen (ControlPaint.LightLight (rect_back_color)), rectangle.X, rectangle.Y, rectangle.X, rectangle.Height-1);
+							graphics.DrawLine ( ResPool.GetPen (this.ColorButtonText), rectangle.X, rectangle.Bottom, rectangle.Width, rectangle.Bottom);
+							graphics.DrawLine ( ResPool.GetPen (this.ColorButtonText), rectangle.Right, rectangle.Y, rectangle.Right, rectangle.Bottom);
+						}
+					}
+					
+					// TODO: draw inner focus rectangle
+					
+				} else {
+					// popup has a ButtonColorText forecolor, not a button.ForeCOlor
+					if (button.FlatStyle == FlatStyle.Popup) {
+						rect_fore_color = this.ColorButtonText;
+					}
+					
+					// fill then draw outer rect
+					graphics.FillRectangle (ResPool.GetSolidBrush (rect_back_color), rectangle);
+					graphics.DrawRectangle(ResPool.GetPen (rect_fore_color), rectangle);
+					
+					// TODO: draw inner focus rectangle
+				}
+				
+				// finally some small tweaks to render radiobutton and checkbox
+				CheckBox checkbox = button as CheckBox;
+				RadioButton radiobutton = button as RadioButton;
+				if ((checkbox != null && checkbox.Checked) ||
+					(radiobutton != null && radiobutton.Checked)) {
+					if (button.FlatStyle == FlatStyle.Flat && button.is_entered && !button.Capture) {
+						// render the hover for flat flatstyle and cheked
+						graphics.DrawRectangle(ResPool.GetPen (this.ColorButtonText), rectangle);
+					} else if (!button.is_entered && !button.Capture) {
+						// render the checked state for popup when unhovered
+						graphics.DrawLine ( ResPool.GetPen (ControlPaint.LightLight (button.BackColor)), rectangle.X, rectangle.Bottom, rectangle.Right, rectangle.Bottom);
+						graphics.DrawLine ( ResPool.GetPen (ControlPaint.LightLight (button.BackColor)), rectangle.Right, rectangle.Bottom, rectangle.Right, rectangle.Y);
+					}
+				}
+			} else {
+				// rendering checkbox or radio button style buttons
+				CheckBox checkbox = button as CheckBox;
+				RadioButton radiobutton = button as RadioButton;
+				bool draw_popup_checked = false;
+				
+				if (button.FlatStyle == FlatStyle.Popup) {
+					rect_fore_color = this.ColorButtonText;
+				
+					// see if we should draw a disabled checked popup button
+					draw_popup_checked = ((checkbox != null && checkbox.Checked) ||
+						(radiobutton != null && radiobutton.Checked));
+				}
+				
+				graphics.FillRectangle (ResPool.GetSolidBrush (rect_back_color), rectangle);
+				graphics.DrawRectangle(ResPool.GetPen (rect_fore_color), rectangle);
+				
+				// finally draw the flatstyle checked effect if need
+				if (draw_popup_checked) {
+					graphics.DrawLine ( ResPool.GetPen (ControlPaint.LightLight (button.BackColor)), rectangle.X, rectangle.Bottom, rectangle.Right, rectangle.Bottom);
+					graphics.DrawLine ( ResPool.GetPen (ControlPaint.LightLight (button.BackColor)), rectangle.Right, rectangle.Bottom, rectangle.Right, rectangle.Y);
 				}
 			}
 		}
@@ -551,6 +661,8 @@
 				text_rectangle.X=client_rectangle.X;
 				text_rectangle.Width=client_rectangle.Width;
 			}
+			
+			text_rectangle.Inflate (-4, -4);
 
 			/* Set the horizontal alignment of our text */
 			switch(checkbox.text_alignment) {
@@ -628,34 +740,53 @@
 			sb=new SolidBrush(checkbox.BackColor);
 			dc.FillRectangle(sb, checkbox.ClientRectangle);
 			sb.Dispose();
-
-			// 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);
+			
+			// render as per normal button
+			if (checkbox.appearance==Appearance.Button) {
+				if (checkbox.FlatStyle == FlatStyle.Flat || checkbox.FlatStyle == FlatStyle.Popup) {
+					DrawFlatStyleButton(dc, checkbox.ClientRectangle, checkbox);
+				} else {
+					CPDrawButton(dc, checkbox.ClientRectangle, state);
+				}
 			} else {
-				// render as per normal
-				if (checkbox.appearance!=Appearance.Button) {
-					ControlPaint.DrawCheckBox(dc, checkbox_rectangle, state);
+				// 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.DrawButton(dc, text_rectangle, state);
+					ControlPaint.DrawCheckBox(dc, checkbox_rectangle, state);
 				}
 			}
 			
 			// win32 compat - win32 seems to give the text a slight (3px) offset when rendering
-			Rectangle inner_text_rectangle = new Rectangle (text_rectangle.X + 3, text_rectangle.Y, Math.Max (text_rectangle.Width - 3, 0), text_rectangle.Height); 
-
+			Rectangle inner_text_rectangle = new Rectangle (text_rectangle.X + 2, text_rectangle.Y + 2, Math.Max (text_rectangle.Width - 4, 0), Math.Max (text_rectangle.Height - 4, 0)); 
+			// offset the text if it's pressed and a button
+			if (checkbox.Appearance == Appearance.Button) {
+				int buttonXOffset = 2;
+				int buttonYOffset = 0;
+				int pressedOffset = 0;
+				
+				if (checkbox.Checked || (checkbox.Capture && checkbox.FlatStyle != FlatStyle.Flat)) {
+					pressedOffset += 2;
+				}
+				
+				inner_text_rectangle = new Rectangle (inner_text_rectangle.X + buttonXOffset + pressedOffset, inner_text_rectangle.Y + buttonYOffset + pressedOffset, inner_text_rectangle.Width - 2*buttonXOffset, inner_text_rectangle.Height - 2*buttonYOffset); 
+			} 
 			/* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
 			if (checkbox.Enabled) {
 				sb = ResPool.GetSolidBrush(checkbox.ForeColor);
 				dc.DrawString(checkbox.Text, checkbox.Font, sb, inner_text_rectangle, text_format);				
 			} else if (checkbox.FlatStyle == FlatStyle.Flat || checkbox.FlatStyle == FlatStyle.Popup) {
-				dc.DrawString(checkbox.Text, checkbox.Font, SystemBrushes.ControlDark, inner_text_rectangle, text_format);
+				dc.DrawString(checkbox.Text, checkbox.Font, ResPool.GetSolidBrush (ControlPaint.DarkDark (this.ColorButtonFace)), inner_text_rectangle, text_format);
 			} else {
 				CPDrawStringDisabled(dc, checkbox.Text, checkbox.Font, ColorButtonText, inner_text_rectangle, text_format);
 			}
 
 			if (checkbox.Focused) {
-				ControlPaint.DrawFocusRectangle(dc, text_rectangle);
+				if (checkbox.FlatStyle != FlatStyle.Flat) {
+					DrawInnerFocusRectangle (dc, text_rectangle, checkbox.BackColor);
+				} else {
+					dc.DrawRectangle (ResPool.GetPen (checkbox.ForeColor), text_rectangle);
+				}
 			}
 		}
 
@@ -699,10 +830,10 @@
 						ControlPaint.DrawBorder(graphics, checkbox_rectangle, checkbox.ForeColor, ButtonBorderStyle.Solid);
 					} else {
 						// draw sunken effect
-						CPDrawBorder3D (graphics, checkbox_rectangle, Border3DStyle.SunkenInner, Border3DSide.Bottom | Border3DSide.Right, checkbox.BackColor);
+						CPDrawBorder3D (graphics, checkbox_rectangle, Border3DStyle.SunkenInner, Border3DSide.All, checkbox.BackColor);
 						// draw top left
-						graphics.DrawLine(ResPool.GetPen (ControlPaint.DarkDark (checkbox.BackColor)), checkbox_rectangle.X, checkbox_rectangle.Y, checkbox_rectangle.X, checkbox_rectangle.Y+checkbox_rectangle.Height);
-						graphics.DrawLine(ResPool.GetPen (ControlPaint.DarkDark (checkbox.BackColor)), checkbox_rectangle.X, checkbox_rectangle.Y, Math.Max(checkbox_rectangle.X + checkbox_rectangle.Width - 1, 0), checkbox_rectangle.Y);
+//						graphics.DrawLine(ResPool.GetPen (ControlPaint.DarkDark (checkbox.BackColor)), checkbox_rectangle.X, checkbox_rectangle.Y, checkbox_rectangle.X, checkbox_rectangle.Y+checkbox_rectangle.Height);
+						//graphics.DrawLine(ResPool.GetPen (ControlPaint.DarkDark (checkbox.BackColor)), checkbox_rectangle.X, checkbox_rectangle.Y, Math.Max(checkbox_rectangle.X + checkbox_rectangle.Width - 1, 0), checkbox_rectangle.Y);
 					}
 				} else {
 					graphics.FillRectangle(ResPool.GetSolidBrush (ControlPaint.LightLight (checkbox.BackColor)), fill_rectangle);				
@@ -1163,6 +1294,8 @@
 				text_rectangle.X=client_rectangle.X;
 				text_rectangle.Width=client_rectangle.Width;
 			}
+			
+			text_rectangle.Inflate (-4, -4);
 
 			/* Set the horizontal alignment of our text */
 			switch(radio_button.text_alignment) {
@@ -1227,29 +1360,58 @@
 			dc.FillRectangle(sb, radio_button.ClientRectangle);
 			sb.Dispose();
 			
-			// 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 {
-				// render as per normal
-				if (radio_button.appearance!=Appearance.Button) {
-					ControlPaint.DrawRadioButton (dc, radiobutton_rectangle, state);
+		
+			
+			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 {				
+					CPDrawButton(dc, radio_button.ClientRectangle, state);
+				}		
+			} 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.DrawButton (dc, text_rectangle, state);
+					ControlPaint.DrawRadioButton (dc, radiobutton_rectangle, state);
 				}
 			}
 			
 			// wind32 compat - win32 seems to give the text a slight (3px) offset when rendering
-			Rectangle inner_text_rectangle = new Rectangle (text_rectangle.X + 3, text_rectangle.Y, Math.Max (text_rectangle.Width - 3, 0), text_rectangle.Height); 
+			Rectangle inner_text_rectangle = new Rectangle (text_rectangle.X + 3, text_rectangle.Y, Math.Max (text_rectangle.Width - 3, 0), text_rectangle.Height);
+			// offset the text if it's pressed and a button
+			if (radio_button.Appearance == Appearance.Button) {
+				int buttonXOffset = 2;
+				int buttonYOffset = 0;
+				int pressedOffset = 0;
+				
+				if (radio_button.Checked || (radio_button.Capture && radio_button.FlatStyle != FlatStyle.Flat)) {
+					pressedOffset += 2;
+				}
+				
+				inner_text_rectangle = new Rectangle (inner_text_rectangle.X + buttonXOffset + pressedOffset, inner_text_rectangle.Y + buttonYOffset + pressedOffset, inner_text_rectangle.Width - 2*buttonXOffset, inner_text_rectangle.Height - 2*buttonYOffset); 
+			} 
 
 			/* Place the text; to be compatible with Windows place it after the radiobutton has been drawn */
 			sb=new SolidBrush(radio_button.ForeColor);
 			dc.DrawString (radio_button.Text, radio_button.Font, sb, inner_text_rectangle, text_format);
 			sb.Dispose();
+			if (radio_button.Enabled) {
+				sb = ResPool.GetSolidBrush(radio_button.ForeColor);
+				dc.DrawString(radio_button.Text, radio_button.Font, sb, inner_text_rectangle, text_format);				
+			} else if (radio_button.FlatStyle == FlatStyle.Flat) {
+				dc.DrawString(radio_button.Text, radio_button.Font, ResPool.GetSolidBrush (ControlPaint.DarkDark (this.ColorButtonFace)), inner_text_rectangle, text_format);
+			} else {
+				CPDrawStringDisabled(dc, radio_button.Text, radio_button.Font, this.ColorButtonText, inner_text_rectangle, text_format);
+			}
 
 			if (radio_button.Focused) {
-				ControlPaint.DrawFocusRectangle(dc, text_rectangle);
-			}
+				if (radio_button.FlatStyle != FlatStyle.Flat) {
+					DrawInnerFocusRectangle (dc, text_rectangle, radio_button.BackColor);
+				} else {
+					dc.DrawRectangle (ResPool.GetPen (radio_button.ForeColor), text_rectangle);
+				}
+			}			
 		}
 
 		// renders a radio button with the Flat and Popup FlatStyle
@@ -1257,24 +1419,40 @@
 		{
 			int	lineWidth;
 			
-			// win32 compat fill in the background of the knob
-			graphics.FillPie (ResPool.GetSolidBrush (this.ColorWindow), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
-			
-			// draw the outer flatstyle arcs
-			if (radio_button.FlatStyle == FlatStyle.Flat) {
-				graphics.DrawArc (ResPool.GetPen (ColorButtonText), rectangle, 0, 359);
-			} else {
-				// must be a popup radio button
-				if (radio_button.is_entered) {
-					// draw the popup 3d button knob
-					graphics.DrawArc (SystemPens.ControlLight, rectangle.X+1, rectangle.Y+1, rectangle.Width-2, rectangle.Height-2, 0, 359);
-
-					graphics.DrawArc (SystemPens.ControlDark, rectangle, 135, 180);
-					graphics.DrawArc (SystemPens.ControlLightLight, rectangle, 315, 180);
+			if (radio_button.Enabled) {
+				// draw the outer flatstyle arcs
+				if (radio_button.FlatStyle == FlatStyle.Flat) {
+					graphics.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) {
+						graphics.FillPie (ResPool.GetSolidBrush (ControlPaint.Light (radio_button.BackColor)), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
+					} else {
+						graphics.FillPie (ResPool.GetSolidBrush (ControlPaint.LightLight (radio_button.BackColor)), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
+					}
 				} else {
-					// just draw lighter flatstyle outer circle
-					graphics.DrawArc (SystemPens.ControlDark, rectangle, 0, 359);
+					// must be a popup radio button
+					// fill the control
+					graphics.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
+						graphics.DrawArc (ResPool.GetPen (ControlPaint.Light (radio_button.BackColor)), rectangle.X+1, rectangle.Y+1, rectangle.Width-2, rectangle.Height-2, 0, 359);
+
+						graphics.DrawArc (ResPool.GetPen (ControlPaint.Dark (radio_button.BackColor)), rectangle, 135, 180);
+						graphics.DrawArc (ResPool.GetPen (ControlPaint.LightLight (radio_button.BackColor)), rectangle, 315, 180);
+						
+					} else {
+						// just draw lighter flatstyle outer circle
+						graphics.DrawArc (ResPool.GetPen (ControlPaint.Dark (this.ColorButtonFace)), rectangle, 0, 359);						
+					}										
 				}
+			} else {
+				// disabled
+				// fill control background color regardless of actual backcolor
+				graphics.FillPie (ResPool.GetSolidBrush (this.ColorButtonFace), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
+				// draw the ark as control dark
+				graphics.DrawArc (ResPool.GetPen (ControlPaint.Dark(this.ColorButtonFace)), rectangle, 0, 359);
 			}
 
 			// draw the check
@@ -1283,12 +1461,14 @@
 				SolidBrush buttonBrush;
 
 				if (!radio_button.Enabled) {
-					buttonBrush = (SolidBrush) SystemBrushes.ControlDark;
+					buttonBrush = ResPool.GetSolidBrush (ControlPaint.Dark (this.ColorButtonFace));
+				} else if (radio_button.FlatStyle == FlatStyle.Popup && radio_button.is_entered && radio_button.Capture) {
+					buttonBrush = ResPool.GetSolidBrush (this.ColorButtonText);
 				} else {
-					buttonBrush = (SolidBrush) SystemBrushes.ControlText;
+					buttonBrush = ResPool.GetSolidBrush (radio_button.ForeColor);
 				}
 				graphics.FillPie (buttonBrush, rectangle.X+lineWidth, rectangle.Y+lineWidth, rectangle.Width-lineWidth*2, rectangle.Height-lineWidth*2, 0, 359);
-			}			
+			}	
 		}
 
 		public override Size RadioButtonDefaultSize {
@@ -2364,7 +2544,7 @@
 
 			if ((style & Border3DStyle.RaisedInner)!=0) {
 				if (doInner) {
-					penTopLeftInner=ResPool.GetPen(ControlPaint.Light(control_color));
+					penTopLeftInner=ResPool.GetPen(control_color);
 					penBottomRightInner=ResPool.GetPen(ControlPaint.Dark(control_color));
 				} else {
 					penTopLeft=ResPool.GetPen(ControlPaint.LightLight(control_color));
@@ -2373,7 +2553,7 @@
 			} else if ((style & Border3DStyle.SunkenInner)!=0) {
 				if (doInner) {
 					penTopLeftInner=ResPool.GetPen(ControlPaint.Dark(control_color));
-					penBottomRightInner=ResPool.GetPen(ControlPaint.Light(control_color));
+					penBottomRightInner=ResPool.GetPen(control_color);
 				} else {
 					penTopLeft=ResPool.GetPen(ControlPaint.DarkDark(control_color));
 					penBottomRight=ResPool.GetPen(ControlPaint.LightLight(control_color));
@@ -2385,20 +2565,20 @@
 			}
 
 			if ((sides & Border3DSide.Left)!=0) {
-				graphics.DrawLine(penTopLeft, rect.Left, rect.Bottom-1, rect.Left, rect.Top);
+				graphics.DrawLine(penTopLeft, rect.Left, rect.Bottom-2, rect.Left, rect.Top);
 				if (doInner) {
-					graphics.DrawLine(penTopLeftInner, rect.Left+1, rect.Bottom-1, rect.Left+1, rect.Top);
+					graphics.DrawLine(penTopLeftInner, rect.Left+1, rect.Bottom-2, rect.Left+1, rect.Top);
 				}
 			}
 
 			if ((sides & Border3DSide.Top)!=0) {
-				graphics.DrawLine(penTopLeft, rect.Left, rect.Top, rect.Right-1, rect.Top);
+				graphics.DrawLine(penTopLeft, rect.Left, rect.Top, rect.Right-2, rect.Top);
 
 				if (doInner) {
 					if ((sides & Border3DSide.Left)!=0) {
-						graphics.DrawLine(penTopLeftInner, rect.Left+1, rect.Top+1, rect.Right-1, rect.Top+1);
+						graphics.DrawLine(penTopLeftInner, rect.Left+1, rect.Top+1, rect.Right-3, rect.Top+1);
 					} else {
-						graphics.DrawLine(penTopLeftInner, rect.Left, rect.Top+1, rect.Right-1, rect.Top+1);
+						graphics.DrawLine(penTopLeftInner, rect.Left, rect.Top+1, rect.Right-3, rect.Top+1);
 					}
 				}
 			}
@@ -2408,9 +2588,9 @@
 
 				if (doInner) {
 					if ((sides & Border3DSide.Top)!=0) {
-						graphics.DrawLine(penBottomRightInner, rect.Right-2, rect.Top+1, rect.Right-2, rect.Bottom-1);
+						graphics.DrawLine(penBottomRightInner, rect.Right-2, rect.Top+1, rect.Right-2, rect.Bottom-2);
 					} else {
-						graphics.DrawLine(penBottomRightInner, rect.Right-2, rect.Top, rect.Right-2, rect.Bottom-1);
+						graphics.DrawLine(penBottomRightInner, rect.Right-2, rect.Top, rect.Right-2, rect.Bottom-2);
 					}
 				}
 			}
@@ -2428,7 +2608,7 @@
 					if ((sides & Border3DSide.Right)!=0) {
 						graphics.DrawLine(penBottomRightInner, left, rect.Bottom-2, rect.Right-2, rect.Bottom-2);
 					} else {
-						graphics.DrawLine(penBottomRightInner, left, rect.Bottom-2, rect.Right-1, rect.Bottom-2);
+						graphics.DrawLine(penBottomRightInner, left, rect.Bottom-2, rect.Right-2, rect.Bottom-2);
 					}
 				}
 			}
@@ -2633,27 +2813,56 @@
 
 		}
 
+		public virtual void DrawFlatStyleFocusRectangle (Graphics graphics, Rectangle rectangle, ButtonBase button, Color foreColor, Color backColor) {
+			Color outerColor = foreColor;
+			// adjust focus color according to the flatstyle
+			if (button.FlatStyle == FlatStyle.Popup && !button.is_pressed) {
+				outerColor = (backColor == ColorButtonFace) ? ControlPaint.Dark(ColorButtonFace) : ColorButtonText;				
+			}
+			
+			// draw the outer rectangle
+			graphics.DrawRectangle (ResPool.GetPen (outerColor), rectangle);			
+			
+			// draw the inner rectangle
+			Rectangle innerRectangle = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
+			innerRectangle.Inflate(-4,-4);
+			if (button.FlatStyle == FlatStyle.Popup) {
+				DrawInnerFocusRectangle (graphics, innerRectangle, backColor);
+			} else {
+				// draw a flat inner rectangle
+				Pen pen = ResPool.GetPen (foreColor);
+				graphics.DrawRectangle(pen, innerRectangle);				
+			}
+		}
+		
+		public virtual void DrawInnerFocusRectangle(Graphics graphics, Rectangle rectangle, Color backColor)
+		{
+			Color colorBackInverted = Color.FromArgb (Math.Abs (backColor.R-255), Math.Abs (backColor.G-255), Math.Abs (backColor.B-255));
+			DashStyle oldStyle; // used for caching old penstyle
+			Pen pen = ResPool.GetPen (colorBackInverted);
+			
+			oldStyle = pen.DashStyle; 
+			pen.DashStyle = DashStyle.Dot;
+			graphics.DrawRectangle (pen, rectangle);
+			pen.DashStyle = oldStyle;
+		}
+				
 
 		public override void CPDrawFocusRectangle (Graphics graphics, Rectangle rectangle, Color foreColor, Color backColor) {
 			//Color			colorForeInverted;
-			Color			colorBackInverted;
 			Pen			pen;
 
-			//colorForeInverted=Color.FromArgb(Math.Abs(foreColor.R-255), Math.Abs(foreColor.G-255), Math.Abs(foreColor.B-255));
+ 			//colorForeInverted=Color.FromArgb(Math.Abs(foreColor.R-255), Math.Abs(foreColor.G-255), Math.Abs(foreColor.B-255));
 			//pen=new Pen(colorForeInverted, 1);
 			// MS seems to always use black
-			pen=new Pen(Color.Black, 1);
-			graphics.DrawRectangle(pen, rectangle);
-			pen.Dispose();
-
-			colorBackInverted=Color.FromArgb(Math.Abs(backColor.R-255), Math.Abs(backColor.G-255), Math.Abs(backColor.B-255));
-			pen=new Pen(colorBackInverted, 1);
-			pen.DashStyle=DashStyle.Dot;
+			pen = ResPool.GetPen (Color.Black);
 			graphics.DrawRectangle(pen, rectangle);
-			pen.Dispose();
+			
+			Rectangle innerRectangle = new Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
+			innerRectangle.Inflate (-4,-4);
+			DrawInnerFocusRectangle (graphics, innerRectangle, backColor);
 		}
-
-
+		
 		public override void CPDrawGrabHandle (Graphics graphics, Rectangle rectangle, bool primary, bool enabled) {
 			SolidBrush	sb;
 			Pen			pen;
@@ -3307,16 +3516,18 @@
 		private void DrawFrameControl(Graphics graphics, Rectangle rectangle, DrawFrameControlTypes Type, DrawFrameControlStates State) {
 			switch(Type) {
 			case DrawFrameControlTypes.Button: {
+
 				if ((State & DrawFrameControlStates.ButtonPush)!=0) {
-					/* Goes first, affects the background */
-					if ((State & DrawFrameControlStates.Checked)!=0) {
-						HatchBrush	hatchBrush=new HatchBrush(HatchStyle.Percent50, ColorButtonLight, ColorButtonHilight);
-						graphics.FillRectangle(hatchBrush,rectangle);
-						hatchBrush.Dispose();
-					}
+// JBA 31 oct 2004 - I don't think that button style should be rendered like this
+//					/* Goes first, affects the background */
+//					if ((State & DrawFrameControlStates.Checked)!=0) {
+//						HatchBrush	hatchBrush=new HatchBrush(HatchStyle.Percent50, ColorButtonLight, ColorButtonHilight);
+//						graphics.FillRectangle(hatchBrush,rectangle);
+//						hatchBrush.Dispose();
+//					}
 
-					if ((State & DrawFrameControlStates.Pushed)!=0) {
-						CPDrawBorder3D(graphics, rectangle, Border3DStyle.Sunken, Border3DSide.Left | Border3DSide.Top | Border3DSide.Right | Border3DSide.Bottom, ColorButtonFace);
+					if ((State & DrawFrameControlStates.Pushed)!=0 || (State & DrawFrameControlStates.Checked)!=0) {
+						graphics.DrawRectangle (ResPool.GetPen (ControlPaint.Dark (ColorButtonFace)), rectangle);
 					} else if ((State & DrawFrameControlStates.Flat)!=0) {
 						ControlPaint.DrawBorder(graphics, rectangle, ColorButtonShadow, ButtonBorderStyle.Solid);
 					} else if ((State & DrawFrameControlStates.Inactive)!=0) {

--=-jxf9CCTHgOs9pBaO3wsn--