{
This demo shows how to display pages in 4 columns.
This is an example of free page positioning.
See the comments in OnGetPagePos event.
}

unit MFColumns;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, RVScroll, RVEdit, ExtCtrls, SclRView, RVStyle, Menus, Ruler, RVRuler,
  SclRVRuler, StdCtrls, Printers, ComCtrls, ToolWin, Buttons, SRVToolBar,
  ImgList, CRVFData, SRVToolWindow, RVTable, RVMisc;

type
  TFColumns = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    btnPrint: TButton;
    btnNewPage: TButton;
    btnLoadRVF: TButton;
    btnSaveRVF: TButton;
    Panel3: TPanel;
    SclRVRuler1: TSclRVRuler;
    Panel4: TPanel;
    Panel5: TPanel;
    SRichViewEdit1: TSRichViewEdit;
    SclRVRuler2: TSclRVRuler;
    btnPageSetup: TButton;
    RVRulerItemSelector1: TRVRulerItemSelector;
    cbShowTextArea: TCheckBox;
    stat1: TStatusBar;
    ImageList2: TImageList;
    ImageList1: TImageList;
    SaveDialog1: TSaveDialog;
    OpenDialog1: TOpenDialog;
    PrintDialog1: TPrintDialog;
    PopupMenu1: TPopupMenu;
    mitCopy: TMenuItem;
    mitCut: TMenuItem;
    mitPaste: TMenuItem;
    mitSelectAll: TMenuItem;
    fd: TFindDialog;
    rd: TReplaceDialog;
    srvtlwndw1: TSRVToolWindow;
    ImageList3: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure btnPrintClick(Sender: TObject);
    procedure btnNewPageClick(Sender: TObject);
    procedure btnLoadRVFClick(Sender: TObject);
    procedure btnSaveRVFClick(Sender: TObject);
    procedure btnPageSetupClick(Sender: TObject);
    procedure SclRVRuler1MarginDblClick(Sender: TObject;
      Margin: TMarginType);
    procedure SRichViewEdit1PageCountChanged(Sender: TObject);
    procedure SRichViewEdit1CurrentPageChange(Sender: TObject);
    procedure SRichViewEdit1PageScrolled(Sender: TObject);
    procedure SRichViewEdit1CaretMove(Sender: TObject);
    procedure cbShowTextAreaClick(Sender: TObject);
    procedure SRichViewEdit1HMenuClickButton(Sender: TObject;
      ToolButton: TSRVToolButton);
    procedure SRichViewEdit1VMenuClickButton(Sender: TObject;
      ToolButton: TSRVToolButton);
    procedure srvtlwndw1ClickButton(Sender: TObject;
      ToolButton: TSRVToolButton);
    procedure fdFind(Sender: TObject);
    procedure mitCopyClick(Sender: TObject);
    procedure mitCutClick(Sender: TObject);
    procedure mitPasteClick(Sender: TObject);
    procedure mitSelectAllClick(Sender: TObject);
    procedure SRichViewEdit1GetPagePos(Sender: TSRichViewEdit; PageNo,
      StartItemNo, EndItemNo, OffsetInStartItem, StartTableRow,
      EndTableRow: Integer; var Position: TPoint; var ZoomPercent: Single;
      var ZOrder: Integer);
  private
    { Private declarations }
    HToolButton, VToolButton: TSRVToolButton;
  public
    { Public declarations }
  end;

var
  FColumns: TFColumns;

implementation

uses Math, f_PageProperty;

{$R *.dfm}

procedure ShowInfo(const msg,cpt: String);
begin
  Application.MessageBox(PChar(msg),PChar(cpt),MB_OK or MB_ICONINFORMATION);
end;
{------------------------------------------------------------------------------}
// Normal 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.BoundLeftRight := 0;
  srve.PageProperty.MinPageBreakHeight := 0;
  srve.PageProperty.MaxPageBreakHeight := 0;
  srve.PageProperty.BorderPen.Style := psClear;
  srve.BackgroundProperty.Visible := False;
  srve.Color := clWhite;
  srve.ViewProperty.ShowScrollHint := True;
  srve.ViewProperty.AlignPageH := srvaphLeft;
  srve.ViewProperty.AlignPageV := srvapvTop;
