/*==============================================================================
 RichEditor Demo
  Menu items disabling/enabling is not implemented here.

  The main idea: new styles are created and added to rvs->TextStyles when needed.
  The right place for this - rve->OnStyleConversion.
  rvfoSaveTextStyles, rvfoSaveParaStyles are included in rve->RVFOptions.

  IMPORTANT: If you right click the editor in design time, choose "Settings"
  in the context menu, you'll see that radiogroup is in state
  "Allow adding styles dynamically"
==============================================================================*/
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RichView"
#pragma link "RVEdit"
#pragma link "RVScroll"
#pragma link "RVStyle"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Parameters for ApplyStyleConversion
#define TEXT_BOLD          1
#define TEXT_ITALIC        2
#define TEXT_UNDERLINE     3
#define TEXT_APPLYFONTNAME 4
#define TEXT_APPLYFONT     5
#define TEXT_APPLYFONTSIZE 6
#define TEXT_COLOR         7
#define TEXT_BACKCOLOR     8
// Parameters for ApplyParaStyleConversion
#define PARA_ALIGNMENT     1
#define PARA_INDENTINC     2
#define PARA_INDENTDEC     3
#define PARA_COLOR         4
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  // Filling font names combobox
  cmbFont->Items->Assign(Screen->Fonts);
  New();
}
//---------------------------------------------------------------------------
// data in editor were changed
void __fastcall TForm1::rveChange(TObject *Sender)
{
  StatusBar1->Panels->Items[0]->Text = "Modified";
}
//---------------------------------------------------------------------------
// current text style was changed
void __fastcall TForm1::rveCurTextStyleChanged(TObject *Sender)
{
  IgnoreChanges = true;
  StatusBar1->Panels->Items[1]->Text = "Style : "+IntToStr(rve->CurTextStyleNo);
  // Changing selection in comboboxes with font names and sizes:
  TFontInfo* fi = rvs->TextStyles->Items[rve->CurTextStyleNo];
  cmbFont->ItemIndex = cmbFont->Items->IndexOf(fi->FontName);
  cmbFontSize->Text = IntToStr(fi->Size);

  // Checking font buttons
  btnBold->Down      = fi->Style.Contains(fsBold);
  btnItalic->Down    = fi->Style.Contains(fsItalic);
  btnUnderline->Down = fi->Style.Contains(fsUnderline);
  IgnoreChanges = false;
}
//---------------------------------------------------------------------------
// current paragraph style was changed
void __fastcall TForm1::rveCurParaStyleChanged(TObject *Sender)
{
  SetAlignmentToUI(rvs->ParaStyles->Items[rve->CurParaStyleNo]->Alignment);
}
//--------------------------------------------------------------------------
TRVAlignment TForm1::GetAlignmentFromUI()
{
  if (btnLeft->Down)
    return rvaLeft;
  else if (btnRight->Down)
    return rvaRight;
  else if (btnCenter->Down)
    return rvaCenter;
  else
    return rvaJustify;
}
//--------------------------------------------------------------------------
void TForm1::SetAlignmentToUI(TRVAlignment Alignment)
{
  switch (Alignment)
  {
    case rvaLeft:
      btnLeft->Down = true;
      break;
    case rvaCenter:
      btnCenter->Down = true;
      break;
    case rvaRight:
      btnRight->Down = true;
      break;
    case rvaJustify:
      btnJustify->Down = true;
      break;
  }
}
//---------------------------------------------------------------------------
// applying font name
void __fastcall TForm1::cmbFontClick(TObject *Sender)
{
  if (cmbFont->ItemIndex!=-1 && !IgnoreChanges)
  {
    FontName = cmbFont->Items->Strings[cmbFont->ItemIndex];
    rve->ApplyStyleConversion(TEXT_APPLYFONTNAME);
  }
  if (Visible)
    rve->SetFocus();
}
//---------------------------------------------------------------------------
// applying font size
void __fastcall TForm1::cmbFontSizeClick(TObject *Sender)
{
  if (cmbFontSize->Text!="" && !IgnoreChanges)
  {
    FontSize = StrToIntDef(cmbFontSize->Text, 10);
    rve->ApplyStyleConversion(TEXT_APPLYFONTSIZE);
  }
  if (Visible)
    rve->SetFocus();
}
//---------------------------------------------------------------------------
// bold, italic, underline
void __fastcall TForm1::FontStyleButtonClick(TObject *Sender)
{
  TSpeedButton*Button = (TSpeedButton*)Sender;
  // constants TEXT_BOLD, TEXT_ITALIC and TEXT_UNDERLINE are
  // assigned to the tags of corresponding buttons
  rve->ApplyStyleConversion(Button->Tag);
}
//---------------------------------------------------------------------------
// applying font
void __fastcall TForm1::mitFontClick(TObject *Sender)
{
  fd->Font->Assign(rvs->TextStyles->Items[rve->CurTextStyleNo]);
  if (fd->Execute())
    rve->ApplyStyleConversion(TEXT_APPLYFONT);
}
//---------------------------------------------------------------------------
// applying text color
void __fastcall TForm1::btnFontColorClick(TObject *Sender)
{
  cd->Color = rvs->TextStyles->Items[rve->CurTextStyleNo]->Color;
  if (cd->Execute())
    rve->ApplyStyleConversion(TEXT_COLOR);
}
//---------------------------------------------------------------------------
// applying text background color
void __fastcall TForm1::btnFontBackColorClick(TObject *Sender)
{
  switch (Application->MessageBox("Make the selected text background transparent?\n"
                            "(YES - make transparent; NO - choose color)",
                            "Text Background", MB_YESNOCANCEL | MB_ICONQUESTION))
  {
    case IDYES:
      cd->Color = clNone;
      break;
    case IDNO:
      cd->Color = rvs->TextStyles->Items[rve->CurTextStyleNo]->BackColor;
        if (cd->Color==clNone)
          cd->Color = clWhite;
        if (! cd->Execute())
          return;
      break;
    case IDCANCEL:
      return;
  }
  rve->ApplyStyleConversion(TEXT_BACKCOLOR);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnParaBackColorClick(TObject *Sender)
{
  switch (Application->MessageBox("Make the selected paragraph background transparent?\n"
                            "(YES - make transparent; NO - choose color)",
                            "Text Background", MB_YESNOCANCEL | MB_ICONQUESTION))
  {
    case IDYES:
      cd->Color = clNone;
      break;
    case IDNO:
      cd->Color = rvs->ParaStyles->Items[rve->CurParaStyleNo]->Background->Color;
      if (cd->Color==clNone)
        cd->Color = clWhite;
      if (! cd->Execute())
        return;
      break;
    case IDCANCEL:
      return;
  }
  rve->ApplyParaStyleConversion(PARA_COLOR);
}
//---------------------------------------------------------------------------
// applying paragraph alignment
void __fastcall TForm1::btnApplyPara(TObject *Sender)
{
   rve->ApplyParaStyleConversion(PARA_ALIGNMENT);
}
//---------------------------------------------------------------------------
// changing paragraph left indent
void __fastcall TForm1::btnIdentDecClick(TObject *Sender)
{
  rve->ApplyParaStyleConversion(PARA_INDENTDEC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnIdentIncClick(TObject *Sender)
{
  rve->ApplyParaStyleConversion(PARA_INDENTINC);
}
//---------------------------------------------------------------------------
// The heart of this demo: rve->OnStyleConversion
void __fastcall TForm1::rveStyleConversion(TCustomRichViewEdit *Sender,
      int StyleNo, int UserData, bool AppliedToText, int &NewStyleNo)
{
  TFontInfo* FontInfo = new TFontInfo(NULL);
  FontInfo->Assign(rvs->TextStyles->Items[StyleNo]);
  switch (UserData)
  {
    case TEXT_BOLD:
    {
      if (btnBold->Down)
        FontInfo->Style << fsBold;
      else
        FontInfo->Style >> fsBold;
      break;
    }
    case TEXT_ITALIC:
    {
      if (btnItalic->Down)
        FontInfo->Style << fsItalic;
      else
        FontInfo->Style >> fsItalic;
      break;
    }
    case TEXT_UNDERLINE:
    {
      if (btnUnderline->Down)
        FontInfo->Style << fsUnderline;
      else
        FontInfo->Style >> fsUnderline;
      break;
    }
    case TEXT_APPLYFONTNAME:
      FontInfo->FontName = FontName;
      break;
    case TEXT_APPLYFONTSIZE:
      FontInfo->Size     = FontSize;
      break;
    case TEXT_APPLYFONT:
      FontInfo->Assign(fd->Font);
      break;
    case TEXT_COLOR:
      FontInfo->Color = cd->Color;
      break;
    case TEXT_BACKCOLOR:
      FontInfo->BackColor = cd->Color;
      break;
      // add your code here....
  }
  NewStyleNo = rvs->TextStyles->FindSuchStyle(StyleNo,FontInfo,RVAllFontInfoProperties);
  if (NewStyleNo<0)
  {
    rvs->TextStyles->Add();
    NewStyleNo = rvs->TextStyles->Count-1;
    rvs->TextStyles->Items[NewStyleNo]->Assign(FontInfo);
    rvs->TextStyles->Items[NewStyleNo]->Standard = false;
  }
  delete FontInfo;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::rveParaStyleConversion(TCustomRichViewEdit *Sender,
	int StyleNo, int UserData, bool AppliedToText, int &NewStyleNo)
{
  TParaInfo* ParaInfo = new TParaInfo(NULL);
  ParaInfo->Assign(rvs->ParaStyles->Items[StyleNo]);
  switch (UserData)
  {
    case PARA_ALIGNMENT:
      ParaInfo->Alignment = GetAlignmentFromUI();
      break;
    case PARA_INDENTINC:
      ParaInfo->LeftIndent = ParaInfo->LeftIndent+20;
      if (ParaInfo->LeftIndent>200)
        ParaInfo->LeftIndent = 200;
      break;
    case PARA_INDENTDEC:
      ParaInfo->LeftIndent = ParaInfo->LeftIndent-20;
      if (ParaInfo->LeftIndent<0)
        ParaInfo->LeftIndent = 0;
      break;
    case PARA_COLOR:
      ParaInfo->Background->Color = cd->Color;
      break;
    // add your code here....
  }
  NewStyleNo = rvs->ParaStyles->FindSuchStyle(StyleNo,ParaInfo,RVAllParaInfoProperties);
  if (NewStyleNo<0)
  {
    rvs->ParaStyles->Add();
    NewStyleNo = rvs->ParaStyles->Count-1;
    rvs->ParaStyles->Items[NewStyleNo]->Assign(ParaInfo);
    rvs->ParaStyles->Items[NewStyleNo]->Standard = false;
  }
  delete ParaInfo;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cmbFontSizeKeyPress(TObject *Sender, char &Key)
{
  if (Key==VK_RETURN)
  {
    Key = 0;
    cmbFontSizeClick(NULL);
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cmbFontSizeExit(TObject *Sender)
{
  cmbFontSizeClick(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitUndoClick(TObject *Sender)
{
  rve->Undo();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitRedoClick(TObject *Sender)
{
  rve->Redo();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitCutClick(TObject *Sender)
{
  rve->CutDef();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitCopyClick(TObject *Sender)
{
  rve->CopyDef();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitPasteClick(TObject *Sender)
{
  rve->Paste();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitDeleteClick(TObject *Sender)
{
  rve->DeleteSelection();
}
//---------------------------------------------------------------------------
bool TForm1::SaveIfNeeded()
{
  if (rve->Modified)
    switch (Application->MessageBox("Save file now?","File was modified",
                                MB_ICONQUESTION | MB_YESNOCANCEL))
    {
      case IDYES:
        return Save();
      case IDNO:
        return true;
      default: //case IDCANCEL:
        return false;
    }
  else
    return true;
}
//---------------------------------------------------------------------------
bool TForm1::Save()
{
  if (FileName=="")
    return SaveAs();
  else
  {
    bool r = rve->SaveRVF(FileName, false);
    if (r)
    {
      rve->Modified = false;
      StatusBar1->Panels->Items[0]->Text = "";
      return true;
    }
    else
    {
      Application->MessageBox("Cannot save file","Error", MB_OK | MB_ICONSTOP);
      return SaveAs();
    }
  }
}
//---------------------------------------------------------------------------
bool TForm1::SaveAs()
{
  if (sd->Execute())
  {
    FileName = sd->FileName;
    bool r = Save();
    if (r)
      Caption = ExtractFileName(FileName) + "- RDemo";
    return r;
  }
  else
    return false;
}
//---------------------------------------------------------------------------
void TForm1::Open()
{
  if (!SaveIfNeeded())
    return;
  rve->Modified = false;
  New();
  if (od->Execute())
  {
    FileName = od->FileName;
    bool r = rve->LoadRVF(FileName);
    rve->Format();
    rveCurTextStyleChanged(NULL);
    rveCurParaStyleChanged(NULL);
    StatusBar1->Panels->Items[0]->Text = "";
    Caption = ExtractFileName(FileName) + "- RDemo";
    if (!r)
      Application->MessageBox("Error while opening or reading file", "Error",
        MB_OK | MB_ICONSTOP);
  }
}
//---------------------------------------------------------------------------
void TForm1::New()
{
  if (!SaveIfNeeded())
    return;
  FileName = "";
  StatusBar1->Panels->Items[0]->Text = "";
  Caption = "Unnamed - RDemo";
  rve->LeftMargin   = 5;
  rve->RightMargin  = 5;
  rve->TopMargin    = 5;
  rve->BottomMargin = 5;
  rve->BackgroundBitmap = NULL;
  rve->BackgroundStyle = bsNoBitmap;
  rve->Clear();
  rve->DeleteUnusedStyles(true, true, true);
  rve->Format();
  rveCurTextStyleChanged(NULL);
  rveCurParaStyleChanged(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitNewClick(TObject *Sender)
{
  New();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitOpenClick(TObject *Sender)
{
  Open();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitSaveClick(TObject *Sender)
{
  Save();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitSaveAsClick(TObject *Sender)
{
  SaveAs();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitExitClick(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
  CanClose = SaveIfNeeded();
}
