Protected section not set automatically on RTF file loading

General TRichView support forum. Please post your questions here
filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Wed May 10, 2017 11:13 am

At first, thank you for your explanation above.
We are using of quite deeply customized Delphi's TRTFEdit along with our own toolbar (font, bullets, aligning).
My task is to find out a suitable rich text editor which has a zooming capabilities and cover all of our needs. It will be a long way but your TScaleRichView looks like a great solution for this.

Back to "protect" tag:
Sergey Tkachenko wrote:
Tue May 09, 2017 1:40 pm
If you describe how you want to change text properties of the protected text, I will try to help.
What is available in our RTF Edit for users now:
Switch:
  • "Highlight protected text"
on: all protected text is rendered with specified background color
off: remove background color of protected text

Methods:
  • "Mark selected text as protected" (add caProtected tag and set background color according to the switch mentioned above)
  • "Mark selected text as unprotected" (remove caProtected tag and remove background color)
  • "Jump after next protected text" (Move caret behind the closest protected text - forward direction)
  • "Jump after previous protected text" (Move caret behind the closest protected text - backward direction)
In addition, as a programmer I need to know if character just before and just after the caret is protected.

I'm not familiar with all possibilities of your TRichView yet so I will wait for your proposals.
Thank you!

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Wed May 10, 2017 7:01 pm

I'll post these functions tomorrow.

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Thu May 11, 2017 6:20 pm

How to highlight protected text.
It's simple, you even do not need to search for protected text. You can check text styles and color them.
To clear highlights, call with Color = clNone.

Code: Select all

procedure HighlightProtectedText(RVStyle: TRVStyle; Color: TColor);
var
  i: Integer;
begin
  for i := 0 to RVStyle.TextStyles.Count - 1 do
    if rvprModifyProtect in RVStyle.TextStyles[i].Protection then
      RVStyle.TextStyles[i].BackColor := Color;

end;

procedure HighlightAllProtectedText(SRV: TSRichViewEdit; Color: TColor);
var
  i: TSRVHeaderFooterType;
begin
  HighlightProtectedText(SRV.RichViewEdit.Style, Color);
  HighlightProtectedText(SRV.RVHeader.Style, Color);
  HighlightProtectedText(SRV.RVFooter.Style, Color);
  for i := Low(TSRVHeaderFooterType) to High(TSRVHeaderFooterType) do
    HighlightProtectedText(SRV.SubDocuments[i].GetRVStyle, Color);
  if SRV.RVNote <> nil then
    HighlightProtectedText(SRV.RVNote.Style, Color);
  SRV.UpdateBuffer;

end;

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Thu May 11, 2017 6:46 pm

How to mark selected text as protected and unprotected.
This example assume that you have ProtectedHighlightColor variable, specifying highlight color for protected text (clNone for no highlighting).

Code: Select all

const
  ProtectionOptions = [rvprModifyProtect, rvprDeleteProtect, rvprSticking,
    rvprStyleProtect, rvprDoNotAutoSwitch];