end;
// Web view mode
procedure WebMode(srve : TSRichViewEdit);
begin
  srve.PageProperty.PageViewMode := False;
  srve.ViewProperty.ShowScrollHint := False;
  srve.BackgroundProperty.Visible := False;
  srve.Color := clWhite;
  srve.PageProperty.BoundLeftRight := 0;
  srve.PageProperty.MinPageBreakHeight := 0;
  srve.PageProperty.MaxPageBreakHeight := 0;
  srve.ViewProperty.AlignPageH := srvaphLeft;
  srve.ViewProperty.AlignPageV := srvapvTop;
  srve.PageProperty.BorderPen.Style := psClear;
  srve.PageProperty.AutoWidth := True;
end;
// Page view 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;
end;
{------------------------------------------------------------------------------}
procedure TFColumns.FormCreate(Sender: TObject);
begin
  VToolButton := nil;
  SRichViewEdit1.CalculateAllPagePositions;
end;
{------------------------------------------------------------------------------}
{ Popup menu commands }
// Copy
procedure TFColumns.mitCopyClick(Sender: TObject);
begin
  SRichViewEdit1.Copy;
end;
// Cut
procedure TFColumns.mitCutClick(Sender: TObject);
begin
  SRichViewEdit1.Cut;
end;
// Paste
procedure TFColumns.mitPasteClick(Sender: TObject);
begin
  SRichViewEdit1.Paste;
end;
// Select All
procedure TFColumns.mitSelectAllClick(Sender: TObject);
begin
  SRichViewEdit1.SelectAll;
end;
{------------------------------------------------------------------------------}
{ Button click: printing }
procedure TFColumns.btnPrintClick(Sender: TObject);
begin
  if PrintDialog1.Execute then
    begin
      if HToolButton <> nil then
        begin
          SRichViewEdit1.CanUpdate := False;
          MultiPageMode(SRichViewEdit1);
          SRichViewEdit1.PrintAll;
          SRichViewEdit1HMenuClickButton(SRichViewEdit1, HToolButton);
        end
      else
        SRichViewEdit1.PrintAll;
    end;
end;
{------------------------------------------------------------------------------}
{ Button click: page setup }
procedure TFColumns.btnPageSetupClick(Sender: TObject);
begin
  SRichViewEdit1.CanUpdate := FALSE;

  With FPageProperty do
    begin
      PageLeft.Text := FloatToStr(Round(SRichViewEdit1.PageProperty.LeftMargin * 100) * 0.01);
      PageRight.Text := FloatToStr(Round(SRichViewEdit1.PageProperty.RightMargin * 100) * 0.01);

      PageTop.Text := FloatToStr(Round(SRichViewEdit1.PageProperty.TopMargin * 100) * 0.01);
      PageBottom.Text := FloatToStr(Round(SRichViewEdit1.PageProperty.BottomMargin * 100) * 0.01);

      if SRichViewEdit1.PageProperty.Orientation = poPortrait then
        begin
          RadioGroup1.ItemIndex := 0;
        end
      else
        begin
          RadioGroup1.ItemIndex := 1;
        end;

      case SRichViewEdit1.PageProperty.PageFormat of
        srvfmA4: ListPaper.ItemIndex := 0;
        srvfmA5: ListPaper.ItemIndex := 1;
      else
        ListPaper.ItemIndex := 0;
      end;
    end;

  if FPageProperty.ShowModal = mrOK then
    begin
      With FPageProperty do
        begin
          SRichViewEdit1.SetMarginUnit(StrToFloat(Trim(PageLeft.Text)),
                                       StrToFloat(Trim(PageTop.Text)),
                                       StrToFloat(Trim(PageRight.Text)),
                                       StrToFloat(Trim(PageBottom.Text)));
{          SRichViewEdit1.SetMarginMM(Round(PageLeft.Value),
                                 Round(PageTop.Value),
                                 Round(PageRight.Value),
                                 Round(PageBottom.Value));}
          SclRVRuler1.Scrolled;
          SclRVRuler2.Scrolled;

          if RadioGroup1.ItemIndex = 0 then
            begin
              if SRichViewEdit1.PageProperty.Orientation <> poPortrait then
                SRichViewEdit1.PageProperty.Orientation := poPortrait;
            end
          else
            begin
              if SRichViewEdit1.PageProperty.Orientation <> poLandscape then
                SRichViewEdit1.PageProperty.Orientation := poLandscape;
            end;

          case ListPaper.ItemIndex of
            0 : if SRichViewEdit1.PageProperty.PageFormat <> srvfmA4 then
                  SRichViewEdit1.PageProperty.PageFormat := srvfmA4;
            1 : if SRichViewEdit1.PageProperty.PageFormat <> srvfmA5 then
                  SRichViewEdit1.PageProperty.PageFormat := srvfmA5;
          end;
        end;
    end;
  SRichViewEdit1.CanUpdate := TRUE;
