unit MFStructDoc;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, SRVSkinManager, SRVTabSet, SclRView, ComCtrls, ExtCtrls, CRVData,
  RVScroll, SRVPageScroll, RichView, RVStyle, RVItem, RVTable, RVNote, RVMarker;

type
  TFStructDoc = class(TForm)
    SRVTabMode: TSRVTabSet;
    TreeView1: TTreeView;
    PanelSRV: TPanel;
    SRVPageScroll1: TSRVPageScroll;
    SRichViewEdit1: TSRichViewEdit;
    Splitter1: TSplitter;
    srvTOC: TSRichViewEdit;
    SRVSkinManager1: TSRVSkinManager;
    procedure SRVTabModeChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    ParaStylesNo: array [0..2] of Integer; // styles of paragraphs in TOC
    TitleStyleNo, TitleParaNo: Integer; // styles for TOC headings   
  public
    { Public declarations }
  end;

var
  FStructDoc: TFStructDoc;


implementation

uses SRVTOC;

{$R *.dfm}

var
  RememberZoomMode : TRVZoomMode;
  RememberZoomPercent : Single;

{------------------------------------------------------------------------------}
// Shows a document structure in tree view
// See http://www.trichview.com/forums/viewtopic.php?t=3627 
procedure ShowStructure(RVData: TCustomRVData; Node: TTreeNode);
var i, StyleNo: Integer;
    ParaNode, ItemNode: TTreeNode;

    function GetExtraBreakProps(i: Integer): String;
    begin
      if RVData.PageBreaksBeforeItems[i] then begin
        Result := '; page break';
        exit; 
      end; 
      if RVData.ClearLeft[i] then
        if RVData.ClearRight[i] then
          Result := '; clear both'
        else 
          Result := '; clear left'
      else 
        if RVData.ClearRight[i] then 
          Result := '; clear right' 
        else 
          Result := ''; 
    end; 

    function GetExtraItemString(i: Integer): String; 
    begin 
      Result := '';
      if RVData.GetItem(i).GetBoolValueEx(rvbpJump, RVData.GetRVStyle) then
        Result := '; hyperlink';
      if RVData.GetItemTag(i)<>0 then 
        if rvoTagsArePChars in RVData.Options then 
          Result := Result+ '; tag: "'+PChar(RVData.GetItemTag(i))+'"' 
        else 
          Result := Result+ '; tag: '+IntToStr(RVData.GetItemTag(i)); 
    end;

    procedure AddCheckpoint(i: Integer);
    var CPTag: Integer;
        CPName: String; 
        CPRE: Boolean;
    begin 
      if RVData.GetItemCheckpoint(i)<>nil then begin
        RVData.GetCheckpointInfo(RVData.GetItemCheckpoint(i), CPTag, CPName, CPRE); 
        Node.Owner.AddChild(ItemNode, Format('Checkpoint "%s"',
          [CPName]));
      end; 
    end; 

    procedure AddTableInfo(i: Integer);
    var r, c: Integer; 
      table: TRVTableItemInfo;
      RowNode, CellNode: TTreeNode;
    begin 
      table := TRVTableItemInfo(RVData.GetItem(i));
      for r := 0 to table.RowCount-1 do begin 
        RowNode := Node.Owner.AddChild(ItemNode, Format('Row %d', [r])); 
        for c := 0 to table.ColCount-1 do begin 
          if table.Cells[r,c]<>nil then begin
            CellNode := Node.Owner.AddChild(RowNode, Format('Cell %d', [c])); 
            ShowStructure(table.Cells[r,c].GetRVData, CellNode); 
          end; 
        end; 
      end
    end; 

    procedure AddListMarkerInfo(i: Integer); 
    var ListNo, Level, StartFrom: Integer;
       UseStartFrom: Boolean; 
       s: String; 
    begin
      RVData.GetListMarkerInfo(i, ListNo, Level, StartFrom, UseStartFrom); 
      s := Format('ListNo=%d, Level=%d',[ListNo, Level]); 
      if UseStartFrom then 
        s := s+Format(', start from %d', [StartFrom]);
      Node.Owner.AddChild(ItemNode, s);
    end; 

