1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2008 George Giolfan
21 // Copyright (c) 2004-2006 Novell, Inc.
24 // George Giolfan, georgegiolfan@yahoo.com
25 // Ernesto Carrea, equistango@gmail.com
28 using System.Windows.Forms.VisualStyles;
30 namespace System.Windows.Forms
33 /// VisualStyles theme.
36 /// This theme uses only the managed VisualStyles API.
37 /// To select it, set MONO_THEME to VisualStyles and call <see cref="Application.EnableVisualStyles"/>.
39 class ThemeVisualStyles : ThemeWin32Classic
42 public override void DrawButtonBase (Graphics dc, Rectangle clip_area, ButtonBase button)
44 if (button.FlatStyle == FlatStyle.System) {
45 ButtonRenderer.DrawButton (
47 new Rectangle (Point.Empty, button.Size),
50 button.TextFormatFlags,
53 ShouldPaintFocusRectagle (button),
54 GetPushButtonState (button)
58 base.DrawButtonBase (dc, clip_area, button);
60 static PushButtonState GetPushButtonState (ButtonBase button)
63 return PushButtonState.Disabled;
65 return PushButtonState.Pressed;
67 return PushButtonState.Hot;
68 if (button.IsDefault || button.Focused || button.paint_as_acceptbutton)
69 return PushButtonState.Default;
70 return PushButtonState.Normal;
75 public override void DrawButtonBackground (Graphics g, Button button, Rectangle clipArea)
77 if (!button.UseVisualStyleBackColor) {
78 base.DrawButtonBackground (g, button, clipArea);
81 ButtonRenderer.GetPushButtonRenderer (GetPushButtonState (button)).DrawBackground (g, new Rectangle (Point.Empty, button.Size));
86 protected override void CheckBox_DrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
88 if (checkbox.Appearance == Appearance.Normal && checkbox.FlatStyle == FlatStyle.System) {
89 CheckBoxRenderer.DrawCheckBox (
91 new Point (checkbox_rectangle.Left, checkbox_rectangle.Top),
92 GetCheckBoxState (checkbox)
96 base.CheckBox_DrawCheckBox(dc, checkbox, state, checkbox_rectangle);
98 static CheckBoxState GetCheckBoxState (CheckBox checkBox)
100 switch (checkBox.CheckState) {
101 case CheckState.Checked:
102 if (!checkBox.Enabled)
103 return CheckBoxState.CheckedDisabled;
104 else if (checkBox.Pressed)
105 return CheckBoxState.CheckedPressed;
106 else if (checkBox.Entered)
107 return CheckBoxState.CheckedHot;
108 return CheckBoxState.CheckedNormal;
109 case CheckState.Indeterminate:
110 if (!checkBox.Enabled)
111 return CheckBoxState.MixedDisabled;
112 else if (checkBox.Pressed)
113 return CheckBoxState.MixedPressed;
114 else if (checkBox.Entered)
115 return CheckBoxState.MixedHot;
116 return CheckBoxState.MixedNormal;
118 if (!checkBox.Enabled)
119 return CheckBoxState.UncheckedDisabled;
120 else if (checkBox.Pressed)
121 return CheckBoxState.UncheckedPressed;
122 else if (checkBox.Entered)
123 return CheckBoxState.UncheckedHot;
124 return CheckBoxState.UncheckedNormal;
129 #region DrawCaptionButton
130 public override void CPDrawCaptionButton (Graphics graphics, Rectangle rectangle, CaptionButton button, ButtonState state)
132 if ((state & ButtonState.Flat) == ButtonState.Flat ||
133 (state & ButtonState.Checked) == ButtonState.Checked) {
134 base.CPDrawCaptionButton (graphics, rectangle, button, state);
137 VisualStyleElement element = GetCaptionButtonVisualStyleElement (button, state);
138 if (!VisualStyleRenderer.IsElementDefined (element)) {
139 base.CPDrawCaptionButton (graphics, rectangle, button, state);
142 new VisualStyleRenderer (element).DrawBackground (graphics, rectangle);
144 static VisualStyleElement GetCaptionButtonVisualStyleElement (CaptionButton button, ButtonState state)
147 case CaptionButton.Minimize:
148 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
149 return VisualStyleElement.Window.MinButton.Disabled;
150 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
151 return VisualStyleElement.Window.MinButton.Pressed;
153 return VisualStyleElement.Window.MinButton.Normal;
154 case CaptionButton.Maximize:
155 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
156 return VisualStyleElement.Window.MaxButton.Disabled;
157 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
158 return VisualStyleElement.Window.MaxButton.Pressed;
160 return VisualStyleElement.Window.MaxButton.Normal;
161 case CaptionButton.Close:
162 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
163 return VisualStyleElement.Window.CloseButton.Disabled;
164 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
165 return VisualStyleElement.Window.CloseButton.Pressed;
167 return VisualStyleElement.Window.CloseButton.Normal;
168 case CaptionButton.Restore:
169 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
170 return VisualStyleElement.Window.RestoreButton.Disabled;
171 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
172 return VisualStyleElement.Window.RestoreButton.Pressed;
174 return VisualStyleElement.Window.RestoreButton.Normal;
176 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
177 return VisualStyleElement.Window.HelpButton.Disabled;
178 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
179 return VisualStyleElement.Window.HelpButton.Pressed;
181 return VisualStyleElement.Window.HelpButton.Normal;
186 public override void CPDrawCheckBox (Graphics dc, Rectangle rectangle, ButtonState state)
188 if ((state & ButtonState.Flat) == ButtonState.Flat) {
189 base.CPDrawCheckBox (dc, rectangle, state);
192 VisualStyleElement element;
193 if ((state & ButtonState.Checked) == ButtonState.Checked)
194 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
195 element = VisualStyleElement.Button.CheckBox.CheckedDisabled;
196 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
197 element = VisualStyleElement.Button.CheckBox.CheckedPressed;
199 element = VisualStyleElement.Button.CheckBox.CheckedNormal;
201 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
202 element = VisualStyleElement.Button.CheckBox.UncheckedDisabled;
203 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
204 element = VisualStyleElement.Button.CheckBox.UncheckedPressed;
206 element = VisualStyleElement.Button.CheckBox.UncheckedNormal;
207 if (!VisualStyleRenderer.IsElementDefined (element)) {
208 base.CPDrawCheckBox (dc, rectangle, state);
211 new VisualStyleRenderer (element).DrawBackground (dc, rectangle);
214 #region DrawRadioButton
215 public override void CPDrawRadioButton (Graphics dc, Rectangle rectangle, ButtonState state)
217 if ((state & ButtonState.Flat) == ButtonState.Flat) {
218 base.CPDrawRadioButton (dc, rectangle, state);
221 VisualStyleElement element;
222 if ((state & ButtonState.Checked) == ButtonState.Checked)
223 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
224 element = VisualStyleElement.Button.RadioButton.CheckedDisabled;
225 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
226 element = VisualStyleElement.Button.RadioButton.CheckedPressed;
228 element = VisualStyleElement.Button.RadioButton.CheckedNormal;
230 if ((state & ButtonState.Inactive) == ButtonState.Inactive)
231 element = VisualStyleElement.Button.RadioButton.UncheckedDisabled;
232 else if ((state & ButtonState.Pushed) == ButtonState.Pushed)
233 element = VisualStyleElement.Button.RadioButton.UncheckedPressed;
235 element = VisualStyleElement.Button.RadioButton.UncheckedNormal;
236 if (!VisualStyleRenderer.IsElementDefined (element)) {
237 base.CPDrawRadioButton (dc, rectangle, state);
240 new VisualStyleRenderer (element).DrawBackground (dc, rectangle);
243 #region DrawScrollButton
244 public override void CPDrawScrollButton (Graphics dc, Rectangle area, ScrollButton type, ButtonState state)
246 if ((state & ButtonState.Flat) == ButtonState.Flat ||
247 (state & ButtonState.Checked) == ButtonState.Checked) {
248 base.CPDrawScrollButton (dc, area, type, state);
251 VisualStyleElement element = GetScrollButtonVisualStyleElement (type, state);
252 if (!VisualStyleRenderer.IsElementDefined (element)) {
253 base.CPDrawScrollButton (dc, area, type, state);
256 new VisualStyleRenderer (element).DrawBackground (dc, area);
258 static VisualStyleElement GetScrollButtonVisualStyleElement (ScrollButton type, ButtonState state)
261 case ScrollButton.Left:
262 if (IsDisabled (state))
263 return VisualStyleElement.ScrollBar.ArrowButton.LeftDisabled;
264 else if (IsPressed (state))
265 return VisualStyleElement.ScrollBar.ArrowButton.LeftPressed;
267 return VisualStyleElement.ScrollBar.ArrowButton.LeftNormal;
268 case ScrollButton.Right:
269 if (IsDisabled (state))
270 return VisualStyleElement.ScrollBar.ArrowButton.RightDisabled;
271 else if (IsPressed (state))
272 return VisualStyleElement.ScrollBar.ArrowButton.RightPressed;
274 return VisualStyleElement.ScrollBar.ArrowButton.RightNormal;
275 case ScrollButton.Up:
276 if (IsDisabled (state))
277 return VisualStyleElement.ScrollBar.ArrowButton.UpDisabled;
278 else if (IsPressed (state))
279 return VisualStyleElement.ScrollBar.ArrowButton.UpPressed;
281 return VisualStyleElement.ScrollBar.ArrowButton.UpNormal;
283 if (IsDisabled (state))
284 return VisualStyleElement.ScrollBar.ArrowButton.DownDisabled;
285 else if (IsPressed (state))
286 return VisualStyleElement.ScrollBar.ArrowButton.DownPressed;
288 return VisualStyleElement.ScrollBar.ArrowButton.DownNormal;
291 static bool IsDisabled (ButtonState state)
293 return (state & ButtonState.Inactive) == ButtonState.Inactive;
295 static bool IsPressed (ButtonState state)
297 return (state & ButtonState.Pushed) == ButtonState.Pushed;
301 #region Managed windows
302 [MonoTODO("When other VisualStyles implementations are supported, check if the visual style elements are defined.")]
303 [MonoTODO("When the rest of the MDI code is fixed, make sure minimized windows are painted correctly,restrict the caption text drawing area to exclude the title buttons and handle the title bar height correctly.")]
304 public override void DrawManagedWindowDecorations (Graphics dc, Rectangle clip, InternalWindowManager wm)
306 if (!wm.HasBorders || (wm.Form.IsMdiChild && wm.IsMaximized))
308 VisualStyleElement element;
309 #region Title bar background
310 #region Select caption visual style element
313 switch (wm.form.window_state) {
314 case FormWindowState.Minimized:
315 if (!wm.Form.Enabled)
316 element = VisualStyleElement.Window.SmallMinCaption.Disabled;
317 else if (wm.IsActive)
318 element = VisualStyleElement.Window.SmallMinCaption.Active;
320 element = VisualStyleElement.Window.SmallMinCaption.Inactive;
322 case FormWindowState.Maximized:
323 if (!wm.Form.Enabled)
324 element = VisualStyleElement.Window.SmallMaxCaption.Disabled;
325 else if (wm.IsActive)
326 element = VisualStyleElement.Window.SmallMaxCaption.Active;
328 element = VisualStyleElement.Window.SmallMaxCaption.Inactive;
331 if (!wm.Form.Enabled)
332 element = VisualStyleElement.Window.SmallCaption.Disabled;
333 else if (wm.IsActive)
334 element = VisualStyleElement.Window.SmallCaption.Active;
336 element = VisualStyleElement.Window.SmallCaption.Inactive;
341 #region Normal window
342 switch (wm.form.window_state) {
343 case FormWindowState.Minimized:
344 if (!wm.Form.Enabled)
345 element = VisualStyleElement.Window.MinCaption.Disabled;
346 else if (wm.IsActive)
347 element = VisualStyleElement.Window.MinCaption.Active;
349 element = VisualStyleElement.Window.MinCaption.Inactive;
351 case FormWindowState.Maximized:
352 if (!wm.Form.Enabled)
353 element = VisualStyleElement.Window.MaxCaption.Disabled;
354 else if (wm.IsActive)
355 element = VisualStyleElement.Window.MaxCaption.Active;
357 element = VisualStyleElement.Window.MaxCaption.Inactive;
360 if (!wm.Form.Enabled)
361 element = VisualStyleElement.Window.Caption.Disabled;
362 else if (wm.IsActive)
363 element = VisualStyleElement.Window.Caption.Active;
365 element = VisualStyleElement.Window.Caption.Inactive;
370 VisualStyleRenderer renderer = new VisualStyleRenderer (element);
371 Rectangle title_bar_rectangle = new Rectangle (
375 renderer.GetPartSize (dc, ThemeSizeType.True).Height
377 Rectangle caption_text_area = title_bar_rectangle;
378 renderer.DrawBackground (dc, title_bar_rectangle, clip);
380 int border_width = ManagedWindowBorderWidth (wm);
382 if (!wm.IsToolWindow && wm.Form.FormBorderStyle != FormBorderStyle.FixedDialog
387 Rectangle icon_rectangle = new Rectangle (
392 caption_text_area.X += icon_rectangle.Width;
393 if (icon_rectangle.IntersectsWith (clip))
394 dc.DrawIcon (wm.Form.Icon, icon_rectangle);
397 #region Title bar buttons
398 foreach (TitleButton button in wm.TitleButtons.AllButtons) {
399 if (!button.Visible || !button.Rectangle.IntersectsWith (clip))
401 new VisualStyleRenderer (GetCaptionButtonVisualStyleElement (button.Caption, button.State)).DrawBackground (dc, button.Rectangle, clip);
405 if (wm.GetWindowState () == FormWindowState.Normal) {
409 element = VisualStyleElement.Window.SmallFrameLeft.Active;
411 element = VisualStyleElement.Window.SmallFrameLeft.Inactive;
414 element = VisualStyleElement.Window.FrameLeft.Active;
416 element = VisualStyleElement.Window.FrameLeft.Inactive;
417 renderer = new VisualStyleRenderer (element);
418 renderer.DrawBackground (dc, new Rectangle (
420 title_bar_rectangle.Bottom,
422 wm.form.Height - title_bar_rectangle.Bottom
428 element = VisualStyleElement.Window.SmallFrameRight.Active;
430 element = VisualStyleElement.Window.SmallFrameRight.Inactive;
433 element = VisualStyleElement.Window.FrameRight.Active;
435 element = VisualStyleElement.Window.FrameRight.Inactive;
437 renderer = new VisualStyleRenderer (element);
438 renderer.DrawBackground (dc, new Rectangle (
439 wm.form.Width - border_width,
440 title_bar_rectangle.Bottom,
442 wm.form.Height - title_bar_rectangle.Bottom
448 element = VisualStyleElement.Window.SmallFrameBottom.Active;
450 element = VisualStyleElement.Window.SmallFrameBottom.Inactive;
453 element = VisualStyleElement.Window.FrameBottom.Active;
455 element = VisualStyleElement.Window.FrameBottom.Inactive;
457 renderer = new VisualStyleRenderer (element);
458 renderer.DrawBackground (dc, new Rectangle (
460 wm.form.Height - border_width,
465 caption_text_area.X += border_width;
469 string window_caption = wm.Form.Text;
470 if (window_caption != null && window_caption.Length != 0 && caption_text_area.IntersectsWith (clip)) {
471 StringFormat format = new StringFormat ();
472 format.FormatFlags = StringFormatFlags.NoWrap;
473 format.Trimming = StringTrimming.EllipsisCharacter;
474 format.LineAlignment = StringAlignment.Center;
478 ThemeEngine.Current.ResPool.GetSolidBrush (Color.White),
487 public override void DrawProgressBar (Graphics dc, Rectangle clip_rect, ProgressBar ctrl)
489 if (!VisualStyleRenderer.IsElementDefined (VisualStyleElement.ProgressBar.Bar.Normal) ||
490 !VisualStyleRenderer.IsElementDefined (VisualStyleElement.ProgressBar.Chunk.Normal)) {
491 base.DrawProgressBar (dc, clip_rect, ctrl);
494 VisualStyleRenderer renderer = new VisualStyleRenderer (VisualStyleElement.ProgressBar.Bar.Normal);
495 renderer.DrawBackground (dc, ctrl.ClientRectangle, clip_rect);
496 Rectangle client_area = renderer.GetBackgroundContentRectangle (dc, new Rectangle (Point.Empty, ctrl.Size));
497 renderer = new VisualStyleRenderer (VisualStyleElement.ProgressBar.Chunk.Normal);
500 int max_blocks = int.MaxValue;
501 int start_pixel = client_area.X;
503 draw_mode = (int)ctrl.Style;
507 case 1: // Continuous
508 client_area.Width = (int)(client_area.Width * ((double)(ctrl.Value - ctrl.Minimum) / (double)(Math.Max (ctrl.Maximum - ctrl.Minimum, 1))));
509 renderer.DrawBackground (dc, client_area, clip_rect);
512 int ms_diff = (int)(DateTime.Now - ctrl.start).TotalMilliseconds;
513 double percent_done = (double)ms_diff % (double)ctrl.MarqueeAnimationSpeed / (double)ctrl.MarqueeAnimationSpeed;
515 start_pixel = client_area.X + (int)(client_area.Width * percent_done);
519 int block_width = renderer.GetInteger (IntegerProperty.ProgressChunkSize);
520 int first_pixel_outside_filled_area = ((ctrl.Value - ctrl.Minimum) * client_area.Width) / (Math.Max (ctrl.Maximum - ctrl.Minimum, 1)) + client_area.X;
522 int increment = block_width + renderer.GetInteger (IntegerProperty.ProgressSpaceSize);
523 Rectangle block_rect = new Rectangle (start_pixel, client_area.Y, block_width, client_area.Height);
525 if (max_blocks != int.MaxValue) {
526 if (block_count == max_blocks)
528 if (block_rect.Right >= client_area.Width)
529 block_rect.X -= client_area.Width;
531 if (block_rect.X >= first_pixel_outside_filled_area)
533 if (block_rect.Right >= first_pixel_outside_filled_area)
534 if (first_pixel_outside_filled_area == client_area.Right)
535 block_rect.Width = first_pixel_outside_filled_area - block_rect.X;
539 if (clip_rect.IntersectsWith (block_rect))
540 renderer.DrawBackground (dc, block_rect, clip_rect);
541 block_rect.X += increment;
549 protected override void RadioButton_DrawButton (RadioButton radio_button, Graphics dc, ButtonState state, Rectangle radiobutton_rectangle) {
550 if (radio_button.Appearance == Appearance.Normal && radio_button.FlatStyle == FlatStyle.System) {
551 RadioButtonRenderer.DrawRadioButton (
553 new Point (radiobutton_rectangle.Left, radiobutton_rectangle.Top),
554 GetRadioButtonState (radio_button)
558 base.RadioButton_DrawButton(radio_button, dc, state, radiobutton_rectangle);
560 static RadioButtonState GetRadioButtonState (RadioButton checkBox)
562 if (checkBox.Checked) {
563 if (!checkBox.Enabled)
564 return RadioButtonState.CheckedDisabled;
565 else if (checkBox.Pressed)
566 return RadioButtonState.CheckedPressed;
567 else if (checkBox.Entered)
568 return RadioButtonState.CheckedHot;
569 return RadioButtonState.CheckedNormal;
571 if (!checkBox.Enabled)
572 return RadioButtonState.UncheckedDisabled;
573 else if (checkBox.Pressed)
574 return RadioButtonState.UncheckedPressed;
575 else if (checkBox.Entered)
576 return RadioButtonState.UncheckedHot;
577 return RadioButtonState.UncheckedNormal;