end;
{------------------------------------------------------------------------------}
{ Button click: inserting page break }
procedure TFColumns.btnNewPageClick(Sender: TObject);
begin
  SRichViewEdit1.InsertPageBreak;
  SRichViewEdit1.SetFocus;
end;
{------------------------------------------------------------------------------}
{ Button click: loading RVF file }
procedure TFColumns.btnLoadRVFClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
    SRichViewEdit1.LoadRVF(OpenDialog1.FileName);
  SclRVRuler2.Scrolled;
end;
{------------------------------------------------------------------------------}
{ Button click: saving RVF file }
procedure TFColumns.btnSaveRVFClick(Sender: TObject);
begin
  if SaveDialog1.Execute then
    SRichViewEdit1.RichViewEdit.SaveRVF(SaveDialog1.FileName, FALSE);
end;
{------------------------------------------------------------------------------}
{ Checkbox: hiding/showing a rectangle around the document area on pages }
procedure TFColumns.cbShowTextAreaClick(Sender: TObject);
begin
  SRichViewEdit1.ViewProperty.BoundTextVisible := cbShowTextArea.Checked;
end;
{------------------------------------------------------------------------------}
{ Double clicking on the rulers' margins shows the page setup dialog }
procedure TFColumns.SclRVRuler1MarginDblClick(Sender: TObject;
  Margin: TMarginType);
begin
  btnPageSetupClick(nil);
end;
{------------------------------------------------------------------------------}
{ Event, occurs when page count is changed }
procedure TFColumns.SRichViewEdit1PageCountChanged(Sender: TObject);
begin
  SRichViewEdit1CurrentPageChange(nil);
end;
{------------------------------------------------------------------------------}
{ Event, occurs when caret moves to another page }
procedure TFColumns.SRichViewEdit1CurrentPageChange(Sender: TObject);
begin
  stat1.Panels.Items[1].Text := IntToStr(SRichViewEdit1.CurrentPage) + '/' +
                                IntToStr(SRichViewEdit1.PageCount);
end;
{------------------------------------------------------------------------------}
{ Event, occurs on scrolling, when another page is displayed }
procedure TFColumns.SRichViewEdit1PageScrolled(Sender: TObject);
begin
  stat1.Panels.Items[0].Text := 'Page ' + IntToStr(SRichViewEdit1.ScrolledPage);
end;
{------------------------------------------------------------------------------}
{ Event, occurs when caret moves }
procedure TFColumns.SRichViewEdit1CaretMove(Sender: TObject);
var Line, Column : Integer;
begin
  SRichViewEdit1.GetCurrentLineCol(Line, Column);
  stat1.Panels.Items[3].Text := 'Line ' + IntToStr(Line);
  stat1.Panels.Items[4].Text := 'Col ' + IntToStr(Column);
end;
{------------------------------------------------------------------------------}
{ Event, occurs when button on horizontal scrollbar is clicked }
{ In this application, these buttons switch view mode: normal / web / page view }
procedure TFColumns.SRichViewEdit1HMenuClickButton(Sender: TObject;
  ToolButton: TSRVToolButton);
begin
  HToolButton := ToolButton;
  if ToolButton = nil then Exit;
  SRichViewEdit1.CanUpdate := False;
  case (ToolButton.Index) of
    0 : OnePageMode(SRichViewEdit1);
    1 : WebMode(SRichViewEdit1);
    2 : MultiPageMode(SRichViewEdit1);
  end;
  SRichViewEdit1.CanUpdate := True;
end;
{------------------------------------------------------------------------------}
{ Event, occurs when button on vertical scrollbar is clicked }
procedure TFColumns.SRichViewEdit1VMenuClickButton(Sender: TObject;
  ToolButton: TSRVToolButton);
var
     sbX, sbY : Integer;
     p : TPoint;
begin
  if ToolButton = nil then Exit;
  case ToolButton.Index of
    0 : // "Up arrows" button, performs search to the top
      begin
        if VToolButton = nil then
          SRichViewEdit1.PriorCurPage
        else
          case VToolButton.Index of
            0 : SRichViewEdit1.PriorCurPage;
            1 : SRichViewEdit1.PriorCurItem([rvsTable]);
            2 : SRichViewEdit1.PriorCurItem([rvsPicture, rvsHotspot, rvsHotPicture]);
            3 : SRichViewEdit1.PriorCurItem([rvsHeading]);
            4 : SRichViewEdit1.PriorCurHyperlink;
            6 :
              begin
                fd.Options := fd.Options - [frDown];
                fdFind(nil);
              end;
          end;
      end;
    1 : // "Circle" button, shows tool window
      begin
        sbX := SRichViewEdit1.MenuVertical.SRVToolBar.Width;
        sbY := SRichViewEdit1.MenuVertical.SRVToolBar.Height div 3;

        p := SRichViewEdit1.MenuVertical.SRVToolBar.ClientToScreen(Point(0, 0));
        p.Y := p.Y + sbY;

        srvtlwndw1.Execute(Bounds(p.x, p.y, sbX, sbY));
      end;
    2 : // "Down arrows" button, performs search to the bottom
      begin
        if VToolButton = nil then
          SRichViewEdit1.NextCurPage
        else
          case VToolButton.Index of
            0 : SRichViewEdit1.NextCurPage;
            1 : SRichViewEdit1.NextCurItem([rvsTable]);
            2 : SRichViewEdit1.NextCurItem([rvsPicture, rvsHotspot, rvsHotPicture]);
            3 : SRichViewEdit1.NextCurItem([rvsHeading]);
            4 : SRichViewEdit1.NextCurHyperlink;
            6 :
              begin
                fd.Options := fd.Options + [frDown];
                fdFind(nil);
              end;
          end;
      end;
  end;
end;
{------------------------------------------------------------------------------}
{ Event, occurs when button in the tool window is clicked }
procedure TFColumns.srvtlwndw1ClickButton(Sender: TObject;
  ToolButton: TSRVToolButton);
var
     s: String;
     posit: Integer;
begin
  VToolButton := ToolButton;
  if ToolButton.Index = 6 then // starting text search
    begin
      SRichViewEdit1.SetFocus;
      fd.CloseDialog;
      if SRichViewEdit1.RichViewEdit.SelectionExists then
        begin
          s := SRichViewEdit1.RichViewEdit.GetSelText;
          posit := Pos(#13,s);
          if posit<>0 then
            s := Copy(s,1,posit-1);
          fd.FindText := s;
        end;
      fd.Execute;
    end
  else // starting search
    SRichViewEdit1VMenuClickButton(Sender,
      TSRVToolButton(SRichViewEdit1.MenuVButtons.Items[2]));
end;
{------------------------------------------------------------------------------}
{ Text search }
procedure TFColumns.fdFind(Sender: TObject);
begin
  if not SRichViewEdit1.RichViewEdit.SearchText(fd.FindText,GetRVESearchOptions(fd.Options)) then
    ShowInfo('String not found','Search and Replace');
  SRichViewEdit1.ScrollToCaret;
end;
{------------------------------------------------------------------------------}
{ In this event, you can define page position and zooming }
procedure TFColumns.SRichViewEdit1GetPagePos(Sender: TSRichViewEdit;
  PageNo, StartItemNo, EndItemNo, OffsetInStartItem, StartTableRow,
  EndTableRow: Integer; var Position: TPoint; var ZoomPercent: Single;
  var ZOrder: Integer);
begin
  ZoomPercent := 25;
  Position.X := 10 + ((PageNo - 1) mod 4) * (Round(SRichViewEdit1.PageWidth100Pix * ZoomPercent * 0.01) + 30);
  Position.Y := 10 + ((PageNo - 1) div 4) * (Round(SRichViewEdit1.PageHeight100Pix * ZoomPercent * 0.01) + 10);
{
  ZoomPercent – default zooming,
  Position – page position,
  PageWidth100Pix – page width in pixels,
  PageHeight100Pix – page height in pixels.
}
end;

end.
