//---------------------------------------------------------------------------
#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->AddNLWTag("Example",1,1,0);
  RichView1->AddNLWTag("This is an example of ",0,0,0);
  RichView1->AddNLWTag("custom drawn text",3,-1,0);
  RichView1->AddNLWTag(".",0,-1,0);
  RichView1->AddNLWTag(" Hot link 1 ",4,1,0);
  RichView1->AddNLWTag(" Hot link 2 ",5,1,0);
  RichView1->AddBreakEx(1, rvbsLine, clBtnShadow);
  RichView1->AddCheckpoint();
  RichView1->AddNLWTag("Another example - a custom drawing of checkpoints.",0,0,0);
  RichView1->AddCheckpoint();
  RichView1->AddNLWTag("For example, you can draw a little nice arrow instead of default dotted line.",0,0,0);
  RichView1->AddBreakEx(1, rvbsLine, clBtnShadow);
  RichView1->AddNLWTag("One more example - a custom displaying of page break",0,0,0);
  RichView1->PageBreaksBeforeItems[RichView1->ItemCount-1] = true;
  RichView1->Format();

  RichView2->AddNLWTag("Cool Effect - ",2,2,0);
  RichView2->SetAddParagraphMode(False);
  RichView2->AddNLWTag("Transparent paragraph background.",2,2,0);
  RichView2->AddNLWTag("example of custom painting of paragraph background",0,2,0);
  RichView2->SetAddParagraphMode(True);
  for (int i=0; i<=20; i++)
	RichView2->AddNLWTag("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)
{
  UnicodeString Text;
  TRVRawByteString s2;

  if (DrawState.Contains(rvtsSelected))
	return; // default drawing for selected text

  if (StyleNo==0 || StyleNo==3 || StyleNo==4)
  {
	if (Sender->TextStyles->Items[StyleNo]->Unicode)
	  s2 = s;
	else
	  s2 = RVU_AnsiToUnicode(
		RVU_Charset2CodePage(Sender->TextStyles->Items[StyleNo]->Charset), s);
	Text = RVU_RawUnicodeToWideString(s);
  }
  else
	Text = "";

  Left += SpaceBefore;
  switch (StyleNo)
  {
    case 0:
    {
      // sunken effect
      Canvas->Font->Color = clBtnHighlight;
	  Canvas->TextOut(Left+1,Top+1, Text);
	  Canvas->Font->Color = clBtnShadow;
	  Canvas->TextOut(Left,Top, Text);
	  DoDefault = false;
	  break;
	}
	case 3:
	{
	  // raised effect
	  Canvas->Font->Color = clBtnHighlight;
	  Canvas->TextOut(Left-1,Top-1, Text);
	  Canvas->Font->Color = clBtnShadow;
	  Canvas->TextOut(Left+1,Top+1, Text);
	  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, Text);
		Canvas->TextOut(Left-1,Top-1, Text);
		Canvas->Font->Color = Sender->TextStyles->Items[StyleNo]->Color;
		Canvas->TextOut(Left,Top, Text);
		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, L"!", 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(L"!",L"!", MB_OK | MB_ICONINFORMATION);
}
//---------------------------------------------------------------------------

