1 | using System;
|
---|
2 | using System.IO;
|
---|
3 | using System.Collections.Generic;
|
---|
4 | using System.Security.AccessControl;
|
---|
5 |
|
---|
6 | using System.Windows;
|
---|
7 | using System.Windows.Media;
|
---|
8 |
|
---|
9 | using SharpVectors.Renderers.Wpf;
|
---|
10 | using SharpVectors.Converters.Utils;
|
---|
11 |
|
---|
12 | namespace SharpVectors.Converters
|
---|
13 | {
|
---|
14 | /// <summary>
|
---|
15 | /// This converts a directory (and optionally the sub-directories) of SVG
|
---|
16 | /// files to XAML files in a specified directory, maintaining the original
|
---|
17 | /// directory structure.
|
---|
18 | /// </summary>
|
---|
19 | public sealed class DirectorySvgConverter : SvgConverter
|
---|
20 | {
|
---|
21 | #region Private Fields
|
---|
22 |
|
---|
23 | private int _convertedCount;
|
---|
24 | private bool _isOverwrite;
|
---|
25 | private bool _isRecursive;
|
---|
26 | private bool _includeHidden;
|
---|
27 | private bool _includeSecurity;
|
---|
28 |
|
---|
29 | private bool _writerErrorOccurred;
|
---|
30 | private bool _fallbackOnWriterError;
|
---|
31 |
|
---|
32 | private string _errorFile;
|
---|
33 |
|
---|
34 | private DirectoryInfo _sourceDir;
|
---|
35 | private DirectoryInfo _destinationDir;
|
---|
36 |
|
---|
37 | #endregion
|
---|
38 |
|
---|
39 | #region Constructors and Destructor
|
---|
40 |
|
---|
41 | /// <summary>
|
---|
42 | /// Initializes a new instance of the <see cref="WpfDrawingSettings"/>
|
---|
43 | /// class with the specified drawing or rendering settings.
|
---|
44 | /// </summary>
|
---|
45 | /// <param name="settings">
|
---|
46 | /// This specifies the settings used by the rendering or drawing engine.
|
---|
47 | /// If this is <see langword="null"/>, the default settings is used.
|
---|
48 | /// </param>
|
---|
49 | public DirectorySvgConverter(WpfDrawingSettings settings)
|
---|
50 | : base(settings)
|
---|
51 | {
|
---|
52 | _isOverwrite = true;
|
---|
53 | _isRecursive = true;
|
---|
54 | }
|
---|
55 |
|
---|
56 | #endregion
|
---|
57 |
|
---|
58 | #region Public Properties
|
---|
59 |
|
---|
60 | /// <summary>
|
---|
61 | /// Gets or sets a value indicating whether the directory copying is
|
---|
62 | /// recursive, that is includes the sub-directories.
|
---|
63 | /// </summary>
|
---|
64 | /// <value>
|
---|
65 | /// This property is <see langword="true"/> if the sub-directories are
|
---|
66 | /// included in the directory copy; otherwise, it is <see langword="false"/>.
|
---|
67 | /// The default is <see langword="true"/>.
|
---|
68 | /// </value>
|
---|
69 | public bool Recursive
|
---|
70 | {
|
---|
71 | get
|
---|
72 | {
|
---|
73 | return _isRecursive;
|
---|
74 | }
|
---|
75 |
|
---|
76 | set
|
---|
77 | {
|
---|
78 | _isRecursive = value;
|
---|
79 | }
|
---|
80 | }
|
---|
81 |
|
---|
82 | /// <summary>
|
---|
83 | /// Gets or sets a value indicating whether an existing file is overwritten.
|
---|
84 | /// </summary>
|
---|
85 | /// <value>
|
---|
86 | /// This property is <see langword="true"/> if existing file is overwritten;
|
---|
87 | /// otherwise, it is <see langword="false"/>. The default is <see langword="true"/>.
|
---|
88 | /// </value>
|
---|
89 | public bool Overwrite
|
---|
90 | {
|
---|
91 | get
|
---|
92 | {
|
---|
93 | return _isOverwrite;
|
---|
94 | }
|
---|
95 |
|
---|
96 | set
|
---|
97 | {
|
---|
98 | _isOverwrite = value;
|
---|
99 | }
|
---|
100 | }
|
---|
101 |
|
---|
102 | /// <summary>
|
---|
103 | /// Gets or sets a value indicating whether the security settings of the
|
---|
104 | /// copied file is retained.
|
---|
105 | /// </summary>
|
---|
106 | /// <value>
|
---|
107 | /// This property is <see langword="true"/> if the security settings of the
|
---|
108 | /// file is also copied; otherwise, it is <see langword="false"/>. The
|
---|
109 | /// default is <see langword="false"/>.
|
---|
110 | /// </value>
|
---|
111 | public bool IncludeSecurity
|
---|
112 | {
|
---|
113 | get
|
---|
114 | {
|
---|
115 | return _includeSecurity;
|
---|
116 | }
|
---|
117 |
|
---|
118 | set
|
---|
119 | {
|
---|
120 | _includeSecurity = value;
|
---|
121 | }
|
---|
122 | }
|
---|
123 |
|
---|
124 | /// <summary>
|
---|
125 | /// Gets or sets a value indicating whether the copy operation includes
|
---|
126 | /// hidden directories and files.
|
---|
127 | /// </summary>
|
---|
128 | /// <value>
|
---|
129 | /// This property is <see langword="true"/> if hidden directories and files
|
---|
130 | /// are included in the copy operation; otherwise, it is
|
---|
131 | /// <see langword="false"/>. The default is <see langword="false"/>.
|
---|
132 | /// </value>
|
---|
133 | public bool IncludeHidden
|
---|
134 | {
|
---|
135 | get
|
---|
136 | {
|
---|
137 | return _includeHidden;
|
---|
138 | }
|
---|
139 |
|
---|
140 | set
|
---|
141 | {
|
---|
142 | _includeHidden = value;
|
---|
143 | }
|
---|
144 | }
|
---|
145 |
|
---|
146 | /// <summary>
|
---|
147 | /// Gets a value indicating whether a writer error occurred when
|
---|
148 | /// using the custom XAML writer.
|
---|
149 | /// </summary>
|
---|
150 | /// <value>
|
---|
151 | /// This is <see langword="true"/> if an error occurred when using
|
---|
152 | /// the custom XAML writer; otherwise, it is <see langword="false"/>.
|
---|
153 | /// </value>
|
---|
154 | public bool WriterErrorOccurred
|
---|
155 | {
|
---|
156 | get
|
---|
157 | {
|
---|
158 | return _writerErrorOccurred;
|
---|
159 | }
|
---|
160 | }
|
---|
161 |
|
---|
162 | /// <summary>
|
---|
163 | /// Gets or sets a value indicating whether to fall back and use
|
---|
164 | /// the .NET Framework XAML writer when an error occurred in using the
|
---|
165 | /// custom writer.
|
---|
166 | /// </summary>
|
---|
167 | /// <value>
|
---|
168 | /// This is <see langword="true"/> if the converter falls back to using
|
---|
169 | /// the system XAML writer when an error occurred in using the custom
|
---|
170 | /// writer; otherwise, it is <see langword="false"/>. If <see langword="false"/>,
|
---|
171 | /// an exception, which occurred in using the custom writer will be
|
---|
172 | /// thrown. The default is <see langword="false"/>.
|
---|
173 | /// </value>
|
---|
174 | public bool FallbackOnWriterError
|
---|
175 | {
|
---|
176 | get
|
---|
177 | {
|
---|
178 | return _fallbackOnWriterError;
|
---|
179 | }
|
---|
180 | set
|
---|
181 | {
|
---|
182 | _fallbackOnWriterError = value;
|
---|
183 | }
|
---|
184 | }
|
---|
185 |
|
---|
186 | /// <summary>
|
---|
187 | /// Gets the source directory of the SVG files to be converted.
|
---|
188 | /// </summary>
|
---|
189 | /// <value>
|
---|
190 | /// A <see cref="DirectoryInfo"/> specifying the source directory of
|
---|
191 | /// the SVG files.
|
---|
192 | /// </value>
|
---|
193 | public DirectoryInfo SourceDir
|
---|
194 | {
|
---|
195 | get
|
---|
196 | {
|
---|
197 | return _sourceDir;
|
---|
198 | }
|
---|
199 | }
|
---|
200 |
|
---|
201 | /// <summary>
|
---|
202 | /// Gets the destination directory of the converted XAML files.
|
---|
203 | /// </summary>
|
---|
204 | /// <value>
|
---|
205 | /// A <see cref="DirectoryInfo"/> specifying the destination directory of
|
---|
206 | /// the converted XAML files.
|
---|
207 | /// </value>
|
---|
208 | public DirectoryInfo DestinationDir
|
---|
209 | {
|
---|
210 | get
|
---|
211 | {
|
---|
212 | return _destinationDir;
|
---|
213 | }
|
---|
214 | }
|
---|
215 |
|
---|
216 | /// <summary>
|
---|
217 | /// Gets the full path of the last SVG file not successfully converted.
|
---|
218 | /// </summary>
|
---|
219 | /// <value>
|
---|
220 | /// A string containing the full path of the last SVG file not
|
---|
221 | /// successfully converted to the XAML
|
---|
222 | /// </value>
|
---|
223 | /// <remarks>
|
---|
224 | /// Whenever an error occurred in the conversion of a file, the
|
---|
225 | /// conversion process will stop. Use this property to retrieve the full
|
---|
226 | /// path of the SVG file causing the error.
|
---|
227 | /// </remarks>
|
---|
228 | public string ErrorFile
|
---|
229 | {
|
---|
230 | get
|
---|
231 | {
|
---|
232 | return _errorFile;
|
---|
233 | }
|
---|
234 | }
|
---|
235 |
|
---|
236 | #endregion
|
---|
237 |
|
---|
238 | #region Public Methods
|
---|
239 |
|
---|
240 | /// <summary>
|
---|
241 | /// Convert the SVG files in the specified source directory, saving the
|
---|
242 | /// results in the specified destination directory.
|
---|
243 | /// </summary>
|
---|
244 | /// <param name="sourceInfo">
|
---|
245 | /// A <see cref="DirectoryInfo"/> specifying the source directory of
|
---|
246 | /// the SVG files.
|
---|
247 | /// </param>
|
---|
248 | /// <param name="destInfo">
|
---|
249 | /// A <see cref="DirectoryInfo"/> specifying the source directory of
|
---|
250 | /// the SVG files.
|
---|
251 | /// </param>
|
---|
252 | /// <exception cref="ArgumentNullException">
|
---|
253 | /// <para>
|
---|
254 | /// If the <paramref name="sourceInfo"/> is <see langword="null"/>.
|
---|
255 | /// </para>
|
---|
256 | /// <para>
|
---|
257 | /// -or-
|
---|
258 | /// </para>
|
---|
259 | /// <para>
|
---|
260 | /// If the <paramref name="destInfo"/> is <see langword="null"/>.
|
---|
261 | /// </para>
|
---|
262 | /// </exception>
|
---|
263 | /// <exception cref="ArgumentException">
|
---|
264 | /// If the directory specified by <paramref name="sourceInfo"/> does not
|
---|
265 | /// exists.
|
---|
266 | /// </exception>
|
---|
267 | public void Convert(DirectoryInfo sourceInfo, DirectoryInfo destInfo)
|
---|
268 | {
|
---|
269 | if (sourceInfo == null)
|
---|
270 | {
|
---|
271 | throw new ArgumentNullException("sourceInfo",
|
---|
272 | "The source directory cannot be null (or Nothing).");
|
---|
273 | }
|
---|
274 | if (destInfo == null)
|
---|
275 | {
|
---|
276 | throw new ArgumentNullException("destInfo",
|
---|
277 | "The destination directory cannot be null (or Nothing).");
|
---|
278 | }
|
---|
279 | if (!sourceInfo.Exists)
|
---|
280 | {
|
---|
281 | throw new ArgumentException(
|
---|
282 | "The source directory must exists.", "sourceInfo");
|
---|
283 | }
|
---|
284 |
|
---|
285 | _convertedCount = 0;
|
---|
286 | _sourceDir = sourceInfo;
|
---|
287 | _destinationDir = destInfo;
|
---|
288 | DirectorySecurity dirSecurity = null;
|
---|
289 | if (_includeSecurity)
|
---|
290 | {
|
---|
291 | dirSecurity = sourceInfo.GetAccessControl();
|
---|
292 | }
|
---|
293 | if (!destInfo.Exists)
|
---|
294 | {
|
---|
295 | if (dirSecurity != null)
|
---|
296 | {
|
---|
297 | destInfo.Create(dirSecurity);
|
---|
298 | }
|
---|
299 | else
|
---|
300 | {
|
---|
301 | destInfo.Create();
|
---|
302 | }
|
---|
303 | destInfo.Attributes = sourceInfo.Attributes;
|
---|
304 | }
|
---|
305 | else
|
---|
306 | {
|
---|
307 | if (dirSecurity != null)
|
---|
308 | {
|
---|
309 | destInfo.SetAccessControl(dirSecurity);
|
---|
310 | }
|
---|
311 | }
|
---|
312 |
|
---|
313 | this.ProcessConversion(_sourceDir, _destinationDir);
|
---|
314 | }
|
---|
315 |
|
---|
316 | #endregion
|
---|
317 |
|
---|
318 | #region Private Methods
|
---|
319 |
|
---|
320 | private void ProcessConversion(DirectoryInfo source, DirectoryInfo target)
|
---|
321 | {
|
---|
322 | // Convert the files in the specified directory...
|
---|
323 | this.ConvertFiles(source, target);
|
---|
324 |
|
---|
325 | if (!_isRecursive)
|
---|
326 | {
|
---|
327 | return;
|
---|
328 | }
|
---|
329 |
|
---|
330 | // If recursive, process any sub-directory...
|
---|
331 | DirectoryInfo[] arrSourceInfo = source.GetDirectories();
|
---|
332 |
|
---|
333 | int dirCount = (arrSourceInfo == null) ? 0 : arrSourceInfo.Length;
|
---|
334 |
|
---|
335 | for (int i = 0; i < dirCount; i++)
|
---|
336 | {
|
---|
337 | DirectoryInfo sourceInfo = arrSourceInfo[i];
|
---|
338 | FileAttributes fileAttr = sourceInfo.Attributes;
|
---|
339 | if (!_includeHidden)
|
---|
340 | {
|
---|
341 | if ((fileAttr & FileAttributes.Hidden) == FileAttributes.Hidden)
|
---|
342 | {
|
---|
343 | continue;
|
---|
344 | }
|
---|
345 | }
|
---|
346 |
|
---|
347 | DirectoryInfo targetInfo = null;
|
---|
348 | if (_includeSecurity)
|
---|
349 | {
|
---|
350 | targetInfo = target.CreateSubdirectory(sourceInfo.Name,
|
---|
351 | sourceInfo.GetAccessControl());
|
---|
352 | }
|
---|
353 | else
|
---|
354 | {
|
---|
355 | targetInfo = target.CreateSubdirectory(sourceInfo.Name);
|
---|
356 | }
|
---|
357 | targetInfo.Attributes = fileAttr;
|
---|
358 |
|
---|
359 | this.ProcessConversion(sourceInfo, targetInfo);
|
---|
360 | }
|
---|
361 | }
|
---|
362 |
|
---|
363 | private void ConvertFiles(DirectoryInfo source, DirectoryInfo target)
|
---|
364 | {
|
---|
365 | _errorFile = null;
|
---|
366 |
|
---|
367 | FileSvgConverter fileConverter = new FileSvgConverter(this.SaveXaml,
|
---|
368 | this.SaveZaml, this.DrawingSettings);
|
---|
369 | fileConverter.FallbackOnWriterError = _fallbackOnWriterError;
|
---|
370 |
|
---|
371 | string targetDirName = target.ToString();
|
---|
372 | string xamlFilePath;
|
---|
373 |
|
---|
374 | IEnumerable<string> fileIterator = DirectoryUtils.FindFiles(
|
---|
375 | source, "*.*", SearchOption.TopDirectoryOnly);
|
---|
376 | foreach (string svgFileName in fileIterator)
|
---|
377 | {
|
---|
378 | string fileExt = Path.GetExtension(svgFileName);
|
---|
379 | if (String.Equals(fileExt, ".svg", StringComparison.OrdinalIgnoreCase) ||
|
---|
380 | String.Equals(fileExt, ".svgz", StringComparison.OrdinalIgnoreCase))
|
---|
381 | {
|
---|
382 | try
|
---|
383 | {
|
---|
384 | FileAttributes fileAttr = File.GetAttributes(svgFileName);
|
---|
385 | if (!_includeHidden)
|
---|
386 | {
|
---|
387 | if ((fileAttr & FileAttributes.Hidden) == FileAttributes.Hidden)
|
---|
388 | {
|
---|
389 | continue;
|
---|
390 | }
|
---|
391 | }
|
---|
392 |
|
---|
393 | xamlFilePath = Path.Combine(targetDirName,
|
---|
394 | Path.GetFileNameWithoutExtension(svgFileName) + ".xaml");
|
---|
395 |
|
---|
396 | fileConverter.Convert(svgFileName, xamlFilePath);
|
---|
397 |
|
---|
398 | File.SetAttributes(xamlFilePath, fileAttr);
|
---|
399 | // if required to set the security or access control
|
---|
400 | if (_includeSecurity)
|
---|
401 | {
|
---|
402 | File.SetAccessControl(xamlFilePath, File.GetAccessControl(svgFileName));
|
---|
403 | }
|
---|
404 |
|
---|
405 | _convertedCount++;
|
---|
406 |
|
---|
407 | if (fileConverter.WriterErrorOccurred)
|
---|
408 | {
|
---|
409 | _writerErrorOccurred = true;
|
---|
410 | }
|
---|
411 | }
|
---|
412 | catch
|
---|
413 | {
|
---|
414 | _errorFile = svgFileName;
|
---|
415 |
|
---|
416 | throw;
|
---|
417 | }
|
---|
418 | }
|
---|
419 | }
|
---|
420 | }
|
---|
421 |
|
---|
422 | #endregion
|
---|
423 | }
|
---|
424 | }
|
---|