unit EpIIStyles;

interface

{$I EpIIVer.inc}

uses
  Classes, Windows, SysUtils, Forms, Controls, Graphics, KsBitmap, KsForms,
  EpIIBitmaps;

type

{ TEpBackground class}

  { The following table lists the possible values:
    <TABLE>
    Value                       Meaning
    -----                       -------
    ebsColor                    Specifies the solid fill mode.
    ebsBitmap                   Specifies the bitmap tile mode.
    ebsGradient                 Specifies the gradient fill mode.
    ebsPlasma                   Specifies the plasma fill mode.
    </TABLE>
  }
  TEpBackgroundStyle = (ebsColor, ebsBitmap, ebsGradient, ebsPlasma);

  { Specifies the gradient kind. The following table lists the possible values:
    <TABLE>
    Value                       Meaning
    -----                       -------
    egsLinear                   Specifies the linear gradint filling.
    egsRadial                   Specifies the radial gradint filling.
    </TABLE>
  }
  TEpGradientStyle = (egsLinear, egsRadial);

  { Specifies the gradient directions for linear gradient style. The following table lists the possible values:
    <TABLE>
    Value                       Meaning
    -----                       -------
    egdVertical                 Specifies the vertical gradient style
    egdHorizontal               Specifies the horizontal gradient style
    </TABLE>
  }
  TEpGradientDirection = (egdVertical, egdHorizontal);

  { Specifies the bitmap tile mode. The following table lists the possible values:
    <TABLE>
    Value                       Meaning
    -----                       -------
    etsTile                     Tile bitmap's
    etsStretch                  Stretch bitmap's
    </TABLE>
  }
  TEpTileStyle = (etsTile, etsStretch);

  TEpBackground = class(TPersistent)
  private
    FStyle: TEpBackgroundStyle;
    FColor: TColor;
    FBitmapList: TEpBitmapList;
    FBitmapIndex: integer;
    FGradientOrPlasmaColor: TColor;
    FGradientStyle: TEpGradientStyle;
    FGradientDirection: TEpGradientDirection;
    FTileStyle: TEpTileStyle;
    FPlasmaBitmap: TKsBitmap;
    FOnChange: TNotifyEvent;
    FGradientCenterY: integer;
    FGradientCenterX: integer; // Correct Assign
    procedure SetBitmaps(const Value: TEpBitmapList);
    procedure SetBitmapIndex(const Value: integer);
    procedure SetColor(const Value: TColor);
    procedure SetGradientOrPlasmaColor(const Value: TColor);
    procedure SetGradientDirection(const Value: TEpGradientDirection);
    procedure SetGradientStyle(const Value: TEpGradientStyle);
    procedure SetStyle(const Value: TEpBackgroundStyle);
    procedure SetTileStyle(const Value: TEpTileStyle);
    procedure SetGradientCenterX(const Value: integer);
    procedure SetGradientCenterY(const Value: integer);
  protected
    procedure Change; 
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;

    procedure Draw(Buffer: TKsBitmap; R: TRect);
  published
    { Specifies the solid color. }
    property Color: TColor read FColor write SetColor;
    { Link to TEpBitmapList with images.
      See Also:
        TEpBitmapList
    }
    property Bitmaps: TEpBitmapList read FBitmapList write SetBitmaps;
    { Specifies the using bitmap index from Bitmaps list     }
    property BitmapIndex: integer read FBitmapIndex write SetBitmapIndex;
    { Specifies the bitmap tile style
      See Also:
        TEpTileStyle
    }
    property BitmapTileStyle: TEpTileStyle read FTileStyle write SetTileStyle;
    { Specifies the gradient style
      See Also:
        TEpGradientStyle
    }
    property GradientStyle: TEpGradientStyle read FGradientStyle write SetGradientStyle;
    { Specifies the gradient or plasma color. TEpBackgroun use Color and GradientOrPlasmaColor for drawing gradient or plasma filling.
    }
    property GradientOrPlasmaColor: TColor read FGradientOrPlasmaColor write SetGradientOrPlasmaColor;
    { Specifies the linear gradient direction
      See Also:
        TEpGradientDirection
    }
    property GradientDirection: TEpGradientDirection read FGradientDirection write SetGradientDirection;
    { Specifies the radial gradient center x position }
    property GradientCenterX: integer read FGradientCenterX write SetGradientCenterX;
    { Specifies the radial gradient center y position }
    property GradientCenterY: integer read FGradientCenterY write SetGradientCenterY;
    { Specifies the filling style
      See Also:
        TEpBackgroundStyle
    }
    property Style: TEpBackgroundStyle read FStyle write SetStyle;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

