Templates - frustrated

General TRichView support forum. Please post your questions here
Post Reply
Jim Knopf
Posts: 171
Joined: Mon Dec 30, 2013 10:07 pm
Location: Austria
Contact:

Templates - frustrated

Post by Jim Knopf » Thu Feb 08, 2018 12:53 pm

Hi there,

since many days I struggle with a problem and in the meantime I am realy very frustrated.

In TRvStyle there are 12 constant templates. 0-4 for individual normal Text and that works pretty good.
5-12 are special formattings for storybooks (characters name, characters text, stage direction, sound, music, stage setting ...). Klick on a button of a tool window should put the cursor at the end of a new line, initialize with the related template. Template 7-12 is simple text (stage direction, sound, music, stage setting ...) and that works - usually.
......................Text
(...... is left indent 130 and first indent -130 - works)

But 5 and 6 are a combination for character in that way:
NAME ........ tab ..... What the char says

whatever I try, insert a combined string (Name + #9 + ' ') or AddNL(Name ...), AddTab(), AddNL() and afterwards reformat to get the proper template - all possible things happen but never what I wish.

So my question: what is the correct way to preset a new item with a spcified template??

Thanks
Martin

Sergey Tkachenko
Site Admin
Posts: 13889
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Templates - frustrated

Post by Sergey Tkachenko » Thu Feb 08, 2018 2:01 pm

By "templates", do you need RVStyle.TextStyles?
Do you want to add new content to the very end of existing document, starting from a new line? Or do you want insert in the middle of document?
Should this operation be undoable by user?

Jim Knopf
Posts: 171
Joined: Mon Dec 30, 2013 10:07 pm
Location: Austria
Contact:

Re: Templates - frustrated

Post by Jim Knopf » Thu Feb 08, 2018 3:42 pm

Yes, add new content, but with a certain style template. They not are TextStyles or ParaStyles but StyleTemplates. Usually it works, but in this special case I assign StyleTemplate No 5 by rv.ApplyStyleTemplate(5, True) but afterwards StyleTemplate 4 is assigned. This paragraph has three items (text - tab - text, see below). Unfortunately it is too much code to post all methods too. So only the main routine.

EDIT sorry, not true, that works. But e.g. first Character is okay and with secon text style not taken from template ...

Code: Select all

var ItS, OfS, ItE, OfE: Integer;
    VS: Integer;
    Curr: Integer;
begin
  fMain.FScreenplayConv := True;
  fMain.rv.BeginUpdate;
  fMain.rv.BeginUndoCustomGroup('Figur');
  fMain.rv.SetUndoGroupMode(True);
  try
    fMain.paRV.Visible := False;
    VS := fMain.rv.VScrollPos;
    fMain.rv.GetSelectionBounds(ItS, OfS, ItE, OfE, False);

    // New text inserted
    if (ItS = ItE) and (OfS = OfE) then
    begin
      // If at end automatically new paragraph
      Curr := fMain.rv.ItemCount;
      if OfE > 1 then
        // this
//      begin
//        fMain.rv.AddNL(AnsiUppercase(tlJ.FocusedNode.Strings[tcJ.Index]), 0, 0);
//        fMain.rv.AddTab(0, -1);
//        fMain.rv.Add(' ', 0);
//        fMain.rv.FormatTail;
//      end;
        // or this
        fMain.rv.InsertText(#13#10 + AnsiUppercase(tlJ.FocusedNode.Strings[tcJ.Index]+#9+' '));

      // reformat
      fMain.rv.SetSelectionBounds(Curr, fMain.rv.GetOffsBeforeItem(Curr), Curr+2, fMain.rv.GetOffsAfterItem(Curr+2));
    end;

    fTemplates.LoadTemplateData;

    fMain.UpdateTemplates(fMain.CurrentNode, True);
    fMain.rv.ApplyStyleTemplate(5, True);

    fMain.rv.SetSelectionBounds(Curr+1, fMain.rv.GetOffsBeforeItem(Curr+1), Curr+2, fMain.rv.GetOffsAfterItem(Curr+2));
    fMain.rv.ApplyStyleTemplate(6, True);

    fMain.rv.Format;
    fMain.rv.VScrollPos := VS;
    fMain.rv.SetSelectionBounds(Curr+2, fMain.rv.GetOffsAfterItem(Curr+2), Curr+2, fMain.rv.GetOffsAfterItem(Curr+2));
  finally
    fMain.FScreenplayConv := False;
    fMain.rv.SetUndoGroupMode(False);
    fMain.rv.EndUpdate;
  end;
  if fMain.rv.CanFocus then
    fMain.rv.SetFocus;
I think myy solution is too complicated. Because of that: What is the most simple way?

Sergey Tkachenko
Site Admin
Posts: 13889
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Templates - frustrated

Post by Sergey Tkachenko » Sun Feb 11, 2018 5:42 pm

I can see two possible problems with this code.

1) StyleTemplates can be applied either to a text or to a paragraph. As I can understand, you want to apply to the selected text, not to its paragraph.
You use ApplyStyleTemplate method which applies style depending on the selection and the StyleTemplate.Kind. Kind=rvstkPara is always applied to a paragraph. Kind=rvstkText is always applied to a text. But Kind=rvstkParaText is applied depending on the selection. If the whole paragraph is selected (your first call), it is applied to the paragraph. If a fragment inside a paragraph is selected (your second call), it is applied to the selected text. If nothing is selected (your third call), it is applied to the paragraph.
Solution: If you want to make sure that it is applied to the text, use ApplyTextStyleTemplate instead of ApplyStyleTemplate

2) You call Format after the last ApplyStyleTemplate. Format resets values of the current text and paragraph style, they are read from the text at the position of the caret. So this last assignment does nothing (it is applied to the empty selection, so it does not modify the document, it only changes the current text style). Then you call SetSelectionBounds, which agains resets values of the current text and paragraph style.
Solution: call the last Apply*StyleTemplate after Format/SetSelectionBounds. Actually, Format is not needed here, because InsertText and Apply*StyleTemplate are editing methods, they do all necessary reformatting themselves.

