merge -r 61110:61111
[mono.git] / mcs / class / System.Drawing / System.Drawing / FontConverter.cs
1 //
2 // System.Drawing.FontConverter.cs
3 //
4 // Authors:
5 //      Dennis Hayes (dennish@Raytek.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //      Ravindra (rkumar@novell.com)
8 //
9 // Copyright (C) 2002,2003 Ximian, Inc.  http://www.ximian.com
10 //
11 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Text;
35 using System.Collections;
36 using System.ComponentModel;
37 using System.Globalization;
38 using System.Drawing.Text;
39 using System.ComponentModel.Design.Serialization;
40 using System.Reflection;
41
42 namespace System.Drawing
43 {
44         public class FontConverter : TypeConverter
45         {
46                 public FontConverter ()
47                 {
48                 }
49
50                 ~FontConverter ()
51                 {
52                                 
53                 }       
54
55                 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
56                 {
57                         if (sourceType == typeof (string))
58                                 return true;
59
60                         return base.CanConvertFrom (context, sourceType);
61                 }
62
63                 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
64                 {
65                         if (destinationType == typeof (String))
66                                 return true;
67
68                         if (destinationType == typeof (InstanceDescriptor))
69                                 return true;
70
71                         return base.CanConvertTo (context, destinationType);
72                 }
73
74                 public override object ConvertTo (ITypeDescriptorContext context,
75                         CultureInfo culture,
76                         object value,
77                         Type destinationType)
78                 {
79                         if ((destinationType == typeof (string)) && (value is Font)) {
80                                 Font font = (Font) value;
81                                 StringBuilder sb = new StringBuilder ();
82                                 sb.Append (font.Name).Append (culture.TextInfo.ListSeparator[0] + " ");
83                                 sb.Append (font.Size);
84
85                                 switch (font.Unit) {
86                                         // MS throws ArgumentException, if unit is set 
87                                         // to GraphicsUnit.Display
88                                         // Don't know what to append for GraphicsUnit.Display
89                                 case GraphicsUnit.Display:
90                                         sb.Append ("display"); break;
91
92                                 case GraphicsUnit.Document:
93                                         sb.Append ("doc"); break;
94
95                                 case GraphicsUnit.Point:
96                                         sb.Append ("pt"); break;
97
98                                 case GraphicsUnit.Inch:
99                                         sb.Append ("in"); break;
100
101                                 case GraphicsUnit.Millimeter:
102                                         sb.Append ("mm"); break;
103
104                                 case GraphicsUnit.Pixel:
105                                         sb.Append ("px"); break;
106
107                                 case GraphicsUnit.World:
108                                         sb.Append ("world"); break;
109                                 }
110
111                                 if (font.Style != FontStyle.Regular)
112                                         sb.Append (culture.TextInfo.ListSeparator[0] + " style=").Append (font.Style);
113
114                                 return sb.ToString ();
115                         }
116
117                         if ((destinationType == typeof (InstanceDescriptor)) && (value is Font)) {
118                                 Font font = (Font) value;
119                                 ConstructorInfo met = typeof(Font).GetConstructor (new Type[] {typeof(string), typeof(float), typeof(FontStyle), typeof(GraphicsUnit)});
120                                 object[] args = new object[4];
121                                 args [0] = font.Name;
122                                 args [1] = font.Size;
123                                 args [2] = font.Style;
124                                 args [3] = font.Unit;
125                                 return new InstanceDescriptor (met, args);
126                         }
127                         
128                         return base.ConvertTo (context, culture, value, destinationType);
129                 }
130
131                 public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
132                 {
133                         FontStyle       f_style;
134                         float           f_size;
135                         GraphicsUnit    f_unit;
136                         string          font;
137                         string          units;
138                         string[]        fields;
139
140                         if (! (value is string)) {
141                                 return base.ConvertFrom (context, culture, value);
142                         }
143
144                         font = (string)value;
145                         font.Trim();
146
147                         if (font.Length == 0) {
148                                 return null;
149                         }
150
151                         if (culture == null) {
152                                 culture = CultureInfo.CurrentCulture;
153                         }
154
155                         // Format is FontFamily, size[<units>[, style=1,2,3]]
156                         // This is a bit tricky since the comma can be used for styles and fields
157                         fields = font.Split(new char[] {culture.TextInfo.ListSeparator[0]});
158                         if (fields.Length < 1) {
159                                 throw new ArgumentException("Failed to parse font format");
160                         }
161
162                         font = fields[0];
163                         f_size = 8f;
164                         units = "px";
165                         f_unit = GraphicsUnit.Pixel;
166                         if (fields.Length > 1) {        // We have a size
167                                 for (int i = 0; i < fields[1].Length; i++) {
168                                         if (Char.IsLetter(fields[1][i])) {
169                                                 f_size = (float)TypeDescriptor.GetConverter(typeof(float)).ConvertFromString(context, culture, fields[1].Substring(0, i));
170                                                 units = fields[1].Substring(i);
171                                                 break;
172                                         }
173                                 }
174                                 if (units == "display") {
175                                         f_unit = GraphicsUnit.Display;
176                                 } else if (units == "doc") {
177                                         f_unit = GraphicsUnit.Document;
178                                 } else if (units == "pt") {
179                                         f_unit = GraphicsUnit.Point;
180                                 } else if (units == "in") {
181                                         f_unit = GraphicsUnit.Inch;
182                                 } else if (units == "mm") {
183                                         f_unit = GraphicsUnit.Millimeter;
184                                 } else if (units == "px") {
185                                         f_unit = GraphicsUnit.Pixel;
186                                 } else if (units == "world") {
187                                         f_unit = GraphicsUnit.World;
188                                 }
189                         }
190
191                         f_style = FontStyle.Regular;
192                         if (fields.Length > 2) {        // We have style
193                                 int             eq;
194                                 string[]        styles;
195                                 string          compare;
196
197                                 for (int i = 2; i < fields.Length; i++) {
198                                         compare = fields[i];
199
200                                         if (compare.IndexOf("Regular") != -1) {
201                                                 f_style |= FontStyle.Regular;
202                                         }
203                                         if (compare.IndexOf("Bold") != -1) {
204                                                 f_style |= FontStyle.Bold;
205                                         }
206                                         if (compare.IndexOf("Italic") != -1) {
207                                                 f_style |= FontStyle.Italic;
208                                         }
209                                         if (compare.IndexOf("Strikeout") != -1) {
210                                                 f_style |= FontStyle.Strikeout;
211                                         }
212                                         if (compare.IndexOf("Underline") != -1) {
213                                                 f_style |= FontStyle.Underline;
214                                         }
215                                 }
216                         }
217
218                         return new Font (font, f_size, f_style, f_unit);
219                 }
220
221                 public override object CreateInstance (ITypeDescriptorContext context, IDictionary propertyValues)
222                 {
223                         Object value;
224                         byte charSet = 1;
225                         float size = 8;
226                         String name = null;
227                         bool vertical = false;
228                         FontStyle style = FontStyle.Regular;
229                         FontFamily fontFamily = null;
230                         GraphicsUnit unit = GraphicsUnit.Point;
231
232                         if ((value = propertyValues ["GdiCharSet"]) != null)
233                                 charSet = (byte) value;
234
235                         if ((value = propertyValues ["Size"]) != null)
236                                 size = (float) value;
237
238                         if ((value = propertyValues ["Unit"]) != null)
239                                 unit = (GraphicsUnit) value;
240
241                         if ((value = propertyValues ["Name"]) != null)
242                                 name = (String) value;
243
244                         if ((value = propertyValues ["GdiVerticalFont"]) != null)
245                                 vertical = (bool) value;
246
247                         if ((value = propertyValues ["Bold"]) != null) {
248                                 bool bold = (bool) value;
249                                 if (bold == true)
250                                         style |= FontStyle.Bold;
251                         }
252
253                         if ((value = propertyValues ["Italic"]) != null) {
254                                 bool italic = (bool) value;
255                                 if (italic == true)
256                                         style |= FontStyle.Italic;
257                         }
258
259                         if ((value = propertyValues ["Strikeout"]) != null) {
260                                 bool strike = (bool) value;
261                                 if (strike == true)
262                                         style |= FontStyle.Strikeout;
263                         }
264
265                         if ((value = propertyValues ["Underline"]) != null) {
266                                 bool underline = (bool) value;
267                                 if (underline == true)
268                                         style |= FontStyle.Underline;
269                         }
270
271                         /* ?? Should default font be culture dependent ?? */
272                         if (name == null)
273                                 fontFamily = new FontFamily ("Tahoma");
274                         else {
275                                 name = name.ToLower ();
276                                 FontCollection collection = new InstalledFontCollection ();
277                                 FontFamily [] installedFontList = collection.Families;
278                                 foreach (FontFamily font in installedFontList) {
279                                         if (name == font.Name.ToLower ()) {
280                                                 fontFamily = font;
281                                                 break;
282                                         }
283                                 }
284
285                                 // font family not found in installed fonts
286                                 if (fontFamily == null) {
287                                         collection = new PrivateFontCollection ();
288                                         FontFamily [] privateFontList = collection.Families;
289                                         foreach (FontFamily font in privateFontList) {
290                                                 if (name == font.Name.ToLower ()) {
291                                                         fontFamily = font;
292                                                         break;
293                                                 }
294                                         }
295                                 }
296
297                                 // font family not found in private fonts also
298                                 if (fontFamily == null)
299                                         fontFamily = FontFamily.GenericSansSerif;
300                         }
301
302                         return new Font (fontFamily, size, style, unit, charSet, vertical);
303                 }
304
305                 public override bool GetCreateInstanceSupported (ITypeDescriptorContext context)
306                 {
307                         return true;
308                 }
309
310                 public override PropertyDescriptorCollection GetProperties
311                         (ITypeDescriptorContext context,
312                         object value, Attribute [] attributes)
313                 {
314                         if (value is Font)
315                                 return TypeDescriptor.GetProperties (value, attributes);
316
317                         return base.GetProperties (context, value, attributes);
318                 }
319
320                 public override bool GetPropertiesSupported (ITypeDescriptorContext context)
321                 {
322                         return true;
323                 }
324
325                 public sealed class FontNameConverter : TypeConverter
326 #if NET_2_0
327                 , IDisposable           
328 #endif
329                 {
330                         FontFamily [] fonts;
331                         
332                         public FontNameConverter ()
333                         {
334                                 fonts = FontFamily.Families;
335                         }       
336 #if NET_2_0                     
337                         void IDisposable.Dispose ()
338                         {
339                         }
340 #endif
341                         public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
342                         {
343                                 if (sourceType == typeof (string))
344                                         return true;
345
346                                 return base.CanConvertFrom (context, sourceType);
347                         }
348
349                         public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
350                         {
351                                 if (value is string)
352                                         return value;
353                                 return base.ConvertFrom (context, culture, value);
354                         }
355
356                         public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
357                         {
358                                 string [] values = new string [fonts.Length];
359                                 for (int i = fonts.Length; i > 0;){
360                                         i--;
361                                         values [i] = fonts [i].Name;
362                                 }
363                                 
364                                 return new TypeConverter.StandardValuesCollection (values);
365                         }
366
367                         public override bool GetStandardValuesExclusive (ITypeDescriptorContext context)
368                         {
369                                 // We allow other values other than those in the font list.
370                                 return false;
371                         }
372
373                         public override bool GetStandardValuesSupported (ITypeDescriptorContext context)
374                         {
375                                 // Yes, we support picking an element from the list. 
376                                 return true;
377                         }
378                 }
379
380                 public class FontUnitConverter : EnumConverter
381                 {
382                         public FontUnitConverter () : base (typeof (GraphicsUnit)) {}
383                         
384                         public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
385                         {
386                                 return base.GetStandardValues (context);
387                         }
388                                 
389                 }
390         }
391 }