Menu

[r2337]: / trunk / Src / FmSnippetsEditorDlg.FrActiveTextEditor.pas  Maximize  Restore  History

Download this file

308 lines (274 with data), 8.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
{
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/
*
* Copyright (C) 2012, Peter Johnson (www.delphidabbler.com).
*
* $Rev$
* $Date$
*
* A frame that provides an editor for entering and ammending active text,
* either as plain text or in markup.
*
* Designed specifically for use in the Snippets Editor.
}
unit FmSnippetsEditorDlg.FrActiveTextEditor;
interface
uses
// Delphi
Forms, ComCtrls, Menus, Classes, ActnList, Controls, StdCtrls, ImgList,
StdActns,
// Project
ActiveText.UMain;
type
TSnippetsActiveTextEdFrame = class(TFrame)
edText: TMemo;
alEditor: TActionList;
mnuEditor: TPopupMenu;
miConvertToPlainText: TMenuItem;
miConvertToREML: TMenuItem;
actConvertToPlainText: TAction;
actConvertToREML: TAction;
tcEditMode: TTabControl;
ilEditor: TImageList;
actCut: TEditCut;
actCopy: TEditCopy;
actPaste: TEditPaste;
actSelectAll: TEditSelectAll;
actUndo: TEditUndo;
miSpace1: TMenuItem;
miCut: TMenuItem;
miCopy: TMenuItem;
miPaste: TMenuItem;
miSelectAll: TMenuItem;
miSpacer2: TMenuItem;
miUndo: TMenuItem;
miSpacer3: TMenuItem;
procedure actConvertToPlainTextExecute(Sender: TObject);
procedure actConvertToREMLExecute(Sender: TObject);
procedure actConvertToPlainTextUpdate(Sender: TObject);
procedure actConvertToREMLUpdate(Sender: TObject);
procedure tcEditModeChange(Sender: TObject);
public
type
TEditMode = (emPlainText, emREML, emAuto);
strict private
var
fEditMode: TEditMode;
fDefaultEditMode: TEditMode;
function ActiveTextToPlainText(ActiveText: IActiveText): string;
function ActiveTextToREML(ActiveText: IActiveText): string;
function PlainTextToActiveText(Text: string): IActiveText;
function REMLToActiveText(const Text: string): IActiveText;
function Parse: IActiveText;
function GetActiveText: IActiveText;
procedure SetActiveText(Value: IActiveText);
procedure SetEditMode(AMode: TEditMode);
public
procedure Validate;
procedure Clear;
procedure Preview;
function CanPreview: Boolean;
property ActiveText: IActiveText read GetActiveText write SetActiveText;
property DefaultEditMode: TEditMode
read fDefaultEditMode write fDefaultEditMode;
end;
implementation
uses
// Project
ActiveText.UValidator, FmActiveTextPreviewDlg, UConsts, UExceptions,
UFontHelper, UIStringList, USnippetExtraHelper, UStrUtils;
{$R *.dfm}
procedure TSnippetsActiveTextEdFrame.actConvertToPlainTextExecute(
Sender: TObject);
var
ActiveText: IActiveText;
begin
ActiveText := GetActiveText; // raises exception on error
edText.Text := ActiveTextToPlainText(ActiveText);
SetEditMode(emPlainText);
end;
procedure TSnippetsActiveTextEdFrame.actConvertToPlainTextUpdate(
Sender: TObject);
begin
(Sender as TAction).Enabled := fEditMode = emREML;
end;
procedure TSnippetsActiveTextEdFrame.actConvertToREMLExecute(Sender: TObject);
var
ActiveText: IActiveText;
begin
ActiveText := GetActiveText;
edText.Text := ActiveTextToREML(ActiveText);
SetEditMode(emREML);
end;
procedure TSnippetsActiveTextEdFrame.actConvertToREMLUpdate(Sender: TObject);
begin
(Sender as TAction).Enabled := fEditMode = emPlainText;
end;
function TSnippetsActiveTextEdFrame.ActiveTextToPlainText(
ActiveText: IActiveText): string;
var
Lines: IStringList;
begin
// NOTE: we use IActiveText.ToString here, because there may be text not in
// blocks and we want to see that: usual renderer will ignore that text.
// However all lines are trimmed and empty blanks are ingored.
Lines := TIStringList.Create(ActiveText.ToString, EOL, False, True);
Result := Lines.GetText(EOL2, False); // insert blank line between paras
end;
function TSnippetsActiveTextEdFrame.ActiveTextToREML(ActiveText: IActiveText):
string;
begin
Result := TSnippetExtraHelper.BuildREMLMarkup(ActiveText);
end;
function TSnippetsActiveTextEdFrame.CanPreview: Boolean;
begin
Result := StrTrim(edText.Text) <> '';
end;
procedure TSnippetsActiveTextEdFrame.Clear;
begin
edText.Clear;
end;
function TSnippetsActiveTextEdFrame.GetActiveText: IActiveText;
var
ValidatorErrInfo: TActiveTextValidator.TErrorInfo;
// active text validation error
ParseError: EDataEntry; // parser error
resourcestring
// parse error message
sActiveTextErr = 'Error parsing extra information markup:' + EOL2 + '%s';
begin
try
Result := Parse;
except
// Convert active text parser to data exception
on E: EActiveTextParserError do
begin
ParseError := EDataEntry.CreateFmt(
sActiveTextErr, [E.Message], edText
);
if E.HasSelection then
ParseError.Selection := E.Selection;
raise ParseError;
end
else
raise;
end;
// Validate the active text
if not TActiveTextValidator.Validate(Result, ValidatorErrInfo) then
raise EDataEntry.Create(
ValidatorErrInfo.Description, edText // no selection info available
);
end;
function TSnippetsActiveTextEdFrame.Parse: IActiveText;
var
Text: string;
begin
Text := StrTrim(edText.Text);
if Text = '' then
Exit(TActiveTextFactory.CreateActiveText);
case fEditMode of
emPlainText:
begin
Result := PlainTextToActiveText(Text);
end;
emREML:
begin
Result := REMLToActiveText(Text);
end;
else
Result := TActiveTextFactory.CreateActiveText;
end;
end;
function TSnippetsActiveTextEdFrame.PlainTextToActiveText(Text: string):
IActiveText;
var
Paragraphs: IStringList; // list of paragraphs (separated by newlines pairs)
Paragraph: string; // each paragraph in paragraphs
begin
// NOTE: TSnippetExtraHelper.PlainTextToActiveText is not sufficient for use
// here since it ignores newlines and we want double newlines to separated
// paragraphs.
Result := TActiveTextFactory.CreateActiveText;
Text := StrTrim(Text);
if Text = '' then
Exit;
Paragraphs := TIStringList.Create(Text, EOL2, False, True);
for Paragraph in Paragraphs do
begin
Result.AddElem(TActiveTextFactory.CreateActionElem(ekPara, fsOpen));
Result.AddElem(
TActiveTextFactory.CreateTextElem(StrCompressWhiteSpace(Paragraph))
);
Result.AddElem(TActiveTextFactory.CreateActionElem(ekPara, fsClose));
end;
end;
procedure TSnippetsActiveTextEdFrame.Preview;
var
ActiveText: IActiveText;
begin
ActiveText := GetActiveText; // raises exceptions on error
TActiveTextPreviewDlg.Execute(nil, ActiveText);
end;
function TSnippetsActiveTextEdFrame.REMLToActiveText(const Text: string):
IActiveText;
var
Paras: IStringList;
begin
Paras := TIStringList.Create(Text, EOL2, False, True);
Result := TSnippetExtraHelper.BuildActiveText(Paras);
end;
procedure TSnippetsActiveTextEdFrame.SetActiveText(Value: IActiveText);
begin
if fDefaultEditMode = emAuto then
if Value.IsPlainText then
SetEditMode(emPlainText)
else
SetEditMode(emREML)
else
SetEditMode(fDefaultEditMode);
if not Value.IsEmpty then
begin
case fEditMode of
emPlainText:
edText.Text := ActiveTextToPlainText(Value);
emREML:
edText.Text := ActiveTextToREML(Value);
else
edText.Text := '';
end;
end
else
edText.Text := '';
end;
procedure TSnippetsActiveTextEdFrame.SetEditMode(AMode: TEditMode);
begin
Assert(AMode <> emAuto, ClassName + '.SetEditMode: AMode is emAuto');
fEditMode := AMode;
case fEditMode of
emPlainText:
begin
tcEditMode.TabIndex := 0;
TFontHelper.SetDefaultFont(edText.Font, True);
end;
emREML:
begin
tcEditMode.TabIndex := 1;
TFontHelper.SetDefaultMonoFont(edText.Font, True);
end;
end;
end;
procedure TSnippetsActiveTextEdFrame.tcEditModeChange(Sender: TObject);
begin
case tcEditMode.TabIndex of
0: SetEditMode(emPlainText);
1: SetEditMode(emREML);
end;
end;
procedure TSnippetsActiveTextEdFrame.Validate;
begin
// Following method parses data entry and converts any exceptions
GetActiveText;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.