Below is my test. I took the demo from TRichView\Demos\DelphiUnicode\Editors\StyleTemplates\.
I added a button that adds the text 'Test'#9' ' from the new line, applies the style template 'heading 1' to 'Test', applies 'heading 2' to #9' ', moves the caret at the end of this text and applies 'heading 3' to the current text:

Code: Select all

procedure TfrmMain.Button1Click(Sender: TObject);
var
  ItemNo: Integer;
  rve: TCustomRichViewEdit;
begin
  rve := Self.rve.TopLevelEditor;
  rve.SetFocus;
  rve.BeginUndoGroup(rvutStyleTemplate);
  rve.SetUndoGroupMode(True);
  rve.BeginUpdate;
  try
    rve.InsertText(#13#10 +'Test'#9' ');
    ItemNo := rve.CurItemNo - 2;
    rve.SetSelectionBounds(
      ItemNo,   rve.GetOffsBeforeItem(ItemNo),
      ItemNo+2, rve.GetOffsAfterItem(ItemNo+2));
    rve.ApplyTextStyleTemplate(rve.Style.StyleTemplates.FindItemByName('heading 1').Index, True);
    rve.SetSelectionBounds(
      ItemNo+1, rve.GetOffsBeforeItem(ItemNo+1),
      ItemNo+2, rve.GetOffsAfterItem(ItemNo+2));
    rve.ApplyTextStyleTemplate(rve.Style.StyleTemplates.FindItemByName('heading 2').Index, True);
    rve.SetSelectionBounds(
      ItemNo+2, rve.GetOffsAfterItem(ItemNo+2),
      ItemNo+2, rve.GetOffsAfterItem(ItemNo+2));
    rve.ApplyTextStyleTemplate(rve.Style.StyleTemplates.FindItemByName('heading 3').Index, True);
  finally
    rve.EndUpdate;
    rve.SetUndoGroupMode(False);
  end;
end;

Sergey Tkachenko
Site Admin
Posts: 13889
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Templates - frustrated

Post by Sergey Tkachenko » Sun Feb 11, 2018 6:28 pm

And here is the alternative code doing the same thing.

Instead of inserting and then applying style, we construct a proper text style, assign it to the current text style, and then insert text. A new text will be formatted accordingly.

Code: Select all

function GetTextStyleWithTemplate(rvs: TRVStyle; StyleNo: Integer;
  StyleTemplate: TRVStyleTemplate): Integer;
var
  TextStyle: TFontInfo;
begin
  Result := StyleNo;
  if (StyleTemplate <> nil) and (StyleTemplate.Kind = rvstkPara) then
    exit;
  TextStyle := TFontInfo.Create(nil);
  try
    TextStyle.Assign(rvs.TextStyles[StyleNo]);
    StyleTemplate.ApplyToTextStyle(TextStyle,
      rvs.StyleTemplates.FindItemById(TextStyle.StyleTemplateId));
    Result := rvs.FindTextStyle(TextStyle);
  finally
    TextStyle.Free;
  end;
end;

procedure TfrmMain.Button1Click(Sender: TObject);
var
  rve: TCustomRichViewEdit;
begin
  rve := Self.rve.TopLevelEditor;
  rve.SetFocus;
  rve.BeginUndoGroup(rvutStyleTemplate);
  rve.SetUndoGroupMode(True);
  rve.BeginUpdate;
  try
    rve.CurTextStyleNo := GetTextStyleWithTemplate(rve.Style,
      rve.CurTextStyleNo, rve.Style.StyleTemplates.FindItemByName('heading 1'));
    rve.InsertText(#13#10'Test');
    rve.CurTextStyleNo := GetTextStyleWithTemplate(rve.Style,
      rve.CurTextStyleNo, rve.Style.StyleTemplates.FindItemByName('heading 2'));
    rve.InsertText(#9' ');
    rve.CurTextStyleNo := GetTextStyleWithTemplate(rve.Style,
      rve.CurTextStyleNo, rve.Style.StyleTemplates.FindItemByName('heading 3'));
  finally
    rve.EndUpdate;
    rve.SetUndoGroupMode(False);
  end;
end;
Visually, results are the same. But this code is more efficient: it peforms (and record to undo buffer) only insertion operations.

Sergey Tkachenko
Site Admin
Posts: 13889
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Templates - frustrated

Post by Sergey Tkachenko » Sun Feb 11, 2018 6:52 pm

And here is a version of this code that does not use editing methods (so it is not undoable).
It adds new content to the very end of the document. The code uses GetTextStyleWithTemplate from the previous code sample.

This code still creates styles basing on CurTextStyleNo and CurParaStyleNo, so the new line inherits text and paragraph attributes of the current text.

Code: Select all

procedure TfrmMain.Button1Click(Sender: TObject);
begin
  rve.SetFocus;
  rve.AddNL('Test', GetTextStyleWithTemplate(rve.Style,
    rve.CurTextStyleNo, rve.Style.StyleTemplates.FindItemByName('heading 1')),
    rve.CurParaStyleNo);
  rve.AddTextNL(#9' ', GetTextStyleWithTemplate(rve.Style,
      rve.CurTextStyleNo, rve.Style.StyleTemplates.FindItemByName('heading 2')),
    -1, 0);
  rve.FormatTail;
  rve.SetSelectionBounds(
    rve.ItemCount - 1, rve.GetOffsAfterItem(rve.ItemCount - 1),
    rve.ItemCount - 1, rve.GetOffsAfterItem(rve.ItemCount - 1));
  rve.CurTextStyleNo := GetTextStyleWithTemplate(rve.Style,
    rve.CurTextStyleNo, rve.Style.StyleTemplates.FindItemByName('heading 3'));
end;

Jim Knopf
Posts: 171
Joined: Mon Dec 30, 2013 10:07 pm
Location: Austria
Contact:

Re: Templates - frustrated

Post by Jim Knopf » Mon Feb 12, 2018 4:40 pm

Thank you very much for the very detailed information!
If that works (and I think it does :D ), it's a load off my mind!
Great illumination :-)
Martin

Jim Knopf
Posts: 171
Joined: Mon Dec 30, 2013 10:07 pm
Location: Austria
Contact:

Re: Templates - frustrated

Post by Jim Knopf » Mon Feb 12, 2018 9:07 pm

Now implemented, works fine! Helps a lot with handling StyleTemplates.
Until now that has been my area of ignorance concerning TRichViewEdit. Seems to change ...

Post Reply