unit EpIIItems;

{$I EpIIVer.inc}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, CommCtrl, Menus, ActnList, ImgList, KsBitmap, KsUtils, KsItems,
  EpIIStyles;

type

{ TEpItem }

  TEpItem = class(TKsCustomItem)
  private
    FBackground: TEpBackground;
    FBorder: TepBorder;
    FPopupBackground: TEpBackground;
    FPopupBorder: TepBorder;
    FFont: TFont;
    procedure SetBackground(const Value: TEpBackground);
    procedure SetBorder(const Value: TepBorder);
    procedure SetPopupBackground(const Value: TEpBackground);
    procedure SetPopupBorder(const Value: TepBorder);
    procedure SetFont(const Value: TFont);
  protected
    class function GetPopupWindowClass: TClass; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure CalcSize(Buffer: TKsBitmap; View: TKsItemView;
      var AWidth, AHeight: integer); override;
    procedure DrawItem(Buffer: TKsBitmap; View: TKsItemView; Rect: TRect;
      Active, Hover: boolean); override;

    property Background: TEpBackground read FBackground write SetBackground;
    property Border: TepBorder read FBorder write SetBorder;
    property Font: TFont read FFont write SetFont;
    property PopupBackground: TEpBackground read FPopupBackground write SetPopupBackground;
    property PopupBorder: TepBorder read FPopupBorder write SetPopupBorder;
  published
    property Checked;
    property Enabled;
    property Caption;
    property ImageIndex;
    property Images;
    property ShortCut;
    property Visible;
    property OnClick;
  end;

implementation {===============================================================}

uses EpIIMenuForm;

{ TEpItem }

constructor TEpItem.Create(AOwner: TComponent);
begin
  inherited;
end;

destructor TEpItem.Destroy;
begin
  inherited;
end;

procedure TEpItem.CalcSize(Buffer: TKsBitmap; View: TKsItemView;
  var AWidth, AHeight: integer);
begin
  if Buffer <> nil then
  begin
    if FFont <> nil then
      Buffer.Font := FFont;

    if View.IsMenuBar then
    begin
      AWidth := Buffer.TextWidth(Caption) + 12;
      AHeight := Buffer.TextHeight(Caption) + 6;
      if AHeight < GetSystemMetrics(SM_CYMENU) then
        AHeight := GetSystemMetrics(SM_CYMENU); 
    end
    else
    begin
      AWidth := GlyphWidth + Buffer.TextWidth(Caption) + ItemStep + Buffer.TextWidth(ShortCutToText(ShortCut)) + SubMenuWidth;
      AHeight := Buffer.TextHeight(Caption) + 6;
      if AHeight < GetSystemMetrics(SM_CYMENU) then
        AHeight := GetSystemMetrics(SM_CYMENU);
      { Separator }
      if Caption = '-' then
        AHeight := SepHeight;
    end;
    if (FBorder <> nil) and (Caption <> '-') then
    begin
      AWidth := AWidth + FBorder.GetWidth;
      AHeight := AHeight + FBorder.GetHeight;
    end
  end
  else
    inherited ;
end;

procedure TEpItem.DrawItem(Buffer: TKsBitmap; View: TKsItemView;
  Rect: TRect; Active, Hover: boolean);
const
  CheckMarkPoints: array[0..11] of TPoint = (
    { Black }
    (X: -2; Y: -2), (X: 0; Y:  0), (X:  4; Y: -4),
    (X:  4; Y: -3), (X: 0; Y:  1), (X: -2; Y: -1),
    (X: -2; Y: -2),
    { White }
    (X: -3; Y: -2), (X: -3; Y: -1), (X: 0; Y: 2),
    (X:  5; Y: -3), (X:  5; Y: -5));
var
  R: TRect;
  Points: array[0..11] of TPoint;
  Canvas: TCanvas;
  i, X, Y: integer;
  B: TBitmap;
  S: string;
