Import anchor links with RVHTMLViewImporter

General TRichView support forum. Please post your questions here
Post Reply
jonjon
Posts: 467
Joined: Sat Aug 27, 2005 4:19 pm

Import anchor links with RVHTMLViewImporter

Post by jonjon »

Is there a way to be notified of an anchor link import (ex: <a name="myAnchor">My Anchor link</a>) using the TRVHTMLViewImporter ?

Thanks a lot.
Sergey Tkachenko
Site Admin
Posts: 17566
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

In this case, RvHtmlImporter will add a checkpoint with the name 'myAnchor'. There are no events or options.

If you use RichViewActions, and you process OnJump event as

Code: Select all

TForm3.RichViewEdit1Jump(Sender: TObject; id: Integer);
begin
  rvActionsResource.rvActionInsertHyperlink1.GoToLink(RichViewEdit1, id);
end;
clicking on the hyperlink with the target '#myAnchor' moves the caret to this checkpoint.
jonjon
Posts: 467
Joined: Sat Aug 27, 2005 4:19 pm

Post by jonjon »

The problem is that my anchors are special TRVLabelItemInfo in TRichViewEdit and not normal checkpoints :(
Any alternative I could use ?

Thanks for the quick reply!
jonjon
Posts: 467
Joined: Sat Aug 27, 2005 4:19 pm

Post by jonjon »

Sergey,

I found a way by parsing the whole TRichView Edit and converting the checkpoints to my custom anchor objects (TRVAnchor). Unfortunately the anchors are not placed exactly where the checkpoints are located but always at the beginning of the line. This might be normal ? What do you think about the code ? Especially the format part which I'm not really sure about:

Code: Select all

procedure RVCheckPointToAnchors(RVData: TCustomRVData);
var
  nCheckPoint, r, c: Integer;
  table: TRVTableItemInfo;
  Tag: Integer;
  Name, Text: String;
  RaiseEvent: Boolean;
  CheckpointData: TCheckpointData;
  oHndAnchor: TRVAnchor;
  RVFormattedData: TCustomRVFormattedData;
  bNeedFormat: Boolean;
begin
  bNeedFormat := False;
  for nCheckPoint := 0 to RVData.ItemCount - 1 do
  begin
    CheckpointData := RVData.GetItemCheckpoint(nCheckPoint);
    if CheckpointData <> nil then
    begin
      bNeedFormat := True;
      RVData.GetCheckpointInfo(CheckpointData, Tag, Name, RaiseEvent);
      // Remove this checkpoint
      RVData.RemoveCheckpoint(nCheckPoint);
      // Insert anchor
      Text := '';
      oHndAnchor := TRVAnchor.CreateEx(RVData, 0, Name);
      oHndAnchor.Inserting(RVData, TRVRawByteString(Text), False);
      RVData.Items.InsertObject(nCheckPoint, TRVRawByteString(Text), oHndAnchor);
      oHndAnchor.Inserted(RVData, nCheckPoint);
    end;
    if RVData.GetItemStyle(nCheckPoint) = rvsTable then
    begin
      table := TRVTableItemInfo(RVData.GetItem(nCheckPoint));
      for r := 0 to table.RowCount-1 do
        for c := 0 to table.ColCount-1 do
          if table.Cells[r,c] <> nil then
            RVCheckPointToAnchors(table.Cells[r,c].GetRVData);
    end;
  end;
  // Format if needed
  if (bNeedFormat) then
  begin
    if (RVData.GetParentControl is TCustomRichView) then
     TCustomRichView(RVData.GetParentControl).Format();
  end;
end;
Regards,

jonjon.
jonjon
Posts: 467
Joined: Sat Aug 27, 2005 4:19 pm

Post by jonjon »

Any thoughts, Sergey ? Thank you in advance.

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

Post by Sergey Tkachenko »

Your code is almost correct, only "this item starts a paragraph" flag must be assigned.

But I suggest considering another solutions.

Why do you need a special item instead of checkpoint? May be you want to display anchors in your own way, instead of the standard dotted line. You can do it using RVStyle.OnDrawCheckpoint event (the only problem: checkpoints do not occupy space, so your drawing will be over the existing text).
jonjon
Posts: 467
Joined: Sat Aug 27, 2005 4:19 pm

Post by jonjon »

Thank you Sergey,

I do not understand the "this item starts a paragraph" flag ? Where did I miss it ?

Also regarding using my own checkpoints, yes the original problem was to make them a small icon where the user could click to rename them. But I will consider reverting to standard checkpoints in the future based on your recommendation.

Thanks again.
Sergey Tkachenko
Site Admin
Posts: 17566
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

First, the cycle direction must be from top to bottom.

Next, you should assign ParaNo property of your item (equal to ParaNo property of other item in the paragraph where you insert your item).

You should also transfer the following properties from the checkpoint's item to your item:
SameAsPrev - true if the item continues paragraph
BR - can be true only if SameAsPrev=false; if true, this is a line break inside a paragraph, not a paragraph start
PageBreakBefore - can be true only if SameAsPrev=false

Code: Select all

procedure RVCheckPointToAnchors(RVData: TCustomRVData); 
var 
  nCheckPoint, r, c: Integer; 
  table: TRVTableItemInfo; 
  Tag: Integer; 
  Name, Text: String; 
  RaiseEvent: Boolean; 
  CheckpointData: TCheckpointData; 
  oHndAnchor: TRVAnchor; 
  RVFormattedData: TCustomRVFormattedData; 
  bNeedFormat: Boolean; 
begin 
  bNeedFormat := False; 
  [color=red]for nCheckPoint := RVData.ItemCount - 1 downto 0 do[/color] 
  begin 
    CheckpointData := RVData.GetItemCheckpoint(nCheckPoint); 
    if CheckpointData <> nil then 
    begin 
      bNeedFormat := True; 
      RVData.GetCheckpointInfo(CheckpointData, Tag, Name, RaiseEvent); 
      // Remove this checkpoint 
      RVData.RemoveCheckpoint(nCheckPoint); 
      // Insert anchor 
      Text := ''; 
      oHndAnchor := TRVAnchor.CreateEx(RVData, 0, Name);      
[color=red]      oHndAnchor.ParaNo := RVData.GetItemPara(nCheckPoint);
      oHndAnchor.SameAsPrev := RVData.GetItem(nCheckPoint).SameAsPrev;
      if not oHndAnchor.SameAsPrev then
        oHndAnchor.BR := RVData.GetItem(nCheckPoint).BR;
      if (RVData.GetItemStyle(nCheckPoint)<>rvsListMarker) and not
        RVData.GetBoolValue(rvbpFullWidth) then begin
        oHndAnchor.PageBreakBefore := RVData.GetItem(nCheckPoint).PageBreakBefore;
        RVData.GetItem(nCheckPoint).SameAsPrev := True;
      end;[/color]
      oHndAnchor.Inserting(RVData, TRVRawByteString(Text), False); 
      RVData.Items.InsertObject(nCheckPoint, TRVRawByteString(Text), oHndAnchor); 
      oHndAnchor.Inserted(RVData, nCheckPoint); 
    end; 
    if RVData.GetItemStyle(nCheckPoint) = rvsTable then 
    begin 
      table := TRVTableItemInfo(RVData.GetItem(nCheckPoint)); 
      for r := 0 to table.RowCount-1 do 
        for c := 0 to table.ColCount-1 do 
          if table.Cells[r,c] <> nil then 
            RVCheckPointToAnchors(table.Cells[r,c].GetRVData); 
    end; 
  end; 
  // Format if needed 
  if (bNeedFormat) then 
  begin 
    if (RVData.GetParentControl is TCustomRichView) then 
     TCustomRichView(RVData.GetParentControl).Format(); 
  end; 
end; 
jonjon
Posts: 467
Joined: Sat Aug 27, 2005 4:19 pm

Post by jonjon »

Thank you very much for your help Sergey, this is working fine.

The only thing I had to change is:

Code: Select all

RVData.GetBoolValue(rvbpFullWidth)
to

Code: Select all

RVData.GetItem(nCheckPoint).GetBoolValue(rvbpFullWidth)
Sergey Tkachenko
Site Admin
Posts: 17566
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Yes, I misprinted
Post Reply