Page 1 of 1

Defining new lines with special fix styles

Posted: Thu Jan 15, 2015 4:59 am
by Jim Knopf
I'm expanding Patchwork for the ability of writing screenplays. The very special (and only) demand are about 10 different line types: character, stage direction, music, sound etc.

For all the line types I defined special text- and parastyles, 8 all in all

It looks that way:

Image

Dialogue (HENRY, ALICE)

Code: Select all

    rv.GetSelectionBounds(ItS, OfS, ItE, OfE, Norm);
    rv.GetCurrentItem.StyleNo := 25;
    rv.GetCurrentItem.ParaNo := 3;
    rv.AddText(AnsiUppercase(tlJ.FocusedNode.Strings[tcJ.Index]), 25);
    rv.AddText(#9, 26);
    rv.GetSelectionBounds(ItS, OfS, ItE, OfE, Norm);
    rv.Format;
    Inc(ItE, 2);
    rv.SetSelectionBounds(ItE, OfE, ItE, OfE);
    if rv.CanFocus then
      rv.SetFocus;
Here the user doubleclicks on a chosen chracter and the text (HENRY, ALICE) will be inserted (from tlJ.FocusedNode.Strings[tcJ.Index]) and he can start writing text.


Directives (Regieanweisung, Sound)
For the other 7 line types the user presse [enter] for a new line and the he presses a button to choose the line typ (stage direction, music, sound etc.) Nothing else should happen that the current (caret position) changes to a spcial defined style.

Code: Select all

procedure TfMain.ScreenplayMode(Text, Para: Integer);
var ItS, OfS, ItE, OfE: Integer;
    Norm: Boolean;
begin
  rv.GetCurrentItem.StyleNo := Text;
  rv.GetCurrentItem.ParaNo := Para;
  rv.AddText('... ', Text);     // +#+#+  bringt nichts
  rv.GetSelectionBounds(ItS, OfS, ItE, OfE, Norm);
  rv.Format;
  rv.SetSelectionBounds(ItE, OfE, ItE, OfE);
end;
You see - image above - it works - on the face of it. But:

1. Dialogue - and I think other types too - change style during reloading the file. I think it is because the text file contains no information about a specific style number (logically) and RVEdit gets during opening the first fitting style. In case of the sample RVEdit changes 'blabla ...', because the textstyle is the same as No. 0 (normal) - should be 25. Thats very bad, because the user should be able to configure style- and para options. But the style assignment is lost ...
Q: How can I permanently assign a text- an parastyle to an item?

2. With the remaining 7 styles it only looks fine on the screen. But if I explore the text- and parastyles, I notice thet there are al large quantity of duplicate styles an each new text is assigned to one or two or three.
Q: How can I define in an existing line a special text-/para style without hundreds of style duplicates and without some text in the line?

I also tried out other ways e.g.
(caret is at the beginning of an empty line too)

Code: Select all

procedure TfMain.ScreenplayMode(Text, Para: Integer);  // Text and Para are the style numbers
var ItS, OfS, ItE, OfE: Integer;
    Norm: Boolean;
begin
  FScreenplayConv := True;
  rv.ApplyStyleConversion(Text);
  FScreenplayConv := True;
  rv.ApplyParaStyleConversion(Para);
end;

procedure TfMain.rvStyleConversion(Sender: TCustomRichViewEdit; StyleNo, UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
begin
  // Screenplay
  if FScreenplayConv then
  begin
    NewStyleNo := UserData;
    FScreenplayConv := False;
  end;
end;

procedure TfMain.rvParaStyleConversion(Sender: TCustomRichViewEdit; StyleNo, UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
begin
  if FScreenplayConv then
  begin
    NewStyleNo := UserData;
    FScreenplayConv := False;
  end
end;
with this alternative RVEdit defines dubious styles, nothing works. Because of no selection? may be, but there IS no text to select ...

The problem is very complex, because the RVEdit rv is the main editor in a 31.000 lines unit and I'm very happy that in the meantime the program works properly

Posted: Thu Jan 15, 2015 8:33 pm
by Jim Knopf
Hi Sergey,

I found out unsmart solutions:

1. question: How can I permanently assign a text- an parastyle to an item?
Only possible using RVF instead of RTF

2. question: How can I define in an existing line a special text-/para style without hundreds of style duplicates and without some text in the line?
Not very smart:

Code: Select all

  rv.InsertText(' ');
  rv.SetSelectionBounds(rv.CurItemNo, 0, rv.CurItemNo, rv.GetOffsAfterItem(rv.ItemCount-1));
  FScreenplayConv := True;
  rv.ApplyStyleConversion(Text);
  rv.ApplyParaStyleConversion(Para);
  FScreenplayConv := False;
  rv.Invalidate;
But that way I only can append new Text at the end of document.

How to insert? The only I'm experimenting with is to add in another RVEdit and insert text via stream not smart too!

Are that the better options?

Posted: Fri Jan 16, 2015 10:48 am
by Jim Knopf
I figured out a solution. Not very smart but it works.

1. Insert (not add! and that made it complicated) new specification with leading text

Code: Select all

    rv.BeginUndoCustomGroup('character');
    rv.SetUndoGroupMode(True);
    FScreenplayConv := False;

    rv.GetSelectionBounds(ItS,OfS, ItE, OfE, Norm);

    if OfE > 1 then
      rv.InsertText(#13#10);

    rv.InsertText(AnsiUppercase(tlJ.FocusedNode.Strings[tcJ.Index]+#9+' '));
    rv.GetSelectionBounds(ItS, OfS, ItE, OfE, Norm);
    rv.SetSelectionBounds(ItS-2, 0, ItS-2, rv.GetOffsAfterItem(ItS-2));
    FScreenplayConv := True;
    rv.ApplyStyleConversion(25);
    rv.ApplyParaStyleConversion(3);
    rv.GetSelectionBounds(ItS, OfS, ItE, OfE, Norm);
    rv.SetSelectionBounds(ItS+1, 0, ItS+2, rv.GetOffsAfterItem(ItS+2));
    rv.ApplyStyleConversion(26);
    FScreenplayConv := False;

    rv.SetSelectionBounds(ItS+2, 0, ItS+2, rv.GetOffsAfterItem(ItS+2));
    rv.SetUndoGroupMode(False);
2. Insert new formatting

Code: Select all

  rv.BeginUndoCustomGroup('instruction');
  rv.SetUndoGroupMode(True);

  rv.GetSelectionBounds(ItS,OfS, ItE, OfE, Norm);

  if OfE > 1 then
    rv.InsertText(#13#10);

  rv.InsertText(' ');
  rv.SetSelectionBounds(rv.CurItemNo, 0, rv.CurItemNo, rv.GetOffsAfterItem(rv.CurItemNo));
  rv.ApplyStyleConversion(Text);
  rv.ApplyParaStyleConversion(Para);
  rv.Invalidate;
  FScreenplayConv := False;
  rv.SetUndoGroupMode(False);

Posted: Fri Jan 16, 2015 11:57 am
by Sergey Tkachenko
I am not sure if I understand your requirements.
Do you have a fixed set of text and paragraph styles (8 in total), and no styles should be added and deleted?

In this case, how could more than 8 styles appear in the document?

Posted: Fri Jan 16, 2015 6:18 pm
by Jim Knopf
Sergey Tkachenko wrote:I am not sure if I understand your requirements.
Do you have a fixed set of text and paragraph styles (8 in total), and no styles should be added and deleted?

In this case, how could more than 8 styles appear in the document?
Exactly: a fixed set. I don't know, why with each new item one or two new styles appeared. I think it was beacause of wrong way of changing the styles by only modifying the number instead of using ApplyStyleConversion method. The last example works and there no longer appear additional worthless styles.

Nevertheless the current solution works, it would be helpful if there were methods also to insert strings with specyfing text- and paragraph style. Something like TRVEdit.InsertEx(Text, TextStyle, ParaStyle). Could ignore ParaStyle if it is in the middle of a paragraph but do it when the method is fired in a new empty line - but not at the end of the document.
Because time and time again I insert e.g. a whole Paragraph or only a part with different styles by programm and not by user.

Posted: Sat Jan 17, 2015 6:08 pm
by Sergey Tkachenko
ApplyStyleConversion with OnStyleConversion assigning NewStyleNo := UserData is identical to ApplyTextStyle method (a difference only in processing a style protection).
The same for ApplyParaStyleConversion and ApplyParaStyle

New style may appear on RTF import, although it normally should not happen on saving and reloading.

As for text insertion in the middle.

If you want to do it as an editing operation, you need to position the caret at the proper place, change the current style, insert text (then, optionally, restore the previous current text style):

Code: Select all

rv.SetSelectionBounds(...);
rv.CurTextStyleNo := ...
rv.InsertText(...)
If you need insertion analog of AddTextNL, you can use the function from RVInsertItems.pas:

Code: Select all

procedure RVInsertString(RVData: TCustomRVData; ItemNo: Integer;
  const s: String; StyleNo, ParaNo: Integer;
  const Tag: TRVTag=RVEMPTYTAG);
(if you want to add to the same paragraph as the ItemNo-1-th item, pass (ParaNo=-1).

Posted: Sat Jan 17, 2015 6:43 pm
by Jim Knopf
"RVInsertString" and the unit is a well-bewared secret ;-) that would have spared a lot of trying hours - thank you!

is there a list of all such useful methods outside the main objects?

Thanks for detailed information!

Posted: Sat Jan 17, 2015 7:20 pm
by Sergey Tkachenko
http://www.trichview.com/help/ , see "Procedures and Functions" in the Content.

Posted: Sat Jan 17, 2015 8:23 pm
by Jim Knopf
Thank you, this help node I know, but there are a lot of other helpful methods I explore peace by peace. I thought there is another more complete list.

One more question: how can I add/insert a soft linebreak (Shift+Enter) by code ...?

Posted: Mon Jan 19, 2015 12:37 pm
by Sergey Tkachenko
How to insert soft line break:
1) As an editing operation in the caret position:
rve.InsertTextW(WideChar($2028));

2) When generating documents using Add*** methods: http://www.trichview.com/help/idh_trich ... hmode.html

Posted: Mon Jan 19, 2015 1:20 pm
by Jim Knopf
Thank you :-)