procedure TForm3.ProtectConversion(Sender: TCustomRichViewEdit; StyleNo,
  UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
var
  TextStyle: TFontInfo;
begin
  TextStyle := nil;
  case UserData of
    ord(True): // applying protection
      if (ProtectionOptions * Sender.Style.TextStyles[StyleNo].Protection) <>
        ProtectionOptions then
      begin
        TextStyle := TFontInfo.Create(nil);
        TextStyle.Assign(Sender.Style.TextStyles[StyleNo]);
        TextStyle.Protection := ProtectionOptions;
        TextStyle.BackColor := ProtectedHighlightColor;
      end;
    ord(False): // clearing protection
      if (ProtectionOptions * Sender.Style.TextStyles[StyleNo].Protection) <>
       [] then
      begin
        TextStyle := TFontInfo.Create(nil);
        TextStyle.Assign(Sender.Style.TextStyles[StyleNo]);
        TextStyle.Protection := [];
        TextStyle.BackColor := clNone;
      end;
  end;
  if TextStyle <> nil then
  begin
    NewStyleNo := Sender.Style.FindTextStyle(TextStyle);
    TextStyle.Free;
  end;
end;

procedure TForm3.ApplyProtection(srv: TSRichViewEdit; Protect: Boolean);
var
  OldStyleConversion: TRVStyleConversionEvent;
begin
  OldStyleConversion := srv.OnStyleConversion;
  try
    srv.OnStyleConversion := ProtectConversion;
    srv.ActiveEditor.ApplyStyleConversion(ord(Protect));
  finally
    srv.OnStyleConversion := OldStyleConversion;
  end;
end;
Call ApplyProtection(srv, True) to protect, ApplyProtection(srv, False) to remove protection.

The rest of functions will be tomorrow.

filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Thu May 11, 2017 8:08 pm

Hi Sergey,
i have already tried your methods in my demo and all of them works like a charm.
Thank you!

filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Fri May 12, 2017 9:37 am

The common font RV actions (bold, italic, strike, ..) reacts to protected as I expect and want, but unfortunately I'm still able to change protected text with changing of style (with TRVStyleTemplateComboBox) or with paragraph actions (ParaBullets, ParaNumbering, ParaList ...).
Maybe there are even more possibilities how to change style which I don't know yet.

From my perspective, the right behavior for changing of protected text is:
  • Disable style changing when paragraph or selected area contains protected text
  • Disable Para* actions if paragraph or selected area contains protected text
Is it possible or am I miss something crucial and there is another way?

Thank you.

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Fri May 12, 2017 7:40 pm

I'll check how the protection option affects applying style templates.
Expected: style templates must not be assigned to text items having rvprStyleProtect protection. However, this option does not prevent assigning styles to paragraphs, and styles of paragraphs may contain font properties affecting even protected text. It's by design: protected text is not changed, but its context is changed.

TRichView also supportы paragraph protection options (see http://www.trichview.com/help/idh_tcust ... tions.html)
rvpaoReadOnly - disallowing editing content of this paragraph
rvpaoStyleProtect - disallows changing paragraph properties
rvpaoDoNotWantReturns - disallowing processing Enter (rvpaoReadOnly does not protect from adding new paragraphs by pressing Enter at the beginning or at the end).
But I am not sure that these options must be applied only because paragraphs contain protected text.

I'll check applications of paragraph lists to protected paragraphs.
Expected: no list markers may be inserted between text items having rvprSticking protection. However, existing list markers are not protected from changes.

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Sat May 13, 2017 7:49 pm

We uploaded an update, it fixes the problem with caret moving when attempting to insert/paste RVF or press DELETE in the protected text.

About moving to the next/previous occurrence of the protected text.
The simplest way is using functions from RVGoToItem.pas unit, included in RichViewActions:

Code: Select all

function GoToNextItemEx(rve: TCustomRichViewEdit; UserData: Pointer;
  Func: TCheckItemFunction; IncludeCurrentItem: Boolean;
  Select: Boolean = False): Boolean;
function GoToPrevItemEx(rve: TCustomRichViewEdit; UserData: Pointer;
  Func: TCheckItemFunction; IncludeCurrentItem: Boolean;
  Select: Boolean = False): Boolean;
As the Func parameter, use:

Code: Select all

function IsProtectedText(RVData: TCustomRVData; ItemNo: Integer;
  UserData: Pointer): Boolean;
var
  StyleNo: Integer;
begin
  StyleNo := RVData.GetItemStyle(ItemNo);
  Result := (StyleNo >= 0) and
    (rvprModifyProtect in RVData.GetRVStyle.TextStyles[StyleNo].Protection)
end;

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Sat May 13, 2017 7:55 pm

As for the function returning "protected" state around the caret:
What should it return at the beginning/end of a document? Of a paragraph? Non-text items (pictures, tables) are treated as characters (TRichView can protect them from deletion only)?

filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Sun May 14, 2017 8:05 pm

Sergey,
thanks to your latest three posts I'm convinced that my request
I need to know if character just before and just after the caret is protected.
is on a too low level and unnecessary.

I see I can use the TCustomRichViewEdit.OnChanging (CanEdit variable) for refusing any user's action.
Can I obtain an information what type of change (text style, para style, font change) is prepared to apply?
If answer is yes, then from my point of view it would be enough to have a method like
"Is there any protected character inside of selected area or in a current paragraph (in case when no text is selected) ?"
With this function I could easily manage changes inside of OnChanging event or maybe there is even more suitable method/event (TRvAction*.ExecuteTarget, TRVStyleTemplateComboBox.DoUpdateSelection ...).

I believe that we are very close to the final solution.
Thank you for your effort, I really appreciate it.

filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Mon May 15, 2017 9:00 am

Sergey, is this information still valid?
Sergey Tkachenko wrote:
Fri Aug 17, 2007 2:09 pm
In TRichView, there are no end-of-line characters. There is only a flag "this item starts a new line/paragraph".
I'm asking because of your methods GoToNextItemEx, GoToPrevItemEx for jumping after the protected text.
May I suggest a little improvement?
If the protected text is a paragraph or it is located at the end of paragraph, it would be better to immediately move caret to the next item (new line) and not stay at the end of paragraph, because user will have to use enter on arrow key anyway.

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Wed May 17, 2017 8:48 am

As for checking selection for the protection, you can use RichViewEdit.CanDelete method.

Yes, this information (no special end-of-paragraph characters) is still valid.
The function below moves the caret to the beginning of the next paragraph, if it is at the end of a paragraph
(more exactly, paragraph section, breaks may be added by Shift+Enter)

Code: Select all

procedure MoveToNextParagraph(rve: TCustomRichViewEdit);
var
  ItemNo, Offs: Integer;
begin
  rve := rve.TopLevelEditor;
  ItemNo := rve.CurItemNo;
  Offs := rve.OffsetInCurItem;
  if (ItemNo < rve.ItemCount - 1) and (Offs >= rve.GetOffsAfterItem(ItemNo)) and
    rve.IsFromNewLine(ItemNo + 1) then
  begin
    inc(ItemNo);
    Offs := rve.GetOffsBeforeItem(ItemNo);
    rve.SetSelectionBounds(ItemNo, Offs, ItemNo, Offs);
  end;
end;

filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Wed May 17, 2017 8:41 pm

Sergey,
thank you very much, my "custom" jumps have needed some small changes, but together with your code work perfectly just as I want.
I have also tried CanDelete inside of OnChanging event, it works too, but I'm a little bit confused about behavior. Due to lack of source code I can't check a reason, but when I do Ctrl+V from clipboard the OnChanging event is fired more than once (mostly twice, rarely three times). I can reproduce this even with one line simple text, such as

Code: Select all

HToolButton := ToolButton;
The similar situation is for Ctrl+X.
Can you explain why is it happened, please?

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

Re: Protected section not set automatically on RTF file loading

Post by Sergey Tkachenko » Mon May 22, 2017 1:34 pm

It's not guaranteed that OnChanging is called only once. Some operations may consist of several smaller operations, each of them testing the editor for possibility to change.
When pasting, the first check occurs at very beginning (if the editor cannot be modified, it makes no sense to get something from the Clipboard). The second check is performed by the insertion procedure.
When cutting, the first check occurs at very beginning (if the editor cannot be modified, the fragment must not be copied). The second check occurs after copying, in the selection deletion procedure.

filo
Posts: 22
Joined: Wed Apr 12, 2017 12:28 pm

Re: Protected section not set automatically on RTF file loading

Post by filo » Tue May 23, 2017 10:57 am

OK, understand, thank you.

Post Reply