{ TEpBorder class }

  TEpBorderStyle = (ebsSingleBorder, ebsBitmapBorder);

  TEpBorder = class(TPersistent)
  private
    FStyle: TEpBorderStyle;
    FColor: TColor;
    FWidth: integer;
    FBitmapMarginY: integer;
    FBitmapMarginX: integer;
    FBitmapIndex: integer;
    FBitmapList: TEpBitmapList;
    FTileStyle: TEpTileStyle;
    FOnChange: TNotifyEvent;
    procedure SetBitmaps(const Value: TEpBitmapList);
    procedure SetBitmapIndex(const Value: integer);
    procedure SetBitmapMarginX(const Value: integer);
    procedure SetBitmapMarginY(const Value: integer);
    procedure SetColor(const Value: TColor);
    procedure SetStyle(const Value: TEpBorderStyle);
    procedure SetTileStyle(const Value: TEpTileStyle);
    procedure SetWidth(const Value: integer);
  protected
    procedure Change; 
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;

    procedure Draw(Buffer: TKsBitmap; R: TRect; Rgn: HRgn);

    function GetWidth: integer;
    function GetHeight: integer;
  published
    { Link to TEpBitmapList with images.
      See Also:
        TEpBitmapList
    }
    property Bitmaps: TEpBitmapList read FBitmapList write SetBitmaps;
    { Specifies the using bitmap index from Bitmaps list }
    property BitmapIndex: integer read FBitmapIndex write SetBitmapIndex;
    { Specifies the bitmap left and right margin }
    property BitmapMarginX: integer read FBitmapMarginX write SetBitmapMarginX;
    { Specifies the bitmap top and bottom margin }
    property BitmapMarginY: integer read FBitmapMarginY write SetBitmapMarginY;
    { Specifies the bitmap tile style
      See Also:
        TEpTileStyle
    }
    property BitmapTileStyle: TEpTileStyle read FTileStyle write SetTileStyle;
    { Specifies the border color }
    property Color: TColor read FColor write SetColor;
    { Specifies the border style
      See Also:
        TEpBorderStyle
    }
    property Style: TEpBorderStyle read FStyle write SetStyle;
    { Specifies the border width and height for solid style }
    property Width: integer read FWidth write SetWidth;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

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

uses KsUtils;

{ TEpBackground }

constructor TEpBackground.Create;
begin
  inherited Create;
  FColor := clWindow;
  FGradientOrPlasmaColor := clHighlight;
  FBitmapIndex := -1;
  FGradientCenterX := 50;
  FGradientCenterY := 50;
end;

destructor TEpBackground.Destroy;
begin
  if FPlasmaBitmap <> nil then
    FPlasmaBitmap.Free;
    
  inherited Destroy;
end;

procedure TEpBackground.Assign(Source: TPersistent);
begin
  if Source is TEpBackground then
  begin
    FColor := (Source as TEpBackground).FColor;
    FBitmapList := (Source as TEpBackground).FBitmapList;
    FBitmapIndex := (Source as TEpBackground).FBitmapIndex;
    FGradientOrPlasmaColor := (Source as TEpBackground).GradientOrPlasmaColor;
    FGradientStyle := (Source as TEpBackground).GradientStyle;
    FGradientDirection := (Source as TEpBackground).FGradientDirection;
    FTileStyle := (Source as TEpBackground).FTileStyle;
    FGradientCenterX := (Source as TEpBackground).FGradientCenterX;
    FGradientCenterY := (Source as TEpBackground).FGradientCenterY;
    Style := (Source as TEpBackground).FStyle;
  end
  else
    inherited;
