Page 1 of 1

Import anchor links with RVHTMLViewImporter

Posted: Fri Jan 15, 2010 6:30 pm
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.

Posted: Fri Jan 15, 2010 7:13 pm
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.

Posted: Fri Jan 15, 2010 8:30 pm
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!

Posted: Sat Jan 16, 2010 1:32 pm
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.

Posted: Wed Jan 27, 2010 9:27 am
by jonjon
Any thoughts, Sergey ? Thank you in advance.

jonjon.

Posted: Thu Jan 28, 2010 9:34 am
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).

Posted: Thu Jan 28, 2010 10:15 am
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.

Posted: Tue Feb 09, 2010 4:28 pm
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; 

Posted: Sat Mar 13, 2010 7:42 am
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)

Posted: Sat Mar 13, 2010 9:14 am
by Sergey Tkachenko
Yes, I misprinted