Page 1 of 1

[Example] StyleTemplates (real styles)

Posted: Sun Jul 09, 2017 2:05 pm
by Sergey Tkachenko
Information in this thread will be useful if you want to generate documents having "real styles" (like in Microsoft Word or other text processor), or if you want using "real styles" without RichViewActions.
If you use RichViewActions, and documents are created by users, RichViewActions do all the necessary work.

Introduction

In our component, the collection of StyleTemplates (I'll abbreviate them as "ST") represents "real styles".
ST do not affect document appearance directly. Instead, they allow changing collections of TextStyles and ParaStyles, which represent text and paragraph attributes.

There are 3 types of "ST" (see Kind property):
- text ST (can be linked to items in TextStyles)
- paragraph ST (can be linked to items in ParaStyles)
- text+paragraph ST (can be linked to the both of them).
If ST is linked to a paragraph, it affects both paragraph and text inside this paragraph.

It's highly recommended to link each item in ParaStyles to some ST. Linking items of TextStyles to some ST is optional.

Items in StyleTemplates are named (see Name property) . You can use any names, but make sure that they are unique in the collection.
However, several names are special.
It's highly recommended use the name "Normal" for the default paragraph ST (like MS Word does). TRichView makes sure that "Normal" ST is paragraph ST.
It's recommended to use the names "heading 1", "heading 2", ... "heading 9" for ST representing headings. However, it's not a name that makes a heading from the paragraph, but OutlineLevel property of items of ParaStyles.
It's highly recommended to use the name 'Hyperlink' for ST representing hyperlinks. However, it's not a name that makes a hyperlink from text, but Jump property of items of TextStyles.

Additional info:
http://www.trichview.com/help/styles_an ... lates.html

Re: StyleTemplates

Posted: Sun Jul 09, 2017 2:15 pm
by Sergey Tkachenko
How to link ST to TextStyles and ParaStyles

Inside the same document, ST are referred by their Id property.
Like the Name property, it is unique, but, unlike Name, it is auto-generated.
It was implemented for efficiency.

To link an item in ParaStyles to ST, assign StyleTemplateId = ST.Id.
If you change properties of a ParaStyle item, make sure that you added changed properties to its ModifiedProperties property.
Properties listed in ModifiedProperties are not influenced by ST.

Items in TextStyles also have StyleTemplateId and ModifiedProperties.
But there is one more property of TextStyle, ParaStyleTemplateId. It must be equal to Id of ST linked to ParaStyle containing text of this TextStyle. If not, the component fixes this problem automatically.

Re: StyleTemplates

Posted: Sun Jul 09, 2017 2:32 pm
by Sergey Tkachenko
Filling collection of style templates

1) If you use RichViewActions, StyleTemplates are filled when you execute TrvActionNew. They are filled from its StyleTemplates property.

2) In the demo Demos\DelphiUnicode\Editors\StyleTemplates, "File | New" command loads the initial set of ST from a file:

Code: Select all

  rvs.StyleTemplates.LoadFromRVST(ExtractFilePath(Application.ExeName) +
    'Default.rvst', rvs.Units);
3) Here is the example how to create ST in code.
Let's create 3 ST:
- "Normal", paragraph ST
- "heading 1", text+paragraph ST, inherited from "Normal"
- "'Emphasis", text ST

Code: Select all

  rvs.StyleTemplates.Clear;
  with rvs.StyleTemplates.Add do
  begin
    Name := 'Normal';
    Kind := rvstkPara;
  end;
  with rvs.StyleTemplates.Add do
  begin
    Name := 'heading 1';
    Kind := rvstkParaText;
    ParentId := rvs.StyleTemplates.NormalStyleTemplate.Id; // inherits from 'Normal'
    NextId := rvs.StyleTemplates.NormalStyleTemplate.Id; // switch to 'Normal' after Enter
    ParaStyle.OutlineLevel := 1;
    ParaStyle.Options := [rvpaoKeepWithNext];
    TextStyle.FontName := 'Tahoma';
    TextStyle.Size := 18;
    ValidParaProperties := [rvpiOutlineLevel, rvpiKeepWithNext];
    ValidTextProperties := [rvfiFontName, rvfiSize];
  end;
  with rvs.StyleTemplates.Add do
  begin
    Name := 'Emphasis';
    Kind := rvstkText;
    TextStyle.Style := [fsItalic];
    ValidTextProperties := [rvfiItalic];
  end;
For ST linked to paragraph:
- all properties listed in ValidParaProperties and ValidTextProperties are defined in this ST
- all other properties are inherited from parent ST; if this ST has no parent, these properties have default values

