Properly update the combo box selected text when the current item is changed, and...
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ControlPaint.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25
26
27 // NOT COMPLETE
28
29 using System.Drawing;
30 using System.Drawing.Drawing2D;
31 using System.Drawing.Imaging;
32
33 namespace System.Windows.Forms {
34         public sealed class ControlPaint {
35                 #region Local Variables
36                 static int              RGBMax=255;
37                 static int              HLSMax=255;
38                 #endregion      // Local Variables
39
40                 #region Private Enumerations
41
42
43                 #region Constructor
44                 // Prevent a public constructor from being created
45                 private ControlPaint() {
46                 }
47                 #endregion      // Constructor
48
49
50                 #endregion      // Private Enumerations
51
52                 #region Helpers
53                 internal static void Color2HBS(Color color, out int h, out int l, out int s) {
54                         int     r;
55                         int     g;
56                         int     b;
57                         int     cMax;
58                         int     cMin;
59                         int     rDelta;
60                         int     gDelta;
61                         int     bDelta;
62
63                         r=color.R;
64                         g=color.G;
65                         b=color.B;
66
67                         cMax = Math.Max(Math.Max(r, g), b);
68                         cMin = Math.Min(Math.Min(r, g), b);
69
70                         l = (((cMax+cMin)*HLSMax)+RGBMax)/(2*RGBMax);
71
72                         if (cMax==cMin) {               // Achromatic
73                                 h=0;                                    // h undefined
74                                 s=0;
75                                 return;
76                         }
77
78                         /* saturation */
79                         if (l<=(HLSMax/2)) {
80                                 s=(((cMax-cMin)*HLSMax)+((cMax+cMin)/2))/(cMax+cMin);
81                         } else {
82                                 s=(((cMax-cMin)*HLSMax)+((2*RGBMax-cMax-cMin)/2))/(2*RGBMax-cMax-cMin);
83                         }
84
85                         /* hue */
86                         rDelta=(((cMax-r)*(HLSMax/6))+((cMax-cMin)/2))/(cMax-cMin);
87                         gDelta=(((cMax-g)*(HLSMax/6))+((cMax-cMin)/2))/(cMax-cMin);
88                         bDelta=(((cMax-b)*(HLSMax/6))+((cMax-cMin)/2))/(cMax-cMin);
89
90                         if (r == cMax) {
91                                 h=bDelta - gDelta;
92                         } else if (g == cMax) {
93                                 h=(HLSMax/3) + rDelta - bDelta;
94                         } else { /* B == cMax */
95                                 h=((2*HLSMax)/3) + gDelta - rDelta;
96                         }
97
98                         if (h<0) {
99                                 h+=HLSMax;
100                         }
101
102                         if (h>HLSMax) {
103                                 h-=HLSMax;
104                         }
105                 }
106
107                 private static int HueToRGB(int n1, int n2, int hue) {
108                         if (hue<0) {
109                                 hue+=HLSMax;
110                         }
111
112                         if (hue>HLSMax) {
113                                 hue -= HLSMax;
114                         }
115
116                         /* return r,g, or b value from this tridrant */
117                         if (hue<(HLSMax/6)) {
118                                 return(n1+(((n2-n1)*hue+(HLSMax/12))/(HLSMax/6)));
119                         }
120
121                         if (hue<(HLSMax/2)) {
122                                 return(n2);
123                         }
124
125                         if (hue<((HLSMax*2)/3)) {
126                                 return(n1+(((n2-n1)*(((HLSMax*2)/3)-hue)+(HLSMax/12))/(HLSMax/6)));
127                         } else {
128                                 return(n1);
129                         }
130                 }
131
132                 internal static Color HBS2Color(int hue, int lum, int sat) {
133                         int     R;
134                         int     G;
135                         int     B;
136                         int     Magic1;
137                         int     Magic2;
138
139                         if (sat == 0) {            /* Achromatic */
140                                 R=G=B=(lum*RGBMax)/HLSMax;
141                                 // FIXME : Should throw exception if hue!=0
142                         } else {
143                                 if (lum<=(HLSMax/2)) {
144                                         Magic2=(lum*(HLSMax+sat)+(HLSMax/2))/HLSMax;
145                                 } else {
146                                         Magic2=sat+lum-((sat*lum)+(HLSMax/2))/HLSMax;
147                                 }
148                                 Magic1=2*lum-Magic2;
149
150                                 R = Math.Min(255, (HueToRGB(Magic1,Magic2,hue+(HLSMax/3))*RGBMax+(HLSMax/2))/HLSMax);
151                                 G = Math.Min(255, (HueToRGB(Magic1,Magic2,hue)*RGBMax+(HLSMax/2))/HLSMax);
152                                 B = Math.Min(255, (HueToRGB(Magic1,Magic2,hue-(HLSMax/3))*RGBMax+(HLSMax/2))/HLSMax);
153                         }
154                         return (Color.FromArgb(R, G, B));
155                 }
156                 #endregion      // Helpers
157
158                 #region Public Static Properties
159                 public static Color ContrastControlDark {
160                         get { return(SystemColors.ControlDark); }
161                 }
162                 #endregion      // Public Static Properties
163
164                 #region Public Static Methods
165                 [MonoTODO ("Not implemented, will throw NotImplementedException")]
166                 public static IntPtr CreateHBitmap16Bit (Bitmap bitmap, Color background)
167                 {
168                         throw new NotImplementedException ();
169                 }
170
171                 [MonoTODO ("Not implemented, will throw NotImplementedException")]
172                 public static IntPtr CreateHBitmapColorMask (Bitmap bitmap, IntPtr monochromeMask)
173                 {
174                         throw new NotImplementedException ();
175                 }
176
177                 [MonoTODO ("Not implemented, will throw NotImplementedException")]
178                 public static IntPtr CreateHBitmapTransparencyMask (Bitmap bitmap)
179                 {
180                         throw new NotImplementedException ();
181                 }
182
183                 public static Color Light(Color baseColor) {
184                         return Light(baseColor, 0.5f);
185                 }
186
187                 public static Color Light (Color baseColor, float percOfLightLight)
188                 {
189                         if (baseColor.ToArgb () == ThemeEngine.Current.ColorControl.ToArgb ()) {
190                                 int r_sub, g_sub, b_sub;
191                                 Color color;
192
193                                 if (percOfLightLight <= 0f)
194                                         return ThemeEngine.Current.ColorControlLight;
195
196                                 if (percOfLightLight == 1.0f)
197                                         return ThemeEngine.Current.ColorControlLightLight;
198                                 
199                                 r_sub = ThemeEngine.Current.ColorControlLightLight.R - ThemeEngine.Current.ColorControlLight.R;
200                                 g_sub = ThemeEngine.Current.ColorControlLightLight.G - ThemeEngine.Current.ColorControlLight.G;
201                                 b_sub = ThemeEngine.Current.ColorControlLightLight.B - ThemeEngine.Current.ColorControlLight.B;
202
203                                 color = Color.FromArgb (ThemeEngine.Current.ColorControlLight.A,
204                                                 (int) (ThemeEngine.Current.ColorControlLight.R + (r_sub * percOfLightLight)),
205                                                 (int) (ThemeEngine.Current.ColorControlLight.G + (g_sub * percOfLightLight)),
206                                                 (int) (ThemeEngine.Current.ColorControlLight.B + (b_sub * percOfLightLight)));
207                                 return color;
208                         }
209                         
210                         int H, I, S;
211
212                         ControlPaint.Color2HBS (baseColor, out H, out I, out S);
213                         int NewIntensity = Math.Min (255, I + (int) ((255 - I) * 0.5f * percOfLightLight));
214                         
215                         return ControlPaint.HBS2Color (H, NewIntensity, S);
216                 }
217
218                 public static Color LightLight (Color baseColor)
219                 {
220                         return Light(baseColor, 1.0f);
221                 }
222
223                 public static Color Dark (Color baseColor)
224                 {
225                         return Dark(baseColor, 0.5f);
226                 }
227
228                 public static Color Dark (Color baseColor, float percOfDarkDark)
229                 {
230                         if (baseColor.ToArgb () == ThemeEngine.Current.ColorControl.ToArgb ()) {
231                                 
232                                 int r_sub, g_sub, b_sub;
233                                 Color color;
234
235                                 if (percOfDarkDark <= 0f)
236                                         return ThemeEngine.Current.ColorControlDark;
237
238                                 if (percOfDarkDark == 1.0f)
239                                         return ThemeEngine.Current.ColorControlDarkDark;
240
241                                 r_sub = ThemeEngine.Current.ColorControlDarkDark.R - ThemeEngine.Current.ColorControlDark.R;
242                                 g_sub = ThemeEngine.Current.ColorControlDarkDark.G - ThemeEngine.Current.ColorControlDark.G;
243                                 b_sub = ThemeEngine.Current.ColorControlDarkDark.B - ThemeEngine.Current.ColorControlDark.B;
244
245                                 color = Color.FromArgb (ThemeEngine.Current.ColorControlDark.A,
246                                                 (int) (ThemeEngine.Current.ColorControlDark.R + (r_sub * percOfDarkDark)),
247                                                 (int) (ThemeEngine.Current.ColorControlDark.G + (g_sub * percOfDarkDark)),
248                                                 (int) (ThemeEngine.Current.ColorControlDark.B + (b_sub * percOfDarkDark)));
249                                 return color;
250                         }
251                 
252                         int H, I, S;
253
254                         ControlPaint.Color2HBS(baseColor, out H, out I, out S);
255                         int PreIntensity = Math.Max (0, I - (int) (I * 0.333f));
256                         int NewIntensity = Math.Max (0, PreIntensity - (int) (PreIntensity * percOfDarkDark));
257                         return ControlPaint.HBS2Color(H, NewIntensity, S);
258                 }
259
260                 public static Color DarkDark (Color baseColor)
261                 {
262                         return Dark(baseColor, 1.0f);
263                 }
264
265                 public static void DrawBorder (Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style)
266                 {
267                         int line_width_top_left = 1;
268                         int line_width_bottom_right = 1;
269                         
270                         if (style == ButtonBorderStyle.Inset)
271                                 line_width_top_left = 2;
272                         if (style == ButtonBorderStyle.Outset) {
273                                 line_width_bottom_right = 2;
274                                 line_width_top_left = 2;
275                         }
276                         
277                         DrawBorder(graphics, bounds, color, line_width_top_left, style, color, line_width_top_left, style, color, line_width_bottom_right, style, color, line_width_bottom_right, style);
278                 }
279
280                 internal static void DrawBorder (Graphics graphics, RectangleF bounds, Color color, ButtonBorderStyle style)
281                 {
282                         int line_width_top_left = 1;
283                         int line_width_bottom_right = 1;
284                         
285                         if (style == ButtonBorderStyle.Inset)
286                                 line_width_top_left = 2;
287                         if (style == ButtonBorderStyle.Outset) {
288                                 line_width_bottom_right = 2;
289                                 line_width_top_left = 2;
290                         }
291                         
292                         ThemeEngine.Current.CPDrawBorder (graphics, bounds, color, line_width_top_left, style, color, line_width_top_left, style, color, line_width_bottom_right, style, color, line_width_bottom_right, style);
293                 }
294
295                 public static void DrawBorder( Graphics graphics, Rectangle bounds, Color leftColor, int leftWidth,
296                         ButtonBorderStyle leftStyle, Color topColor, int topWidth, ButtonBorderStyle topStyle,
297                         Color rightColor, int rightWidth, ButtonBorderStyle rightStyle, Color bottomColor, int bottomWidth,
298                         ButtonBorderStyle bottomStyle) {
299
300                         ThemeEngine.Current.CPDrawBorder (graphics, bounds, leftColor, leftWidth,
301                                 leftStyle, topColor, topWidth, topStyle, rightColor, rightWidth, rightStyle,
302                                 bottomColor, bottomWidth, bottomStyle);
303                 }
304
305
306                 public static void DrawBorder3D(Graphics graphics, Rectangle rectangle) {
307                         DrawBorder3D(graphics, rectangle, Border3DStyle.Etched, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom);
308                 }
309
310                 public static void DrawBorder3D(Graphics graphics, Rectangle rectangle, Border3DStyle style) {
311                         DrawBorder3D(graphics, rectangle, style, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom);
312                 }
313
314                 public static void DrawBorder3D(Graphics graphics, int x, int y, int width, int height) {
315                         DrawBorder3D(graphics, new Rectangle(x, y, width, height), Border3DStyle.Etched, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom);
316                 }
317
318                 public static void DrawBorder3D(Graphics graphics, int x, int y, int width, int height, Border3DStyle style) {
319                         DrawBorder3D(graphics, new Rectangle(x, y, width, height), style, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom);
320                 }
321
322                 public static void DrawBorder3D( Graphics graphics, int x, int y, int width, int height, Border3DStyle style,Border3DSide sides) {
323                         DrawBorder3D( graphics, new Rectangle(x, y, width, height), style, sides);
324                 }
325
326                 public static void DrawBorder3D( Graphics graphics, Rectangle rectangle, Border3DStyle style, Border3DSide sides) {
327
328                         ThemeEngine.Current.CPDrawBorder3D (graphics, rectangle, style, sides);
329                 }
330
331                 public static void DrawButton( Graphics graphics, int x, int y, int width, int height, ButtonState state) {
332                         DrawButton(graphics, new Rectangle(x, y, width, height), state);
333                 }
334
335                 public static void DrawButton( Graphics graphics, Rectangle rectangle, ButtonState state) {
336
337                         ThemeEngine.Current.CPDrawButton (graphics, rectangle, state);
338                 }
339
340
341                 public static void DrawCaptionButton(Graphics graphics, int x, int y, int width, int height, CaptionButton button, ButtonState state) {
342                         DrawCaptionButton(graphics, new Rectangle(x, y, width, height), button, state);
343                 }
344
345                 public static void DrawCaptionButton(Graphics graphics, Rectangle rectangle, CaptionButton button, ButtonState state) {
346
347                         ThemeEngine.Current.CPDrawCaptionButton (graphics, rectangle, button, state);
348                 }
349
350                 public static void DrawCheckBox(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
351                         DrawCheckBox(graphics, new Rectangle(x, y, width, height), state);
352                 }
353
354                 public static void DrawCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state) {
355
356                         ThemeEngine.Current.CPDrawCheckBox (graphics, rectangle, state);
357                 }
358
359                 public static void DrawComboButton(Graphics graphics, Rectangle rectangle, ButtonState state) {
360
361                         ThemeEngine.Current.CPDrawComboButton (graphics, rectangle,  state);
362                 }
363
364                 public static void DrawComboButton(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
365                         DrawComboButton(graphics, new Rectangle(x, y, width, height), state);
366                 }
367
368                 public static void DrawContainerGrabHandle(Graphics graphics, Rectangle bounds) {
369
370                         ThemeEngine.Current.CPDrawContainerGrabHandle (graphics, bounds);
371                 }
372
373                 public static void DrawFocusRectangle( Graphics graphics, Rectangle rectangle) {
374                         DrawFocusRectangle(graphics, rectangle, SystemColors.Control, SystemColors.ControlText);
375                 }
376
377                 public static void DrawFocusRectangle( Graphics graphics, Rectangle rectangle, Color foreColor, Color backColor) {
378
379                         ThemeEngine.Current.CPDrawFocusRectangle (graphics, rectangle, foreColor, backColor);
380                 }
381
382                 public static void DrawGrabHandle(Graphics graphics, Rectangle rectangle, bool primary, bool enabled) {
383
384                         ThemeEngine.Current.CPDrawGrabHandle (graphics, rectangle, primary, enabled);
385                 }
386
387                 public static void DrawGrid(Graphics graphics, Rectangle area, Size pixelsBetweenDots, Color backColor) {
388
389                         ThemeEngine.Current.CPDrawGrid (graphics, area, pixelsBetweenDots, backColor);
390                 }
391
392                 public static void DrawImageDisabled(Graphics graphics, Image image, int x, int y, Color background) {
393
394                         ThemeEngine.Current.CPDrawImageDisabled (graphics, image, x, y, background);
395                 }
396
397                 public static void DrawLockedFrame(Graphics graphics, Rectangle rectangle, bool primary) {
398
399                         ThemeEngine.Current.CPDrawLockedFrame (graphics, rectangle, primary);
400                 }
401
402                 public static void DrawMenuGlyph(Graphics graphics, Rectangle rectangle, MenuGlyph glyph) {
403
404                         ThemeEngine.Current.CPDrawMenuGlyph (graphics, rectangle, glyph, ThemeEngine.Current.ColorMenuText, Color.Empty);
405                 }
406
407                 public static void DrawMenuGlyph (Graphics graphics, Rectangle rectangle, MenuGlyph glyph, Color foreColor, Color backColor)
408                 {
409                         ThemeEngine.Current.CPDrawMenuGlyph (graphics, rectangle, glyph, foreColor, backColor);
410                 }
411         
412                 public static void DrawMenuGlyph(Graphics graphics, int x, int y, int width, int height, MenuGlyph glyph) {
413                         DrawMenuGlyph(graphics, new Rectangle(x, y, width, height), glyph);
414                 }
415
416                 public static void DrawMenuGlyph (Graphics graphics, int x, int y, int width, int height, MenuGlyph glyph, Color foreColor, Color backColor)
417                 {
418                         DrawMenuGlyph (graphics, new Rectangle (x, y, width, height), glyph, foreColor, backColor);
419                 }
420
421                 public static void DrawMixedCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state) {
422                         ThemeEngine.Current.CPDrawMixedCheckBox (graphics, rectangle, state);
423                 }
424
425                 public static void DrawMixedCheckBox(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
426                         DrawMixedCheckBox(graphics, new Rectangle(x, y, width, height), state);
427                 }
428
429
430                 public static void DrawRadioButton(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
431                         DrawRadioButton(graphics, new Rectangle(x, y, width, height), state);
432                 }
433
434                 public static void DrawRadioButton(Graphics graphics, Rectangle rectangle, ButtonState state) {
435
436                         ThemeEngine.Current.CPDrawRadioButton (graphics, rectangle, state);
437                 }
438
439                 public static void DrawReversibleFrame(Rectangle rectangle, Color backColor, FrameStyle style) {
440                         XplatUI.DrawReversibleFrame (rectangle, backColor, style);
441                 }
442
443                 public static void DrawReversibleLine(Point start, Point end, Color backColor) {
444                         XplatUI.DrawReversibleLine (start, end, backColor);
445                 }
446
447                 public static void FillReversibleRectangle(Rectangle rectangle, Color backColor) {
448                         XplatUI.FillReversibleRectangle (rectangle, backColor);
449                 }
450
451                 public static void DrawScrollButton (Graphics graphics, int x, int y, int width, int height, ScrollButton button, ButtonState state) {
452                         ThemeEngine.Current.CPDrawScrollButton (graphics, new Rectangle(x, y, width, height), button, state);
453                 }
454
455                 public static void DrawScrollButton (Graphics graphics, Rectangle rectangle, ScrollButton button, ButtonState state) {
456                         ThemeEngine.Current.CPDrawScrollButton (graphics, rectangle, button, state);
457                 }
458
459                 [MonoTODO ("Stub, does nothing")]
460                 private static bool DSFNotImpl = false;
461                 public static void DrawSelectionFrame(Graphics graphics, bool active, Rectangle outsideRect, Rectangle insideRect, Color backColor) {
462                         if (!DSFNotImpl) {
463                                 DSFNotImpl = true;
464                                 Console.WriteLine("NOT IMPLEMENTED: DrawSelectionFrame(Graphics graphics, bool active, Rectangle outsideRect, Rectangle insideRect, Color backColor)");
465                         }
466                         //throw new NotImplementedException();
467                 }
468
469                 public static void DrawSizeGrip (Graphics graphics, Color backColor, Rectangle bounds)
470                 {
471                         ThemeEngine.Current.CPDrawSizeGrip (graphics,  backColor,  bounds);
472                 }
473
474                 public static void DrawSizeGrip(Graphics graphics, Color backColor, int x, int y, int width, int height) {
475                         DrawSizeGrip(graphics, backColor, new Rectangle(x, y, width, height));
476                 }
477
478                 public static void DrawStringDisabled(Graphics graphics, string s, Font font, Color color, RectangleF layoutRectangle, StringFormat format) {
479
480                         ThemeEngine.Current.CPDrawStringDisabled (graphics, s, font, color, layoutRectangle, format);
481                 }
482
483                 public static void DrawStringDisabled (IDeviceContext dc, string s, Font font, Color color, Rectangle layoutRectangle, TextFormatFlags format)
484                 {
485                         ThemeEngine.Current.CPDrawStringDisabled (dc, s, font, color, layoutRectangle, format);
486                 }
487                 
488                 public static void DrawVisualStyleBorder (Graphics graphics, Rectangle bounds)
489                 {
490                         ThemeEngine.Current.CPDrawVisualStyleBorder (graphics, bounds);
491                 }
492                 #endregion      // Public Static Methods
493         }
494 }