//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "CustomDrawTreeView.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TCustomDrawForm *CustomDrawForm;
//---------------------------------------------------------------------------
__fastcall TCustomDrawForm::TCustomDrawForm(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TCustomDrawForm::FormCreate(TObject *Sender)
{
  FBackgroundColor = clWindow;
  FDefaultDraw = True;
  FDefaultDrawItem = True;
  FBrushStyle = bsSolid;
  FButtonSize = 5;
  BkgColorDialog->Color = clWindow;
  SelBkgColorDialog->Color = clHighlight;
  TVFontDialog->Font->Assign(TV->Font);
  SelectedFontDialog->Font->Assign(TV->Font);
  SelectedFontDialog->Font->Color = clHighlightText;
  SelBkgColorDialog->Color = clHighlight;
  TVColorDialog->Color = TV->Color;
}
//---------------------------------------------------------------------------


// BeginExample: TVCustomDraw
// Event: ComCtrls.TCustomTreeView.OnCustomDraw
// Property: ComCtrls.TCustomTreeView.Canvas
// Property: Graphics.TPicture.Bitmap
// Method: Graphics.TCanvas.StretchDraw

// BeginCode
/*
The following example is taken from the custom draw demo. It
shows how the OnCustomDraw event handler draws the
background for the tree view before the items and lines are
drawn.
*/
void __fastcall TCustomDrawForm::TVCustomDraw(TCustomTreeView *Sender,
	  const TRect &ARect, bool &DefaultDraw)
{
/*
This event should be used to draw any background colors or 
images.  ARect represents the entire client area of the TreeView.
Use the TreeView's canvas to do the drawing.
Note that drawing a background bitmap is not really 
supported by CustomDraw, so scrolling can get messy. Best to
subclass the TreeView and handle scrolling messages.
*/
  if (None1 != NULL)
  {
	if (None1->Checked) //no picture
	{
	  TV->Canvas->Brush->Color = BkgColorDialog->Color;
	  TV->Canvas->Brush->Style = FBrushStyle;
	  TV->Canvas->FillRect(ARect);
	}
	else if (Tile1->Checked) //tile bitmap
	{
	  TV->Canvas->Brush->Bitmap = Image1->Picture->Bitmap;
	  TV->Canvas->FillRect(ARect);
	}
	else //Stretch across the canvas.
	  TV->Canvas->StretchDraw(ARect, Image1->Picture->Bitmap);
  };
  DefaultDraw = FDefaultDraw;
  // Setting DefaultDraw to false here prevents all calls to
  // OnCustomDrawItem.
}
// EndCode
// EndExample: TVCustomDraw

void __fastcall TCustomDrawForm::DrawButton(TRect *ARect, TTreeNode *Node)
{
  int cx = ARect->Left + TV->Indent/2;
  int cy = ARect->Top + (ARect->Bottom - ARect->Top)/2;
  TV->Canvas->Pen->Color = ButtonColorDialog->Color;
  //draw horizontal line.
  if (Node->HasChildren)
  {
	TV->Canvas->PenPos = Point(cx + FButtonSize, cy);
	TV->Canvas->LineTo(ARect->Left + TV->Indent + FButtonSize, cy);
  }
  else
  {
	TV->Canvas->PenPos = Point(cx, cy);
	TV->Canvas->LineTo(ARect->Left + TV->Indent + FButtonSize, cy);
  };

  //draw half vertical line, top portion.
  TV->Canvas->PenPos = Point(cx, cy);
  TV->Canvas->LineTo(cx, ARect->Top-1);

  if (((Node->GetNextVisible() != NULL) && (Node->GetNextVisible()->Level == Node->Level))
	|| (Node->getNextSibling() != NULL))
  //draw bottom portion of half vertical line.
  {
	TV->Canvas->PenPos = Point(cx, cy);
	TV->Canvas->LineTo(cx, ARect->Bottom+1);
  };

  if (Node->HasChildren)
  {
	//Let's try a circular button instead
	TV->Canvas->Ellipse(
	  cx - FButtonSize, cy - FButtonSize,
	  cx + FButtonSize, cy + FButtonSize);

	//draw the horizontal indicator.
	TV->Canvas->PenPos = Point(cx-FButtonSize+2, cy);
	TV->Canvas->LineTo(cx+FButtonSize-2, cy);
	//draw the vertical indicator if the node is collapsed
	if (!Node->Expanded)
	{
	  TV->Canvas->PenPos = Point(cx, cy-FButtonSize+2);
	  TV->Canvas->LineTo(cx, cy+FButtonSize-2);
	};
  };
  //now connect vertical lines of higher level nodes.
  Node = Node->Parent;
  while (Node != NULL)
  {
	cx = cx - TV->Indent;
	if (Node->getNextSibling() != NULL)
	{
	  TV->Canvas->PenPos = Point(cx, ARect->Top);
	  TV->Canvas->LineTo(cx, ARect->Bottom);
	};
	Node = Node->Parent;
  };
}

void __fastcall TCustomDrawForm::DrawImage(TRect *NodeRect, int ImageIndex)
{
  int cy = NodeRect->Top + (NodeRect->Bottom - NodeRect->Top)/2;
  //center image in NodeRect.
  ImageList->Draw(TV->Canvas, NodeRect->Left, cy - TV->Images->Height/2,
                 ImageIndex, True);
}

// BeginExample: TVCustomDrawItem

// Event: ComCtrls.TCustomTreeView.OnCustomDrawItem
// Method: ComCtrls.TTreeNode.DisplayRect
// Property: ComCtrls.TTreeNode.Level
// Property: ComCtrls.TCustomTreeView.Indent

// BeginCode
/*
The following example shows how the OnCustomDrawItem event
handler draws items and lines of the tree view after the 
OnCustomDraw event handler has filled in the background.
*/ 
void __fastcall TCustomDrawForm::TVCustomDrawItem(TCustomTreeView *Sender,
	  TTreeNode *Node, TCustomDrawState State, bool &DefaultDraw)
{
  TRect NodeRect;
/*
	If DefaultDraw it is true, any of the node's font
    properties can be changed. Note also that when 
    DefaultDraw = True, Windows draws the buttons and 
    ignores our font background colors, using instead the
	TreeView's Color property.
*/
	if (State.Contains(cdsSelected))
	{
	  TV->Canvas->Font->Assign(SelectedFontDialog->Font);
	  TV->Canvas->Brush->Color = SelBkgColorDialog->Color;
	};

	DefaultDraw = FDefaultDrawItem;
/*
    DefaultDraw = False means you have to handle all the
    item drawing yourself, including the buttons, lines,
    images, and text.
*/
	if (!DefaultDraw)
	{
      //draw the selection rect.
	  if (State.Contains(cdsSelected))
	  {
		NodeRect = Node->DisplayRect(True);
		TV->Canvas->FillRect(NodeRect);
	  };
	  NodeRect = Node->DisplayRect(False);

	  if (None1->Checked)
      //no bitmap, so paint in the background color.
	  {
		TV->Canvas->Brush->Color = BkgColorDialog->Color;
		TV->Canvas->Brush->Style = FBrushStyle;
		TV->Canvas->FillRect(NodeRect);
	  }
	  else
        //don't paint over the background bitmap.
		TV->Canvas->Brush->Style = bsClear;

	  NodeRect.Left = NodeRect.Left + (Node->Level * TV->Indent);
      // NodeRect.Left now represents the left-most portion 
      // of the expand button
	  DrawButton(&NodeRect, Node); // See the CustomDraw demo

	  NodeRect.Left = NodeRect.Left + TV->Indent + FButtonSize;
	  //NodeRect->Left is now the leftmost portion of the image.
	  DrawImage(&NodeRect, Node->ImageIndex); // See the CustomDraw demo

	  NodeRect.Left = NodeRect.Left + ImageList->Width;
      //Now we are finally in a position to draw the text.

	  TV->Canvas->TextOut(NodeRect.Left, NodeRect.Top, Node->Text);
	};
}
// EndCode
// EndExample: TVCustomDrawItem

void __fastcall TCustomDrawForm::TVGetImageIndex(TObject *Sender,
	  TTreeNode *Node)
{
  if (Node->HasChildren)
  {
	if (Node->Expanded)
	  Node->ImageIndex = 3;
	else
	  Node->ImageIndex = 0;
  }
  else
	Node->ImageIndex = 1;
}

void __fastcall TCustomDrawForm::TVGetSelectedIndex(TObject *Sender,
	  TTreeNode *Node)
{
  Node->SelectedIndex = Node->ImageIndex;
}

void __fastcall TCustomDrawForm::Exit1Click(TObject *Sender)
{
  Close();
}

void __fastcall TCustomDrawForm::Selection1Click(TObject *Sender)
{
  if (SelectedFontDialog->Execute())
	TV->Repaint();
}

void __fastcall TCustomDrawForm::Color1Click(TObject *Sender)
{
  if (BkgColorDialog->Execute())
	TV->Repaint();
}

void __fastcall TCustomDrawForm::SelectionBackground1Click(TObject *Sender)
{
  if (SelBkgColorDialog->Execute())
    TV->Repaint();
}

void __fastcall TCustomDrawForm::Solid1Click(TObject *Sender)
{
  TMenuItem *menuItem = dynamic_cast<TMenuItem *>(Sender);
  FBrushStyle = TBrushStyle(Tag);
  menuItem->Checked = True;
  TV->Repaint();
}

void __fastcall TCustomDrawForm::None1Click(TObject *Sender)
{
  TMenuItem *menuItem = dynamic_cast<TMenuItem *>(Sender);
  menuItem->Checked = True;
  TV->Repaint();
}

void __fastcall TCustomDrawForm::OnCustomDraw1Click(TObject *Sender)
{
  FDefaultDraw = !FDefaultDraw;
  OnCustomDraw1->Checked = FDefaultDraw;
  TV->Repaint();
}

void __fastcall TCustomDrawForm::OnCustomDrawItem1Click(TObject *Sender)
{
  FDefaultDrawItem = !FDefaultDrawItem;
  OnCustomDrawItem1->Checked = FDefaultDrawItem;
  TV->Repaint();
}

void __fastcall TCustomDrawForm::TVExpanded(TObject *Sender, TTreeNode *Node)
{
  TV->Repaint();
}

void __fastcall TCustomDrawForm::ButtonColor1Click(TObject *Sender)
{
  if (ButtonColorDialog->Execute()) TV->Repaint();
}

void __fastcall TCustomDrawForm::ButtonSize1Click(TObject *Sender)
{
  String S = IntToStr(FButtonSize);
  if (InputQuery("Change button size", "Enter new size", S))
	FButtonSize = StrToInt(S);
  TV->Repaint();
}

void __fastcall TCustomDrawForm::Drawing1Click(TObject *Sender)
{
  ButtonColor1->Enabled = !OnCustomDrawItem1->Checked;
  ButtonSize1->Enabled = ButtonColor1->Enabled;
}

void __fastcall TCustomDrawForm::Color2Click(TObject *Sender)
{
  if (TVColorDialog->Execute())
  {
	TV->Color = TVColorDialog->Color;
	TV->Repaint();
  };
}

void __fastcall TCustomDrawForm::SetCustomDraw(bool Value)
{
  if (!Value)
  {
	TV->OnCustomDraw = NULL;
	TV->OnCustomDrawItem = NULL;
  }
  else
  {
	TV->OnCustomDraw = TVCustomDraw;
	TV->OnCustomDrawItem = TVCustomDrawItem;
  };
  Drawing1->Enabled = Value;
  TV->Repaint();
}

void __fastcall TCustomDrawForm::CustomDraw1Click(TObject *Sender)
{
  CustomDraw1->Checked = !CustomDraw1->Checked;
  SetCustomDraw(CustomDraw1->Checked);
}
//---------------------------------------------------------------------------

void __fastcall TCustomDrawForm::Font2Click(TObject *Sender)
{
  if (TVFontDialog->Execute())
    TV->Font->Assign(TVFontDialog->Font);
}
//---------------------------------------------------------------------------

