/*=============================================================================}
{ RichView Printing Demo.                                                      }
{------------------------------------------------------------------------------}
{ Note:                                                                        }
{ This demo does not show how to create user interface to setup margins.       }
{------------------------------------------------------------------------------}
{ Note:                                                                        }
{ This demo does not show how to implement custom scaling of print preview.    }
{ Look at example of  RichViewEdit based editor.                               }
{=============================================================================*/
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma link "RichView"
#pragma link "RVScroll"
#pragma link "RVPP"
#pragma link "CRVPP"
#pragma link "RVStyle"
#pragma link "PtblRV"
#pragma link "CtrlImg"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
const wchar_t* longtext = L"A simple way of describing Delphi is a sophisticated Pascal compiler."
               " Delphi’s roots lie in Borland’s Turbo Pascal, introduced in the mid-1980s."
               " This view of Delphi, however, doesn’t capture the real power of Delphi."
               " Object Pascal, the object-oriented extensions to Pascal, is the underlying"
               " language of Delphi. The Visual Component Library, or VCL, is a hierarchy of "
               "Object Pascal objects that allow you to design programs. A better way of describing "
               "Delphi is an Object Pascal-based visual development environment.\n"
               "The VCL is intimately tied to the Delphi IDE, and is what gives you the ability "
               "to quickly develop applications. The Component palette and Object Inspector allow "
               "you to drop VCL components on forms and then manipulate the properties and events of "
               "those controls without having to write a single line of code.\n"
               "Despite its name, the VCL is not entirely made up of visual components. "
               "In fact, of the over 600 objects in the VCL, most are not visual. "
               "The Delphi IDE allows you to visually add some nonvisual components to "
               "your programs. For example, if you wanted to write a database application "
               "that connected to a table, you would drop a TDataSource component on your "
               "form. TDataSource is a nonvisual component, but is represented on the form by "
               "an icon (which doesn’t show up at runtime), and you can manipulate the properties "
               "and events of TDataSource in the Object Inspector just as you would a visual control.\n"
               "All VCL objects, and in fact all objects in Object Pascal, are derived from TObject. "
               "TObject is unique in that it is an abstract object that has no properties or events, "
               "only methods that allow you to derive objects from this base class. Use TObject as the "
               "immediate base class when writing simple objects that are not components. Components are "
               "objects that you can manipulate at design time. All components in the VCL are derived "
               "from the abstract component type TComponent. The VCL components you will likely use the "
               "most are the VCL’s controls, such as TForm or TSpeedButton. Controls are visual components"
               " derived from the abstract component type TControl.\n"
               "You can use Delphi to create Object Pascal objects without using the VCL, "
               "although by creating any objects in Object Pascal, both your objects and VCL "
               "objects will share a common ancestor in TObject. However, by deriving new objects "
               "from VCL object, much of the work in designing applications is done for you by Delphi. "
               "For example, if you wanted to use a progress bar in your application but didn’t like "
               "TProgressBar, Delphi’s control that creates a progress bar, you could create a new "
               "object based on TProgressBar and override its properties, events, or methods.";

  // Creating sample document
  RichView1->AddNLWTag("Printing Demo",1,2,0);
  RichView1->AddTextNLW(longtext,0,0,0,false);
  RichView1->AddBreak();
  RichView1->AddTextNLW(longtext,0,1,1,false);
  RichView1->AddBreak();
  RichView1->AddTextNLW(longtext,0,2,2,false);
  RichView1->AddBreak();
  RichView1->AddTextNLW(longtext,0,3,3,false);
  RichView1->AddBreak();
  RichView1->AddTextNLW(longtext,0,4,4,false);
  RichView1->AddBreak();
  RichView1->AddTextNLW(longtext,0,5,5,false);
  RichView1->AddBreak();
  RichView1->AddTextNLW(longtext,0,7,7,false);

  RichView1->AddControlEx("", Panel2, 2, rvvaBaseline);

  TGraphic * gr = new TIcon;
  gr->Assign(Image1->Picture);
  RichView1->AddPictureEx("", gr, -1,  rvvaBaseline);

  gr = new TMetafile;
  gr->Assign(Image2->Picture);
  RichView1->AddPictureEx("", gr, -1,  rvvaBaseline);

  // Created...
  RichView1->Format();

  // Assigning margins: 20 mm.
  RVPrint1->LeftMarginMM   = 20;
  RVPrint1->RightMarginMM  = 20;
  RVPrint1->BottomMarginMM = 20;
  // Top margin: 25 mm.
  RVPrint1->TopMarginMM    = 25;

  // Making printable area on preview visible...
  RVPrintPreview1->MarginsPen->Style = psDot;

  // Assigning OnPrintComponent at run time - there is a problem specifying Graphics::TBitmap
  // in event handlers
  RVPrint1->OnPrintComponent = RVPrint1PrintComponent;
}
//---------------------------------------------------------------------------
// Switching page to "Preview"
//---------------------------------------------------------------------------
void __fastcall TForm1::PageControl1Change(TObject *Sender)
{
  if (PageControl1->ActivePage->PageIndex==1 && !PreviewCreated)
  {
    PreviewCreated = true;
    UpdatePreview();
  }
  RVPrintPreview1->ZoomMode = rvzmFullPage;
}
//---------------------------------------------------------------------------
void TForm1::UpdatePreview()
{
  Screen->Cursor = crHourGlass;
  // Assigning document for printing:
  RVPrint1->AssignSource(RichView1);
  // Formatting pages:
  RVPrint1->FormatPages(TRVDisplayOptions());
  // Updating user interface for preview:
  ScrollBar1->Min = 1;
  ScrollBar1->Position = 1;
  ScrollBar1->PageSize = 1;
  ScrollBar1->Max = RVPrint1->PagesCount;
  // Preview will show full page:
  RVPrintPreview1->ZoomMode = rvzmFullPage;
  // Preview will show 1st page:
  RVPrintPreview1->First();
  Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------
// Page turning:
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
  if (ScrollBar1->Position>0)
  {
    RVPrintPreview1->PageNo = ScrollBar1->Position;
    StatusBar1->SimpleText = Sysutils::Format("Page %d of %d",
      ARRAYOFCONST((RVPrintPreview1->PageNo, RVPrint1->PagesCount)));
  }
}
//---------------------------------------------------------------------------
// Event: printing inserted components.
// We need to create bitmap, draw component onto it,
// and assign this bitmap to ComponentImage parameter.
// Bitmap should have the same size as component. (if not, it will be scaled)
// CtrlImg.pas from RichView package has useful function DrawControl.
//---------------------------------------------------------------------------
void __fastcall TForm1::RVPrint1PrintComponent(TCustomRVPrint *Sender,
    TControl *PrintMe, Graphics::TBitmap *&ComponentImage)
{
  ComponentImage = DrawControl(PrintMe);
  // actually, DrawControl is used by default. You need to process this
  // event only if you are not satisfied with its results.
}
//---------------------------------------------------------------------------
// Printing...
//---------------------------------------------------------------------------
void __fastcall TForm1::btnPrintClick(TObject *Sender)
{
  if (!PreviewCreated)
  {
    PreviewCreated = true;
    UpdatePreview();
  }
  // do not print empty document!
  if (RichView1->ItemCount==0)
    return;
  PrintDialog1->MinPage = 1;
  PrintDialog1->MaxPage = RVPrint1->PagesCount;
  PrintDialog1->FromPage = 1;
  PrintDialog1->ToPage = RVPrint1->PagesCount;
  // we can print a whole document or specified pages:
  if (PrintDialog1->Execute())
  {
    // it's possible that current printer was changed.
    // so we need to reformat document and update preview:
    UpdatePreview();
    switch (PrintDialog1->PrintRange)
    {
      case prAllPages:
        RVPrint1->Print( "Test", PrintDialog1->Copies, PrintDialog1->Collate);
        break;
      case prPageNums:
        RVPrint1->PrintPages(PrintDialog1->FromPage, PrintDialog1->ToPage,
              "Test", PrintDialog1->Copies, PrintDialog1->Collate);
    }
  }
}
//---------------------------------------------------------------------------
// Event: displaying formatting progress...
//---------------------------------------------------------------------------
void __fastcall TForm1::RVPrint1Formatting(TCustomRichView *Sender,
    int PageCompleted, TRVPrintingStep Step)
{
  switch (Step)
  {
    case rvpsStarting:
      StatusBar1->SimpleText = "Repaginating...";
      break;
    case rvpsProceeding:
      StatusBar1->SimpleText =
        Sysutils::Format("Repaginating (%d)", ARRAYOFCONST((PageCompleted)));
      break;
    case rvpsFinished:
      StatusBar1->SimpleText = "";
  }
}
//---------------------------------------------------------------------------
// Event: displaying printing (spooling) progress...
//---------------------------------------------------------------------------
void __fastcall TForm1::RVPrint1SendingToPrinter(TCustomRichView *Sender,
    int PageCompleted, TRVPrintingStep Step)
{
  switch (Step)
  {
    case rvpsStarting:
      StatusBar1->SimpleText = "Starting...";
      break;
    case rvpsProceeding:
      StatusBar1->SimpleText =
        Sysutils::Format("Printing (%d)", ARRAYOFCONST((PageCompleted)));
      break;
    case rvpsFinished:
      StatusBar1->SimpleText = "";
  }
}
//---------------------------------------------------------------------------
// Event: prepaint on page
//---------------------------------------------------------------------------
void __fastcall TForm1::RVPrint1PagePrepaint(TRVPrint *Sender, int PageNo,
    TCanvas *Canvas, bool Preview, TRect &PageRect, TRect &PrintAreaRect)
{

  // This is a temporary solution for drawing page numbers and similalar stuff

  // This example outputs string just above RichView contents

  UnicodeString s = Sysutils::Format ("-- Page %d of %d --",
    ARRAYOFCONST((PageNo, Sender->PagesCount)));
  Canvas->Brush->Style = bsClear;
  Canvas->Font->Assign(RVStyle1->TextStyles->Items[0]);
  int w = Canvas->TextWidth(s);
  int h = Canvas->TextHeight(s);
  TextOut(Canvas->Handle, (PrintAreaRect.Right+PrintAreaRect.Left-w) / 2,
    PrintAreaRect.Top - h - 10, s.w_str(), s.Length());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Panel3Resize(TObject *Sender)
{
  // In earlier versions of C++Builder scrollbars do not have Align property...
  // Aligning to the right side of panel
  ScrollBar1->SetBounds(Panel3->ClientWidth-ScrollBar1->Width, 0,
    ScrollBar1->Width, Panel3->ClientHeight);
}
//---------------------------------------------------------------------------