end;

procedure TEpBackground.Change;
begin
  if Assigned(FOnChange) then FOnChange(Self);
end;

procedure TEpBackground.Draw(Buffer: TKsBitmap; R: TRect);
var
  B: TKsBitmap;
begin
  case FStyle of
    ebsColor: begin
      Buffer.FillRect(R, KColor(Color));
    end;
    ebsBitmap: if (Bitmaps <> nil) and (FBitmapIndex >= 0) and (FBitmapIndex < Bitmaps.Count) then
    begin
      B := Bitmaps.Bitmaps[FBitmapIndex];
      case BitmapTileStyle of
        etsTile: B.DrawTile(Buffer, R, Rect(0, 0, B.Width, B.Height));
        etsStretch: B.DrawStretch(Buffer, R, Rect(0, 0, B.Width, B.Height));
      end;
    end;
    ebsGradient: begin
      case FGradientStyle of
        egsLinear: Buffer.FillGradientRect(R, KColor(Color), KColor(GradientOrPlasmaColor),
          GradientDirection = egdVertical);
        egsRadial: Buffer.FillRadialGradientRect(R, KColor(Color),
          KColor(GradientOrPlasmaColor), Point(FGradientCenterX, FGradientCenterY));
      end;
    end;
    ebsPlasma: if FPlasmaBitmap <> nil then begin
      FPlasmaBitmap.DrawTile(Buffer, R, Rect(0, 0, FPlasmaBitmap.Width, FPlasmaBitmap.Height));
    end;
  end;
end;

procedure TEpBackground.SetBitmaps(const Value: TEpBitmapList);
begin
  FBitmapList := Value;
  Change;
end;

procedure TEpBackground.SetBitmapIndex(const Value: integer);
begin
  FBitmapIndex := Value;
  if (Bitmaps <> nil) and (FBitmapIndex > Bitmaps.Count) then
    FBitmapIndex := Bitmaps.Count;
  Change;
end;

procedure TEpBackground.SetColor(const Value: TColor);
begin
  FColor := Value;
  Style := FStyle;
  Change;
end;

procedure TEpBackground.SetGradientOrPlasmaColor(const Value: TColor);
begin
  FGradientOrPlasmaColor := Value;
  Style := FStyle;
  Change;
end;

procedure TEpBackground.SetGradientDirection(
  const Value: TEpGradientDirection);
begin
  FGradientDirection := Value;
  Change;
end;

procedure TEpBackground.SetGradientStyle(const Value: TEpGradientStyle);
begin
  FGradientStyle := Value;
  Change;
end;

