* Mono.Posix.dll.sources: Rename Mono.Posix to Mono.Unix.
[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 // $Log: ControlPaint.cs,v $
27 // Revision 1.5  2004/10/13 03:15:16  pbartok
28 // - Fixed Dark(), DarkDark(), Light() and LightLight() methods to match MS
29 //   documentation. They need to return defined colors if the passed
30 //   color matches the configured control color. Thanks to John BouAntoun for
31 //   pointing this out.
32 //
33 // Revision 1.4  2004/09/28 18:44:25  pbartok
34 // - Streamlined Theme interfaces:
35 //   * Each DrawXXX method for a control now is passed the object for the
36 //     control to be drawn in order to allow accessing any state the theme
37 //     might require
38 //
39 //   * ControlPaint methods for the theme now have a CP prefix to avoid
40 //     name clashes with the Draw methods for controls
41 //
42 //   * Every control now retrieves it's DefaultSize from the current theme
43 //
44 // Revision 1.3  2004/08/11 22:20:59  pbartok
45 // - Signature fixes
46 //
47 // Revision 1.2  2004/07/26 17:42:03  jordi
48 // Theme support
49 //
50 // Revision 1.1  2004/07/09 05:21:25  pbartok
51 // - Initial check-in
52 //
53 //
54
55 // NOT COMPLETE
56
57 using System.Drawing;
58 using System.Drawing.Drawing2D;
59 using System.Drawing.Imaging;
60
61 namespace System.Windows.Forms {
62         public sealed class ControlPaint {
63                 #region Local Variables
64                 static int              RGBMax=255;
65                 static int              HLSMax=255;
66                 #endregion      // Local Variables
67
68                 #region Private Enumerations
69
70
71                 #region Constructor
72                 // Prevent a public constructor from being created
73                 private ControlPaint() {
74                 }
75                 #endregion      // Constructor
76
77
78                 #endregion      // Private Enumerations
79
80                 #region Helpers
81                 private static Color Win32ToColor(int Win32Color) {
82                         return(Color.FromArgb(
83                                 (int)(Win32Color) & 0xff0000 >> 16,             // blue
84                                 (int)(Win32Color) & 0xff00 >> 8,                // green
85                                 (int)(Win32Color) & 0xff                        // red
86                         ));
87                 }
88
89                 internal static void Color2HBS(Color color, out int h, out int l, out int s) {
90                         int     r;
91                         int     g;
92                         int     b;
93                         int     cMax;
94                         int     cMin;
95                         int     rDelta;
96                         int     gDelta;
97                         int     bDelta;
98
99                         r=color.R;
100                         g=color.G;
101                         b=color.B;
102
103                         cMax = Math.Max(Math.Max(r, g), b);
104                         cMin = Math.Min(Math.Min(r, g), b);
105
106                         l = (((cMax+cMin)*HLSMax)+RGBMax)/(2*RGBMax);
107
108                         if (cMax==cMin) {               // Achromatic
109                                 h=0;                                    // h undefined
110                                 s=0;
111                                 l=r;
112                                 return;
113                         }
114
115                         /* saturation */
116                         if (l<=(HLSMax/2)) {
117                                 s=(((cMax-cMin)*HLSMax)+((cMax+cMin)/2))/(cMax+cMin);
118                         } else {
119                                 s=(((cMax-cMin)*HLSMax)+((2*RGBMax-cMax-cMin)/2))/(2*RGBMax-cMax-cMin);
120                         }
121
122                         /* hue */
123                         rDelta=(((cMax-r)*(HLSMax/6))+((cMax-cMin)/2))/(cMax-cMin);
124                         gDelta=(((cMax-g)*(HLSMax/6))+((cMax-cMin)/2))/(cMax-cMin);
125                         bDelta=(((cMax-b)*(HLSMax/6))+((cMax-cMin)/2))/(cMax-cMin);
126
127                         if (r == cMax) {
128                                 h=bDelta - gDelta;
129                         } else if (g == cMax) {
130                                 h=(HLSMax/3) + rDelta - bDelta;
131                         } else { /* B == cMax */
132                                 h=((2*HLSMax)/3) + gDelta - rDelta;
133                         }
134
135                         if (h<0) {
136                                 h+=HLSMax;
137                         }
138
139                         if (h>HLSMax) {
140                                 h-=HLSMax;
141                         }
142                 }
143
144                 private static int HueToRGB(int n1, int n2, int hue) {
145                         if (hue<0) {
146                                 hue+=HLSMax;
147                         }
148
149                         if (hue>HLSMax) {
150                                 hue -= HLSMax;
151                         }
152
153                         /* return r,g, or b value from this tridrant */
154                         if (hue<(HLSMax/6)) {
155                                 return(n1+(((n2-n1)*hue+(HLSMax/12))/(HLSMax/6)));
156                         }
157
158                         if (hue<(HLSMax/2)) {
159                                 return(n2);
160                         }
161
162                         if (hue<((HLSMax*2)/3)) {
163                                 return(n1+(((n2-n1)*(((HLSMax*2)/3)-hue)+(HLSMax/12))/(HLSMax/6)));
164                         } else {
165                                 return(n1);
166                         }
167                 }
168
169                 internal static Color HBS2Color(int hue, int lum, int sat) {
170                         int     R;
171                         int     G;
172                         int     B;
173                         int     Magic1;
174                         int     Magic2;
175
176                         if (sat == 0) {            /* Achromatic */
177                                 R=G=B=(lum*RGBMax)/HLSMax;
178                                 // FIXME : Should throw exception if hue!=0
179                         } else {
180                                 if (lum<=(HLSMax/2)) {
181                                         Magic2=(lum*(HLSMax+sat)+(HLSMax/2))/HLSMax;
182                                 } else {
183                                         Magic2=sat+lum-((sat*lum)+(HLSMax/2))/HLSMax;
184                                 }
185                                 Magic1=2*lum-Magic2;
186
187                                 R = Math.Min(255, (HueToRGB(Magic1,Magic2,hue+(HLSMax/3))*RGBMax+(HLSMax/2))/HLSMax);
188                                 G = Math.Min(255, (HueToRGB(Magic1,Magic2,hue)*RGBMax+(HLSMax/2))/HLSMax);
189                                 B = Math.Min(255, (HueToRGB(Magic1,Magic2,hue-(HLSMax/3))*RGBMax+(HLSMax/2))/HLSMax);
190                         }
191                         return(Color.FromArgb(R, G, B));
192                 }
193                 #endregion      // Helpers
194
195                 #region Public Static Properties
196                 public static Color ContrastControlDark {
197                         get { return(SystemColors.ControlDark); }
198                 }
199                 #endregion      // Public Static Properties
200
201                 #region Public Static Methods
202                 public static IntPtr CreateHBitmap16Bit(Bitmap bitmap, Color background){
203                         throw new NotImplementedException ();
204                 }
205
206                 public static IntPtr CreateHBitmapColorMask(Bitmap bitmap, IntPtr monochromeMask){
207                         throw new NotImplementedException ();
208                 }
209
210                 public static IntPtr CreateHBitmapTransparencyMask(Bitmap bitmap){
211                         throw new NotImplementedException ();
212                 }
213
214                 public static Color Light(Color baseColor) {
215                         if (baseColor == ThemeEngine.Current.ColorButtonFace) {
216                                 return ThemeEngine.Current.ColorButtonLight;
217                         }
218
219                         return Light( baseColor, 10.0f);
220                 }
221
222                 public static Color Light(Color baseColor,float percOfLightLight) {
223                         int H, I, S;
224
225                         ControlPaint.Color2HBS(baseColor, out H, out I, out S);
226                         int NewIntensity = Math.Min( 255, I + ((255*(int)percOfLightLight)/100));
227                         return ControlPaint.HBS2Color(H, NewIntensity, S);
228                 }
229
230                 public static Color LightLight(Color baseColor) {
231                         if (baseColor == ThemeEngine.Current.ColorButtonFace) {
232                                 return ThemeEngine.Current.ColorButtonHilight;
233                         }
234
235                         return Light( baseColor, 20.0f);
236                 }
237
238                 public static Color Dark(Color baseColor) {
239                         if (baseColor == ThemeEngine.Current.ColorButtonFace) {
240                                 return ThemeEngine.Current.ColorButtonShadow;
241                         }
242
243                         return Dark(baseColor, 10.0f);
244                 }
245
246                 public static Color Dark(Color baseColor,float percOfDarkDark) {
247                         int H, I, S;
248
249                         ControlPaint.Color2HBS(baseColor, out H, out I, out S);
250                         int NewIntensity = Math.Max(0, I - ((255*(int)percOfDarkDark) / 100));
251                         return ControlPaint.HBS2Color(H, NewIntensity, S);
252                 }
253
254                 public static Color DarkDark(Color baseColor) {
255                         if (baseColor == ThemeEngine.Current.ColorButtonFace) {
256                                 return ThemeEngine.Current.ColorButtonDkShadow;
257                         }
258
259                         return Dark(baseColor, 20.0f);
260                 }
261
262                 public static void DrawBorder(Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style) {
263                         DrawBorder(graphics, bounds, color, 1, style, color, 1, style, color, 1, style, color, 1, style);
264                 }
265
266                 public static void DrawBorder( Graphics graphics, Rectangle bounds, Color leftColor, int leftWidth,
267                         ButtonBorderStyle leftStyle, Color topColor, int topWidth, ButtonBorderStyle topStyle,
268                         Color rightColor, int rightWidth, ButtonBorderStyle rightStyle, Color bottomColor, int bottomWidth,
269                         ButtonBorderStyle bottomStyle) {
270
271                         ThemeEngine.Current.CPDrawBorder (graphics, bounds, leftColor, leftWidth,
272                                 leftStyle, topColor, topWidth, topStyle, rightColor, rightWidth, rightStyle,
273                                 bottomColor, bottomWidth, bottomStyle);
274                 }
275
276
277                 public static void DrawBorder3D(Graphics graphics, Rectangle rectangle) {
278                         DrawBorder3D(graphics, rectangle, Border3DStyle.Etched, Border3DSide.All);
279                 }
280
281                 public static void DrawBorder3D(Graphics graphics, Rectangle rectangle, Border3DStyle style) {
282                         DrawBorder3D(graphics, rectangle, style, Border3DSide.All);
283                 }
284
285                 public static void DrawBorder3D(Graphics graphics, int x, int y, int width, int height) {
286                         DrawBorder3D(graphics, new Rectangle(x, y, width, height), Border3DStyle.Etched, Border3DSide.All);
287                 }
288
289                 public static void DrawBorder3D(Graphics graphics, int x, int y, int width, int height, Border3DStyle style) {
290                         DrawBorder3D(graphics, new Rectangle(x, y, width, height), style, Border3DSide.All);
291                 }
292
293                 public static void DrawBorder3D( Graphics graphics, int x, int y, int width, int height, Border3DStyle style,Border3DSide sides) {
294                         DrawBorder3D( graphics, new Rectangle(x, y, width, height), style, sides);
295                 }
296
297                 public static void DrawBorder3D( Graphics graphics, Rectangle rectangle, Border3DStyle style, Border3DSide sides) {
298
299                         ThemeEngine.Current.CPDrawBorder3D (graphics, rectangle, style, sides);
300                 }
301
302                 public static void DrawButton( Graphics graphics, int x, int y, int width, int height, ButtonState state) {
303                         DrawButton(graphics, new Rectangle(x, y, width, height), state);
304                 }
305
306                 public static void DrawButton( Graphics graphics, Rectangle rectangle, ButtonState state) {
307
308                         ThemeEngine.Current.CPDrawButton (graphics, rectangle, state);
309                 }
310
311
312                 public static void DrawCaptionButton(Graphics graphics, int x, int y, int width, int height, CaptionButton button, ButtonState state) {
313                         DrawCaptionButton(graphics, new Rectangle(x, y, width, height), button, state);
314                 }
315
316                 public static void DrawCaptionButton(Graphics graphics, Rectangle rectangle, CaptionButton button, ButtonState state) {
317
318                         ThemeEngine.Current.CPDrawCaptionButton (graphics, rectangle, button, state);
319                 }
320
321                 public static void DrawCheckBox(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
322                         DrawCheckBox(graphics, new Rectangle(x, y, width, height), state);
323                 }
324
325                 public static void DrawCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state) {
326
327                         ThemeEngine.Current.CPDrawCheckBox (graphics, rectangle, state);
328                 }
329
330                 public static void DrawComboButton(Graphics graphics, Rectangle rectangle, ButtonState state) {
331
332                         ThemeEngine.Current.CPDrawComboButton (graphics, rectangle,  state);
333                 }
334
335                 public static void DrawComboButton(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
336                         DrawComboButton(graphics, new Rectangle(x, y, width, height), state);
337                 }
338
339                 public static void DrawContainerGrabHandle(Graphics graphics, Rectangle bounds) {
340
341                         ThemeEngine.Current.CPDrawContainerGrabHandle (graphics, bounds);
342                 }
343
344                 public static void DrawFocusRectangle( Graphics graphics, Rectangle rectangle) {
345                         DrawFocusRectangle(graphics, rectangle, Color.White, Color.Black);
346                 }
347
348                 public static void DrawFocusRectangle( Graphics graphics, Rectangle rectangle, Color foreColor, Color backColor) {
349
350                         ThemeEngine.Current.CPDrawFocusRectangle (graphics, rectangle, foreColor, backColor);
351                 }
352
353                 public static void DrawGrabHandle(Graphics graphics, Rectangle rectangle, bool primary, bool enabled) {
354
355                         ThemeEngine.Current.CPDrawGrabHandle (graphics, rectangle, primary, enabled);
356                 }
357
358                 public static void DrawGrid(Graphics graphics, Rectangle area, Size pixelsBetweenDots, Color backColor) {
359
360                         ThemeEngine.Current.CPDrawGrid (graphics, area, pixelsBetweenDots, backColor);
361                 }
362
363                 public static void DrawImageDisabled(Graphics graphics, Image image, int x, int y, Color background) {
364
365                         ThemeEngine.Current.CPDrawImageDisabled (graphics, image, x, y, background);
366                 }
367
368                 public static void DrawLockedFrame(Graphics graphics, Rectangle rectangle, bool primary) {
369
370                         ThemeEngine.Current.CPDrawLockedFrame (graphics, rectangle, primary);
371                 }
372
373                 public static void DrawMenuGlyph(Graphics graphics, Rectangle rectangle, MenuGlyph glyph) {
374
375                         ThemeEngine.Current.CPDrawMenuGlyph (graphics, rectangle, glyph);
376                 }
377
378                 public static void DrawMenuGlyph(Graphics graphics, int x, int y, int width, int height, MenuGlyph glyph) {
379                         DrawMenuGlyph(graphics, new Rectangle(x, y, width, height), glyph);
380                 }
381
382                 public static void DrawMixedCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state) {
383                         DrawCheckBox(graphics, rectangle, state);
384                 }
385
386                 public static void DrawMixedCheckBox(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
387                         DrawMixedCheckBox(graphics, new Rectangle(x, y, width, height), state);
388                 }
389
390
391                 public static void DrawRadioButton(Graphics graphics, int x, int y, int width, int height, ButtonState state) {
392                         DrawRadioButton(graphics, new Rectangle(x, y, width, height), state);
393                 }
394
395                 public static void DrawRadioButton(Graphics graphics, Rectangle rectangle, ButtonState state) {
396
397                         ThemeEngine.Current.CPDrawRadioButton (graphics, rectangle, state);
398                 }
399
400                 [MonoTODO("Figure out a good System.Drawing way for XOR drawing")]
401                 public static void DrawReversibleFrame(Rectangle rectangle, Color backColor, FrameStyle style) {
402                         throw new NotImplementedException();
403                 }
404
405                 [MonoTODO("Figure out a good System.Drawing way for XOR drawing")]
406                 public static void DrawReversibleLine(Point start, Point end, Color backColor) {
407                         throw new NotImplementedException();
408                 }
409
410                 [MonoTODO("Figure out a good System.Drawing way for XOR drawing")]
411                 public static void FillReversibleRectangle(Rectangle rectangle, Color backColor) {
412                         throw new NotImplementedException();
413                 }
414
415
416                 public static void DrawScrollButton (Graphics graphics, int x, int y, int width, int height, ScrollButton button, ButtonState state) {
417                         ThemeEngine.Current.CPDrawScrollButton (graphics, new Rectangle(x, y, width, height), button, state);
418                 }
419
420                 public static void DrawScrollButton (Graphics graphics, Rectangle rectangle, ScrollButton button, ButtonState state) {
421                         ThemeEngine.Current.CPDrawScrollButton (graphics, rectangle, button, state);
422                 }
423
424                 [MonoTODO]
425                 public static void DrawSelectionFrame(Graphics graphics, bool active, Rectangle outsideRect, Rectangle insideRect, Color backColor) {
426                         throw new NotImplementedException();
427                 }
428
429                 public static void DrawSizeGrip (Graphics graphics, Color backColor, Rectangle bounds)
430                 {
431                         ThemeEngine.Current.CPDrawSizeGrip (graphics,  backColor,  bounds);
432                 }
433
434                 public static void DrawSizeGrip(Graphics graphics, Color backColor, int x, int y, int width, int height) {
435                         DrawSizeGrip(graphics, backColor, new Rectangle(x, y, width, height));
436                 }
437
438                 public static void DrawStringDisabled(Graphics graphics, string s, Font font, Color color, RectangleF layoutRectangle, StringFormat format) {
439
440                         ThemeEngine.Current.CPDrawStringDisabled (graphics, s, font, color, layoutRectangle, format);
441                 }
442                 #endregion      // Public Static Methods
443         }
444 }