{==============================================================================

  Copyright (C) 2000-2001 by Evgeny Kryukov
  All rights reserved

  All contents of this file and all other files included in this archive
  are Copyright (C) 2001 Evgeny Kryukov. Use and/or distribution of
  them requires acceptance of the License Agreement.

  See License.txt for licence information

===============================================================================}

unit EpIIButtons;

{$I EpIIVer.inc}
{$T-,W-,X+,P+}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Buttons,
  KsUtils, KsBitmap, KsControls, KsButtons, EpIIStyles, EpIIVersion;

type

{ TEpButton class }

  TEpButton = class(TKsCustomButton)
  private
    FBackground: TEpBackground;
    FBorder: TepBorder;
    FShowBevel: boolean;
    FBevelWidth: integer;
    FHotTextColor: TColor;
    procedure DoBackgroundChange(Sender: TObject);
    procedure DoBorderChange(Sender: TObject);

    function GetVersion: TEpVersion;
    procedure SetVersion(const Value: TEpVersion);
    procedure SetBackground(const Value: TEpBackground);
    procedure SetBorder(const Value: TepBorder);
    procedure SetShowBevel(const Value: boolean);
    procedure SetBevelWidth(const Value: integer);
    procedure SetHotTextColor(const Value: TColor);
  protected
    procedure PaintFace; override;
    procedure PaintText; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Loaded; override;
  published
    property Align;
    { It's possible to draw the background for control. Based on TEpBackground class.
      See Also:
        TEpBackground
    }
    property Background: TEpBackground read FBackground write SetBackground;
    property BevelWidth: integer read FBevelWidth write SetBevelWidth default 3;
    property Blend;
    property BlendValue;
    { It's possible to draw the border for control. Based on TEpBorder class.
      See Also:
        TEpBorder
    }
    property Border: TepBorder read FBorder write SetBorder;
    property Font;
    { Rollover text color. }
    property HotTextColor: TColor read FHotTextColor write SetHotTextColor;
    { It's possible to draw the bevel for the button. }
    property ShowBevel: boolean read FShowBevel write SetShowBevel;
    property Transparent;
    property Version: TEpVersion read GetVersion write SetVersion
      stored false;
    property OnClick;
  end;

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

{ TEpButton }

constructor TEpButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FShowBevel := true;
  FBevelWidth := 2;

  FBackground := TEpBackground.Create;
  FBackground.OnChange := DoBackgroundChange;
  FBorder := TEpBorder.Create;
  FBorder.OnChange := DoBorderChange;
end;

destructor TEpButton.Destroy;
begin
  FBackground.Free;
  FBorder.Free;
  inherited Destroy;
end;

procedure TEpButton.Loaded;
begin
  inherited;
  Invalidate;
end;

procedure TEpButton.PaintFace;
var
  R: TRect;
  bw, i: integer;
  C: TKColor;
begin
  if FBorder = nil then Exit;
  if FBackground = nil then Exit;

  R := Rect(0, 0, FWidth, FHeight);

  if State <> kbsPressed then
  begin
    InflateRect(R, 1, 1);
    FBackground.Draw(Buffer, R);
    InflateRect(R, -1, -1);
  end
  else
    FBackground.Draw(Buffer, R);
    
  FBorder.Draw(Buffer, R, 0);

  { Add Bevel }
  if FShowBevel then
  begin
    for bw := FBorder.Width to FBorder.Width + FBevelWidth - 1 do
    begin
      { Top Bevel }
      for i := bw to FWidth-Bw do
      begin
        C := Buffer.Pixels[i, bw];

        if State = kbsPressed then
          C := SunkenColor(C, 20*(FBorder.Width + FBevelWidth-bw))
        else
          C := RaisedColor(C, 20*(FBorder.Width + FBevelWidth-bw));

        Buffer.Pixels[i, bw] := C;
      end;

      { Bottom Bevel }
      for i := bw to FWidth-Bw do
      begin
        C := Buffer.Pixels[i, FHeight-bw-1];

        if State = kbsPressed then
          C := RaisedColor(C, 20*(FBorder.Width + FBevelWidth-bw))
        else
          C := SunkenColor(C, 20*(FBorder.Width + FBevelWidth-bw));

        Buffer.Pixels[i, FHeight-bw-1] := C;
      end;

      { Left Bevel }
      for i := bw + 1 to FHeight-Bw - 1 do
      begin
        C := Buffer.Pixels[bw, i];

        if State = kbsPressed then
          C := SunkenColor(C, 20*(FBorder.Width + FBevelWidth-bw))
        else
          C := RaisedColor(C, 20*(FBorder.Width + FBevelWidth-bw));

        Buffer.Pixels[bw, i] := C;
      end;

      { Right Bevel }
      for i := bw + 1 to FHeight - Bw - 1 do
      begin
        C := Buffer.Pixels[FWidth-bw-1, i];

        if State = kbsPressed then
          C := RaisedColor(C, 20*(FBorder.Width + FBevelWidth-bw))
        else
          C := SunkenColor(C, 20*(FBorder.Width + FBevelWidth-bw));

        Buffer.Pixels[FWidth-bw-1, i] := C;
      end;

    end;
  end;
end;

procedure TEpButton.PaintText;
var
  R: TRect;
begin
  with Buffer do
  begin
    Font.Assign(Self.Font);

    if MouseInControl then
      Font.Color := FHotTextColor;

    R := Rect(0, 0, TextWidth(Caption), TextHeight(Caption));
    OffsetRect(R, (RectWidth(GetCaptionRect) - R.Right) div 2, (RectHeight(GetCaptionRect) - R.Bottom) div 2);
    OffsetRect(R, GetCaptionRect.Left, GetCaptionRect.Top);

    if not Enabled then
    begin
      Font.Color := clBtnHighlight;
      OffsetRect(R, 1, 1);
      DrawText(Caption, R, DT_CENTER);
      OffsetRect(R, -1, -1);
      Font.Color := clBtnShadow;
    end;

    { Draw Text }
    DrawText(Caption, R, DT_CENTER);
  end;
end;

procedure TEpButton.DoBackgroundChange(Sender: TObject);
begin
  Invalidate;
end;

procedure TEpButton.DoBorderChange(Sender: TObject);
begin
  Invalidate;
end;

{ Properties }

function TEpButton.GetVersion: TEpVersion;
begin
  Result := EpVersion;
end;

procedure TEpButton.SetVersion(const Value: TEpVersion);
begin
end;

procedure TEpButton.SetBackground(const Value: TEpBackground);
begin
  FBackground.Assign(Value);
end;

procedure TEpButton.SetBorder(const Value: TepBorder);
begin
  FBorder.Assign(Value);
end;

procedure TEpButton.SetShowBevel(const Value: boolean);
begin
  if FShowBevel <> Value then
  begin
    FShowBevel := Value;
    Invalidate;
  end;
end;

procedure TEpButton.SetBevelWidth(const Value: integer);
begin
  if FBevelWidth <> Value then
  begin
    FBevelWidth := Value;
    Invalidate;
  end;
end;

procedure TEpButton.SetHotTextColor(const Value: TColor);
begin
  if FHotTextColor <> Value then
  begin
    FHotTextColor := Value;
    Invalidate;
  end;
end;

end.
