//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RichView"
#pragma link "RVScroll"
#pragma link "RVStyle"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//-----------------------------------------------------------------------------
// Drawing left to right arrow
//-----------------------------------------------------------------------------
void DrawArrow(TCanvas* Canvas, int Left, int Top, int Width, int Height)
{
   int midx = Left+Width / 2;
   int midy = Top+Height / 2;
   int one, two;
   if (Width>0)
   {
     one = 1;
     two = -2;
   }
   else
   {
     one = -1;
     two = 2;
   }
   TPoint points[8];
   points[0].x = Left+one;
   points[0].y = Top+3;
   points[1].x = midx;
   points[1].y = Top+3;
   points[2].x = midx;
   points[2].y = Top+1;
   points[3].x = Left+Width+two;
   points[3].y = midy;
   points[4].x = midx;
   points[4].y = Top+Height-2;
   points[5].x = midx;
   points[5].y = Top+Height-4;
   points[6].x = Left+one;
   points[6].y = Top+Height-4;
   points[7].x = Left+one;
   points[7].y = Top+3;
   Canvas->Polyline(points, 7);
}
//-----------------------------------------------------------------------------
// Drawing an icon for page breaks
//-----------------------------------------------------------------------------
void DrawPageIcon(TCanvas* Canvas, int Left, int Top, int Width, int Height)
{
   int LeftS  = Left+2;
   int RightS = Left+Width-4;
   TPoint points[8];
   points[0].x = RightS-3;
   points[0].y = Top;
   points[1].x = LeftS;
   points[1].y = Top;
   points[2].x = LeftS;
   points[2].y = Top+Height;
   points[3].x = RightS;
   points[3].y = Top+Height;
   points[4].x = RightS;
   points[4].y = Top+3;
   points[5].x = RightS-3;
   points[5].y = Top;
   points[6].x = RightS-3;
   points[6].y = Top+3;
   points[7].x = RightS;
   points[7].y = Top+3;
   Canvas->Polyline(points, 7);
   Canvas->Pen->Style = psDot;
   Canvas->Pen->Color = clRed;
   Canvas->MoveTo(Left, Top+Height/2);
   Canvas->LineTo(Left+Width, Top+Height/2);
}
//------------------------------------------------------------------------------
// Drawing a colored rectangle with specified degree of opacity (0..255)
// (quite slow...)
//------------------------------------------------------------------------------
void DrawTrRect(TCanvas* Canvas, const TRect ARect,
                     TColor Color, int Opacity)
{
  RGBQUAD rgb;

  long int Clr = ColorToRGB(Color);
  rgb.rgbRed      = (unsigned char)(Clr & 0x000000FF);
  rgb.rgbGreen    = (unsigned char)((Clr & 0x0000FF00) >> 8);
  rgb.rgbBlue     = (unsigned char)((Clr & 0x00FFFFFF) >> 16);
  rgb.rgbReserved = 0;

  Graphics::TBitmap* bmp = new Graphics::TBitmap;
  bmp->PixelFormat = pf32bit;
  bmp->Width       = ARect.Right-ARect.Left;
  bmp->Height      = ARect.Bottom-ARect.Top;
  bmp->Canvas->CopyRect(Rect(0,0,bmp->Width,bmp->Height), Canvas, ARect);

  int tr = 255 - Opacity;
  for (int i=0; i<bmp->Height; i++)
  {
    RGBQUAD* prgb = (RGBQUAD*)(bmp->ScanLine[i]);
    for (int j=0; j<bmp->Width; j++)
    {
      prgb[j].rgbBlue  = (unsigned char)((prgb[j].rgbBlue*tr  + rgb.rgbBlue*Opacity) / 255);
      prgb[j].rgbGreen = (unsigned char)((prgb[j].rgbGreen*tr + rgb.rgbGreen*Opacity) / 255);
      prgb[j].rgbRed   = (unsigned char)((prgb[j].rgbRed*tr   + rgb.rgbRed*Opacity) / 255);
    }
  }
  Canvas->Draw(ARect.Left, ARect.Top, bmp);
  delete bmp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  RichView1->AddNLATag("Example",1,1,0);
  RichView1->AddNLATag("This is an example of ",0,0,0);
  RichView1->AddNLATag("custom drawn text",3,-1,0);
  RichView1->AddNLATag(".",0,-1,0);
  RichView1->AddNLATag(" Hot link 1 ",4,1,0);
  RichView1->AddNLATag(" Hot link 2 ",5,1,0);
  RichView1->AddBreakEx(1, rvbsLine, clBtnShadow);
  RichView1->AddCheckpoint();
  RichView1->AddNLATag("Another example - a custom drawing of checkpoints.",0,0,0);
  RichView1->AddCheckpoint();
  RichView1->AddNLATag("For example, you can draw a little nice arrow instead of default dotted line.",0,0,0);
  RichView1->AddBreakEx(1, rvbsLine, clBtnShadow);
  RichView1->AddNLATag("One more example - a custom displaying of page break",0,0,0);
  RichView1->PageBreaksBeforeItems[RichView1->ItemCount-1] = true;
  RichView1->Format();

  RichView2->AddNLATag("Cool Effect - ",2,2,0);
  RichView2->SetAddParagraphMode(False);
  RichView2->AddNLATag("Transparent paragraph background.",2,2,0);
  RichView2->AddNLATag("example of custom painting of paragraph background",0,2,0);
  RichView2->SetAddParagraphMode(True);
  for (int i=0; i<=20; i++)
    RichView2->AddNLATag("This is the example of using of OnDrawParaBack event.",0,0,0);
  RichView2->Format();
}
//-----------------------------------------------------------------------------
// Should RichView repaint itself if mouse is over text of specified style?
//-----------------------------------------------------------------------------
void __fastcall TForm1::RVStyle1StyleHoverSensitive(TRVStyle *Sender,
      int StyleNo, bool &Sensitive)
{
  if (StyleNo==4 || StyleNo==5)
    Sensitive = true; // (default for other styles)
}
//-----------------------------------------------------------------------------
// Drawing a background of text
//-----------------------------------------------------------------------------
void __fastcall TForm1::RVStyle1DrawTextBack(TRVStyle *Sender,
      TCanvas *Canvas, int StyleNo, int Left, int Top, int Width,
      int Height, TRVTextDrawStates DrawState, bool &DoDefault)
{
  switch (StyleNo)
  {
    case 5:
    {
      // drawing a sunken edge for style #5:
      RECT r = Bounds(Left,Top,Width,Height);
      if (DrawState.Contains(rvtsHover))
        DrawEdge(Canvas->Handle, &r, BDR_SUNKENOUTER | BF_ADJUST, BF_RECT);
      break;
    }
  }
}
//-----------------------------------------------------------------------------
// Drawing a text
//-----------------------------------------------------------------------------
void __fastcall TForm1::RVStyle1DrawStyleText(TRVStyle *Sender,
      const TRVRawByteString s, TCanvas *Canvas, int StyleNo, int SpaceBefore,
      int Left, int Top, int Width, int Height,
      TRVTextDrawStates DrawState, bool &DoDefault)
{
  // This implementation does not support Unicode text items.
  // For Unicode text items, s contains "raw Unicode". It must be
  // converted to ANSI or Unicode string before using.
  // See the same example for C++Builder 2009+ (Demos\CBuilderUnicode\)


  if (DrawState.Contains(rvtsSelected))
    return; // default drawing for selected text
  Left += SpaceBefore;
  switch (StyleNo)
  {
    case 0:
    {
      // sunken effect
      Canvas->Font->Color = clBtnHighlight;
      Canvas->TextOut(Left+1,Top+1, s);
      Canvas->Font->Color = clBtnShadow;
      Canvas->TextOut(Left,Top, s);
      DoDefault = false;
      break;
    }
    case 3:
    {
      // raised effect
      Canvas->Font->Color = clBtnHighlight;
      Canvas->TextOut(Left-1,Top-1, s);
      Canvas->Font->Color = clBtnShadow;
      Canvas->TextOut(Left+1,Top+1, s);
      DoDefault = false;
      break;
    }
    case 4:
    {
      if (DrawState.Contains(rvtsHover))
      {
        // hot glow effect
        Canvas->Font->Color = Sender->TextStyles->Items[StyleNo]->HoverColor;
        Canvas->TextOut(Left+1,Top+1, s);
        Canvas->TextOut(Left-1,Top-1, s);
        Canvas->Font->Color = Sender->TextStyles->Items[StyleNo]->Color;
        Canvas->TextOut(Left,Top, s);
        DoDefault = false;
      }
    }
  }
}
//-----------------------------------------------------------------------------
// Drawing checkpoint as arrow icon
//-----------------------------------------------------------------------------
void __fastcall TForm1::RVStyle1DrawCheckpoint(TRVStyle *Sender,
      TCanvas *Canvas, int X, int Y, int ItemNo, int XShift,
      bool RaiseEvent, TControl *Control, bool &DoDefault)
{
  if (RaiseEvent)
    Canvas->Pen->Color = Sender->CheckpointEvColor;
  else
    Canvas->Pen->Color = Sender->CheckpointColor;
  DrawArrow(Canvas, -XShift+2, Y-5, RichView1->LeftMargin-4, 10);
  DoDefault = false;
}
//-----------------------------------------------------------------------------
// Drawing page break as icon
//-----------------------------------------------------------------------------
void __fastcall TForm1::RVStyle1DrawPageBreak(TRVStyle *Sender,
      TCanvas *Canvas, int Y, int XShift, TRVPageBreakType PageBreakType,
      TControl *Control,
      bool &DoDefault)
{
  Canvas->Pen->Color = Sender->PageBreakColor;
  DrawPageIcon(Canvas, -XShift+2, Y-8, 16, 16);
  DoDefault = false;
}
//-----------------------------------------------------------------------------
// Drawing a background of paragraphs
//-----------------------------------------------------------------------------
void __fastcall TForm1::RVStyle1DrawParaBack(TRVStyle *Sender,
      TCanvas *Canvas, int ParaNo, TRect &ARect, bool &DoDefault)
{
  if (ParaNo==2)
  {
    // semi-transparent background for paragraph style #2:
    DrawTrRect(Canvas, ARect, Sender->ParaStyles->Items[ParaNo]->Background->Color, 150);
    DoDefault = False;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RichView2Paint(TCustomRichView *Sender,
      TCanvas *Canvas, bool Prepaint)
{
  Canvas->Pen->Color = clRed;
  Canvas->Pen->Width = 3;
  Canvas->Brush->Color = clBlack;
  int x = Sender->ClientWidth-10;
  int y = Sender->ClientHeight-10;
  Canvas->Ellipse(x-10, y-10, x+10, y+10);
  tagRECT r = Bounds(x-10, y-10, 20, 20);
  Canvas->Brush->Style = bsClear;
  Canvas->Font->Color = clRed;
  Canvas->Font->Name  = "Arial";
  Canvas->Font->Style = TFontStyles();
  Canvas->Font->Style << fsBold;
  Canvas->Font->Size = 12;
  DrawText(Canvas->Handle, "!", 1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::RichView2RVMouseUp(TCustomRichView *Sender,
      TMouseButton Button, TShiftState Shift, int ItemNo, int X, int Y)
{
  if (X>Sender->ClientWidth-20 && Y>Sender->ClientHeight-20)
    Application->MessageBox("!","!", MB_OK | MB_ICONINFORMATION);
}
//---------------------------------------------------------------------------

