source: trunk/Components/RichTextStyleUnit.pas@ 15

Last change on this file since 15 was 15, checked in by RBRi, 19 years ago

+ components stuff

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