begin 
  ParaNode := nil;
  for i := 0 to RVData.ItemCount-1 do begin 
    if RVData.IsParaStart(i) then 
      ParaNode := Node.Owner.AddChild(Node, Format('Paragraph, ParaNo=%d%s', 
        [RVData.GetItemPara(i), GetExtraBreakProps(i)])) 
    else if RVData.IsFromNewLine(i) then 
      Node.Owner.AddChild(ParaNode, Format('Line break%s', 
        [GetExtraBreakProps(i)])); 
    StyleNo := RVData.GetItemStyle(i); 
    if StyleNo>=0 then
      ItemNode := Node.Owner.AddChild(ParaNode, Format('Text "%s", StyleNo=%d%s', 
        [RVData.GetItemText(i), StyleNo, GetExtraItemString(i)])) 
    else begin 
      ItemNode := Node.Owner.AddChild(ParaNode, Format('%s [StyleNo=%d]%s',
        [RVData.GetItem(i).ClassName, StyleNo, GetExtraItemString(i)])); 
      if RVData.GetItem(i) is TRVTableItemInfo then 
        AddTableInfo(i)
      else if RVData.GetItem(i) is TCustomRVNoteItemInfo then
        ShowStructure(TCustomRVNoteItemInfo(RVData.GetItem(i)).Document,
          Node.Owner.AddChild(ItemNode, 'Note text')) 
      else if RVData.GetItem(i) is TRVMarkerItemInfo then
        AddListMarkerInfo(i);
    end; 
    AddCheckpoint(i);
  end; 
end;
{----------------------------- View Modes -------------------------------------}
// Normal (draft) view mode (as one long page)
procedure OnePageMode(srve : TSRichViewEdit);
begin
  srve.PageProperty.AutoWidth := False;
  srve.PageProperty.PageFormat := srvfmA4;
  srve.PageProperty.PageViewMode := False;
  srve.PageProperty.BorderPen.Style := psClear;
  srve.PageProperty.BoundLeftRight := 20;
  srve.BackgroundProperty.Visible := False;
  srve.Color := clWhite;
  srve.ViewProperty.ShowScrollHint := True;
  srve.ViewProperty.AlignPageH := srvaphLeft;
  srve.ViewProperty.AlignPageV := srvapvTop;
  srve.ViewProperty.ZoomPercent := RememberZoomPercent;
  srve.ViewProperty.ZoomMode := RememberZoomMode;
end;
// Web view mode
procedure WebMode(srve : TSRichViewEdit);
begin
  RememberZoomPercent := srve.ViewProperty.ZoomPercent;
  RememberZoomMode := srve.ViewProperty.ZoomMode;
  srve.ViewProperty.ZoomPercent := 100;
  srve.PageProperty.PageViewMode := False;
  srve.PageProperty.BoundLeftRight := 0;
  srve.ViewProperty.ShowScrollHint := False;
  srve.BackgroundProperty.Visible := False;
  srve.Color := clWhite;
  srve.ViewProperty.AlignPageH := srvaphLeft;
  srve.ViewProperty.AlignPageV := srvapvTop;
  srve.PageProperty.BorderPen.Style := psClear;
  srve.PageProperty.AutoWidth := True;
  srve.ViewProperty.ZoomPercent := RememberZoomPercent;
end;

// Page view (print) mode
procedure MultiPageMode(srve : TSRichViewEdit);
begin
  srve.PageProperty.AutoWidth := False;
  srve.PageProperty.PageViewMode := True;
  srve.PageProperty.PageFormat := srvfmA4;
  srve.ViewProperty.ShowScrollHint := True;
  srve.BackgroundProperty.Visible := True;
  srve.Color := $0099A8AC;
  srve.PageProperty.BoundLeftRight := 20;
  srve.PageProperty.MinPageBreakHeight := 5;
  srve.PageProperty.MaxPageBreakHeight := 25;
  srve.PageProperty.BorderPen.Style := psSolid;
  srve.ViewProperty.AlignPageH := srvaphCenter;
  srve.ViewProperty.AlignPageV := srvapvCenter;
  srve.ViewProperty.ZoomPercent := RememberZoomPercent;
  srve.ViewProperty.ZoomMode := RememberZoomMode;
end;
{------------------------------------------------------------------------------}
// Adds Count paragraph styles in rv.Style (or reusing existing styles, if possible). 
// Indices of these styles are returned in ParaStyleNos 
// (this array must have at least Count items). 
// All these paragraphs have one right-aligned tab stop at the position
// equal to the width of printable area in RVPrint.
// Each next paragraph is indented by IndentStep.
procedure GenerateTOCParagraphsSRV(srv : TSRichViewEdit;
  Count, IndentStep: Integer; var ParaStyleNos: array of Integer);
