@@ -16,34 +16,94 @@ interface
16
16
17
17
uses
18
18
// Project
19
+ UBaseObjects,
19
20
UEncodings,
21
+ USaveSourceDlg,
22
+ USourceFileInfo,
20
23
UView;
21
24
22
25
23
26
type
24
- // / <summary>Method-only record that saves information about a snippet to
25
- // / file in rich text format. The snippet is obtained from a view. Only
26
- // / snippet views are supported.</summary>
27
- TSaveInfoMgr = record
27
+ // / <summary>Class that saves information about a snippet to file a user
28
+ // / specified format. The snippet is obtained from a view. Only snippet views
29
+ // / are supported.</summary>
30
+ TSaveInfoMgr = class (TNoPublicConstructObject)
28
31
strict private
29
- // / <summary>Attempts to name of the file to be written from the user.
30
- // / </summary>
31
- // / <param name="AFileName"><c>string</c> [out] Set to the name of the file
32
- // / entered by the user. Undefined if the user cancelled.</param>
33
- // / <returns><c>Boolean</c>. <c>True</c> if the user entered and accepted a
34
- // / file name of <c>False</c> if the user cancelled.</returns>
35
- class function TryGetFileNameFromUser (out AFileName: string): Boolean;
36
- static;
32
+ var
33
+ fView: IView;
34
+ fSaveDlg: TSaveSourceDlg;
35
+ fSourceFileInfo: TSourceFileInfo;
36
+
37
37
// / <summary>Returns encoded data containing a RTF representation of
38
38
// / information about the snippet represented by the given view.</summary>
39
- class function GenerateRichText (View : IView): TEncodedData; static;
39
+ class function GenerateRichText (View : IView; const AUseHiliting: Boolean):
40
+ TEncodedData; static;
41
+
42
+ // / <summary>Returns encoded data containing a plain text representation of
43
+ // / information about the snippet represented by the given view.</summary>
44
+ function GeneratePlainText : TEncodedData;
45
+
46
+ // / <summary>Returns type of file selected in the associated save dialogue
47
+ // / box.</summary>
48
+ function SelectedFileType : TSourceFileType;
49
+
50
+ // / <summary>Handles the custom save dialogue's <c>OnPreview</c> event.
51
+ // / Displays the required snippet information, appropriately formatted, in
52
+ // / a preview dialogues box.</summary>
53
+ // / <param name="Sender"><c>TObject</c> [in] Reference to the object that
54
+ // / triggered the event.</param>
55
+ procedure PreviewHandler (Sender: TObject);
56
+
57
+ // / <summary>Handles the custom save dialogue's <c>OnHiliteQuery</c> event.
58
+ // / Determines whether syntax highlighting is supported for the source code
59
+ // / section of the required snippet information..</summary>
60
+ // / <param name="Sender"><c>TObject</c> [in] Reference to the object that
61
+ // / triggered the event.</param>
62
+ // / <param name="CanHilite"><c>Boolean</c> [in/out] Set to <c>False</c>
63
+ // / when called. Should be set to <c>True</c> iff highlighting is
64
+ // / supported.</param>
65
+ procedure HighlightQueryHandler (Sender: TObject; var CanHilite: Boolean);
66
+
67
+ // / <summary>Handles the custom save dialogue's <c>OnEncodingQuery</c>
68
+ // / event.</summary>
69
+ // / <param name="Sender"><c>TObject</c> [in] Reference to the object that
70
+ // / triggered the event.</param>
71
+ // / <param name="Encodings"><c>TSourceFileEncodings</c> [in/out] Called
72
+ // / with an empty array which the event handler must be set to contain the
73
+ // / encodings supported by the currently selected file type.</param>
74
+ procedure EncodingQueryHandler (Sender: TObject;
75
+ var Encodings: TSourceFileEncodings);
76
+
77
+ // / <summary>Generates the required snippet information in the requested
78
+ // / format.</summary>
79
+ // / <param name="FileType"><c>TSourceFileType</c> [in] Type of file to be
80
+ // / generated.</param>
81
+ // / <returns><c>TEncodedData</c>. The formatted snippet information, syntax
82
+ // / highlighted if required.</returns>
83
+ function GenerateOutput (const FileType: TSourceFileType): TEncodedData;
84
+
85
+ // / <summary>Displays the save dialogue box and creates required type of
86
+ // / snippet information file if the user OKs.</summary>
87
+ procedure DoExecute ;
88
+
89
+ strict protected
90
+
91
+ // / <summary>Internal constructor. Initialises managed save source dialogue
92
+ // / box and records information about supported file types.</summary>
93
+ constructor InternalCreate(AView: IView);
94
+
40
95
public
96
+
97
+ // / <summary>Object descructor. Tears down object.</summary>
98
+ destructor Destroy; override;
99
+
41
100
// / <summary>Saves information about the snippet referenced by the a given
42
101
// / view to file.</summary>
43
102
// / <remarks>The view must be a snippet view.</remarks>
44
103
class procedure Execute (View : IView); static;
45
- // / <summary>Checks if a given view can be saved to the clipboard. Returns
46
- // / True only if the view represents a snippet.</summary>
104
+
105
+ // / <summary>Checks if the given view can be saved to file. Returns
106
+ // / <c>True</c> if the view represents a snippet.</summary>
47
107
class function CanHandleView (View : IView): Boolean; static;
48
108
49
109
end ;
@@ -55,13 +115,17 @@ implementation
55
115
SysUtils,
56
116
Dialogs,
57
117
// Project
118
+ FmPreviewDlg,
58
119
Hiliter.UAttrs,
120
+ Hiliter.UFileHiliter,
59
121
Hiliter.UGlobals,
60
122
UIOUtils,
61
123
UOpenDialogHelper,
124
+ UPreferences,
62
125
URTFSnippetDoc,
63
126
URTFUtils,
64
- USaveDialogEx;
127
+ USourceGen,
128
+ UTextSnippetDoc;
65
129
66
130
{ TSaveInfoMgr }
67
131
@@ -70,27 +134,101 @@ class function TSaveInfoMgr.CanHandleView(View: IView): Boolean;
70
134
Result := Supports(View , ISnippetView);
71
135
end ;
72
136
137
+ destructor TSaveInfoMgr.Destroy;
138
+ begin
139
+ fSourceFileInfo.Free;
140
+ fSaveDlg.Free;
141
+ inherited ;
142
+ end ;
143
+
144
+ procedure TSaveInfoMgr.DoExecute ;
145
+ var
146
+ Encoding: TEncoding; // encoding to use for output file
147
+ FileContent: string; // output file content before encoding
148
+ FileType: TSourceFileType; // type of source file
149
+ begin
150
+ // Set up dialog box
151
+ fSaveDlg.Filter := fSourceFileInfo.FilterString;
152
+ fSaveDlg.FilterIndex := FilterDescToIndex(
153
+ fSaveDlg.Filter,
154
+ fSourceFileInfo.FileTypeInfo[Preferences.SourceDefaultFileType].DisplayName,
155
+ 1
156
+ );
157
+ fSaveDlg.FileName := fSourceFileInfo.DefaultFileName;
158
+ // Display dialog box and save file if user OKs
159
+ if fSaveDlg.Execute then
160
+ begin
161
+ FileType := SelectedFileType;
162
+ FileContent := GenerateOutput(FileType).ToString;
163
+ Encoding := TEncodingHelper.GetEncoding(fSaveDlg.SelectedEncoding);
164
+ try
165
+ FileContent := GenerateOutput(FileType).ToString;
166
+ TFileIO.WriteAllText(fSaveDlg.FileName, FileContent, Encoding, True);
167
+ finally
168
+ TEncodingHelper.FreeEncoding(Encoding);
169
+ end ;
170
+ end ;
171
+ end ;
172
+
173
+ procedure TSaveInfoMgr.EncodingQueryHandler (Sender: TObject;
174
+ var Encodings: TSourceFileEncodings);
175
+ begin
176
+ Encodings := fSourceFileInfo.FileTypeInfo[SelectedFileType].Encodings;
177
+ end ;
178
+
73
179
class procedure TSaveInfoMgr.Execute (View : IView);
74
180
var
75
- FileName: string;
76
- RTFMarkup: TRTFMarkup;
181
+ Instance: TSaveInfoMgr;
77
182
begin
78
183
Assert(Assigned(View ), ' TSaveInfoMgr.Execute: View is nil' );
79
184
Assert(CanHandleView(View ), ' TSaveInfoMgr.Execute: View not supported' );
80
- if not TryGetFileNameFromUser(FileName) then
81
- Exit;
82
- RTFMarkup := TRTFMarkup.Create(GenerateRichText(View ));
83
- TFileIO.WriteAllBytes(FileName, RTFMarkup.ToBytes);
185
+
186
+ Instance := TSaveInfoMgr.InternalCreate(View );
187
+ try
188
+ Instance.DoExecute;
189
+ finally
190
+ Instance.Free;
191
+ end ;
84
192
end ;
85
193
86
- class function TSaveInfoMgr.GenerateRichText (View : IView): TEncodedData;
194
+ function TSaveInfoMgr.GenerateOutput (const FileType: TSourceFileType):
195
+ TEncodedData;
196
+ var
197
+ UseHiliting: Boolean;
198
+ begin
199
+ UseHiliting := fSaveDlg.UseSyntaxHiliting and
200
+ TFileHiliter.IsHilitingSupported(FileType);
201
+ case FileType of
202
+ sfRTF: Result := GenerateRichText(fView, UseHiliting);
203
+ sfText: Result := GeneratePlainText;
204
+ end ;
205
+ end ;
206
+
207
+ function TSaveInfoMgr.GeneratePlainText : TEncodedData;
208
+ var
209
+ Doc: TTextSnippetDoc; // object that generates RTF document
210
+ HiliteAttrs: IHiliteAttrs; // syntax highlighter formatting attributes
211
+ begin
212
+ Assert(Supports(fView, ISnippetView),
213
+ ClassName + ' .GeneratePlainText: View is not a snippet view' );
214
+ HiliteAttrs := THiliteAttrsFactory.CreateNulAttrs;
215
+ Doc := TTextSnippetDoc.Create;
216
+ try
217
+ Result := Doc.Generate((fView as ISnippetView).Snippet);
218
+ finally
219
+ Doc.Free;
220
+ end ;
221
+ end ;
222
+
223
+ class function TSaveInfoMgr.GenerateRichText (View : IView;
224
+ const AUseHiliting: Boolean): TEncodedData;
87
225
var
88
226
Doc: TRTFSnippetDoc; // object that generates RTF document
89
227
HiliteAttrs: IHiliteAttrs; // syntax highlighter formatting attributes
90
228
begin
91
229
Assert(Supports(View , ISnippetView),
92
230
' TSaveInfoMgr.GenerateRichText: View is not a snippet view' );
93
- if (View as ISnippetView).Snippet.HiliteSource then
231
+ if (View as ISnippetView).Snippet.HiliteSource and AUseHiliting then
94
232
HiliteAttrs := THiliteAttrsFactory.CreateUserAttrs
95
233
else
96
234
HiliteAttrs := THiliteAttrsFactory.CreateNulAttrs;
@@ -105,28 +243,103 @@ class function TSaveInfoMgr.GenerateRichText(View: IView): TEncodedData;
105
243
end ;
106
244
end ;
107
245
108
- class function TSaveInfoMgr.TryGetFileNameFromUser (
109
- out AFileName: string): Boolean;
110
- var
111
- Dlg: TSaveDialogEx;
246
+ procedure TSaveInfoMgr.HighlightQueryHandler (Sender: TObject;
247
+ var CanHilite: Boolean);
248
+ begin
249
+ CanHilite := TFileHiliter.IsHilitingSupported(SelectedFileType);
250
+ end ;
251
+
252
+ constructor TSaveInfoMgr.InternalCreate(AView: IView);
253
+ const
254
+ DlgHelpKeyword = ' SnippetInfoFileDlg' ;
112
255
resourcestring
113
- sCaption = ' Save Snippet Information' ; // dialogue box caption
114
- sFilter = ' Rich Text File (*.rtf)|*.rtf|' // file filter
115
- + ' All files (*.*)|*.*' ;
256
+ sDefFileName = ' SnippetInfo' ;
257
+ sDlgCaption = ' Save Snippet Information' ;
258
+ // descriptions of supported encodings
259
+ sASCIIEncoding = ' ASCII' ;
260
+ sANSIDefaultEncoding = ' ANSI (Default)' ;
261
+ sUTF8Encoding = ' UTF-8' ;
262
+ sUTF16LEEncoding = ' Unicode (Little Endian)' ;
263
+ sUTF16BEEncoding = ' Unicode (Big Endian)' ;
264
+ // descriptions of supported file filter strings
265
+ sRTFDesc = ' Rich text file' ;
266
+ sTextDesc = ' Plain text file' ;
116
267
begin
117
- Dlg := TSaveDialogEx.Create(nil );
118
- try
119
- Dlg.Title := sCaption;
120
- Dlg.Options := [ofShowHelp, ofNoTestFileCreate, ofEnableSizing];
121
- Dlg.Filter := sFilter;
122
- Dlg.FilterIndex := 1 ;
123
- Dlg.HelpKeyword := ' SnippetInfoFileDlg' ;
124
- Result := Dlg.Execute;
125
- if Result then
126
- AFileName := FileOpenFileNameWithExt(Dlg)
127
- finally
128
- Dlg.Free;
268
+ inherited InternalCreate;
269
+ fView := AView;
270
+ fSourceFileInfo := TSourceFileInfo.Create;
271
+ // RTF and plain text files supported at present
272
+ fSourceFileInfo.FileTypeInfo[sfRTF] := TSourceFileTypeInfo.Create(
273
+ ' .rtf' ,
274
+ sRTFDesc,
275
+ [
276
+ TSourceFileEncoding.Create(etASCII, sASCIIEncoding)
277
+ ]
278
+ );
279
+ fSourceFileInfo.FileTypeInfo[sfText] := TSourceFileTypeInfo.Create(
280
+ ' .txt' ,
281
+ sTextDesc,
282
+ [
283
+ TSourceFileEncoding.Create(etUTF8, sUTF8Encoding),
284
+ TSourceFileEncoding.Create(etUTF16LE, sUTF16LEEncoding),
285
+ TSourceFileEncoding.Create(etUTF16BE, sUTF16BEEncoding),
286
+ TSourceFileEncoding.Create(etSysDefault, sANSIDefaultEncoding)
287
+ ]
288
+ );
289
+ fSourceFileInfo.DefaultFileName := sDefFileName;
290
+
291
+ fSaveDlg := TSaveSourceDlg.Create(nil );
292
+ fSaveDlg.Title := sDlgCaption;
293
+ fSaveDlg.HelpKeyword := DlgHelpKeyword;
294
+ fSaveDlg.CommentStyle := TCommentStyle.csNone;
295
+ fSaveDlg.EnableCommentStyles := False;
296
+ fSaveDlg.TruncateComments := Preferences.TruncateSourceComments;
297
+ fSaveDlg.UseSyntaxHiliting := Preferences.SourceSyntaxHilited;
298
+ fSaveDlg.OnPreview := PreviewHandler;
299
+ fSaveDlg.OnHiliteQuery := HighlightQueryHandler;
300
+ fSaveDlg.OnEncodingQuery := EncodingQueryHandler;
301
+ end ;
302
+
303
+ procedure TSaveInfoMgr.PreviewHandler (Sender: TObject);
304
+ resourcestring
305
+ sDocTitle = ' "%0:s" snippet' ;
306
+ var
307
+ // Type of snippet information document to preview: this is not always the
308
+ // same as the selected file type, because preview dialogue box doesn't
309
+ // support some types & we have to use an alternate.
310
+ PreviewFileType: TSourceFileType;
311
+ // Type of preview document supported by preview dialogue box
312
+ PreviewDocType: TPreviewDocType;
313
+ begin
314
+ case SelectedFileType of
315
+ sfRTF:
316
+ begin
317
+ PreviewDocType := dtRTF;
318
+ PreviewFileType := sfRTF;
319
+ end ;
320
+ sfText:
321
+ begin
322
+ PreviewDocType := dtPlainText;
323
+ PreviewFileType := sfText;
324
+ end ;
325
+ else
326
+ raise Exception.Create(
327
+ ClassName + ' .PreviewHandler: unsupported file type'
328
+ );
129
329
end ;
330
+ // Display preview dialog box. We use save dialog as owner to ensure preview
331
+ // dialog box is aligned over save dialog box
332
+ TPreviewDlg.Execute(
333
+ fSaveDlg,
334
+ GenerateOutput(PreviewFileType),
335
+ PreviewDocType,
336
+ Format(sDocTitle, [fView.Description])
337
+ );
338
+ end ;
339
+
340
+ function TSaveInfoMgr.SelectedFileType : TSourceFileType;
341
+ begin
342
+ Result := fSourceFileInfo.FileTypeFromFilterIdx(fSaveDlg.FilterIndex);
130
343
end ;
131
344
132
345
end .
0 commit comments