diff options
author | Rob Mensching <rob@firegiant.com> | 2019-05-08 14:13:31 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2019-05-08 14:44:43 -0700 |
commit | 75fd55d5a71c492c6ea904768858c51aa97da29f (patch) | |
tree | 610047db1d5759a726ce88277bb2dfddcd01da45 /src/WixToolset.Core/Compiler_UI.cs | |
parent | d1dbe29f3856d012acf5f96e8e66c43b74ab490d (diff) | |
download | wix-75fd55d5a71c492c6ea904768858c51aa97da29f.tar.gz wix-75fd55d5a71c492c6ea904768858c51aa97da29f.tar.bz2 wix-75fd55d5a71c492c6ea904768858c51aa97da29f.zip |
Use new strongly typed tuples
Diffstat (limited to 'src/WixToolset.Core/Compiler_UI.cs')
-rw-r--r-- | src/WixToolset.Core/Compiler_UI.cs | 1730 |
1 files changed, 1730 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Compiler_UI.cs b/src/WixToolset.Core/Compiler_UI.cs new file mode 100644 index 00000000..fddb9061 --- /dev/null +++ b/src/WixToolset.Core/Compiler_UI.cs | |||
@@ -0,0 +1,1730 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections; | ||
7 | using System.Xml.Linq; | ||
8 | using WixToolset.Data; | ||
9 | using WixToolset.Data.Tuples; | ||
10 | using WixToolset.Data.WindowsInstaller; | ||
11 | using WixToolset.Extensibility; | ||
12 | |||
13 | /// <summary> | ||
14 | /// Compiler of the WiX toolset. | ||
15 | /// </summary> | ||
16 | internal partial class Compiler : ICompiler | ||
17 | { | ||
18 | // NameToBit arrays | ||
19 | private static readonly string[] TextControlAttributes = { "Transparent", "NoPrefix", "NoWrap", "FormatSize", "UserLanguage" }; | ||
20 | private static readonly string[] HyperlinkControlAttributes = { "Transparent" }; | ||
21 | private static readonly string[] EditControlAttributes = { "Multiline", null, null, null, null, "Password" }; | ||
22 | private static readonly string[] ProgressControlAttributes = { "ProgressBlocks" }; | ||
23 | private static readonly string[] VolumeControlAttributes = { "Removable", "Fixed", "Remote", "CDROM", "RAMDisk", "Floppy", "ShowRollbackCost" }; | ||
24 | private static readonly string[] ListboxControlAttributes = { "Sorted", null, null, null, "UserLanguage" }; | ||
25 | private static readonly string[] ListviewControlAttributes = { "Sorted", null, null, null, "FixedSize", "Icon16", "Icon32" }; | ||
26 | private static readonly string[] ComboboxControlAttributes = { "Sorted", "ComboList", null, null, "UserLanguage" }; | ||
27 | private static readonly string[] RadioControlAttributes = { "Image", "PushLike", "Bitmap", "Icon", "FixedSize", "Icon16", "Icon32", null, "HasBorder" }; | ||
28 | private static readonly string[] ButtonControlAttributes = { "Image", null, "Bitmap", "Icon", "FixedSize", "Icon16", "Icon32", "ElevationShield" }; | ||
29 | private static readonly string[] IconControlAttributes = { "Image", null, null, null, "FixedSize", "Icon16", "Icon32" }; | ||
30 | private static readonly string[] BitmapControlAttributes = { "Image", null, null, null, "FixedSize" }; | ||
31 | private static readonly string[] CheckboxControlAttributes = { null, "PushLike", "Bitmap", "Icon", "FixedSize", "Icon16", "Icon32" }; | ||
32 | |||
33 | /// <summary> | ||
34 | /// Parses UI elements. | ||
35 | /// </summary> | ||
36 | /// <param name="node">Element to parse.</param> | ||
37 | private void ParseUIElement(XElement node) | ||
38 | { | ||
39 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
40 | Identifier id = null; | ||
41 | var embeddedUICount = 0; | ||
42 | |||
43 | foreach (var attrib in node.Attributes()) | ||
44 | { | ||
45 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
46 | { | ||
47 | switch (attrib.Name.LocalName) | ||
48 | { | ||
49 | case "Id": | ||
50 | id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
51 | break; | ||
52 | default: | ||
53 | this.Core.UnexpectedAttribute(node, attrib); | ||
54 | break; | ||
55 | } | ||
56 | } | ||
57 | else | ||
58 | { | ||
59 | this.Core.ParseExtensionAttribute(node, attrib); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | foreach (var child in node.Elements()) | ||
64 | { | ||
65 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
66 | { | ||
67 | switch (child.Name.LocalName) | ||
68 | { | ||
69 | case "BillboardAction": | ||
70 | this.ParseBillboardActionElement(child); | ||
71 | break; | ||
72 | case "ComboBox": | ||
73 | this.ParseControlGroupElement(child, TupleDefinitionType.ComboBox, "ListItem"); | ||
74 | break; | ||
75 | case "Dialog": | ||
76 | this.ParseDialogElement(child); | ||
77 | break; | ||
78 | case "DialogRef": | ||
79 | this.ParseSimpleRefElement(child, "Dialog"); | ||
80 | break; | ||
81 | case "EmbeddedUI": | ||
82 | if (0 < embeddedUICount) // there can be only one embedded UI | ||
83 | { | ||
84 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
85 | this.Core.Write(ErrorMessages.TooManyChildren(childSourceLineNumbers, node.Name.LocalName, child.Name.LocalName)); | ||
86 | } | ||
87 | this.ParseEmbeddedUIElement(child); | ||
88 | ++embeddedUICount; | ||
89 | break; | ||
90 | case "Error": | ||
91 | this.ParseErrorElement(child); | ||
92 | break; | ||
93 | case "ListBox": | ||
94 | this.ParseControlGroupElement(child, TupleDefinitionType.ListBox, "ListItem"); | ||
95 | break; | ||
96 | case "ListView": | ||
97 | this.ParseControlGroupElement(child, TupleDefinitionType.ListView, "ListItem"); | ||
98 | break; | ||
99 | case "ProgressText": | ||
100 | this.ParseActionTextElement(child); | ||
101 | break; | ||
102 | case "Publish": | ||
103 | var order = 0; | ||
104 | this.ParsePublishElement(child, null, null, ref order); | ||
105 | break; | ||
106 | case "RadioButtonGroup": | ||
107 | var radioButtonType = this.ParseRadioButtonGroupElement(child, null, RadioButtonType.NotSet); | ||
108 | if (RadioButtonType.Bitmap == radioButtonType || RadioButtonType.Icon == radioButtonType) | ||
109 | { | ||
110 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
111 | this.Core.Write(ErrorMessages.RadioButtonBitmapAndIconDisallowed(childSourceLineNumbers)); | ||
112 | } | ||
113 | break; | ||
114 | case "TextStyle": | ||
115 | this.ParseTextStyleElement(child); | ||
116 | break; | ||
117 | case "UIText": | ||
118 | this.ParseUITextElement(child); | ||
119 | break; | ||
120 | |||
121 | // the following are available indentically under the UI and Product elements for document organization use only | ||
122 | case "AdminUISequence": | ||
123 | case "InstallUISequence": | ||
124 | this.ParseSequenceElement(child, child.Name.LocalName); | ||
125 | break; | ||
126 | case "Binary": | ||
127 | this.ParseBinaryElement(child); | ||
128 | break; | ||
129 | case "Property": | ||
130 | this.ParsePropertyElement(child); | ||
131 | break; | ||
132 | case "PropertyRef": | ||
133 | this.ParseSimpleRefElement(child, "Property"); | ||
134 | break; | ||
135 | case "UIRef": | ||
136 | this.ParseSimpleRefElement(child, "WixUI"); | ||
137 | break; | ||
138 | |||
139 | default: | ||
140 | this.Core.UnexpectedElement(node, child); | ||
141 | break; | ||
142 | } | ||
143 | } | ||
144 | else | ||
145 | { | ||
146 | this.Core.ParseExtensionElement(node, child); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | if (null != id && !this.Core.EncounteredError) | ||
151 | { | ||
152 | this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixUI, id); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /// <summary> | ||
157 | /// Parses a list item element. | ||
158 | /// </summary> | ||
159 | /// <param name="node">Element to parse.</param> | ||
160 | /// <param name="table">Table to add row to.</param> | ||
161 | /// <param name="property">Identifier of property referred to by list item.</param> | ||
162 | /// <param name="order">Relative order of list items.</param> | ||
163 | private void ParseListItemElement(XElement node, TupleDefinitionType tableName, string property, ref int order) | ||
164 | { | ||
165 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
166 | string icon = null; | ||
167 | string text = null; | ||
168 | string value = null; | ||
169 | |||
170 | foreach (var attrib in node.Attributes()) | ||
171 | { | ||
172 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
173 | { | ||
174 | switch (attrib.Name.LocalName) | ||
175 | { | ||
176 | case "Icon": | ||
177 | if (TupleDefinitionType.ListView == tableName) | ||
178 | { | ||
179 | icon = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
180 | this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", icon); | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | this.Core.Write(ErrorMessages.IllegalAttributeExceptOnElement(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ListView")); | ||
185 | } | ||
186 | break; | ||
187 | case "Text": | ||
188 | text = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
189 | break; | ||
190 | case "Value": | ||
191 | value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
192 | break; | ||
193 | default: | ||
194 | this.Core.UnexpectedAttribute(node, attrib); | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | else | ||
199 | { | ||
200 | this.Core.ParseExtensionAttribute(node, attrib); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | if (null == value) | ||
205 | { | ||
206 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value")); | ||
207 | } | ||
208 | |||
209 | this.Core.ParseForExtensionElements(node); | ||
210 | |||
211 | if (!this.Core.EncounteredError) | ||
212 | { | ||
213 | var row = this.Core.CreateRow(sourceLineNumbers, tableName); | ||
214 | row.Set(0, property); | ||
215 | row.Set(1, ++order); | ||
216 | row.Set(2, value); | ||
217 | row.Set(3, text); | ||
218 | if (null != icon) | ||
219 | { | ||
220 | row.Set(4, icon); | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /// <summary> | ||
226 | /// Parses a radio button element. | ||
227 | /// </summary> | ||
228 | /// <param name="node">Element to parse.</param> | ||
229 | /// <param name="property">Identifier of property referred to by radio button.</param> | ||
230 | /// <param name="order">Relative order of radio buttons.</param> | ||
231 | /// <returns>Type of this radio button.</returns> | ||
232 | private RadioButtonType ParseRadioButtonElement(XElement node, string property, ref int order) | ||
233 | { | ||
234 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
235 | var type = RadioButtonType.NotSet; | ||
236 | string value = null; | ||
237 | string x = null; | ||
238 | string y = null; | ||
239 | string width = null; | ||
240 | string height = null; | ||
241 | string text = null; | ||
242 | string tooltip = null; | ||
243 | string help = null; | ||
244 | |||
245 | foreach (var attrib in node.Attributes()) | ||
246 | { | ||
247 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
248 | { | ||
249 | switch (attrib.Name.LocalName) | ||
250 | { | ||
251 | case "Bitmap": | ||
252 | if (RadioButtonType.NotSet != type) | ||
253 | { | ||
254 | this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Icon", "Text")); | ||
255 | } | ||
256 | text = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
257 | this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", text); | ||
258 | type = RadioButtonType.Bitmap; | ||
259 | break; | ||
260 | case "Height": | ||
261 | height = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
262 | break; | ||
263 | case "Help": | ||
264 | help = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
265 | break; | ||
266 | case "Icon": | ||
267 | if (RadioButtonType.NotSet != type) | ||
268 | { | ||
269 | this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Bitmap", "Text")); | ||
270 | } | ||
271 | text = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
272 | this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", text); | ||
273 | type = RadioButtonType.Icon; | ||
274 | break; | ||
275 | case "Text": | ||
276 | if (RadioButtonType.NotSet != type) | ||
277 | { | ||
278 | this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Bitmap", "Icon")); | ||
279 | } | ||
280 | text = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
281 | type = RadioButtonType.Text; | ||
282 | break; | ||
283 | case "ToolTip": | ||
284 | tooltip = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
285 | break; | ||
286 | case "Value": | ||
287 | value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
288 | break; | ||
289 | case "Width": | ||
290 | width = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
291 | break; | ||
292 | case "X": | ||
293 | x = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
294 | break; | ||
295 | case "Y": | ||
296 | y = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
297 | break; | ||
298 | default: | ||
299 | this.Core.UnexpectedAttribute(node, attrib); | ||
300 | break; | ||
301 | } | ||
302 | } | ||
303 | else | ||
304 | { | ||
305 | this.Core.ParseExtensionAttribute(node, attrib); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | if (null == value) | ||
310 | { | ||
311 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value")); | ||
312 | } | ||
313 | |||
314 | if (null == x) | ||
315 | { | ||
316 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "X")); | ||
317 | } | ||
318 | |||
319 | if (null == y) | ||
320 | { | ||
321 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Y")); | ||
322 | } | ||
323 | |||
324 | if (null == width) | ||
325 | { | ||
326 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Width")); | ||
327 | } | ||
328 | |||
329 | if (null == height) | ||
330 | { | ||
331 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Height")); | ||
332 | } | ||
333 | |||
334 | this.Core.ParseForExtensionElements(node); | ||
335 | |||
336 | if (!this.Core.EncounteredError) | ||
337 | { | ||
338 | var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RadioButton); | ||
339 | row.Set(0, property); | ||
340 | row.Set(1, ++order); | ||
341 | row.Set(2, value); | ||
342 | row.Set(3, x); | ||
343 | row.Set(4, y); | ||
344 | row.Set(5, width); | ||
345 | row.Set(6, height); | ||
346 | row.Set(7, text); | ||
347 | if (null != tooltip || null != help) | ||
348 | { | ||
349 | row.Set(8, String.Concat(tooltip, "|", help)); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | return type; | ||
354 | } | ||
355 | |||
356 | /// <summary> | ||
357 | /// Parses a billboard element. | ||
358 | /// </summary> | ||
359 | /// <param name="node">Element to parse.</param> | ||
360 | private void ParseBillboardActionElement(XElement node) | ||
361 | { | ||
362 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
363 | string action = null; | ||
364 | var order = 0; | ||
365 | |||
366 | foreach (var attrib in node.Attributes()) | ||
367 | { | ||
368 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
369 | { | ||
370 | switch (attrib.Name.LocalName) | ||
371 | { | ||
372 | case "Id": | ||
373 | action = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
374 | this.Core.CreateSimpleReference(sourceLineNumbers, "WixAction", "InstallExecuteSequence", action); | ||
375 | break; | ||
376 | default: | ||
377 | this.Core.UnexpectedAttribute(node, attrib); | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | else | ||
382 | { | ||
383 | this.Core.ParseExtensionAttribute(node, attrib); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | if (null == action) | ||
388 | { | ||
389 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
390 | } | ||
391 | |||
392 | foreach (var child in node.Elements()) | ||
393 | { | ||
394 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
395 | { | ||
396 | switch (child.Name.LocalName) | ||
397 | { | ||
398 | case "Billboard": | ||
399 | order = order + 1; | ||
400 | this.ParseBillboardElement(child, action, order); | ||
401 | break; | ||
402 | default: | ||
403 | this.Core.UnexpectedElement(node, child); | ||
404 | break; | ||
405 | } | ||
406 | } | ||
407 | else | ||
408 | { | ||
409 | this.Core.ParseExtensionElement(node, child); | ||
410 | } | ||
411 | } | ||
412 | } | ||
413 | |||
414 | /// <summary> | ||
415 | /// Parses a billboard element. | ||
416 | /// </summary> | ||
417 | /// <param name="node">Element to parse.</param> | ||
418 | /// <param name="action">Action for the billboard.</param> | ||
419 | /// <param name="order">Order of the billboard.</param> | ||
420 | private void ParseBillboardElement(XElement node, string action, int order) | ||
421 | { | ||
422 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
423 | Identifier id = null; | ||
424 | string feature = null; | ||
425 | |||
426 | foreach (var attrib in node.Attributes()) | ||
427 | { | ||
428 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
429 | { | ||
430 | switch (attrib.Name.LocalName) | ||
431 | { | ||
432 | case "Id": | ||
433 | id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
434 | break; | ||
435 | case "Feature": | ||
436 | feature = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
437 | this.Core.CreateSimpleReference(sourceLineNumbers, "Feature", feature); | ||
438 | break; | ||
439 | default: | ||
440 | this.Core.UnexpectedAttribute(node, attrib); | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | else | ||
445 | { | ||
446 | this.Core.ParseExtensionAttribute(node, attrib); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | if (null == id) | ||
451 | { | ||
452 | id = this.Core.CreateIdentifier("bil", action, order.ToString(), feature); | ||
453 | } | ||
454 | |||
455 | foreach (var child in node.Elements()) | ||
456 | { | ||
457 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
458 | { | ||
459 | switch (child.Name.LocalName) | ||
460 | { | ||
461 | case "Control": | ||
462 | // These are all thrown away. | ||
463 | IntermediateTuple lastTabRow = null; | ||
464 | string firstControl = null; | ||
465 | string defaultControl = null; | ||
466 | string cancelControl = null; | ||
467 | |||
468 | this.ParseControlElement(child, id.Id, TupleDefinitionType.BBControl, ref lastTabRow, ref firstControl, ref defaultControl, ref cancelControl, false); | ||
469 | break; | ||
470 | default: | ||
471 | this.Core.UnexpectedElement(node, child); | ||
472 | break; | ||
473 | } | ||
474 | } | ||
475 | else | ||
476 | { | ||
477 | this.Core.ParseExtensionElement(node, child); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | |||
482 | if (!this.Core.EncounteredError) | ||
483 | { | ||
484 | var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Billboard, id); | ||
485 | row.Set(1, feature); | ||
486 | row.Set(2, action); | ||
487 | row.Set(3, order); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /// <summary> | ||
492 | /// Parses a control group element. | ||
493 | /// </summary> | ||
494 | /// <param name="node">Element to parse.</param> | ||
495 | /// <param name="table">Table referred to by control group.</param> | ||
496 | /// <param name="childTag">Expected child elements.</param> | ||
497 | private void ParseControlGroupElement(XElement node, TupleDefinitionType tableName, string childTag) | ||
498 | { | ||
499 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
500 | var order = 0; | ||
501 | string property = null; | ||
502 | |||
503 | foreach (var attrib in node.Attributes()) | ||
504 | { | ||
505 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
506 | { | ||
507 | switch (attrib.Name.LocalName) | ||
508 | { | ||
509 | case "Property": | ||
510 | property = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
511 | break; | ||
512 | default: | ||
513 | this.Core.UnexpectedAttribute(node, attrib); | ||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | this.Core.ParseExtensionAttribute(node, attrib); | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if (null == property) | ||
524 | { | ||
525 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property")); | ||
526 | } | ||
527 | |||
528 | foreach (var child in node.Elements()) | ||
529 | { | ||
530 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
531 | { | ||
532 | if (childTag != child.Name.LocalName) | ||
533 | { | ||
534 | this.Core.UnexpectedElement(node, child); | ||
535 | } | ||
536 | |||
537 | switch (child.Name.LocalName) | ||
538 | { | ||
539 | case "ListItem": | ||
540 | this.ParseListItemElement(child, tableName, property, ref order); | ||
541 | break; | ||
542 | case "Property": | ||
543 | this.ParsePropertyElement(child); | ||
544 | break; | ||
545 | default: | ||
546 | this.Core.UnexpectedElement(node, child); | ||
547 | break; | ||
548 | } | ||
549 | } | ||
550 | else | ||
551 | { | ||
552 | this.Core.ParseExtensionElement(node, child); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | } | ||
557 | |||
558 | /// <summary> | ||
559 | /// Parses a radio button control group element. | ||
560 | /// </summary> | ||
561 | /// <param name="node">Element to parse.</param> | ||
562 | /// <param name="property">Property associated with this radio button group.</param> | ||
563 | /// <param name="groupType">Specifies the current type of radio buttons in the group.</param> | ||
564 | /// <returns>The current type of radio buttons in the group.</returns> | ||
565 | private RadioButtonType ParseRadioButtonGroupElement(XElement node, string property, RadioButtonType groupType) | ||
566 | { | ||
567 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
568 | var order = 0; | ||
569 | |||
570 | foreach (var attrib in node.Attributes()) | ||
571 | { | ||
572 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
573 | { | ||
574 | switch (attrib.Name.LocalName) | ||
575 | { | ||
576 | case "Property": | ||
577 | property = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
578 | this.Core.CreateSimpleReference(sourceLineNumbers, "Property", property); | ||
579 | break; | ||
580 | default: | ||
581 | this.Core.UnexpectedAttribute(node, attrib); | ||
582 | break; | ||
583 | } | ||
584 | } | ||
585 | else | ||
586 | { | ||
587 | this.Core.ParseExtensionAttribute(node, attrib); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | if (null == property) | ||
592 | { | ||
593 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property")); | ||
594 | } | ||
595 | |||
596 | foreach (var child in node.Elements()) | ||
597 | { | ||
598 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
599 | { | ||
600 | switch (child.Name.LocalName) | ||
601 | { | ||
602 | case "RadioButton": | ||
603 | var type = this.ParseRadioButtonElement(child, property, ref order); | ||
604 | if (RadioButtonType.NotSet == groupType) | ||
605 | { | ||
606 | groupType = type; | ||
607 | } | ||
608 | else if (groupType != type) | ||
609 | { | ||
610 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
611 | this.Core.Write(ErrorMessages.RadioButtonTypeInconsistent(childSourceLineNumbers)); | ||
612 | } | ||
613 | break; | ||
614 | default: | ||
615 | this.Core.UnexpectedElement(node, child); | ||
616 | break; | ||
617 | } | ||
618 | } | ||
619 | else | ||
620 | { | ||
621 | this.Core.ParseExtensionElement(node, child); | ||
622 | } | ||
623 | } | ||
624 | |||
625 | |||
626 | return groupType; | ||
627 | } | ||
628 | |||
629 | /// <summary> | ||
630 | /// Parses an action text element. | ||
631 | /// </summary> | ||
632 | /// <param name="node">Element to parse.</param> | ||
633 | private void ParseActionTextElement(XElement node) | ||
634 | { | ||
635 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
636 | string action = null; | ||
637 | string template = null; | ||
638 | |||
639 | foreach (var attrib in node.Attributes()) | ||
640 | { | ||
641 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
642 | { | ||
643 | switch (attrib.Name.LocalName) | ||
644 | { | ||
645 | case "Action": | ||
646 | action = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
647 | break; | ||
648 | case "Template": | ||
649 | template = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
650 | break; | ||
651 | default: | ||
652 | this.Core.UnexpectedAttribute(node, attrib); | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | else | ||
657 | { | ||
658 | this.Core.ParseExtensionAttribute(node, attrib); | ||
659 | } | ||
660 | } | ||
661 | |||
662 | if (null == action) | ||
663 | { | ||
664 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Action")); | ||
665 | } | ||
666 | |||
667 | this.Core.ParseForExtensionElements(node); | ||
668 | |||
669 | if (!this.Core.EncounteredError) | ||
670 | { | ||
671 | var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ActionText); | ||
672 | row.Set(0, action); | ||
673 | row.Set(1, Common.GetInnerText(node)); | ||
674 | row.Set(2, template); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | /// <summary> | ||
679 | /// Parses an ui text element. | ||
680 | /// </summary> | ||
681 | /// <param name="node">Element to parse.</param> | ||
682 | private void ParseUITextElement(XElement node) | ||
683 | { | ||
684 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
685 | Identifier id = null; | ||
686 | string text = null; | ||
687 | |||
688 | foreach (var attrib in node.Attributes()) | ||
689 | { | ||
690 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
691 | { | ||
692 | switch (attrib.Name.LocalName) | ||
693 | { | ||
694 | case "Id": | ||
695 | id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
696 | break; | ||
697 | default: | ||
698 | this.Core.UnexpectedAttribute(node, attrib); | ||
699 | break; | ||
700 | } | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | this.Core.ParseExtensionAttribute(node, attrib); | ||
705 | } | ||
706 | } | ||
707 | |||
708 | text = Common.GetInnerText(node); | ||
709 | |||
710 | if (null == id) | ||
711 | { | ||
712 | id = this.Core.CreateIdentifier("txt", text); | ||
713 | } | ||
714 | |||
715 | this.Core.ParseForExtensionElements(node); | ||
716 | |||
717 | if (!this.Core.EncounteredError) | ||
718 | { | ||
719 | var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UIText, id); | ||
720 | row.Set(1, text); | ||
721 | } | ||
722 | } | ||
723 | |||
724 | /// <summary> | ||
725 | /// Parses a text style element. | ||
726 | /// </summary> | ||
727 | /// <param name="node">Element to parse.</param> | ||
728 | private void ParseTextStyleElement(XElement node) | ||
729 | { | ||
730 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
731 | Identifier id = null; | ||
732 | var color = CompilerConstants.IntegerNotSet; | ||
733 | var bold = false; | ||
734 | var italic = false; | ||
735 | var strike = false; | ||
736 | var underline = false; | ||
737 | string faceName = null; | ||
738 | var size = "0"; | ||
739 | |||
740 | foreach (var attrib in node.Attributes()) | ||
741 | { | ||
742 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
743 | { | ||
744 | switch (attrib.Name.LocalName) | ||
745 | { | ||
746 | case "Id": | ||
747 | id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
748 | break; | ||
749 | |||
750 | // RGB Values | ||
751 | case "Red": | ||
752 | var redColor = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Byte.MaxValue); | ||
753 | if (CompilerConstants.IllegalInteger != redColor) | ||
754 | { | ||
755 | if (CompilerConstants.IntegerNotSet == color) | ||
756 | { | ||
757 | color = redColor; | ||
758 | } | ||
759 | else | ||
760 | { | ||
761 | color += redColor; | ||
762 | } | ||
763 | } | ||
764 | break; | ||
765 | case "Green": | ||
766 | var greenColor = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Byte.MaxValue); | ||
767 | if (CompilerConstants.IllegalInteger != greenColor) | ||
768 | { | ||
769 | if (CompilerConstants.IntegerNotSet == color) | ||
770 | { | ||
771 | color = greenColor * 256; | ||
772 | } | ||
773 | else | ||
774 | { | ||
775 | color += greenColor * 256; | ||
776 | } | ||
777 | } | ||
778 | break; | ||
779 | case "Blue": | ||
780 | var blueColor = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Byte.MaxValue); | ||
781 | if (CompilerConstants.IllegalInteger != blueColor) | ||
782 | { | ||
783 | if (CompilerConstants.IntegerNotSet == color) | ||
784 | { | ||
785 | color = blueColor * 65536; | ||
786 | } | ||
787 | else | ||
788 | { | ||
789 | color += blueColor * 65536; | ||
790 | } | ||
791 | } | ||
792 | break; | ||
793 | |||
794 | // Style values | ||
795 | case "Bold": | ||
796 | bold = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
797 | break; | ||
798 | case "Italic": | ||
799 | italic = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
800 | break; | ||
801 | case "Strike": | ||
802 | strike = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
803 | break; | ||
804 | case "Underline": | ||
805 | underline = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
806 | break; | ||
807 | |||
808 | // Font values | ||
809 | case "FaceName": | ||
810 | faceName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
811 | break; | ||
812 | case "Size": | ||
813 | size = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
814 | break; | ||
815 | |||
816 | default: | ||
817 | this.Core.UnexpectedAttribute(node, attrib); | ||
818 | break; | ||
819 | } | ||
820 | } | ||
821 | else | ||
822 | { | ||
823 | this.Core.ParseExtensionAttribute(node, attrib); | ||
824 | } | ||
825 | } | ||
826 | |||
827 | if (null == id) | ||
828 | { | ||
829 | this.Core.CreateIdentifier("txs", faceName, size.ToString(), color.ToString(), bold.ToString(), italic.ToString(), strike.ToString(), underline.ToString()); | ||
830 | } | ||
831 | |||
832 | if (null == faceName) | ||
833 | { | ||
834 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "FaceName")); | ||
835 | } | ||
836 | |||
837 | this.Core.ParseForExtensionElements(node); | ||
838 | |||
839 | if (!this.Core.EncounteredError) | ||
840 | { | ||
841 | var tuple = new TextStyleTuple(sourceLineNumbers, id) | ||
842 | { | ||
843 | FaceName = faceName, | ||
844 | Color = color, | ||
845 | Bold = bold, | ||
846 | Italic = italic, | ||
847 | Strike = strike, | ||
848 | Underline = underline, | ||
849 | }; | ||
850 | |||
851 | tuple.Set((int)TextStyleTupleFields.Size, size); | ||
852 | |||
853 | this.Core.AddTuple(tuple); | ||
854 | } | ||
855 | } | ||
856 | |||
857 | /// <summary> | ||
858 | /// Parses a dialog element. | ||
859 | /// </summary> | ||
860 | /// <param name="node">Element to parse.</param> | ||
861 | private void ParseDialogElement(XElement node) | ||
862 | { | ||
863 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
864 | Identifier id = null; | ||
865 | var hidden = false; | ||
866 | var modal = true; | ||
867 | var minimize = true; | ||
868 | var customPalette = false; | ||
869 | var errorDialog = false; | ||
870 | var keepModeless = false; | ||
871 | var height = 0; | ||
872 | string title = null; | ||
873 | var leftScroll = false; | ||
874 | var rightAligned = false; | ||
875 | var rightToLeft = false; | ||
876 | var systemModal = false; | ||
877 | var trackDiskSpace = false; | ||
878 | var width = 0; | ||
879 | var x = 50; | ||
880 | var y = 50; | ||
881 | |||
882 | foreach (var attrib in node.Attributes()) | ||
883 | { | ||
884 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
885 | { | ||
886 | switch (attrib.Name.LocalName) | ||
887 | { | ||
888 | case "Id": | ||
889 | id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
890 | break; | ||
891 | case "Height": | ||
892 | height = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
893 | break; | ||
894 | case "Title": | ||
895 | title = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
896 | break; | ||
897 | case "Width": | ||
898 | width = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
899 | break; | ||
900 | case "X": | ||
901 | x = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100); | ||
902 | break; | ||
903 | case "Y": | ||
904 | y = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100); | ||
905 | break; | ||
906 | case "CustomPalette": | ||
907 | customPalette = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
908 | break; | ||
909 | case "ErrorDialog": | ||
910 | errorDialog = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
911 | break; | ||
912 | case "Hidden": | ||
913 | hidden = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
914 | break; | ||
915 | case "KeepModeless": | ||
916 | keepModeless = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
917 | break; | ||
918 | case "LeftScroll": | ||
919 | leftScroll = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
920 | break; | ||
921 | case "Modeless": | ||
922 | modal = YesNoType.Yes != this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
923 | break; | ||
924 | case "NoMinimize": | ||
925 | minimize = YesNoType.Yes != this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
926 | break; | ||
927 | case "RightAligned": | ||
928 | rightAligned = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
929 | break; | ||
930 | case "RightToLeft": | ||
931 | rightToLeft = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
932 | break; | ||
933 | case "SystemModal": | ||
934 | systemModal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
935 | break; | ||
936 | case "TrackDiskSpace": | ||
937 | trackDiskSpace = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
938 | break; | ||
939 | |||
940 | default: | ||
941 | this.Core.UnexpectedAttribute(node, attrib); | ||
942 | break; | ||
943 | } | ||
944 | } | ||
945 | else | ||
946 | { | ||
947 | this.Core.ParseExtensionAttribute(node, attrib); | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if (null == id) | ||
952 | { | ||
953 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
954 | id = Identifier.Invalid; | ||
955 | } | ||
956 | |||
957 | IntermediateTuple lastTabRow = null; | ||
958 | string cancelControl = null; | ||
959 | string defaultControl = null; | ||
960 | string firstControl = null; | ||
961 | |||
962 | foreach (var child in node.Elements()) | ||
963 | { | ||
964 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
965 | { | ||
966 | switch (child.Name.LocalName) | ||
967 | { | ||
968 | case "Control": | ||
969 | this.ParseControlElement(child, id.Id, TupleDefinitionType.Control, ref lastTabRow, ref firstControl, ref defaultControl, ref cancelControl, trackDiskSpace); | ||
970 | break; | ||
971 | default: | ||
972 | this.Core.UnexpectedElement(node, child); | ||
973 | break; | ||
974 | } | ||
975 | } | ||
976 | else | ||
977 | { | ||
978 | this.Core.ParseExtensionElement(node, child); | ||
979 | } | ||
980 | } | ||
981 | |||
982 | if (null != lastTabRow && null != lastTabRow[1]) | ||
983 | { | ||
984 | if (firstControl != lastTabRow[1].ToString()) | ||
985 | { | ||
986 | lastTabRow.Set(10, firstControl); | ||
987 | } | ||
988 | } | ||
989 | |||
990 | if (null == firstControl) | ||
991 | { | ||
992 | this.Core.Write(ErrorMessages.NoFirstControlSpecified(sourceLineNumbers, id.Id)); | ||
993 | } | ||
994 | |||
995 | if (!this.Core.EncounteredError) | ||
996 | { | ||
997 | var tuple = new DialogTuple(sourceLineNumbers, id) | ||
998 | { | ||
999 | HCentering = x, | ||
1000 | VCentering = y, | ||
1001 | Width = width, | ||
1002 | Height = height, | ||
1003 | CustomPalette = customPalette, | ||
1004 | ErrorDialog = errorDialog, | ||
1005 | Visible = !hidden, | ||
1006 | Modal = modal, | ||
1007 | KeepModeless = keepModeless, | ||
1008 | LeftScroll = leftScroll, | ||
1009 | Minimize = minimize, | ||
1010 | RightAligned = rightAligned, | ||
1011 | RightToLeft = rightToLeft, | ||
1012 | SystemModal = systemModal, | ||
1013 | TrackDiskSpace = trackDiskSpace, | ||
1014 | Title = title, | ||
1015 | Control_First = firstControl, | ||
1016 | Control_Default = defaultControl, | ||
1017 | Control_Cancel = cancelControl, | ||
1018 | }; | ||
1019 | |||
1020 | this.Core.AddTuple(tuple); | ||
1021 | } | ||
1022 | } | ||
1023 | |||
1024 | /// <summary> | ||
1025 | /// Parses a control element. | ||
1026 | /// </summary> | ||
1027 | /// <param name="node">Element to parse.</param> | ||
1028 | /// <param name="dialog">Identifier for parent dialog.</param> | ||
1029 | /// <param name="table">Table control belongs in.</param> | ||
1030 | /// <param name="lastTabTuple">Last row in the tab order.</param> | ||
1031 | /// <param name="firstControl">Name of the first control in the tab order.</param> | ||
1032 | /// <param name="defaultControl">Name of the default control.</param> | ||
1033 | /// <param name="cancelControl">Name of the candle control.</param> | ||
1034 | /// <param name="trackDiskSpace">True if the containing dialog tracks disk space.</param> | ||
1035 | private void ParseControlElement(XElement node, string dialog, TupleDefinitionType tupleType, ref IntermediateTuple lastTabTuple, ref string firstControl, ref string defaultControl, ref string cancelControl, bool trackDiskSpace) | ||
1036 | { | ||
1037 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1038 | Identifier controlId = null; | ||
1039 | var bits = new BitArray(32); | ||
1040 | string checkBoxPropertyRef = null; | ||
1041 | string checkboxValue = null; | ||
1042 | string controlType = null; | ||
1043 | var disabled = false; | ||
1044 | string height = null; | ||
1045 | string help = null; | ||
1046 | var isCancel = false; | ||
1047 | var isDefault = false; | ||
1048 | var notTabbable = false; | ||
1049 | string property = null; | ||
1050 | var publishOrder = 0; | ||
1051 | string sourceFile = null; | ||
1052 | string text = null; | ||
1053 | string tooltip = null; | ||
1054 | var radioButtonsType = RadioButtonType.NotSet; | ||
1055 | string width = null; | ||
1056 | string x = null; | ||
1057 | string y = null; | ||
1058 | |||
1059 | var hidden = false; | ||
1060 | var sunken = false; | ||
1061 | var indirect = false; | ||
1062 | var integer = false; | ||
1063 | var rightToLeft = false; | ||
1064 | var rightAligned = false; | ||
1065 | var leftScroll = false; | ||
1066 | |||
1067 | // The rest of the method relies on the control's Type, so we have to get that first. | ||
1068 | var typeAttribute = node.Attribute("Type"); | ||
1069 | if (null == typeAttribute) | ||
1070 | { | ||
1071 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Type")); | ||
1072 | } | ||
1073 | else | ||
1074 | { | ||
1075 | controlType = this.Core.GetAttributeValue(sourceLineNumbers, typeAttribute); | ||
1076 | } | ||
1077 | |||
1078 | string[] specialAttributes; | ||
1079 | switch (controlType) | ||
1080 | { | ||
1081 | case "Billboard": | ||
1082 | specialAttributes = null; | ||
1083 | notTabbable = true; | ||
1084 | disabled = true; | ||
1085 | |||
1086 | this.Core.EnsureTable(sourceLineNumbers, "Billboard"); | ||
1087 | break; | ||
1088 | case "Bitmap": | ||
1089 | specialAttributes = BitmapControlAttributes; | ||
1090 | notTabbable = true; | ||
1091 | disabled = true; | ||
1092 | break; | ||
1093 | case "CheckBox": | ||
1094 | specialAttributes = CheckboxControlAttributes; | ||
1095 | break; | ||
1096 | case "ComboBox": | ||
1097 | specialAttributes = ComboboxControlAttributes; | ||
1098 | break; | ||
1099 | case "DirectoryCombo": | ||
1100 | specialAttributes = VolumeControlAttributes; | ||
1101 | break; | ||
1102 | case "DirectoryList": | ||
1103 | specialAttributes = null; | ||
1104 | break; | ||
1105 | case "Edit": | ||
1106 | specialAttributes = EditControlAttributes; | ||
1107 | break; | ||
1108 | case "GroupBox": | ||
1109 | specialAttributes = null; | ||
1110 | notTabbable = true; | ||
1111 | break; | ||
1112 | case "Hyperlink": | ||
1113 | specialAttributes = HyperlinkControlAttributes; | ||
1114 | break; | ||
1115 | case "Icon": | ||
1116 | specialAttributes = IconControlAttributes; | ||
1117 | notTabbable = true; | ||
1118 | disabled = true; | ||
1119 | break; | ||
1120 | case "Line": | ||
1121 | specialAttributes = null; | ||
1122 | notTabbable = true; | ||
1123 | disabled = true; | ||
1124 | break; | ||
1125 | case "ListBox": | ||
1126 | specialAttributes = ListboxControlAttributes; | ||
1127 | break; | ||
1128 | case "ListView": | ||
1129 | specialAttributes = ListviewControlAttributes; | ||
1130 | break; | ||
1131 | case "MaskedEdit": | ||
1132 | specialAttributes = EditControlAttributes; | ||
1133 | break; | ||
1134 | case "PathEdit": | ||
1135 | specialAttributes = EditControlAttributes; | ||
1136 | break; | ||
1137 | case "ProgressBar": | ||
1138 | specialAttributes = ProgressControlAttributes; | ||
1139 | notTabbable = true; | ||
1140 | disabled = true; | ||
1141 | break; | ||
1142 | case "PushButton": | ||
1143 | specialAttributes = ButtonControlAttributes; | ||
1144 | break; | ||
1145 | case "RadioButtonGroup": | ||
1146 | specialAttributes = RadioControlAttributes; | ||
1147 | break; | ||
1148 | case "ScrollableText": | ||
1149 | specialAttributes = null; | ||
1150 | break; | ||
1151 | case "SelectionTree": | ||
1152 | specialAttributes = null; | ||
1153 | break; | ||
1154 | case "Text": | ||
1155 | specialAttributes = TextControlAttributes; | ||
1156 | notTabbable = true; | ||
1157 | break; | ||
1158 | case "VolumeCostList": | ||
1159 | specialAttributes = VolumeControlAttributes; | ||
1160 | notTabbable = true; | ||
1161 | break; | ||
1162 | case "VolumeSelectCombo": | ||
1163 | specialAttributes = VolumeControlAttributes; | ||
1164 | break; | ||
1165 | default: | ||
1166 | specialAttributes = null; | ||
1167 | notTabbable = true; | ||
1168 | break; | ||
1169 | } | ||
1170 | |||
1171 | foreach (var attrib in node.Attributes()) | ||
1172 | { | ||
1173 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
1174 | { | ||
1175 | switch (attrib.Name.LocalName) | ||
1176 | { | ||
1177 | case "Id": | ||
1178 | controlId = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
1179 | break; | ||
1180 | case "Type": // already processed | ||
1181 | break; | ||
1182 | case "Cancel": | ||
1183 | isCancel = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1184 | break; | ||
1185 | case "CheckBoxPropertyRef": | ||
1186 | checkBoxPropertyRef = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1187 | break; | ||
1188 | case "CheckBoxValue": | ||
1189 | checkboxValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1190 | break; | ||
1191 | case "Default": | ||
1192 | isDefault = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1193 | break; | ||
1194 | case "Height": | ||
1195 | height = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
1196 | break; | ||
1197 | case "Help": | ||
1198 | help = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1199 | break; | ||
1200 | case "IconSize": | ||
1201 | var iconSizeValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1202 | if (null != specialAttributes) | ||
1203 | { | ||
1204 | switch (iconSizeValue) | ||
1205 | { | ||
1206 | case "16": | ||
1207 | this.Core.TrySetBitFromName(specialAttributes, "Icon16", YesNoType.Yes, bits, 16); | ||
1208 | break; | ||
1209 | case "32": | ||
1210 | this.Core.TrySetBitFromName(specialAttributes, "Icon32", YesNoType.Yes, bits, 16); | ||
1211 | break; | ||
1212 | case "48": | ||
1213 | this.Core.TrySetBitFromName(specialAttributes, "Icon16", YesNoType.Yes, bits, 16); | ||
1214 | this.Core.TrySetBitFromName(specialAttributes, "Icon32", YesNoType.Yes, bits, 16); | ||
1215 | break; | ||
1216 | case "": | ||
1217 | break; | ||
1218 | default: | ||
1219 | this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, iconSizeValue, "16", "32", "48")); | ||
1220 | break; | ||
1221 | } | ||
1222 | //if (0 < iconSizeValue.Length) | ||
1223 | //{ | ||
1224 | // var iconsSizeType = Wix.Control.ParseIconSizeType(iconSizeValue); | ||
1225 | // switch (iconsSizeType) | ||
1226 | // { | ||
1227 | // case Wix.Control.IconSizeType.Item16: | ||
1228 | // this.Core.TrySetBitFromName(specialAttributes, "Icon16", YesNoType.Yes, bits, 16); | ||
1229 | // break; | ||
1230 | // case Wix.Control.IconSizeType.Item32: | ||
1231 | // this.Core.TrySetBitFromName(specialAttributes, "Icon32", YesNoType.Yes, bits, 16); | ||
1232 | // break; | ||
1233 | // case Wix.Control.IconSizeType.Item48: | ||
1234 | // this.Core.TrySetBitFromName(specialAttributes, "Icon16", YesNoType.Yes, bits, 16); | ||
1235 | // this.Core.TrySetBitFromName(specialAttributes, "Icon32", YesNoType.Yes, bits, 16); | ||
1236 | // break; | ||
1237 | // default: | ||
1238 | // this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, iconSizeValue, "16", "32", "48")); | ||
1239 | // break; | ||
1240 | // } | ||
1241 | //} | ||
1242 | } | ||
1243 | else | ||
1244 | { | ||
1245 | this.Core.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, iconSizeValue, "Type")); | ||
1246 | } | ||
1247 | break; | ||
1248 | case "Property": | ||
1249 | property = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1250 | break; | ||
1251 | case "TabSkip": | ||
1252 | notTabbable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1253 | break; | ||
1254 | case "Text": | ||
1255 | text = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1256 | break; | ||
1257 | case "ToolTip": | ||
1258 | tooltip = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1259 | break; | ||
1260 | case "Width": | ||
1261 | width = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
1262 | break; | ||
1263 | case "X": | ||
1264 | x = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
1265 | break; | ||
1266 | case "Y": | ||
1267 | y = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); | ||
1268 | break; | ||
1269 | case "Disabled": | ||
1270 | disabled = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1271 | break; | ||
1272 | case "Hidden": | ||
1273 | hidden = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1274 | break; | ||
1275 | case "Sunken": | ||
1276 | sunken = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1277 | break; | ||
1278 | case "Indirect": | ||
1279 | indirect = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1280 | break; | ||
1281 | case "Integer": | ||
1282 | integer = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1283 | break; | ||
1284 | case "RightToLeft": | ||
1285 | rightToLeft = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1286 | break; | ||
1287 | case "RightAligned": | ||
1288 | rightAligned = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1289 | break; | ||
1290 | case "LeftScroll": | ||
1291 | leftScroll = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1292 | break; | ||
1293 | default: | ||
1294 | var attribValue = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
1295 | if (null == specialAttributes || !this.Core.TrySetBitFromName(specialAttributes, attrib.Name.LocalName, attribValue, bits, 16)) | ||
1296 | { | ||
1297 | this.Core.UnexpectedAttribute(node, attrib); | ||
1298 | } | ||
1299 | break; | ||
1300 | } | ||
1301 | } | ||
1302 | else | ||
1303 | { | ||
1304 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | var attributes = this.Core.CreateIntegerFromBitArray(bits); | ||
1309 | |||
1310 | //if (disabled) | ||
1311 | //{ | ||
1312 | // attributes |= WindowsInstallerConstants.MsidbControlAttributesEnabled; // bit will be inverted when stored | ||
1313 | //} | ||
1314 | |||
1315 | if (null == height) | ||
1316 | { | ||
1317 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Height")); | ||
1318 | } | ||
1319 | |||
1320 | if (null == width) | ||
1321 | { | ||
1322 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Width")); | ||
1323 | } | ||
1324 | |||
1325 | if (null == x) | ||
1326 | { | ||
1327 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "X")); | ||
1328 | } | ||
1329 | |||
1330 | if (null == y) | ||
1331 | { | ||
1332 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Y")); | ||
1333 | } | ||
1334 | |||
1335 | if (null == controlId) | ||
1336 | { | ||
1337 | controlId = this.Core.CreateIdentifier("ctl", dialog, x, y, height, width); | ||
1338 | } | ||
1339 | |||
1340 | if (isCancel) | ||
1341 | { | ||
1342 | cancelControl = controlId.Id; | ||
1343 | } | ||
1344 | |||
1345 | if (isDefault) | ||
1346 | { | ||
1347 | defaultControl = controlId.Id; | ||
1348 | } | ||
1349 | |||
1350 | foreach (var child in node.Elements()) | ||
1351 | { | ||
1352 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
1353 | { | ||
1354 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
1355 | switch (child.Name.LocalName) | ||
1356 | { | ||
1357 | case "Binary": | ||
1358 | this.ParseBinaryElement(child); | ||
1359 | break; | ||
1360 | case "ComboBox": | ||
1361 | this.ParseControlGroupElement(child, TupleDefinitionType.ComboBox, "ListItem"); | ||
1362 | break; | ||
1363 | case "Condition": | ||
1364 | this.ParseConditionElement(child, node.Name.LocalName, controlId.Id, dialog); | ||
1365 | break; | ||
1366 | case "ListBox": | ||
1367 | this.ParseControlGroupElement(child, TupleDefinitionType.ListBox, "ListItem"); | ||
1368 | break; | ||
1369 | case "ListView": | ||
1370 | this.ParseControlGroupElement(child, TupleDefinitionType.ListView, "ListItem"); | ||
1371 | break; | ||
1372 | case "Property": | ||
1373 | this.ParsePropertyElement(child); | ||
1374 | break; | ||
1375 | case "Publish": | ||
1376 | this.ParsePublishElement(child, dialog ?? String.Empty, controlId.Id, ref publishOrder); | ||
1377 | break; | ||
1378 | case "RadioButtonGroup": | ||
1379 | radioButtonsType = this.ParseRadioButtonGroupElement(child, property, radioButtonsType); | ||
1380 | break; | ||
1381 | case "Subscribe": | ||
1382 | this.ParseSubscribeElement(child, dialog, controlId.Id); | ||
1383 | break; | ||
1384 | case "Text": | ||
1385 | foreach (var attrib in child.Attributes()) | ||
1386 | { | ||
1387 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
1388 | { | ||
1389 | switch (attrib.Name.LocalName) | ||
1390 | { | ||
1391 | case "SourceFile": | ||
1392 | sourceFile = this.Core.GetAttributeValue(childSourceLineNumbers, attrib); | ||
1393 | break; | ||
1394 | default: | ||
1395 | this.Core.UnexpectedAttribute(child, attrib); | ||
1396 | break; | ||
1397 | } | ||
1398 | } | ||
1399 | else | ||
1400 | { | ||
1401 | this.Core.ParseExtensionAttribute(child, attrib); | ||
1402 | } | ||
1403 | } | ||
1404 | |||
1405 | text = Common.GetInnerText(child); | ||
1406 | if (!String.IsNullOrEmpty(text) && null != sourceFile) | ||
1407 | { | ||
1408 | this.Core.Write(ErrorMessages.IllegalAttributeWithInnerText(childSourceLineNumbers, child.Name.LocalName, "SourceFile")); | ||
1409 | } | ||
1410 | break; | ||
1411 | default: | ||
1412 | this.Core.UnexpectedElement(node, child); | ||
1413 | break; | ||
1414 | } | ||
1415 | } | ||
1416 | else | ||
1417 | { | ||
1418 | this.Core.ParseExtensionElement(node, child); | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | // If the radio buttons have icons, then we need to add the icon attribute. | ||
1423 | switch (radioButtonsType) | ||
1424 | { | ||
1425 | case RadioButtonType.Bitmap: | ||
1426 | attributes |= WindowsInstallerConstants.MsidbControlAttributesBitmap; | ||
1427 | break; | ||
1428 | case RadioButtonType.Icon: | ||
1429 | attributes |= WindowsInstallerConstants.MsidbControlAttributesIcon; | ||
1430 | break; | ||
1431 | case RadioButtonType.Text: | ||
1432 | // Text is the default so nothing needs to be added bits | ||
1433 | break; | ||
1434 | } | ||
1435 | |||
1436 | // the logic for creating control rows is a little tricky because of the way tabable controls are set | ||
1437 | IntermediateTuple tuple = null; | ||
1438 | if (!this.Core.EncounteredError) | ||
1439 | { | ||
1440 | if ("CheckBox" == controlType) | ||
1441 | { | ||
1442 | if (String.IsNullOrEmpty(property) && String.IsNullOrEmpty(checkBoxPropertyRef)) | ||
1443 | { | ||
1444 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property", "CheckBoxPropertyRef", true)); | ||
1445 | } | ||
1446 | else if (!String.IsNullOrEmpty(property) && !String.IsNullOrEmpty(checkBoxPropertyRef)) | ||
1447 | { | ||
1448 | this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "Property", "CheckBoxPropertyRef")); | ||
1449 | } | ||
1450 | else if (!String.IsNullOrEmpty(property)) | ||
1451 | { | ||
1452 | var checkBoxTuple = new CheckBoxTuple(sourceLineNumbers) | ||
1453 | { | ||
1454 | Property = property, | ||
1455 | Value = checkboxValue | ||
1456 | }; | ||
1457 | |||
1458 | this.Core.AddTuple(checkBoxTuple); | ||
1459 | } | ||
1460 | else | ||
1461 | { | ||
1462 | this.Core.CreateSimpleReference(sourceLineNumbers, "CheckBox", checkBoxPropertyRef); | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | var id = new Identifier(controlId.Access, dialog, controlId.Id); | ||
1467 | |||
1468 | if (TupleDefinitionType.BBControl == tupleType) | ||
1469 | { | ||
1470 | var bbTuple = new BBControlTuple(sourceLineNumbers, id) | ||
1471 | { | ||
1472 | Billboard_ = dialog, | ||
1473 | BBControl = controlId.Id, | ||
1474 | Type = controlType, | ||
1475 | Attributes = attributes, | ||
1476 | Enabled = !disabled, | ||
1477 | Indirect = indirect, | ||
1478 | Integer = integer, | ||
1479 | LeftScroll = leftScroll, | ||
1480 | RightAligned = rightAligned, | ||
1481 | RightToLeft = rightToLeft, | ||
1482 | Sunken = sunken, | ||
1483 | Visible = !hidden, | ||
1484 | Text = text, | ||
1485 | SourceFile = sourceFile | ||
1486 | }; | ||
1487 | |||
1488 | bbTuple.Set((int)BBControlTupleFields.X, x); | ||
1489 | bbTuple.Set((int)BBControlTupleFields.Y, y); | ||
1490 | bbTuple.Set((int)BBControlTupleFields.Width, width); | ||
1491 | bbTuple.Set((int)BBControlTupleFields.Height, height); | ||
1492 | |||
1493 | this.Core.AddTuple(bbTuple); | ||
1494 | |||
1495 | tuple = bbTuple; | ||
1496 | } | ||
1497 | else | ||
1498 | { | ||
1499 | var controlTuple = new ControlTuple(sourceLineNumbers, id) | ||
1500 | { | ||
1501 | Dialog_ = dialog, | ||
1502 | Control = controlId.Id, | ||
1503 | Type = controlType, | ||
1504 | Attributes = attributes, | ||
1505 | Enabled = !disabled, | ||
1506 | Indirect = indirect, | ||
1507 | Integer = integer, | ||
1508 | LeftScroll = leftScroll, | ||
1509 | RightAligned = rightAligned, | ||
1510 | RightToLeft = rightToLeft, | ||
1511 | Sunken = sunken, | ||
1512 | Visible = !hidden, | ||
1513 | Property = !String.IsNullOrEmpty(property) ? property : checkBoxPropertyRef, | ||
1514 | Text = text, | ||
1515 | Help = (null == tooltip && null == help) ? null : String.Concat(tooltip, "|", help), // Separator is required, even if only one is non-null.}; | ||
1516 | SourceFile = sourceFile | ||
1517 | }; | ||
1518 | |||
1519 | controlTuple.Set((int)BBControlTupleFields.X, x); | ||
1520 | controlTuple.Set((int)BBControlTupleFields.Y, y); | ||
1521 | controlTuple.Set((int)BBControlTupleFields.Width, width); | ||
1522 | controlTuple.Set((int)BBControlTupleFields.Height, height); | ||
1523 | |||
1524 | this.Core.AddTuple(controlTuple); | ||
1525 | |||
1526 | tuple = controlTuple; | ||
1527 | } | ||
1528 | } | ||
1529 | |||
1530 | if (!notTabbable) | ||
1531 | { | ||
1532 | if (TupleDefinitionType.BBControl == tupleType) | ||
1533 | { | ||
1534 | this.Core.Write(ErrorMessages.TabbableControlNotAllowedInBillboard(sourceLineNumbers, node.Name.LocalName, controlType)); | ||
1535 | } | ||
1536 | |||
1537 | if (null == firstControl) | ||
1538 | { | ||
1539 | firstControl = controlId.Id; | ||
1540 | } | ||
1541 | |||
1542 | if (null != lastTabTuple) | ||
1543 | { | ||
1544 | lastTabTuple.Set(10, controlId.Id); | ||
1545 | } | ||
1546 | lastTabTuple = tuple; | ||
1547 | } | ||
1548 | |||
1549 | // bitmap and icon controls contain a foreign key into the binary table in the text column; | ||
1550 | // add a reference if the identifier of the binary entry is known during compilation | ||
1551 | if (("Bitmap" == controlType || "Icon" == controlType) && Common.IsIdentifier(text)) | ||
1552 | { | ||
1553 | this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", text); | ||
1554 | } | ||
1555 | } | ||
1556 | |||
1557 | /// <summary> | ||
1558 | /// Parses a publish control event element. | ||
1559 | /// </summary> | ||
1560 | /// <param name="node">Element to parse.</param> | ||
1561 | /// <param name="dialog">Identifier of parent dialog.</param> | ||
1562 | /// <param name="control">Identifier of parent control.</param> | ||
1563 | /// <param name="order">Relative order of controls.</param> | ||
1564 | private void ParsePublishElement(XElement node, string dialog, string control, ref int order) | ||
1565 | { | ||
1566 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1567 | string argument = null; | ||
1568 | string condition = null; | ||
1569 | string controlEvent = null; | ||
1570 | string property = null; | ||
1571 | |||
1572 | // give this control event a unique ordering | ||
1573 | order++; | ||
1574 | |||
1575 | foreach (var attrib in node.Attributes()) | ||
1576 | { | ||
1577 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
1578 | { | ||
1579 | switch (attrib.Name.LocalName) | ||
1580 | { | ||
1581 | case "Control": | ||
1582 | if (null != control) | ||
1583 | { | ||
1584 | this.Core.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1585 | } | ||
1586 | control = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1587 | break; | ||
1588 | case "Dialog": | ||
1589 | if (null != dialog) | ||
1590 | { | ||
1591 | this.Core.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1592 | } | ||
1593 | dialog = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1594 | this.Core.CreateSimpleReference(sourceLineNumbers, "Dialog", dialog); | ||
1595 | break; | ||
1596 | case "Event": | ||
1597 | controlEvent = Compiler.UppercaseFirstChar(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
1598 | break; | ||
1599 | case "Order": | ||
1600 | order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 2147483647); | ||
1601 | break; | ||
1602 | case "Property": | ||
1603 | property = String.Concat("[", this.Core.GetAttributeValue(sourceLineNumbers, attrib), "]"); | ||
1604 | break; | ||
1605 | case "Value": | ||
1606 | argument = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1607 | break; | ||
1608 | default: | ||
1609 | this.Core.UnexpectedAttribute(node, attrib); | ||
1610 | break; | ||
1611 | } | ||
1612 | } | ||
1613 | else | ||
1614 | { | ||
1615 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1619 | condition = this.Core.GetConditionInnerText(node); | ||
1620 | |||
1621 | if (null == control) | ||
1622 | { | ||
1623 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Control")); | ||
1624 | } | ||
1625 | |||
1626 | if (null == dialog) | ||
1627 | { | ||
1628 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Dialog")); | ||
1629 | } | ||
1630 | |||
1631 | if (null == controlEvent && null == property) // need to specify at least one | ||
1632 | { | ||
1633 | this.Core.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, node.Name.LocalName, "Event", "Property")); | ||
1634 | } | ||
1635 | else if (null != controlEvent && null != property) // cannot specify both | ||
1636 | { | ||
1637 | this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "Event", "Property")); | ||
1638 | } | ||
1639 | |||
1640 | if (null == argument) | ||
1641 | { | ||
1642 | if (null != controlEvent) | ||
1643 | { | ||
1644 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value", "Event")); | ||
1645 | } | ||
1646 | else if (null != property) | ||
1647 | { | ||
1648 | // if this is setting a property to null, put a special value in the argument column | ||
1649 | argument = "{}"; | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | this.Core.ParseForExtensionElements(node); | ||
1654 | |||
1655 | if (!this.Core.EncounteredError) | ||
1656 | { | ||
1657 | var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ControlEvent); | ||
1658 | row.Set(0, dialog); | ||
1659 | row.Set(1, control); | ||
1660 | row.Set(2, (null != controlEvent ? controlEvent : property)); | ||
1661 | row.Set(3, argument); | ||
1662 | row.Set(4, condition); | ||
1663 | row.Set(5, order); | ||
1664 | } | ||
1665 | |||
1666 | if ("DoAction" == controlEvent && null != argument) | ||
1667 | { | ||
1668 | // if we're not looking at a standard action or a formatted string then create a reference | ||
1669 | // to the custom action. | ||
1670 | if (!WindowsInstallerStandard.IsStandardAction(argument) && !Common.ContainsProperty(argument)) | ||
1671 | { | ||
1672 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", argument); | ||
1673 | } | ||
1674 | } | ||
1675 | |||
1676 | // if we're referring to a dialog but not through a property, add it to the references | ||
1677 | if (("NewDialog" == controlEvent || "SpawnDialog" == controlEvent || "SpawnWaitDialog" == controlEvent || "SelectionBrowse" == controlEvent) && Common.IsIdentifier(argument)) | ||
1678 | { | ||
1679 | this.Core.CreateSimpleReference(sourceLineNumbers, "Dialog", argument); | ||
1680 | } | ||
1681 | } | ||
1682 | |||
1683 | /// <summary> | ||
1684 | /// Parses a control subscription element. | ||
1685 | /// </summary> | ||
1686 | /// <param name="node">Element to parse.</param> | ||
1687 | /// <param name="dialog">Identifier of dialog.</param> | ||
1688 | /// <param name="control">Identifier of control.</param> | ||
1689 | private void ParseSubscribeElement(XElement node, string dialog, string control) | ||
1690 | { | ||
1691 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1692 | string controlAttribute = null; | ||
1693 | string eventMapping = null; | ||
1694 | |||
1695 | foreach (var attrib in node.Attributes()) | ||
1696 | { | ||
1697 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
1698 | { | ||
1699 | switch (attrib.Name.LocalName) | ||
1700 | { | ||
1701 | case "Attribute": | ||
1702 | controlAttribute = Compiler.UppercaseFirstChar(this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib)); | ||
1703 | break; | ||
1704 | case "Event": | ||
1705 | eventMapping = Compiler.UppercaseFirstChar(this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib)); | ||
1706 | break; | ||
1707 | default: | ||
1708 | this.Core.UnexpectedAttribute(node, attrib); | ||
1709 | break; | ||
1710 | } | ||
1711 | } | ||
1712 | else | ||
1713 | { | ||
1714 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1715 | } | ||
1716 | } | ||
1717 | |||
1718 | this.Core.ParseForExtensionElements(node); | ||
1719 | |||
1720 | if (!this.Core.EncounteredError) | ||
1721 | { | ||
1722 | var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.EventMapping); | ||
1723 | row.Set(0, dialog); | ||
1724 | row.Set(1, control); | ||
1725 | row.Set(2, eventMapping); | ||
1726 | row.Set(3, controlAttribute); | ||
1727 | } | ||
1728 | } | ||
1729 | } | ||
1730 | } | ||