575c0fe753e93b495544fca17d481f0b17195325
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms.Layout / TableLayoutSettingsTypeConverter.cs
1 // Permission is hereby granted, free of charge, to any person obtaining\r
2 // a copy of this software and associated documentation files (the\r
3 // "Software"), to deal in the Software without restriction, including\r
4 // without limitation the rights to use, copy, modify, merge, publish,\r
5 // distribute, sublicense, and/or sell copies of the Software, and to\r
6 // permit persons to whom the Software is furnished to do so, subject to\r
7 // the following conditions:\r
8 // \r
9 // The above copyright notice and this permission notice shall be\r
10 // included in all copies or substantial portions of the Software.\r
11 // \r
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
19 //\r
20 // Copyright (c) 2006 Novell, Inc.\r
21 //\r
22 \r
23 \r
24 using System;\r
25 using System.ComponentModel;\r
26 using System.Drawing;\r
27 using System.Globalization;\r
28 using System.Xml;\r
29 using System.IO;\r
30 using System.Collections.Generic;\r
31 \r
32 namespace System.Windows.Forms.Layout\r
33 {\r
34         public class TableLayoutSettingsTypeConverter : TypeConverter\r
35         {\r
36                 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)\r
37                 {\r
38                         if (destinationType == typeof (string))\r
39                                 return true;\r
40 \r
41                         return base.CanConvertTo (context, destinationType);\r
42                 }\r
43 \r
44                 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)\r
45                 {\r
46                         if (sourceType == typeof(string))\r
47                                 return true;\r
48 \r
49                         return base.CanConvertFrom (context, sourceType);\r
50                 }\r
51 \r
52                 \r
53 \r
54                 public override object ConvertTo (ITypeDescriptorContext context,\r
55                                                   CultureInfo culture,\r
56                                                   object value,\r
57                                                   Type destinationType)\r
58                 {\r
59                         if (!(value is TableLayoutSettings) || destinationType != typeof (string))\r
60                                 return base.ConvertTo (context, culture, value, destinationType);\r
61 \r
62                         TableLayoutSettings settings = value as TableLayoutSettings;\r
63                         StringWriter sw = new StringWriter ();\r
64                         XmlTextWriter xw = new XmlTextWriter (sw);\r
65                         xw.WriteStartDocument ();\r
66                         List<ControlInfo> list = settings.GetControls ();\r
67                         xw.WriteStartElement ("TableLayoutSettings");\r
68                         xw.WriteStartElement ("Controls");\r
69                         \r
70                         foreach (ControlInfo info in list) {\r
71                                 xw.WriteStartElement ("Control");\r
72                                 xw.WriteAttributeString ("Name", info.Control.ToString ());\r
73                                 xw.WriteAttributeString ("Row", info.Row.ToString ());\r
74                                 xw.WriteAttributeString ("RowSpan", info.RowSpan.ToString ());\r
75                                 xw.WriteAttributeString ("Column", info.Col.ToString ());\r
76                                 xw.WriteAttributeString ("ColumnSpan", info.ColSpan.ToString ());\r
77                                 xw.WriteEndElement ();\r
78                         }\r
79                         xw.WriteEndElement ();\r
80 \r
81 \r
82                         List<string> styles = new List<string> ();\r
83                         \r
84                         foreach (ColumnStyle style in settings.ColumnStyles) {\r
85                                 styles.Add (style.SizeType.ToString ());\r
86                                 styles.Add (style.Width.ToString (CultureInfo.InvariantCulture));\r
87                         }\r
88 \r
89                         \r
90                         xw.WriteStartElement ("Columns");\r
91                         xw.WriteAttributeString ("Styles", String.Join (",", styles.ToArray ()));\r
92                         xw.WriteEndElement ();\r
93                         \r
94                         styles.Clear();\r
95                         foreach (RowStyle style in settings.RowStyles) {\r
96                                 styles.Add (style.SizeType.ToString ());\r
97                                 styles.Add (style.Height.ToString (CultureInfo.InvariantCulture));\r
98                         }\r
99 \r
100                         xw.WriteStartElement ("Rows");\r
101                         xw.WriteAttributeString ("Styles", String.Join (",", styles.ToArray ()));\r
102                         xw.WriteEndElement ();\r
103 \r
104                         xw.WriteEndElement ();\r
105                         xw.WriteEndDocument ();\r
106                         xw.Close ();\r
107 \r
108                         return sw.ToString ();\r
109 \r
110                 }\r
111 \r
112                 public override object ConvertFrom (ITypeDescriptorContext context,\r
113                                                     CultureInfo culture,\r
114                                                     object value)\r
115                 {\r
116                         if (!(value is string))\r
117                                 return base.ConvertFrom(context, culture, value);\r
118 \r
119                         XmlDocument xmldoc = new XmlDocument();\r
120                         xmldoc.LoadXml (value as string);\r
121                         TableLayoutSettings settings = new TableLayoutSettings(new TableLayoutPanel());\r
122                         int count = ParseControl (xmldoc, settings);\r
123                         ParseColumnStyle (xmldoc, settings);\r
124                         ParseRowStyle (xmldoc, settings);\r
125                         settings.RowCount = count;\r
126                         \r
127 \r
128                         return settings;\r
129                 }\r
130 \r
131 \r
132                 private int ParseControl (XmlDocument xmldoc, TableLayoutSettings settings)\r
133                 {\r
134                         int count = 0;\r
135                         foreach (XmlNode node in xmldoc.GetElementsByTagName ("Control")) {\r
136                                 if (node.Attributes["Name"] == null || string.IsNullOrEmpty(node.Attributes["Name"].Value))\r
137                                         continue;\r
138                                 if (node.Attributes["Row"] != null) {\r
139                                         settings.SetRow (node.Attributes["Name"].Value, GetValue (node.Attributes["Row"].Value));\r
140                                         count++;\r
141                                 }\r
142                                 if (node.Attributes["RowSpan"] != null) {\r
143                                         settings.SetRowSpan (node.Attributes["Name"].Value, GetValue (node.Attributes["RowSpan"].Value));\r
144                                 }\r
145                                 if (node.Attributes["Column"] != null)\r
146                                         settings.SetColumn (node.Attributes["Name"].Value, GetValue (node.Attributes["Column"].Value));\r
147                                 if (node.Attributes["ColumnSpan"] != null)\r
148                                         settings.SetColumnSpan (node.Attributes["Name"].Value, GetValue (node.Attributes["ColumnSpan"].Value));\r
149                         }\r
150                         return count;\r
151                 }\r
152 \r
153                 private void ParseColumnStyle (XmlDocument xmldoc, TableLayoutSettings settings)\r
154                 {\r
155                         foreach (XmlNode node in xmldoc.GetElementsByTagName ("Columns")) {\r
156                                 if (node.Attributes["Styles"] == null)\r
157                                         continue;\r
158                                 string styles = node.Attributes["Styles"].Value;\r
159                                 if (string.IsNullOrEmpty (styles))\r
160                                         continue;\r
161                                 string[] list = BuggySplit (styles);\r
162                                 for (int i = 0; i < list.Length; i+=2) {\r
163                                         float width = 0f;\r
164                                         SizeType type = (SizeType) Enum.Parse (typeof (SizeType), list[i]);\r
165                                         float.TryParse (list[i+1], NumberStyles.Float, CultureInfo.InvariantCulture, out width);\r
166                                         settings.ColumnStyles.Add (new ColumnStyle (type, width));\r
167                                 }                               \r
168                         }\r
169                 }\r
170 \r
171                 private void ParseRowStyle (XmlDocument xmldoc, TableLayoutSettings settings)\r
172                 {\r
173                         foreach (XmlNode node in xmldoc.GetElementsByTagName ("Rows")) {\r
174                                 if (node.Attributes["Styles"] == null)\r
175                                         continue;\r
176                                 string styles = node.Attributes["Styles"].Value;\r
177                                 if (string.IsNullOrEmpty(styles))\r
178                                         continue;\r
179                                 string[] list = BuggySplit (styles);\r
180                                 for (int i = 0; i < list.Length; i += 2) {\r
181                                         float height = 0f;\r
182                                         SizeType type = (SizeType) Enum.Parse (typeof (SizeType), list[i]);\r
183                                         float.TryParse (list[i + 1], NumberStyles.Float, CultureInfo.InvariantCulture, out height);\r
184                                         settings.RowStyles.Add (new RowStyle (type, height));\r
185                                 }\r
186                         }\r
187                 }\r
188 \r
189                 private int GetValue (string attValue)\r
190                 {\r
191                         int val = -1;\r
192                         if (!string.IsNullOrEmpty (attValue)) {\r
193                                 int.TryParse (attValue, out val);\r
194                         }\r
195                         return val;\r
196                 }\r
197 \r
198                 // .Net accidently uses the local culture separator, so\r
199                 // Percent,50.0,Percent,50.0    can be\r
200                 // Percent,50,0,Percent,50,0\r
201                 // Make sure we can handle this\r
202                 private string[] BuggySplit (string s)\r
203                 {\r
204                         List<string> l = new List<string> ();\r
205                         \r
206                         string[] split = s.Split (',');\r
207                         \r
208                         for (int i = 0; i < split.Length; i++) {\r
209                                 switch (split[i].ToLowerInvariant ()) {\r
210                                         case "autosize":\r
211                                         case "absolute":\r
212                                         case "percent":\r
213                                                 l.Add (split[i]);\r
214                                                 break;\r
215                                         default:\r
216                                                 if (i + 1 < split.Length) {\r
217                                                         float test;\r
218                                                         \r
219                                                         if (float.TryParse (split[i + 1], out test)) {\r
220                                                                 l.Add (string.Format ("{0}.{1}", split[i], split[i + 1]));\r
221                                                                 i++;    \r
222                                                         } else\r
223                                                                 l.Add (split[i]);\r
224                                                 } else\r
225                                                         l.Add (split[i]);\r
226                                                 break;\r
227                                 }\r
228                         }\r
229                         \r
230                         return l.ToArray ();\r
231                 }\r
232         }\r
233 }\r