source: branches/2.20_branch/Components/RichTextStyleUnit.pas@ 415

Last change on this file since 415 was 214, checked in by RBRi, 18 years ago

using StringUtilsUnit

  • Property svn:eol-style set to native
File size: 17.3 KB
Line 
1Unit RichTextStyleUnit;
2
3Interface
4
5uses
6 Forms,
7 Classes,
8 Graphics,
9 CanvasFontManager,
10 RichTextDocumentUnit;
11
12type
13 TTextDrawStyle = record
14 Font: TFontSpec;
15 Color: TColor;
16 BackgroundColor: TColor;
17 Alignment: TTextAlignment;
18 Wrap: boolean;
19 LeftMargin: longint;
20 RightMargin: longint;
21 end;
22
23 TMarginSizeStyle = ( msAverageCharWidth, msMaximumCharWidth, msSpecifiedChar );
24
25 TRichTextSettings = class( TComponent )
26 protected
27 FHeading1Font: TFont;
28 FHeading2Font: TFont;
29 FHeading3Font: TFont;
30
31 FFixedFont: TFont;
32 FNormalFont: TFont;
33
34 FDefaultBackgroundColor: TColor;
35 FDefaultColor: TColor;
36
37 FDefaultAlignment: TTextAlignment;
38 FDefaultWrap: boolean;
39
40 FAtLeastOneWordBeforeWrap: boolean;
41
42 FMarginSizeStyle: TMarginSizeStyle;
43 FMarginChar: longint;
44
45 FOnChange: TNotifyEvent;
46
47 FMargins: TRect;
48
49 FUpdateCount: longint;
50 FChangesPending: boolean;
51
52 Procedure Change;
53
54 Procedure SetNormalFont( NewFont: TFont );
55 Procedure SetFixedFont( NewFont: TFont );
56 Procedure SetHeading1Font( NewFont: TFont );
57 Procedure SetHeading2Font( NewFont: TFont );
58 Procedure SetHeading3Font( NewFont: TFont );
59
60 Procedure SetDefaultColor( NewColor: TColor );
61 Procedure SetDefaultBackgroundColor( NewColor: TColor );
62
63 Procedure SetDefaultAlignment( Alignment: TTextAlignment );
64 Procedure SetDefaultWrap( Wrap: boolean );
65 Procedure SetAtLeastOneWordBeforeWrap( NewValue: boolean );
66
67 Procedure SetMarginSizeStyle( NewValue: TMarginSizeStyle );
68 Procedure SetMarginChar( NewValue: longint );
69
70 Procedure SetMargins( const NewMargins: TRect );
71
72 function GetMargin_Left: longint;
73 Procedure SetMargin_Left( NewValue: longint );
74 function GetMargin_Bottom: longint;
75 Procedure SetMargin_Bottom( NewValue: longint );
76 function GetMargin_Right: longint;
77 Procedure SetMargin_Right( NewValue: longint );
78 function GetMargin_Top: longint;
79 Procedure SetMargin_Top( NewValue: longint );
80
81 Procedure SetupComponent; override;
82 destructor Destroy; override;
83
84 Procedure AssignFont( Var Font: TFont;
85 NewFont: TFont );
86
87 // Hide properties...
88 property Name;
89
90 public
91 property OnChange: TNotifyEvent read FOnChange write FOnChange;
92
93 procedure BeginUpdate;
94 procedure EndUpdate;
95
96 // Stream in/out
97 Procedure ReadSCUResource( Const ResName: TResourceName;
98 Var Data;
99 DataLen: LongInt ); override;
100 Function WriteSCUResource( Stream: TResourceStream ): boolean; override;
101
102 property Margins: TRect read FMargins write SetMargins;
103
104 property Heading1Font: TFont read FHeading1Font write SetHeading1Font;
105 property Heading2Font: TFont read FHeading2Font write SetHeading2Font;
106 property Heading3Font: TFont read FHeading3Font write SetHeading3Font;
107 property FixedFont: TFont read FFixedFont write SetFixedFont;
108 property NormalFont: TFont read FNormalFont write SetNormalFont;
109
110 published
111
112 property DefaultBackgroundColor: TColor read FDefaultBackgroundColor write SetDefaultBackgroundColor;
113 property DefaultColor: TColor read FDefaultColor write SetDefaultColor;
114
115 property DefaultAlignment: TTextAlignment read FDefaultAlignment write SetDefaultAlignment;
116 property DefaultWrap: boolean read FDefaultWrap write SetDefaultWrap;
117 property AtLeastOneWordBeforeWrap: boolean read FAtLeastOneWordBeforeWrap write SetAtLeastOneWordBeforeWrap;
118
119 property MarginSizeStyle: TMarginSizeStyle read FMarginSizeStyle write SeTMarginSizeStyle;
120 property MarginChar: longint read FMarginChar write SetMarginChar;
121
122 // margins are exposed as individual properties here
123 // since the Sibyl IDE cannot cope with editing a record property
124 // within a class property (as in RichTextView)
125 property Margin_Left: longint read GetMargin_Left write SetMargin_Left;
126 property Margin_Bottom: longint read GetMargin_Bottom write SetMargin_Bottom;
127 property Margin_Right: longint read GetMargin_Right write SetMargin_Right;
128 property Margin_Top: longint read GetMargin_Top write SetMargin_Top;
129 end;
130
131// pRichTextSettings = ^TRichTextSettings;
132 Procedure ApplyStyle( const Style: TTextDrawStyle;
133 FontManager: TCanvasFontManager );
134
135 Procedure ApplyStyleTag( const Tag: TTag;
136 Var Style: TTextDrawStyle;
137 FontManager: TCanvasFontManager;
138 const Settings: TRichTextSettings;
139 const X: longint );
140
141 function GetDefaultStyle( const Settings: TRichTextSettings ): TTextDrawStyle;
142
143Exports
144 TRichTextSettings,'User','';
145
146Implementation
147
148uses
149 SysUtils,
150 StringUtilsUnit;
151
152Procedure ApplyStyle( const Style: TTextDrawStyle;
153 FontManager: TCanvasFontManager );
154begin
155 FontManager.SetFont( Style.Font );
156 FontManager.Canvas.Pen.Color := Style.Color;
157end;
158
159Procedure ApplyStyleTag( Const Tag: TTag;
160 Var Style: TTextDrawStyle;
161 FontManager: TCanvasFontManager;
162 const Settings: TRichTextSettings;
163 const X: longint );
164var
165 MarginParam1: string;
166 MarginParam2: string;
167 NewMargin: longint;
168 FontFaceName: string;
169 FontSizeString: string;
170 NewStyle: TTextDrawStyle;
171 ParseIndex: longint;
172 XSizeStr: string;
173 YSizeStr: string;
174 tmpFontParts : TStringList;
175
176 MarginSize: longint;
177 ParsePoint: longint;
178begin
179 case Tag.TagType of
180 ttBold:
181 Include( Style.Font.Attributes, faBold );
182 ttBoldOff:
183 Exclude( Style.Font.Attributes, faBold );
184 ttItalic:
185 Include( Style.Font.Attributes, faItalic );
186 ttItalicOff:
187 Exclude( Style.Font.Attributes, faItalic );
188 ttUnderline:
189 Include( Style.Font.Attributes, faUnderscore );
190 ttUnderlineOff:
191 Exclude( Style.Font.Attributes, faUnderscore );
192
193 ttFixedWidthOn:
194 SibylFontToFontSpec( Settings.FFixedFont, Style.Font );
195 ttFixedWidthOff:
196 SibylFontToFontSpec( Settings.FNormalFont, Style.Font );
197
198 ttHeading1:
199 SibylFontToFontSpec( Settings.FHeading1Font, Style.Font );
200 ttHeading2:
201 SibylFontToFontSpec( Settings.FHeading2Font, Style.Font );
202 ttHeading3:
203 SibylFontToFontSpec( Settings.FHeading3Font, Style.Font );
204 ttHeadingOff:
205 SibylFontToFontSpec( Settings.FNormalFont, Style.Font );
206
207 ttFont:
208 begin
209 tmpFontParts := TStringList.Create;
210 StrExtractStringsQuoted(tmpFontParts, Tag.Arguments);
211 FontFaceName := tmpFontParts[0];
212 FontSizeString := tmpFontParts[1];
213 tmpFontParts.Destroy;
214
215 NewStyle := Style;
216 try
217 NewStyle.Font.FaceName := FontFaceName;
218
219 if Pos( 'x', FontSizeString ) > 0 then
220 begin
221 tmpFontParts := TStringList.Create;
222 StrExtractStrings(tmpFontParts, FontSizeString, ['x'], #0);
223 XSizeStr := tmpFontParts[0];
224 YSizeStr := tmpFontParts[1];
225 tmpFontParts.Destroy;
226
227 NewStyle.Font.XSize := StrToInt( XSizeStr );
228 NewStyle.Font.YSize := StrToInt( YSizeStr );
229 NewStyle.Font.PointSize := 0;
230 end
231 else
232 begin
233 NewStyle.Font.PointSize := StrToInt( FontSizeString );
234 end;
235
236 if ( NewStyle.Font.FaceName <> '' )
237 and ( NewStyle.Font.PointSize >= 1 ) then
238 begin
239 Style := NewStyle;
240 end;
241
242 except
243 end;
244 end;
245
246 ttFontOff:
247 // restore default
248 SibylFontToFontSpec( Settings.FNormalFont, Style.Font );
249
250 ttColor:
251 GetTagColor( Tag.Arguments, Style.Color );
252 ttColorOff:
253 Style.Color := Settings.FDefaultColor;
254 ttBackgroundColor:
255 GetTagColor( Tag.Arguments, Style.BackgroundColor );
256 ttBackgroundColorOff:
257 Style.BackgroundColor := Settings.FDefaultBackgroundColor;
258
259 ttRed:
260 Style.Color := clRed;
261 ttBlue:
262 Style.Color := clBlue;
263 ttGreen:
264 Style.Color := clGreen;
265 ttBlack:
266 Style.Color := clBlack;
267
268 ttAlign:
269 Style.Alignment := GetTagTextAlignment( Tag.Arguments,
270 Settings.FDefaultAlignment );
271
272 ttWrap:
273 Style.Wrap := GetTagTextWrap( Tag.Arguments );
274
275 ttSetLeftMargin,
276 ttSetRightMargin:
277 begin
278 tmpFontParts := TStringList.Create;
279 StrExtractStrings(tmpFontParts, Tag.Arguments, [' '], #0);
280 MarginParam1 := tmpFontParts[0];
281 tmpFontParts.Destroy;
282
283 ParsePoint := 1;
284 if ( Tag.TagType = ttSetLeftMargin )
285 and ( MarginParam1 = 'here' ) then
286 begin
287 Style.LeftMargin := X div FontWidthPrecisionFactor;
288 end
289 else
290 begin
291 try
292 MarginSize := StrToInt( MarginParam1 );
293 MarginParam2 := tmpFontParts[1];
294 if MarginParam2 = 'pixels' then
295 NewMargin := MarginSize
296
297 else if MarginParam2 = 'deffont' then
298 NewMargin := MarginSize
299 * Settings.NormalFont.Width
300
301 else
302 begin
303 case Settings.MarginSizeStyle of
304 msAverageCharWidth:
305 NewMargin := MarginSize * FontManager.AverageCharWidth;
306 msMaximumCharWidth:
307 NewMargin := MarginSize * FontManager.MaximumCharWidth;
308 msSpecifiedChar:
309 NewMargin := MarginSize
310 * FontManager.CharWidth( Chr( Settings.MarginChar ) )
311 div FontWidthPrecisionFactor;
312 end;
313 end;
314 except
315 NewMargin := 0;
316 end;
317
318 if Tag.TagType = ttSetLeftMargin then
319 Style.LeftMargin := Settings.Margins.Left
320 + NewMargin
321 else
322 Style.RightMargin := Settings.Margins.Right
323 + NewMargin;
324 end;
325 end;
326
327 end;
328
329 ApplyStyle( Style, FontManager );
330
331end;
332
333function GetDefaultStyle( const Settings: TRichTextSettings ): TTextDrawStyle;
334begin
335 SibylFontToFontSpec( Settings.FNormalFont, Result.Font );
336 Result.Alignment := Settings.FDefaultAlignment;
337 Result.Wrap := Settings.FDefaultWrap;
338 Result.Color := Settings.FDefaultColor;
339 Result.BackgroundColor := Settings.FDefaultBackgroundColor;
340 Result.LeftMargin := Settings.Margins.Left;
341 Result.RightMargin := Settings.Margins.Right;
342end;
343
344Procedure GetStartupFont( Var Font: TFont;
345 Const Face: string;
346 Const Size: longint );
347begin
348 Font := Screen.CreateCompatibleFont( Screen.GetFontFromPointSize( Face, Size ) );
349 ReferenceFont( Font );
350 Font.AutoDestroy := true;
351end;
352
353Procedure TRichTextSettings.SetupComponent;
354begin
355 inherited SetupComponent;
356
357 Name := 'RichTextSettings';
358
359 GetStartupFont( FNormalFont, 'Helv', 8 );
360 GetStartupFont( FFixedFont, 'Courier', 8 );
361 GetStartupFont( FHeading1Font, 'Helv', 18 );
362 GetStartupFont( FHeading2Font, 'Helv', 12 );
363 GetStartupFont( FHeading3Font, 'Helv', 8 );
364 FHeading3Font.Attributes := [ faBold ];
365
366 FDefaultColor := clBlack;
367 FDefaultBackgroundColor := clWhite;
368
369 FDefaultAlignment := taLeft;
370 FDefaultWrap := true;
371 FAtLeastOneWordBeforeWrap := false;
372
373 FMarginSizeStyle := msMaximumCharWidth;
374 FMarginChar := Ord( ' ' );
375
376 FMargins.Left := 0;
377 FMargins.Right := 0;
378 FMargins.Top := 0;
379 FMargins.Bottom := 0;
380
381 FUpdateCount := 0;
382 FChangesPending := false;
383end;
384
385destructor TRichTextSettings.Destroy;
386begin
387 DereferenceFont( FNormalFont );
388 DereferenceFont( FFixedFont );
389 DereferenceFont( FHeading1Font );
390 DereferenceFont( FHeading2Font );
391 DereferenceFont( FHeading3Font );
392
393 Inherited Destroy;
394end;
395
396// Font read/write from SCU. I have NO IDEA why I have to do this manually. But
397// this way works and everything else I tried doesn't
398Procedure TRichTextSettings.ReadSCUResource( Const ResName: TResourceName;
399 Var Data;
400 DataLen: LongInt );
401Begin
402 If ResName = 'Heading1Font' Then
403 Begin
404 If DataLen <> 0 Then
405 FHeading1Font := ReadSCUFont( Data, DataLen );
406 End
407 Else If ResName = 'Heading2Font' Then
408 Begin
409 If DataLen <> 0 Then
410 FHeading2Font := ReadSCUFont( Data, DataLen );
411 End
412 Else If ResName = 'Heading3Font' Then
413 Begin
414 If DataLen <> 0 Then
415 FHeading3Font := ReadSCUFont( Data, DataLen );
416 End
417 Else If ResName = 'FixedFont' Then
418 Begin
419 If DataLen <> 0 Then
420 FFixedFont := ReadSCUFont( Data, DataLen );
421 End
422 Else if ResName = 'NormalFont' then
423 Begin
424 If DataLen <> 0 Then
425 FNormalFont := ReadSCUFont( Data, DataLen );
426 End
427 Else
428 Inherited ReadSCUResource( ResName, Data, DataLen );
429End;
430
431Function TRichTextSettings.WriteSCUResource( Stream: TResourceStream ): boolean;
432begin
433 Result := Inherited WriteSCUResource( Stream );
434 If Not Result Then
435 Exit;
436
437 If FHeading1Font <> Nil then
438 Result := FHeading1Font.WriteSCUResourceName( Stream, 'Heading1Font' );
439 If FHeading2Font <> Nil then
440 Result := FHeading2Font.WriteSCUResourceName( Stream, 'Heading2Font' );
441 If FHeading3Font <> Nil then
442 Result := FHeading3Font.WriteSCUResourceName( Stream, 'Heading3Font' );
443 If FFixedFont <> Nil then
444 Result := FFixedFont.WriteSCUResourceName( Stream, 'FixedFont' );
445 If FNormalFont <> Nil then
446 Result := FNormalFont.WriteSCUResourceName( Stream, 'NormalFont' );
447
448end;
449
450Procedure TRichTextSettings.Change;
451begin
452 if FUpdateCount > 0 then
453 begin
454 FChangesPending := true;
455 exit;
456 end;
457
458 if FOnChange <> nil then
459 FOnChange( self );
460end;
461
462Procedure TRichTextSettings.SetDefaultAlignment( Alignment: TTextAlignment );
463begin
464 if Alignment = FDefaultAlignment then
465 exit; // no change
466
467 FDefaultAlignment := Alignment;
468 Change;
469end;
470
471Procedure TRichTextSettings.SetDefaultWrap( Wrap: boolean );
472begin
473 if Wrap = FDefaultWrap then
474 exit; // no change
475
476 FDefaultWrap := Wrap;
477 Change;
478end;
479
480Procedure TRichTextSettings.SetAtLeastOneWordBeforeWrap( NewValue: boolean );
481begin
482 if NewValue = FAtLeastOneWordBeforeWrap then
483 exit; // no change
484
485 FAtLeastOneWordBeforeWrap := NewValue;
486 Change;
487end;
488
489Procedure TRichTextSettings.SetMarginChar( NewValue: longint );
490begin
491 if NewValue = FMarginChar then
492 exit; // no change
493
494 FMarginChar := NewValue;
495
496 if FMarginSizeStyle <> msSpecifiedChar then
497 // doesn't matter, will be ignored
498 exit;
499 Change;
500end;
501
502Procedure TRichTextSettings.SetMarginSizeStyle( NewValue: TMarginSizeStyle );
503begin
504 if NewValue = FMarginSizeStyle then
505 exit; // no change
506
507 FMarginSizeStyle := NewValue;
508 Change;
509end;
510
511Function FontSame( FontA: TFont; FontB: TFont ): boolean;
512begin
513 if ( FontA = nil )
514 or ( FontB = nil ) then
515 begin
516 Result := FontA = FontB;
517 exit;
518 end;
519
520 Result := ( FontA.FaceName = FontB.FaceName )
521 and ( FontA.PointSize = FontB.PointSize )
522 and ( FontA.Attributes = FontB.Attributes );
523end;
524
525Procedure TRichTextSettings.AssignFont( Var Font: TFont;
526 NewFont: TFont );
527begin
528 If NewFont = Nil Then
529 NewFont := Screen.DefaultFont;
530
531 if FontSame( NewFont, Font ) then
532 exit; // no change
533
534 DereferenceFont( Font );
535 Font := NewFont;
536 ReferenceFont( Font );
537
538 Change;
539End;
540
541Procedure TRichTextSettings.SetHeading1Font( NewFont: TFont );
542begin
543// ProfileEvent( 'TRichTextSettings.SetHeading1Font' );
544 AssignFont( FHeading1Font, NewFont );
545
546// if FHeading1FOnt = nil then
547// ProfileEvent( ' Set to nil' );
548
549end;
550
551Procedure TRichTextSettings.SetHeading2Font( NewFont: TFont );
552begin
553 AssignFont( FHeading2Font, NewFont );
554End;
555
556Procedure TRichTextSettings.SetHeading3Font( NewFont: TFont );
557begin
558 AssignFont( FHeading3Font, NewFont );
559End;
560
561Procedure TRichTextSettings.SetFixedFont( NewFont: TFont );
562begin
563 AssignFont( FFixedFont, NewFont );
564end;
565
566Procedure TRichTextSettings.SetNormalFont( NewFont: TFont );
567begin
568 AssignFont( FNormalFont, NewFont );
569end;
570
571Procedure TRichTextSettings.SetMargins( const NewMargins: TRect );
572begin
573 if NewMargins = FMargins then
574 exit; // no change
575 FMargins := NewMargins;
576 Change;
577end;
578
579function TRichTextSettings.GetMargin_Left: longint;
580begin
581 Result := FMargins.Left;
582end;
583
584Procedure TRichTextSettings.SetMargin_Left( NewValue: longint );
585begin
586 Margins.Left := NewValue;
587end;
588
589function TRichTextSettings.GetMargin_Bottom: longint;
590begin
591 Result := FMargins.Bottom;
592end;
593
594Procedure TRichTextSettings.SetMargin_Bottom( NewValue: longint );
595begin
596 Margins.Bottom := NewValue;
597end;
598
599function TRichTextSettings.GetMargin_Right: longint;
600begin
601 Result := FMargins.Right;
602end;
603
604Procedure TRichTextSettings.SetMargin_Right( NewValue: longint );
605begin
606 Margins.Right := NewValue;
607end;
608
609function TRichTextSettings.GetMargin_Top: longint;
610begin
611 Result := FMargins.Top;
612end;
613
614Procedure TRichTextSettings.SetMargin_Top( NewValue: longint );
615begin
616 Margins.Top := NewValue;
617end;
618
619Procedure TRichTextSettings.SetDefaultColor( NewColor: TColor );
620begin
621 if NewColor = FDefaultColor then
622 exit;
623 FDefaultColor := NewColor;
624 Change;
625end;
626
627Procedure TRichTextSettings.SetDefaultBackgroundColor( NewColor: TColor );
628begin
629 if NewColor = FDefaultBackgroundColor then
630 exit;
631 FDefaultBackgroundColor := NewColor;
632 Change;
633end;
634
635procedure TRichTextSettings.BeginUpdate;
636begin
637 inc( FUpdateCount );
638end;
639
640procedure TRichTextSettings.EndUpdate;
641begin
642 if FUpdateCount = 0 then
643 exit;
644
645 dec( FUpdateCount );
646 if FUpdateCount = 0 then
647 begin
648 if FChangesPending then
649 begin
650 Change;
651 FChangesPending := false;
652 end;
653 end;
654end;
655
656Initialization
657 RegisterClasses( [ TRichTextSettings ] );
658End.
Note: See TracBrowser for help on using the repository browser.