var ParaStyle: TParaInfo;
    Width, i: Integer;
    rv: TCustomRichView;
begin
  rv := srv.RichViewEdit;
  Width := srv.PageWidth100Pix;
  dec(Width, srv.LeftMargin100Pix+srv.RightMargin100Pix);
  ParaStyle := TParaInfo.Create(nil);
  try
    with ParaStyle.Tabs.Add do begin
      Position := Width-1;
      Align := rvtaRight; 
      Leader := '.';
    end; 
    for i := 0 to Count-1 do begin 
      ParaStyle.LeftIndent := IndentStep*i;
      ParaStyleNos[i] :=
        rv.Style.ParaStyles.FindSuchStyle(0, ParaStyle, RVAllParaInfoProperties); 
      if ParaStyleNos[i]<0 then begin 
        rv.Style.ParaStyles.Add; 
        ParaStyleNos[i] := rv.Style.ParaStyles.Count-1;
        rv.Style.ParaStyles[ParaStyleNos[i]].Assign(ParaStyle);
        rv.Style.ParaStyles[ParaStyleNos[i]].Standard := False;
      end;
    end;
  finally
    ParaStyle.Free;
  end;
end;
{------------------------------------------------------------------------------}
procedure TFStructDoc.SRVTabModeChange(Sender: TObject);
begin
  case SRVTabMode.TabIndex of
    0: // multipage mode with thumbnails
      begin
        SRVPageScroll1.SRichViewEdit := SRichViewEdit1;
        MultiPageMode(SRichViewEdit1);
        SRVPageScroll1.Show;
        Splitter1.Show;
        PanelSRV.Show;
        TreeView1.Hide;
        srvTOC.Hide;
      end;
    1: // TOC
      begin
        TreeView1.Hide;
        PanelSRV.Hide;
        // Adding 3-level TOC
        srvTOC.RichViewEdit.Clear;
        AddTableOfContentsSRV(SRichViewEdit1, srvTOC, 3, [0,0,0], ParaStylesNo, SRichViewEdit1.RichViewEdit.ItemCount,
          'Table of Contents', TitleStyleNo, TitleParaNo);
        srvTOC.Format;
        srvTOC.Show;
      end;
    2:
      begin
        TreeView1.Items.BeginUpdate;
        TreeView1.Items.Clear;
        TreeView1.Items.AddChildFirst(nil, 'Document');
        ShowStructure(SRichViewEdit1.RichViewEdit.RVData, TreeView1.Items[0]);
        TreeView1.Items.EndUpdate;
        TreeView1.Show;
        PanelSRV.Hide;
        srvTOC.Hide;
      end;
    3:
      begin
        SRVPageScroll1.SRichViewEdit := nil;
        SRVPageScroll1.Hide;
        WebMode(SRichViewEdit1);
        Splitter1.Hide;
        PanelSRV.Show;
        TreeView1.Hide;
        srvTOC.Hide;
      end;
    4:
      begin
        SRVPageScroll1.SRichViewEdit := nil;
        SRVPageScroll1.Hide;
        OnePageMode(SRichViewEdit1);
        Splitter1.Hide;
        PanelSRV.Show;
        TreeView1.Hide;
        srvTOC.Hide;
      end;
  end;
end;

procedure TFStructDoc.FormCreate(Sender: TObject);
begin
  SRichViewEdit1.LoadRVF('readme.rvf');

  srvTOC.RichViewEdit.Style.TextStyles := SRichViewEdit1.RichViewEdit.Style.TextStyles;
  srvTOC.RichViewEdit.Style.ParaStyles := SRichViewEdit1.RichViewEdit.Style.ParaStyles;
  srvTOC.RichViewEdit.Style.ListStyles := SRichViewEdit1.RichViewEdit.Style.ListStyles;
  GetStylesForOutlineLevel(SRichViewEdit1.RichViewEdit, 1, TitleStyleNo, TitleParaNo);
  GenerateTOCParagraphsSRV(srvTOC, 3, 24, ParaStylesNo);
  RememberZoomPercent := SRichViewEdit1.ViewProperty.ZoomPercent;
  RememberZoomMode := SRichViewEdit1.ViewProperty.ZoomMode;
end;

end.