For ST linked to text:
- all properties listed in ValidTextProperties are defined in this ST
- all other properties are inherited from parent ST; if this ST has no parent, these properties are not defined (so they will be taken from ST linked to this text's paragraph).

Re: StyleTemplates

Posted: Sun Jul 09, 2017 2:43 pm
by Sergey Tkachenko
Ok, we created or loaded ST.
Now we need to create the default TextStyle and ParaStyle.

If you use RichViewActions, they do it for you.
If not, you need to do it yourself.

ParaStyle[0] will be linked to "Normal" ST, TextStyle[0] will not be linked to any text ST. But since text must be inside a paragraph linked to "Normal" ST, its ParaStyleTemplateId must be assigned.

The code below is coped from the demo in Demos\DephiUnicode\Editors\StyleTemplates.
It is executed in "File | New" command, after loading ST from a file.

Code: Select all

  // creating default text and paragraph styles
  rvs.TextStyles.Clear;
  rvs.ParaStyles.Clear;
  rvs.ListStyles.Clear;
  rvs.ParaStyles.Add;
  rvs.TextStyles.Add;
  // formatting them according to "Normal" style template
  if rvs.StyleTemplates.NormalStyleTemplate <> nil then
  begin
    rvs.StyleTemplates.NormalStyleTemplate.ApplyToParaStyle(rvs.ParaStyles[0]);
    TRVStyleTemplate(nil).ApplyToTextStyle(rvs.TextStyles[0],
      rvs.StyleTemplates.NormalStyleTemplate);
    rvs.TextStyles[0].ParaStyleTemplateId :=
      rvs.StyleTemplates.NormalStyleTemplate.Id;
  end;
This code uses the following methods:
1) RVStyle.StyleTemplates.NormalStyleTemplate returns ST with the name "Normal"
2) ST.ApplyToParaStyle:
- assigns ST.Id to the ParaStyle.StyleTemplateId
- applies all properties of ST to ParaStyle (except for properties listed in ParaStyle.ModifiedProperties, but it is empty in our case)
3) ST.ApplyToTextStyle:
- applies ST.Id to TextStyle.StyleTemplateId
- applies properties of ST to TextStyle; also, it applies properties of paragraph ST specified in the parameter.
As you can see, this method can be called even for ST = nil. In this case, this ST is not applied, only paragraph ST is applied.

Re: StyleTemplates

Posted: Sun Jul 09, 2017 3:09 pm
by Sergey Tkachenko
Generating document

Let's use 3 ST created in the previous post to generate a document.
First, let's create the functions returning indexes of items with the desired properties in rvs.TextStyles and rvs.ParaStyles.

MakeParaStyle returns the paragraph style linked to the specified ParaStyleTemplate, optionally with the specified Alignment (applied on top of ST).
MakeTextStyle returns the text style linked to the specified StyleTemplate, for insertion in paragraphs linked to ParaStyleTemplate, optionally with the specified Color (applied on top of ST).

Code: Select all

function MakeParaStyle(rvs: TRVStyle;
  ParaStyleTemplate: TRVStyleTemplate; Alignment: TRVAlignment = rvaLeft;
  ModifiedProperties: TRVParaInfoProperties = []): Integer;
var
  ParaInfo: TParaInfo;
begin
  ParaInfo := TParaInfo.Create(nil);
  if rvpiAlignment in ModifiedProperties then
    ParaInfo.Alignment := Alignment;
  ParaInfo.ModifiedProperties := ModifiedProperties;
  ParaInfo.StyleTemplateId := ParaStyleTemplate.Id;
  ParaStyleTemplate.ApplyToParaStyle(ParaInfo);
  Result := rvs.FindParaStyle(ParaInfo);
  ParaInfo.Free;
end;

function MakeTextStyle(rvs: TRVStyle;
  StyleTemplate, ParaStyleTemplate: TRVStyleTemplate; Color: TColor = clWindowText;
  ModifiedProperties: TRVFontInfoProperties = []): Integer;
var
  TextInfo: TFontInfo;
begin
  TextInfo := TFontInfo.Create(nil);
  if rvfiColor in ModifiedProperties then
    TextInfo.Color := Color;
  TextInfo.ModifiedProperties := ModifiedProperties;
  StyleTemplate.ApplyToTextStyle(TextInfo, ParaStyleTemplate);
  TextInfo.ParaStyleTemplateId := ParaStyleTemplate.Id;
  Result := rvs.FindTextStyle(TextInfo);
  TextInfo.Free;
end;
Now, the code to generate doc:

Code: Select all

  rve.Clear;
  rve.AddNL('Hello ',
    MakeTextStyle(rvs, nil, rvs.StyleTemplates[1]),
    MakeParaStyle(rvs, rvs.StyleTemplates[1]));
  rve.AddNL('World',
    MakeTextStyle(rvs, nil, rvs.StyleTemplates[1], clRed, [rvfiColor]),
    -1);
  rve.AddNL(' Demo',
    MakeTextStyle(rvs, rvs.StyleTemplates[2], rvs.StyleTemplates[1]),
    -1);
  rve.AddNL('Default alignment',
    MakeTextStyle(rvs, nil, rvs.StyleTemplates[0]),
    MakeParaStyle(rvs, rvs.StyleTemplates[0]));
  rve.AddNL('Centered',
    MakeTextStyle(rvs, nil, rvs.StyleTemplates[0]),
    MakeParaStyle(rvs, rvs.StyleTemplates[0], rvaCenter, [rvpiAlignment]));
  rve.Format;
Result:
styletemplates.png
styletemplates.png (14.02 KiB) Viewed 29243 times