@@ -16,34 +16,90 @@ interface
1616
1717uses
1818 // Project
19+ UBaseObjects,
1920 UEncodings,
21+ USaveSourceDlg,
22+ USourceFileInfo,
2023 UView;
2124
2225
2326type
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 in rich
28+ // / text format. The snippet is obtained from a view. Only snippet views are
29+ // / supported.</summary>
30+ TSaveInfoMgr = class (TNoPublicConstructObject)
2831 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+
3737 // / <summary>Returns encoded data containing a RTF representation of
3838 // / 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 type of file selected in the associated save dialogue
43+ // / box.</summary>
44+ function SelectedFileType : TSourceFileType;
45+
46+ // / <summary>Handles the custom save dialogue's <c>OnPreview</c> event.
47+ // / Displays the required snippet information, appropriately formatted, in
48+ // / a preview dialogues box.</summary>
49+ // / <param name="Sender"><c>TObject</c> [in] Reference to the object that
50+ // / triggered the event.</param>
51+ procedure PreviewHandler (Sender: TObject);
52+
53+ // / <summary>Handles the custom save dialogue's <c>OnHiliteQuery</c> event.
54+ // / Determines whether syntax highlighting is supported for the source code
55+ // / section of the required snippet information..</summary>
56+ // / <param name="Sender"><c>TObject</c> [in] Reference to the object that
57+ // / triggered the event.</param>
58+ // / <param name="CanHilite"><c>Boolean</c> [in/out] Set to <c>False</c>
59+ // / when called. Should be set to <c>True</c> iff highlighting is
60+ // / supported.</param>
61+ procedure HighlightQueryHandler (Sender: TObject; var CanHilite: Boolean);
62+
63+ // / <summary>Handles the custom save dialogue's <c>OnEncodingQuery</c>
64+ // / event.</summary>
65+ // / <param name="Sender"><c>TObject</c> [in] Reference to the object that
66+ // / triggered the event.</param>
67+ // / <param name="Encodings"><c>TSourceFileEncodings</c> [in/out] Called
68+ // / with an empty array which the event handler must be set to contain the
69+ // / encodings supported by the currently selected file type.</param>
70+ procedure EncodingQueryHandler (Sender: TObject;
71+ var Encodings: TSourceFileEncodings);
72+
73+ // / <summary>Generates the required snippet information in the requested
74+ // / format.</summary>
75+ // / <param name="FileType"><c>TSourceFileType</c> [in] Type of file to be
76+ // / generated.</param>
77+ // / <returns><c>TEncodedData</c>. The formatted snippet information, syntax
78+ // / highlighted if required.</returns>
79+ function GenerateOutput (const FileType: TSourceFileType): TEncodedData;
80+
81+ // / <summary>Displays the save dialogue box and creates required type of
82+ // / snippet information file if the user OKs.</summary>
83+ procedure DoExecute ;
84+
85+ strict protected
86+
87+ // / <summary>Internal constructor. Initialises managed save source dialogue
88+ // / box and records information about supported file types.</summary>
89+ constructor InternalCreate(AView: IView);
90+
4091 public
92+
93+ // / <summary>Object descructor. Tears down object.</summary>
94+ destructor Destroy; override;
95+
4196 // / <summary>Saves information about the snippet referenced by the a given
4297 // / view to file.</summary>
4398 // / <remarks>The view must be a snippet view.</remarks>
4499 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>
100+
101+ // / <summary>Checks if the given view can be saved to file. Returns
102+ // / <c>True</c> if the view represents a snippet.</summary>
47103 class function CanHandleView (View : IView): Boolean; static;
48104
49105 end ;
@@ -55,13 +111,16 @@ implementation
55111 SysUtils,
56112 Dialogs,
57113 // Project
114+ FmPreviewDlg,
58115 Hiliter.UAttrs,
116+ Hiliter.UFileHiliter,
59117 Hiliter.UGlobals,
60118 UIOUtils,
61119 UOpenDialogHelper,
120+ UPreferences,
62121 URTFSnippetDoc,
63122 URTFUtils,
64- USaveDialogEx ;
123+ USourceGen ;
65124
66125{ TSaveInfoMgr }
67126
@@ -70,27 +129,84 @@ class function TSaveInfoMgr.CanHandleView(View: IView): Boolean;
70129 Result := Supports(View , ISnippetView);
71130end ;
72131
132+ destructor TSaveInfoMgr.Destroy;
133+ begin
134+ fSourceFileInfo.Free;
135+ fSaveDlg.Free;
136+ inherited ;
137+ end ;
138+
139+ procedure TSaveInfoMgr.DoExecute ;
140+ var
141+ Encoding: TEncoding; // encoding to use for output file
142+ FileContent: string; // output file content before encoding
143+ FileType: TSourceFileType; // type of source file
144+ begin
145+ // Set up dialog box
146+ fSaveDlg.Filter := fSourceFileInfo.FilterString;
147+ fSaveDlg.FilterIndex := FilterDescToIndex(
148+ fSaveDlg.Filter,
149+ fSourceFileInfo.FileTypeInfo[Preferences.SourceDefaultFileType].DisplayName,
150+ 1
151+ );
152+ fSaveDlg.FileName := fSourceFileInfo.DefaultFileName;
153+ // Display dialog box and save file if user OKs
154+ if fSaveDlg.Execute then
155+ begin
156+ FileType := SelectedFileType;
157+ FileContent := GenerateOutput(FileType).ToString;
158+ Encoding := TEncodingHelper.GetEncoding(fSaveDlg.SelectedEncoding);
159+ try
160+ FileContent := GenerateOutput(FileType).ToString;
161+ TFileIO.WriteAllText(fSaveDlg.FileName, FileContent, Encoding, True);
162+ finally
163+ TEncodingHelper.FreeEncoding(Encoding);
164+ end ;
165+ end ;
166+ end ;
167+
168+ procedure TSaveInfoMgr.EncodingQueryHandler (Sender: TObject;
169+ var Encodings: TSourceFileEncodings);
170+ begin
171+ Encodings := fSourceFileInfo.FileTypeInfo[SelectedFileType].Encodings;
172+ end ;
173+
73174class procedure TSaveInfoMgr.Execute (View : IView);
74175var
75- FileName: string;
76- RTFMarkup: TRTFMarkup;
176+ Instance: TSaveInfoMgr;
77177begin
78178 Assert(Assigned(View ), ' TSaveInfoMgr.Execute: View is nil' );
79179 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);
180+
181+ Instance := TSaveInfoMgr.InternalCreate(View );
182+ try
183+ Instance.DoExecute;
184+ finally
185+ Instance.Free;
186+ end ;
187+ end ;
188+
189+ function TSaveInfoMgr.GenerateOutput (const FileType: TSourceFileType):
190+ TEncodedData;
191+ var
192+ UseHiliting: Boolean;
193+ begin
194+ UseHiliting := fSaveDlg.UseSyntaxHiliting and
195+ TFileHiliter.IsHilitingSupported(FileType);
196+ case FileType of
197+ sfRTF: Result := GenerateRichText(fView, UseHiliting);
198+ end ;
84199end ;
85200
86- class function TSaveInfoMgr.GenerateRichText (View : IView): TEncodedData;
201+ class function TSaveInfoMgr.GenerateRichText (View : IView;
202+ const AUseHiliting: Boolean): TEncodedData;
87203var
88204 Doc: TRTFSnippetDoc; // object that generates RTF document
89205 HiliteAttrs: IHiliteAttrs; // syntax highlighter formatting attributes
90206begin
91207 Assert(Supports(View , ISnippetView),
92208 ' TSaveInfoMgr.GenerateRichText: View is not a snippet view' );
93- if (View as ISnippetView).Snippet.HiliteSource then
209+ if (View as ISnippetView).Snippet.HiliteSource and AUseHiliting then
94210 HiliteAttrs := THiliteAttrsFactory.CreateUserAttrs
95211 else
96212 HiliteAttrs := THiliteAttrsFactory.CreateNulAttrs;
@@ -105,28 +221,65 @@ class function TSaveInfoMgr.GenerateRichText(View: IView): TEncodedData;
105221 end ;
106222end ;
107223
108- class function TSaveInfoMgr.TryGetFileNameFromUser (
109- out AFileName: string): Boolean;
110- var
111- Dlg: TSaveDialogEx;
224+ procedure TSaveInfoMgr.HighlightQueryHandler (Sender: TObject;
225+ var CanHilite: Boolean);
226+ begin
227+ CanHilite := TFileHiliter.IsHilitingSupported(SelectedFileType);
228+ end ;
229+
230+ constructor TSaveInfoMgr.InternalCreate(AView: IView);
231+ const
232+ DlgHelpKeyword = ' SnippetInfoFileDlg' ;
112233resourcestring
113- sCaption = ' Save Snippet Information' ; // dialogue box caption
114- sFilter = ' Rich Text File (*.rtf)|*.rtf|' // file filter
115- + ' All files (*.*)|*.*' ;
234+ sDefFileName = ' SnippetInfo' ;
235+ sDlgCaption = ' Save Snippet Information' ;
236+ // descriptions of supported encodings
237+ sASCIIEncoding = ' ASCII' ;
238+ // descriptions of supported file filter strings
239+ sRTFDesc = ' Rich text file' ;
116240begin
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;
129- end ;
241+ inherited InternalCreate;
242+ fView := AView;
243+ fSourceFileInfo := TSourceFileInfo.Create;
244+ // only RTF file type supported at present
245+ fSourceFileInfo.FileTypeInfo[sfRTF] := TSourceFileTypeInfo.Create(
246+ ' .rtf' ,
247+ sRTFDesc,
248+ [
249+ TSourceFileEncoding.Create(etASCII, sASCIIEncoding)
250+ ]
251+ );
252+ fSourceFileInfo.DefaultFileName := sDefFileName;
253+
254+ fSaveDlg := TSaveSourceDlg.Create(nil );
255+ fSaveDlg.Title := sDlgCaption;
256+ fSaveDlg.HelpKeyword := DlgHelpKeyword;
257+ fSaveDlg.CommentStyle := TCommentStyle.csNone;
258+ fSaveDlg.EnableCommentStyles := False;
259+ fSaveDlg.TruncateComments := Preferences.TruncateSourceComments;
260+ fSaveDlg.UseSyntaxHiliting := Preferences.SourceSyntaxHilited;
261+ fSaveDlg.OnPreview := PreviewHandler;
262+ fSaveDlg.OnHiliteQuery := HighlightQueryHandler;
263+ fSaveDlg.OnEncodingQuery := EncodingQueryHandler;
264+ end ;
265+
266+ procedure TSaveInfoMgr.PreviewHandler (Sender: TObject);
267+ resourcestring
268+ sDocTitle = ' "%0:s" snippet' ;
269+ begin
270+ // Display preview dialog box. We use save dialog as owner to ensure preview
271+ // dialog box is aligned over save dialog box
272+ TPreviewDlg.Execute(
273+ fSaveDlg,
274+ GenerateOutput(sfRTF),
275+ dtRTF,
276+ Format(sDocTitle, [fView.Description])
277+ );
278+ end ;
279+
280+ function TSaveInfoMgr.SelectedFileType : TSourceFileType;
281+ begin
282+ Result := fSourceFileInfo.FileTypeFromFilterIdx(fSaveDlg.FilterIndex);
130283end ;
131284
132285end .
0 commit comments