[12762] | 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 | }
|
---|