11using System ;
22using System . Collections . Generic ;
33using System . ComponentModel ;
4+ using System . Diagnostics ;
45using System . Drawing ;
56using System . Drawing . Text ;
67using System . IO ;
78using System . Runtime . CompilerServices ;
89using System . Threading . Tasks ;
10+ using Serilog ;
911using WinPrint . Core . Models ;
1012using WinPrint . Core . Services ;
1113
@@ -33,7 +35,10 @@ public abstract class ContentTypeEngineBase : ModelBase, INotifyPropertyChanged
3335 /// <summary>
3436 /// ContentType identifier (shorthand for class name).
3537 /// </summary>
36- public static string ContentType = "base" ;
38+ public virtual string GetContentType ( ) {
39+ return _contentType ;
40+ }
41+ private static readonly string _contentType = "base" ;
3742
3843 /// <summary>
3944 /// Calculated page size. Set by Sheet view model.
@@ -54,6 +59,15 @@ public abstract class ContentTypeEngineBase : ModelBase, INotifyPropertyChanged
5459 //}
5560
5661 internal string filePath = null ;
62+
63+ /// <summary>
64+ /// The contents of the file to be printed.
65+ /// </summary>
66+ public string Document { get => document ; set {
67+ //LogService.TraceMessage($"Document is {document.Length} chars.");
68+ SetField ( ref document , value ) ;
69+ }
70+ }
5771 internal string document = null ;
5872
5973 internal StringFormat stringFormat = new StringFormat ( StringFormat . GenericTypographic ) {
@@ -67,23 +81,16 @@ public abstract class ContentTypeEngineBase : ModelBase, INotifyPropertyChanged
6781
6882
6983 /// <summary>
70- /// Loads the file specified into memeory. (holds in document property) .
84+ /// Loads the file specified into Document property.
7185 /// </summary>
7286 /// <param name="filePath"></param>
7387 /// <returns>True if file was read. False if the file was empty or failed to read.</returns>
7488 public async virtual Task < bool > LoadAsync ( string filePath ) {
7589 LogService . TraceMessage ( ) ;
7690 this . filePath = filePath ;
7791 using StreamReader streamToPrint = new StreamReader ( filePath ) ;
78- //try {
79- document = await streamToPrint . ReadToEndAsync ( ) ;
80- LogService . TraceMessage ( $ "document is { document . Length } chars.") ;
81- //}
82- //catch (Exception e) {
83- // LogService.TraceMessage($"Exception {e.Message}");
84- // return false;
85- //}
86- return ! String . IsNullOrEmpty ( document ) ;
92+ Document = await streamToPrint . ReadToEndAsync ( ) ;
93+ return ! String . IsNullOrEmpty ( Document ) ;
8794 }
8895
8996 /// <summary>
@@ -93,8 +100,8 @@ public async virtual Task<bool> LoadAsync(string filePath) {
93100 /// <returns>Number of sheets.</returns>
94101 public virtual async Task < int > RenderAsync ( System . Drawing . Printing . PrinterResolution printerResolution , EventHandler < string > reflowProgress ) {
95102 LogService . TraceMessage ( ) ;
96- if ( document == null )
97- throw new ArgumentNullException ( "document can't be null for Render" ) ;
103+ if ( Document == null )
104+ throw new ArgumentNullException ( "Document can't be null for Render" ) ;
98105 return await Task . FromResult ( 0 ) ;
99106 }
100107
@@ -105,5 +112,59 @@ public virtual async Task<int> RenderAsync(System.Drawing.Printing.PrinterResolu
105112 /// <param name="pageNum">Page number to print</param>
106113 public abstract void PaintPage ( Graphics g , int pageNum ) ;
107114
115+ public static async Task < ContentTypeEngineBase > CreateContentTypeEngine ( string filePath = null , string contentType = null ) {
116+ ContentTypeEngineBase cte = null ;
117+
118+ // If no contenttype was provied, but path was, determine from path.
119+ if ( string . IsNullOrEmpty ( contentType ) && ! string . IsNullOrEmpty ( filePath ) ) {
120+ var ext = Path . GetExtension ( filePath ) . ToLower ( ) ;
121+ // Use file assocations to figure it out
122+ if ( ! ModelLocator . Current . Associations . FilesAssociations . TryGetValue ( "*" + ext , out contentType ) )
123+ contentType = "text/plain" ; // default
124+ }
125+ Debug . Assert ( ! string . IsNullOrEmpty ( contentType ) ) ;
126+
127+ switch ( contentType ) {
128+ case "text/html" :
129+ cte = HtmlCte . Create ( ) ;
130+ break ;
131+
132+ case "text/plain" :
133+ cte = TextCte . Create ( ) ;
134+ break ;
135+
136+ // TODO: Figure out if we really want to use the sourcecode CTE.
137+ case "sourcecode" :
138+ cte = CodeCte . Create ( ) ;
139+ ( ( CodeCte ) cte ) . Language = contentType ;
140+ break ;
141+
142+ default :
143+ // Not text or html. Is it a language?
144+ if ( ( ( List < Langauge > ) ModelLocator . Current . Associations . Languages ) . Exists ( lang => lang . Id == contentType ) ) {
145+ // It's a language. Verify node.js and Prism are installed
146+ if ( await ServiceLocator . Current . NodeService . IsInstalled ( ) ) {
147+ // contentType == Language
148+ cte = PrismCte . Create ( ) ;
149+ ( ( PrismCte ) cte ) . Language = contentType ;
150+ }
151+ else {
152+ Log . Information ( "Node.js must be installed for Prism-based ({lang}) syntax highlighting. Using {def} instead." , contentType , "text/plain" ) ;
153+ contentType = "text/plain" ;
154+ cte = TextCte . Create ( ) ;
155+ }
156+ }
157+ else {
158+ // No language mapping found, just use contentType as the language
159+ // TODO: Do more error checking here
160+ cte = PrismCte . Create ( ) ;
161+ ( ( PrismCte ) cte ) . Language = contentType ;
162+ }
163+ break ;
164+ }
165+
166+ return cte ;
167+ }
168+
108169 }
109170}
0 commit comments