Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorConverters/SvgViewbox.cs @ 13046

Last change on this file since 13046 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 16.7 KB
Line 
1using System;
2using System.IO;
3using System.IO.Compression;
4using System.Xml;
5using System.Reflection;
6using System.Globalization;
7using System.ComponentModel;
8
9using System.Windows;
10using System.Windows.Media;
11using System.Windows.Markup;
12using System.Windows.Controls;
13using System.Windows.Resources;
14
15using SharpVectors.Runtime;
16using SharpVectors.Renderers.Wpf;
17
18namespace SharpVectors.Converters
19{
20    /// <summary>
21    /// This is a <see cref="Viewbox"/> control for viewing SVG file in WPF
22    /// applications.
23    /// </summary>
24    /// <remarks>
25    /// It wraps the drawing canvas, <see cref="SvgDrawingCanvas"/>, instead of
26    /// image control, therefore any interactivity support implemented in the
27    /// drawing canvas will be available in the <see cref="Viewbox"/>.
28    /// </remarks>
29    public class SvgViewbox : Viewbox, IUriContext
30    {
31        #region Private Fields
32
33        private bool _isAutoSized;
34        private bool _autoSize;
35        private bool _textAsGeometry;
36        private bool _includeRuntime;
37        private bool _optimizePath;
38
39        private DrawingGroup _svgDrawing;
40
41        private CultureInfo _culture;
42
43        private Uri _baseUri;
44        private Uri _sourceUri;
45
46        private SvgDrawingCanvas _drawingCanvas;
47
48        #endregion
49
50        #region Constructors and Destructor
51
52        /// <summary>
53        /// Initializes a new instance of the <see cref="SvgViewbox"/> class.
54        /// </summary>
55        public SvgViewbox()
56        {
57            _textAsGeometry = false;
58            _includeRuntime = true;
59            _optimizePath   = true;
60            _drawingCanvas  = new SvgDrawingCanvas();
61
62            this.Child      = _drawingCanvas;
63        }
64
65        #endregion
66
67        #region Public Properties
68
69        /// <summary>
70        /// Gets or sets the path to the SVG file to load into this
71        /// <see cref="Viewbox"/>.
72        /// </summary>
73        /// <value>
74        /// A <see cref="System.Uri"/> specifying the path to the SVG source file.
75        /// The file can be located on a computer, network or assembly resources.
76        /// Settings this to <see langword="null"/> will close any opened diagram.
77        /// </value>
78        public Uri Source
79        {
80            get
81            {
82                return _sourceUri;
83            }
84            set
85            {
86                _sourceUri = value;
87
88                if (_sourceUri == null)
89                {
90                    this.OnUnloadDiagram();
91                }
92                else
93                {
94                    this.OnSettingsChanged();
95                }
96            }
97        }
98
99        /// <summary>
100        /// Gets the drawing canvas, which is the child of this <see cref="Viewbox"/>.
101        /// </summary>
102        /// <value>
103        /// An instance of the <see cref="SvgDrawingCanvas"/> specifying the child
104        /// of this <see cref="Viewbox"/>, which handles the rendering.
105        /// </value>
106        public Canvas DrawingCanvas
107        {
108            get
109            {
110                return _drawingCanvas;
111            }
112        }
113
114        /// <summary>
115        /// Gets or sets a value indicating whether to automatically resize this
116        /// <see cref="Viewbox"/> based on the size of the loaded drawing.
117        /// </summary>
118        /// <value>
119        /// This is <see langword="true"/> if this <see cref="Viewbox"/> is
120        /// automatically resized based on the size of the loaded drawing;
121        /// otherwise, it is <see langword="false"/>. The default is
122        /// <see langword="false"/>, and the user-defined size or the parent assigned
123        /// layout size is used.
124        /// </value>
125        public bool AutoSize
126        {
127            get
128            {
129                return _autoSize;
130            }
131            set
132            {
133                _autoSize = value;
134
135                this.OnAutoSizeChanged();
136            }
137        }
138
139        /// <summary>
140        /// Gets or sets a value indicating whether the path geometry is
141        /// optimized using the <see cref="StreamGeometry"/>.
142        /// </summary>
143        /// <value>
144        /// This is <see langword="true"/> if the path geometry is optimized
145        /// using the <see cref="StreamGeometry"/>; otherwise, it is
146        /// <see langword="false"/>. The default is <see langword="true"/>.
147        /// </value>
148        public bool OptimizePath
149        {
150            get
151            {
152                return _optimizePath;
153            }
154            set
155            {
156                _optimizePath = value;
157
158                this.OnSettingsChanged();
159            }
160        }
161
162        /// <summary>
163        /// Gets or sets a value indicating whether the texts are rendered as
164        /// path geometry.
165        /// </summary>
166        /// <value>
167        /// This is <see langword="true"/> if texts are rendered as path
168        /// geometries; otherwise, this is <see langword="false"/>. The default
169        /// is <see langword="false"/>.
170        /// </value>
171        public bool TextAsGeometry
172        {
173            get
174            {
175                return _textAsGeometry;
176            }
177            set
178            {
179                _textAsGeometry = value;
180
181                this.OnSettingsChanged();
182            }
183        }
184
185        /// <summary>
186        /// Gets or sets a value indicating whether the <c>SharpVectors.Runtime.dll</c>
187        /// classes are used in the generated output.
188        /// </summary>
189        /// <value>
190        /// This is <see langword="true"/> if the <c>SharpVectors.Runtime.dll</c>
191        /// classes and types are used in the generated output; otherwise, it is
192        /// <see langword="false"/>. The default is <see langword="true"/>.
193        /// </value>
194        /// <remarks>
195        /// The use of the <c>SharpVectors.Runtime.dll</c> prevents the hard-coded
196        /// font path generated by the <see cref="FormattedText"/> class, support
197        /// for embedded images etc.
198        /// </remarks>
199        public bool IncludeRuntime
200        {
201            get
202            {
203                return _includeRuntime;
204            }
205            set
206            {
207                _includeRuntime = value;
208
209                this.OnSettingsChanged();
210            }
211        }
212
213        /// <summary>
214        /// Gets or sets the main culture information used for rendering texts.
215        /// </summary>
216        /// <value>
217        /// An instance of the <see cref="CultureInfo"/> specifying the main
218        /// culture information for texts. The default is the English culture.
219        /// </value>
220        /// <remarks>
221        /// <para>
222        /// This is the culture information passed to the <see cref="FormattedText"/>
223        /// class instance for the text rendering.
224        /// </para>
225        /// <para>
226        /// The library does not currently provide any means of splitting texts
227        /// into its multi-language parts.
228        /// </para>
229        /// </remarks>
230        public CultureInfo CultureInfo
231        {
232            get
233            {
234                return _culture;
235            }
236            set
237            {
238                if (value != null)
239                {
240                    _culture = value;
241
242                    this.OnSettingsChanged();
243                }
244            }
245        }
246
247        #endregion
248
249        #region Public Methods
250
251        #endregion
252
253        #region Protected Methods
254
255        /// <summary>
256        /// Raises the Initialized event. This method is invoked whenever IsInitialized is set to true.
257        /// </summary>
258        /// <param name="e">Event data for the event.</param>
259        protected override void OnInitialized(EventArgs e)
260        {
261            base.OnInitialized(e);
262
263            if (_sourceUri != null)
264            {
265                if (_svgDrawing == null)
266                {
267                    DrawingGroup drawing = this.CreateDrawing();
268                    if (drawing != null)
269                    {
270                        this.OnLoadDrawing(drawing);
271                    }
272                }
273            }
274        }
275
276        /// <summary>
277        /// This handles changes in the rendering settings of this control.
278        /// </summary>
279        protected virtual void OnSettingsChanged()
280        {   
281            if (!this.IsInitialized || _sourceUri == null)
282            {
283                return;
284            }
285
286            DrawingGroup drawing = this.CreateDrawing();
287            if (drawing != null)
288            {
289                this.OnLoadDrawing(drawing);
290            }
291        }
292
293        /// <summary>
294        /// This handles changes in the automatic resizing property of this control.
295        /// </summary>
296        protected virtual void OnAutoSizeChanged()
297        {   
298            if (_autoSize)
299            {
300                if (this.IsInitialized && _svgDrawing != null)
301                {
302                    Rect rectDrawing = _svgDrawing.Bounds;
303                    if (!rectDrawing.IsEmpty)
304                    {
305                        this.Width   = rectDrawing.Width;
306                        this.Height  = rectDrawing.Height;
307
308                        _isAutoSized = true;
309                    }
310                }
311            }
312            else
313            {
314                if (_isAutoSized)
315                {
316                    this.Width  = Double.NaN;
317                    this.Height = Double.NaN;
318                }
319            }
320        }
321
322        /// <summary>
323        /// Performs the conversion of a valid SVG source file to the
324        /// <see cref="DrawingGroup"/>.
325        /// </summary>
326        /// <returns>
327        /// This returns <see cref="DrawingGroup"/> if successful; otherwise, it
328        /// returns <see langword="null"/>.
329        /// </returns>
330        protected virtual DrawingGroup CreateDrawing()
331        {
332            Uri svgSource = this.GetAbsoluteUri();
333
334            DrawingGroup drawing = null;
335
336            if (svgSource == null)
337            {
338                return drawing;
339            }
340
341            try
342            {
343                string scheme = svgSource.Scheme;
344                if (String.IsNullOrEmpty(scheme))
345                {
346                    return null;
347                }
348
349                WpfDrawingSettings settings = new WpfDrawingSettings();
350                settings.IncludeRuntime = _includeRuntime;
351                settings.TextAsGeometry = _textAsGeometry;
352                settings.OptimizePath   = _optimizePath;
353                if (_culture != null)
354                {
355                    settings.CultureInfo = _culture;
356                }
357
358                switch (scheme)
359                {
360                    case "file":
361                    //case "ftp":
362                    //case "https":
363                    case "http":
364                        using (FileSvgReader reader =
365                            new FileSvgReader(settings))
366                        {
367                            drawing = reader.Read(svgSource);
368                        }
369                        break;
370                    case "pack":
371                        StreamResourceInfo svgStreamInfo = null;
372                        if (svgSource.ToString().IndexOf("siteoforigin",
373                            StringComparison.OrdinalIgnoreCase) >= 0)
374                        {
375                            svgStreamInfo = Application.GetRemoteStream(svgSource);
376                        }
377                        else
378                        {
379                            svgStreamInfo = Application.GetResourceStream(svgSource);
380                        }
381
382                        Stream svgStream = (svgStreamInfo != null) ?
383                            svgStreamInfo.Stream : null;
384
385                        if (svgStream != null)
386                        {
387                            string fileExt = Path.GetExtension(svgSource.ToString());
388                            bool isCompressed = !String.IsNullOrEmpty(fileExt) &&
389                                String.Equals(fileExt, ".svgz",
390                                StringComparison.OrdinalIgnoreCase);
391
392                            if (isCompressed)
393                            {
394                                using (svgStream)
395                                {
396                                    using (GZipStream zipStream =
397                                        new GZipStream(svgStream, CompressionMode.Decompress))
398                                    {
399                                        using (FileSvgReader reader =
400                                            new FileSvgReader(settings))
401                                        {
402                                            drawing = reader.Read(zipStream);
403                                        }
404                                    }
405                                }
406                            }
407                            else
408                            {
409                                using (svgStream)
410                                {
411                                    using (FileSvgReader reader =
412                                        new FileSvgReader(settings))
413                                    {
414                                        drawing = reader.Read(svgStream);
415                                    }
416                                }
417                            }
418                        }
419                        break;
420                }
421
422            }
423            catch
424            {
425                if (DesignerProperties.GetIsInDesignMode(new DependencyObject()) ||
426                    LicenseManager.UsageMode == LicenseUsageMode.Designtime)
427                {
428                    return drawing;
429                }
430
431                throw;
432            }
433
434            return drawing;
435        }
436
437        #endregion
438
439        #region Private Methods
440
441        private void OnLoadDrawing(DrawingGroup drawing)
442        {   
443            if (drawing == null || _drawingCanvas == null)
444            {
445                return;
446            }
447
448            this.OnUnloadDiagram();
449
450            _drawingCanvas.RenderDiagrams(drawing);
451
452            _svgDrawing = drawing;
453
454            this.OnAutoSizeChanged();
455        }
456
457        private void OnUnloadDiagram()
458        {
459            if (_drawingCanvas != null)
460            {
461                _drawingCanvas.UnloadDiagrams();
462
463                if (_isAutoSized)
464                {
465                    this.Width  = Double.NaN;
466                    this.Height = Double.NaN;
467                }
468            }
469        }
470
471        private Uri GetAbsoluteUri()
472        {
473            if (_sourceUri == null)
474            {
475                return null;
476            }
477            Uri svgSource = _sourceUri;
478
479            if (svgSource.IsAbsoluteUri)
480            {
481                return svgSource;
482            }
483            else
484            {
485                // Try getting a local file in the same directory....
486                string svgPath = svgSource.ToString();
487                if (svgPath[0] == '\\' || svgPath[0] == '/')
488                {
489                    svgPath = svgPath.Substring(1);
490                }
491                svgPath = svgPath.Replace('/', '\\');
492
493                Assembly assembly = Assembly.GetExecutingAssembly();
494                string localFile = Path.Combine(Path.GetDirectoryName(
495                    assembly.Location), svgPath);
496
497                if (File.Exists(localFile))
498                {
499                    return new Uri(localFile);
500                }
501
502                // Try getting it as resource file...
503                if (_baseUri != null)
504                {
505                    return new Uri(_baseUri, svgSource);
506                }
507                else
508                {
509                    string asmName = assembly.GetName().Name;
510                    string uriString = String.Format(
511                        "pack://application:,,,/{0};component/{1}",
512                        asmName, svgPath);
513
514                    return new Uri(uriString);
515                }
516            }
517        }
518
519        #endregion
520
521        #region IUriContext Members
522
523        /// <summary>
524        /// Gets or sets the base URI of the current application context.
525        /// </summary>
526        /// <value>
527        /// The base URI of the application context.
528        /// </value>
529        public Uri BaseUri
530        {
531            get
532            {
533                return _baseUri;
534            }
535            set
536            {
537                _baseUri = value;
538            }
539        }
540
541        #endregion
542    }
543}
Note: See TracBrowser for help on using the repository browser.