procedure TEpBackground.SetStyle(const Value: TEpBackgroundStyle);
begin
  FStyle := Value;

  if FStyle = ebsPlasma then
  begin
    { Create FPlasmaBitmap }
    if FPlasmaBitmap <> nil then
      FPlasmaBitmap.Free;

    FPlasmaBitmap := GetPlasma(KColor(FColor), KColor(FGradientOrPlasmaColor));
  end
  else
    if FPlasmaBitmap <> nil then
    begin
      { Free if don't need }
      FPlasmaBitmap.Free;
      FPlasmaBitmap := nil;
    end;

  Change;
end;

procedure TEpBackground.SetTileStyle(const Value: TEpTileStyle);
begin
  FTileStyle := Value;
  Change;
end;

procedure TEpBackground.SetGradientCenterX(const Value: integer);
begin
  FGradientCenterX := Value;
  if FGradientCenterX < 10 then FGradientCenterX := 10;
  if FGradientCenterX > 90 then FGradientCenterX := 90;
  Change;
end;

procedure TEpBackground.SetGradientCenterY(const Value: integer);
begin
  FGradientCenterY := Value;
  if FGradientCenterY < 10 then FGradientCenterY := 10;
  if FGradientCenterY > 90 then FGradientCenterY := 90;
  Change;
end;

{ TEpBorder ====================================================================}

constructor TEpBorder.Create;
begin
  inherited Create;
  FWidth := 1;
  FBitmapIndex := -1;
  FBitmapMarginX := 3;
  FBitmapMarginY := 3;
end;

destructor TEpBorder.Destroy;
begin
  inherited Destroy;
end;

procedure TEpBorder.Assign(Source: TPersistent);
begin
  if Source is TEpBorder then
  begin
    FBitmapList := (Source as TEpBorder).FBitmapList;
    FBitmapIndex := (Source as TEpBorder).FBitmapIndex;
    FBitmapMarginX := (Source as TEpBorder).FBitmapMarginX;
    FBitmapMarginY := (Source as TEpBorder).FBitmapMarginY;
    FTileStyle := (Source as TEpBorder).FTileStyle;
    FColor := (Source as TEpBorder).FColor;
    FStyle := (Source as TEpBorder).FStyle;
    FWidth := (Source as TEpBorder).FWidth;
  end
  else
    inherited ;
end;

procedure TEpBorder.Change;
begin
  if Assigned(FOnChange) then FOnChange(Self);
end;

procedure TEpBorder.Draw(Buffer: TKsBitmap; R: TRect; Rgn: HRgn);
var
  SrcR, DstR: TRect;
  Brush: TBrush;
  B: TKsBitmap;
begin
  with Buffer do
  begin
    case Style of
      ebsSingleBorder: begin
        { Single Border }
        Brush := TBrush.Create;
        try
          Brush.Color := Self.Color;
          if Rgn = 0 then
          begin
            Rgn := CreateRectRgn(R.Left, R.Top, R.Right, R.Bottom);
            FrameRgn(DC, Rgn, Brush.Handle, Self.Width, Self.Width);
            DeleteObject(Rgn);
          end
          else
            FrameRgn(DC, Rgn, Brush.Handle, Self.Width, Self.Width);
        finally
          Brush.Free;
        end;
      end;
      ebsBitmapBorder: if (Bitmaps <> nil) and (BitmapIndex >= 0) and (BitmapIndex < Bitmaps.Count) then
      begin
        { Border from Bitmap }
        B := Bitmaps.Bitmaps[BitmapIndex];
        { Draw Border }
        if BitmapTileStyle = etsTile then
        begin
          { Top line }
          SrcR := Rect(BitmapMarginX, 0, B.Width-BitmapMarginX, BitmapMarginY);
          DstR := Rect(R.Left + BitmapMarginX, R.Top, R.Right-BitmapMarginX, R.Top+BitmapMarginY);
          B.DrawTile(Buffer, DstR, SrcR);
          { Bottom line }
          SrcR := Rect(BitmapMarginX, B.Height-BitmapMarginY, B.Width-BitmapMarginX, B.Height);
          DstR := Rect(R.Left + BitmapMarginX, R.Bottom-BitmapMarginY, R.Right-BitmapMarginX, R.Bottom);
          B.DrawTile(Buffer, DstR, SrcR);
          { Left line }
          SrcR := Rect(0, BitmapMarginY, BitmapMarginX, B.Height-BitmapMarginY);
          DstR := Rect(R.Left, R.Top + BitmapMarginY, R.Left + BitmapMarginX, R.Bottom-BitmapMarginY);
          B.DrawTile(Buffer, DstR, SrcR);
          { Bottom line }
          SrcR := Rect(B.Width-BitmapMarginX, BitmapMarginY, B.Width, B.Height-BitmapMarginY);
          DstR := Rect(R.Right-BitmapMarginX, R.Top + BitmapMarginY, R.Right, R.Bottom-BitmapMarginY);
          B.DrawTile(Buffer, DstR, SrcR);
        end
        else
        begin
          { Top line }
          SrcR := Rect(BitmapMarginX, 0, B.Width-BitmapMarginX, BitmapMarginY);
          DstR := Rect(R.Left + BitmapMarginX, R.Top, R.Right-BitmapMarginX, R.Top+BitmapMarginY);
          B.DrawStretch(Buffer, DstR, SrcR);
          { Bottom line }
          SrcR := Rect(BitmapMarginX, B.Height-BitmapMarginY, B.Width-BitmapMarginX, B.Height);
          DstR := Rect(R.Left + BitmapMarginX, R.Bottom-BitmapMarginY, R.Right-BitmapMarginX, R.Bottom);
          B.DrawStretch(Buffer, DstR, SrcR);
          { Left line }
          SrcR := Rect(0, BitmapMarginY, BitmapMarginX, B.Height-BitmapMarginY);
          DstR := Rect(R.Left, R.Top + BitmapMarginY, R.Left + BitmapMarginX, R.Bottom-BitmapMarginY);
          B.DrawStretch(Buffer, DstR, SrcR);
          { Bottom line }
          SrcR := Rect(B.Width-BitmapMarginX, BitmapMarginY, B.Width, B.Height-BitmapMarginY);
          DstR := Rect(R.Right-BitmapMarginX, R.Top + BitmapMarginY, R.Right, R.Bottom-BitmapMarginY);
          B.DrawStretch(Buffer, DstR, SrcR);
        end;
        { Draw Angles }
        B.Draw(Buffer, R.Left, R.Top, Rect(0, 0, BitmapMarginX, BitmapMarginY));
        B.Draw(Buffer, R.Right-BitmapMarginX, R.Top,
          Rect(B.Width-BitmapMarginX, 0, B.Width, BitmapMarginY));
        B.Draw(Buffer, R.Left, R.Bottom-BitmapMarginY,
          Rect(0, B.Height-BitmapMarginY, BitmapMarginX, B.Height));
        B.Draw(Buffer, R.Right-BitmapMarginX, R.Bottom-BitmapMarginY,
          Rect(B.Width-BitmapMarginX, B.Height-BitmapMarginY, B.Width, B.Height));
      end;
    end;
  end;
end;

procedure TEpBorder.SetBitmaps(const Value: TEpBitmapList);
begin
  FBitmapList := Value;
end;

function TEpBorder.GetHeight: integer;
begin
  case FStyle of
    ebsSingleBorder: Result := FWidth;
    ebsBitmapBorder: Result := FBitmapMarginY;
  else
    Result := 1;
  end;
end;

function TEpBorder.GetWidth: integer;
begin
  case FStyle of
    ebsSingleBorder: Result := FWidth;
    ebsBitmapBorder: Result := FBitmapMarginX;
  else
    Result := 1;
  end;
end;

procedure TEpBorder.SetBitmapIndex(const Value: integer);
begin
  FBitmapIndex := Value;
  if (Bitmaps <> nil) and (FBitmapIndex > Bitmaps.Count) then
    FBitmapIndex := Bitmaps.Count;
  Change;
end;

procedure TEpBorder.SetBitmapMarginX(const Value: integer);
begin
  FBitmapMarginX := Value;
  Change;
end;

procedure TEpBorder.SetBitmapMarginY(const Value: integer);
begin
  FBitmapMarginY := Value;
  Change;
end;

procedure TEpBorder.SetColor(const Value: TColor);
begin
  FColor := Value;
  Change;
end;

procedure TEpBorder.SetStyle(const Value: TEpBorderStyle);
begin
  FStyle := Value;
  Change;
end;

procedure TEpBorder.SetTileStyle(const Value: TEpTileStyle);
begin
  FTileStyle := Value;
  Change;
end;

procedure TEpBorder.SetWidth(const Value: integer);
begin
  FWidth := Value;
  Change;
end;

end.