begin
  if (Buffer <> nil) and (FBackground <> nil) and (FBorder <> nil) then
  begin
    if FFont <> nil then
      Buffer.Font.Assign(FFont);

    { Draw Sepearator }
    if Caption = '-' then
    begin
      InflateRect(Rect, -2, -((SepHeight div 2)-1));
      Rect.Bottom := Rect.Top + 1;
      if FFont <> nil then
        Buffer.FillRect(Rect, KColor(FFont.Color))
      else
        Buffer.FillRect(Rect, ckBlack);
      Exit;
    end;

    if Active then
    begin
      FBackground.Draw(Buffer, Rect);
      FBorder.Draw(Buffer, Rect, 0);
    end;

    if View.IsMenuBar then
    begin
      { Draw Caption }
      Buffer.DrawText(Caption, Rect, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
    end
    else
    begin
      { Draw Caption }
      R := Rect;
      Inc(R.Left, GlyphWidth);
      { Check Enabled }
      if not Enabled then
        Buffer.Font.Color := clBtnShadow;
      { Draw Caption }
      Buffer.DrawText(Caption, R, DT_VCENTER or DT_SINGLELINE);
      { Draw ShortCut }
      if ShortCut <> 0 then
      begin
        S := ShortCutToText(ShortCut);
        Dec(R.Right, SubMenuWidth);
        { Check Enabled }
        if not Enabled then
          Buffer.Font.Color := clBtnShadow;
        { Draw Shortcut }
        Buffer.DrawText(S, R, DT_RIGHT or DT_VCENTER or DT_SINGLELINE);
      end;
    end;

    if View.IsMenuBar then Exit;

    { Draw Image and Checked }
    if (Checked) or ((ImgList <> nil) and (ImageIndex >= 0)) then
    begin
      { Draw Glyph }
      Canvas := TCanvas.Create;
      try
        Canvas.Handle := Buffer.DC;
        R := Rect;
        R.Right := R.Left + RectHeight(R);
        if (ImgList <> nil) and (ImageIndex >= 0) then
        begin
          { Draw Image }
          ImgList.Draw(Canvas,
            R.Left + ((R.Right - R.Left) - ImgList.Width) div 2,
            R.Top + ((R.Bottom - R.Top) - ImgList.Height) div 2,
            ImageIndex, Enabled);
        end
        else
        begin
          { Draw CheckBox }
          X := (R.Left + R.Right) div 2 - 2;
          Y := (R.Top + R.Bottom) div 2 + 1;
          System.Move(CheckMarkPoints, Points, 12 * SizeOf(TPoint));
          for i := Low(Points) to High(Points) do
          begin
            Inc (Points[I].X, X);
            Inc (Points[I].Y, Y);
          end;
          Canvas.Pen.Color := clBlack;
          Polyline(Canvas.Handle, Points[0], 7);
          Canvas.Pen.Color := clWhite;
          Polyline(Canvas.Handle, Points[7], 5);
        end;
      finally
        Canvas.Handle := 0;
        Canvas.Free;
      end;
    end;

    { Draw Submenu Arrow }
    if Count > 0 then
    begin
      R := Rect;
      R.Left := R.Right - SubMenuWidth;

      B := TBitmap.Create;
      try
        B.Width := RectWidth(R);
        B.Height := RectHeight(R);
        { Draw to B }
        DrawFrameControl(B.Canvas.Handle, Classes.Rect(0, 0, RectWidth(R),
          RectHeight(R)), DFC_MENU, DFCS_MENUARROW);
        { Copy to Buffer }
        for X := 0 to B.Width-1 do
          for Y := 0 to B.Height-1 do
            if B.Canvas.Pixels[X, Y] = clBlack then
              Buffer.Pixels[R.Left + X, R.Top + Y] := ckBlack;
      finally
        B.Free;
      end;
    end;
  end
  else
    inherited;
end;

class function TEpItem.GetPopupWindowClass: TClass;
begin
  Result := TEpPopupWindow;
end;

procedure TEpItem.SetBackground(const Value: TEpBackground);
var
  i: integer;
begin
  FBackground := Value;
  if Count > 0 then
    for i := 0 to Count-1 do
      TEpItem(Items[i]).Background := Value;
end;

procedure TEpItem.SetBorder(const Value: TepBorder);
var
  i: integer;
begin
  FBorder := Value;
  if Count > 0 then
    for i := 0 to Count-1 do
      TEpItem(Items[i]).Border := Value;
end;

procedure TEpItem.SetPopupBackground(const Value: TEpBackground);
var
  i: integer;
begin
  FPopupBackground := Value;
  if Count > 0 then
    for i := 0 to Count-1 do
      TEpItem(Items[i]).PopupBackground := Value;
end;

procedure TEpItem.SetPopupBorder(const Value: TepBorder);
var
  i: integer;
begin
  FPopupBorder := Value;
  if Count > 0 then
    for i := 0 to Count-1 do
      TEpItem(Items[i]).PopupBorder := Value;
end;

procedure TEpItem.SetFont(const Value: TFont);
var
  i: integer;
begin
  FFont := Value;
  if Count > 0 then
    for i := 0 to Count-1 do
      TEpItem(Items[i]).Font := Value;
end;

initialization
  RegisterClasses([TEpItem]);
finalization
end.
