unit SlavaSplitter;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  NaturalNumber = 1..High(Integer);

  TCanResizeEvent = procedure(Sender: TObject; var NewSize: Integer;
    var Accept: Boolean) of object;

  TResizeStyle = (rsNone, rsLine, rsUpdate, rsPattern);
  THandleAlign = (haLeft, haCenter, haRight);
  TClickOrientation = (coLeft, coRight, coUp, coDown);
  TDirection = (diLeft, diRight, diUp, diDown);

  TSlavaSplitter = class(TGraphicControl)
  private
    cMinHandledSize: Integer;
    fBorder1,fBorder2:TColor;
    bOver: Boolean;
    ctop, cbottom,
    cleft, cright: Integer;
    MouseX, MouseY: Integer;
    bmLeft, bmRight, bmUp, bmDown: TBitmap;
    bmLeftOver, bmRightOver, bmUpOver, bmDownOver: TBitmap;
    ctrl1, ctrl2: TControl;
    FOldControlSize: Integer;

    FSplitCursor: TCursor;
    FHandleCursor: TCursor;
    FActiveControl: TWinControl;
    FHandled: Boolean;
    FHandleSize: NaturalNumber;
    FHandleAlign: THandleAlign;
    FBrush: TBrush;
    FControl: TControl;
    FDownPos: TPoint;
    FLineDC: HDC;
    FLineVisible: Boolean;
    FMinSize: NaturalNumber;
    FMaxSize: Integer;
    FNewSize: Integer;
    FOldKeyDown: TKeyEvent;
    FOldSize: Integer;
    FPrevBrush: HBrush;
    FResizeStyle: TResizeStyle;
    FSplit: Integer;

    FOnCanResize: TCanResizeEvent;
    FOnMoved: TNotifyEvent;
    FOnPaint: TNotifyEvent;
    FClickOrientation: TClickOrientation;
    procedure AllocateLineDC;
    procedure CalcSplitSize(X, Y: Integer; var NewSize, Split: Integer);
    procedure DrawLine;
    function FindControl(aDirection: TDirection): TControl;
    procedure FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure ReleaseLineDC;
    procedure SetHandled(Value: Boolean);
    procedure UpdateControlSize;
    procedure UpdateSize(X, Y: Integer);
    procedure SetClickOrientation(const Value: TClickOrientation);
    function GetAlign: TAlign;
    procedure SetAlign(const Value: TAlign);
    procedure SetHandleSize(const Value: NaturalNumber);
    procedure SetHandleAlign(const Value: THandleAlign);
    function GetWidth: Integer;
    procedure SetWidth(const Value: Integer);
    procedure SetHeight(Value: Integer);
    function GetHeight: Integer;
    procedure SetCursor(Value: TCursor);
    procedure SetHandleCursor(Value: TCursor);
    function isValidBitmap(bmp:TBitmap):Boolean;
    procedure SetBmDown(Value: TBitmap);
    procedure SetBmDownOver(Value: TBitmap);
    procedure SetBmLeft(Value: TBitmap);
    procedure SetBmLeftOver(Value: TBitmap);
    procedure SetBmRight(Value: Tbitmap);
    procedure SetBmRightOver(Value :TBitmap);
    procedure SetBmUp(Value: TBitmap);
    procedure SetBmUpOver(Value: TBitmap);
  protected
    function CanResize(var NewSize: Integer): Boolean; reintroduce; virtual;
    function DoCanResize(var NewSize: Integer): Boolean; virtual;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure Paint; override;
    procedure RequestAlign; {$IFDEF VER140}override;{$ENDIF}
    procedure StopSizing; dynamic;

    function MouseInHandle: Boolean;

    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;

    // protected -> no one has to know
    property ClickOrientation: TClickOrientation read FClickOrientation write SetClickOrientation;
    property ResizeStyle: TResizeStyle read FResizeStyle write FResizeStyle default rsPattern;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Loaded; override;
  published
    property Align: TAlign read GetAlign write SetAlign default alLeft;
    property Handled: Boolean read FHandled write SetHandled default True;
    property HandleSize: NaturalNumber read FHandleSize write SetHandleSize default 80;
    property HandleAlign: THandleAlign read FHandleAlign write SetHandleAlign default haCenter;
    property Color;
{$IFDEF VER120}
    property Constraints;
{$ENDIF}
    property MinSize: NaturalNumber read FMinSize write FMinSize default 30;
    property ParentColor;
    property Visible;
    property Width: Integer read GetWidth write SetWidth;

    property OnCanResize: TCanResizeEvent read FOnCanResize write FOnCanResize;
    property OnMoved: TNotifyEvent read FOnMoved write FOnMoved;
    property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
    property Height: Integer read GetHeight write SetHeight;
    property SplitterCursor: TCursor read FSplitCursor write SetCursor;
    property HandleCursor: TCursor read FHandleCursor write SetHandleCursor;

    property BitmapLeft: TBitmap read bmLeft write SetBmLeft;
    property BitmapLeftOver: TBitmap read bmLeftOver write SetbmLeftOver;
    property BitmapRight: TBitmap read bmRight write SetBmRight;
    property BitmapRightOver: Tbitmap read bmRightOver write SetbmRightOver;
    property BitmapUp: Tbitmap read bmUp write SetBmUp;
    property BitmapUpOver: Tbitmap read bmUpOver write SetbmUpOver;
    property BitmapDown: TBitmap read bmDown write SetBmDown;
    property BitmapDownOver: TBitmap read bmDownOver write SetbmDownOver;
    property BorderColor1: TColor read fBorder1 write fBorder1;
    property BorderColor2: TColor read fBorder2 write fBorder2;
  end;

procedure Register;

implementation

type
  TWinControlAccess = class(TWinControl);

procedure Register;
begin
  RegisterComponents('SlavaNap', [TSlavaSplitter]);
end;

constructor TSlavaSplitter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  cMinHandledSize:=5;
  Align := alLeft;
  Width := 7;
  Cursor := crHSplit;
  HandleCursor:= crDefault;
  FHandled := True;
  FHandleSize := 118;
  FHandleAlign := haCenter;
  FMinSize := 30;
  FResizeStyle := rsPattern;
  FOldSize := -1;
  fBorder1:=clWhite;
  fBorder2:=clGray;
  Color:=clSilver;
  bmLeft     := TBitmap.Create;
  bmRight    := TBitmap.Create;
  bmUp       := TBitmap.Create;
  bmDown     := TBitmap.Create;
  bmLeftOver := TBitmap.Create;
  bmRightOver:= TBitmap.Create;
  bmUpOver   := TBitmap.Create;
  bmDownOver := Tbitmap.Create;
end;

destructor TSlavaSplitter.Destroy;
begin
  FBrush.Free;
  bmLeft.Free;
  bmRight.Free;
  bmUp.Free;
  bmDown.Free;
  bmLeftOver.Free;
  bmRightOver.Free;
  bmUpOver.Free;
  bmDownOver.Free;
  inherited Destroy;
end;

procedure TSlavaSplitter.AllocateLineDC;
begin
  FLineDC := GetDCEx(Parent.Handle, 0, DCX_CACHE or DCX_CLIPSIBLINGS
    or DCX_LOCKWINDOWUPDATE);
  {if ResizeStyle = rsPattern then
  begin
    if FBrush = nil then
    begin
      FBrush := TBrush.Create;
     // FBrush.Bitmap := AllocPatternBitmap(clBlack, clWhite);
    end;
    FPrevBrush := SelectObject(FLineDC, FBrush.Handle);
  end;}
end;

procedure TSlavaSplitter.DrawLine;
var
  P: TPoint;
begin
  FLineVisible := not FLineVisible;
  P := Point(Left, Top);
  if Align in [alLeft, alRight] then
    P.X := Left + FSplit else
    P.Y := Top + FSplit;
  with P do PatBlt(FLineDC, X, Y, Width, Height, PATINVERT);
end;

procedure TSlavaSplitter.ReleaseLineDC;
begin
  if FPrevBrush <> 0 then
    SelectObject(FLineDC, FPrevBrush);
  ReleaseDC(Parent.Handle, FLineDC);
  if FBrush <> nil then
  begin
    FBrush.Free;
    FBrush := nil;
  end;
end;

function TSlavaSplitter.FindControl(aDirection: TDirection): TControl;
var
  P: TPoint;
  I: Integer;
  R: TRect;
begin
  // Result := nil;
  P := Point(Left, Top);
  case aDirection of
    diLeft   : Dec(p.x);
    diRight  : Inc(p.x, Width);
    diUp     : Dec(p.y);
    diDown   : Inc(p.y, Height);
  end;
{  case Align of
    alLeft: Dec(P.X);
    alRight: Inc(P.X, Width);
    alTop: Dec(P.Y);
    alBottom: Inc(P.Y, Height);
  else
    Exit;
  end;}
  for I := 0 to Parent.ControlCount - 1 do
  begin
    Result := Parent.Controls[I];
    if Result.Visible and Result.Enabled then
    begin
      R := Result.BoundsRect;
      if (R.Right - R.Left) = 0 then
        if Align in [alTop, alLeft] then
          Dec(R.Left)
        else
          Inc(R.Right);
      if (R.Bottom - R.Top) = 0 then
        if Align in [alTop, alLeft] then
          Dec(R.Top)
        else
          Inc(R.Bottom);
      if PtInRect(R, P) then Exit;
    end;
  end;
  Result := nil;
end;

procedure TSlavaSplitter.RequestAlign;
begin
{$IFDEF VER120}
  inherited RequestAlign;
{$ENDIF}
  if (Cursor <> crVSplit) and (Cursor <> crHSplit) then Exit;
  if Align in [alBottom, alTop] then
    Cursor := crVSplit
  else
    Cursor := crHSplit;
end;

procedure TSlavaSplitter.Paint;
const
  XorColor = $00FFD8CE;
var
  R: TRect;
  bm: TBitmap;
begin
  R := ClientRect;
  with Canvas
  do begin
       Pen.Color := Color;
       Pen.Style := psSolid;
       Brush.Color := Color;
       Pen.Mode := pmCopy;
       FillRect(ClientRect);
       Pen.Color := fBorder1;
       MoveTo(0,0);
       if Align in [alLeft, alRight] then
        LineTo(0,Height)
       else
        Lineto(Width,0);
       Pen.Color := fBorder2;
       MoveTo(Width-1,Height-1);
       if Align in [alLeft, alRight] then
        LineTo(Width-1,-1)
       else
        LineTo(-1,Height-1);
       Pen.Color := clBtnShadow;
     end;

  if Align in [alLeft, alRight]
  then begin
         case HandleAlign of
           haLeft   : begin
                        ctop := 2;
                        cbottom := ctop + HandleSize;
                      end;
           haCenter : begin
                        ctop := (Height div 2) - (HandleSize div 2);
                        cbottom := ctop + HandleSize;
                      end;
           haRight  : begin
                        ctop := Height - HandleSize - 2;
                        cbottom := ctop + HandleSize;
                      end;
         end;
       end
  else begin
         case HandleAlign of
           haLeft   : begin
                        cleft := 2;
                        cright := cleft + HandleSize;
                      end;
           haCenter : begin
                        cleft := (Width div 2) - (HandleSize div 2);
                        cright := cleft + HandleSize;
                      end;
           haRight  : begin
                        cleft := Width - HandleSize - 2;
                        cright := cleft + HandleSize;
                      end;
         end;
       end;

  if Handled
  then case ClickOrientation of
         coUp,
         coDown  : begin
                     with Canvas
                     do begin
                       if Width>HandleSize then
                       begin
//                          Polygon([Point(cright - 1, 0), Point(cleft, 0),
//                                   Point(cleft, Height - 1), Point(cright - 1, Height - 1),
//                                   Point(cright - 1, 0)]);
//                          Pen.Color := clBtnHighlight;
//                          PolyLine([Point(cleft + 1, Height - 2), Point(cleft + 1, 1), Point(cright - 1, 1)]);

//                          if bOver then
//                          begin
//                           i:=Brush.Color;
//                           Brush.Color:=$00FFCFCF;
//                           FillRect(Rect(cleft+2,2,cright-1,height-1));
//                           Brush.Color:=i;
//                          end;

// old code
                          if ClickOrientation = coUp
                          then
                          begin
                            if bOver then
                             bm := bmUpOver
                            else
                             bm := bmUp;
                          end
                          else
                          begin
                            if bOver then
                             bm := bmDownOver
                            else
                             bm := bmDown;
                          end;
                          if isValidBitmap(bm) then
                           Draw(cleft,0, bm);
                        end;
                      end;
                   end;
         coLeft,
         coRight : begin
                     with Canvas
                     do begin
                       if Height>HandleSize then
                       begin
//                          PolyLine([Point(0, cbottom - 1), Point(0, ctop), Point(Width - 1, ctop),
//                                    Point(Width - 1, cbottom - 1), Point(0, cbottom - 1)]);
//                          Pen.Color := clBtnHighlight;
//                          PolyLine([Point(Width - 2, ctop + 1), Point(1, ctop + 1), Point(1, cbottom - 1)]);

//                          if bOver then
//                          begin
//                           i:=Brush.Color;
//                           Brush.Color:=$00FFCFCF;
//                           FillRect(Rect(2,ctop+2,width-1,cbottom-1));
//                           Brush.Color:=i;
//                          end;

// old code
                          if ClickOrientation = coLeft
                          then
                          begin
                            if bOver then
                             bm:=bmLeftOver
                            else
                             bm := bmLeft;
                          end
                          else
                          begin
                            if bOver then
                             bm:=bmRightOver
                            else
                             bm := bmRight;
                          end;
                          if isValidBitmap(bm) then
                           Draw(0, ctop, bm);
                        end;
                      end;
                   end;
       end;

//  if csDesigning in ComponentState then
//    { Draw outline }
//    with Canvas do
//    begin
//      Pen.Style := psDot;
//      Pen.Mode := pmXor;
//      Pen.Color := XorColor;
//      Brush.Style := bsClear;
//      Rectangle(0, 0, ClientWidth, ClientHeight);
//    end;
  if Assigned(FOnPaint) then FOnPaint(Self);
end;

function TSlavaSplitter.DoCanResize(var NewSize: Integer): Boolean;
begin
  Result := CanResize(NewSize);
  if Result and (NewSize <= MinSize) then
    NewSize := MinSize;// MT this was the bug in the TSplitter component in Delphi 4 (NewSize := 0)
end;

function TSlavaSplitter.CanResize(var NewSize: Integer): Boolean;
begin
  Result := True;
  if Assigned(FOnCanResize) then FOnCanResize(Self, NewSize, Result);
end;

procedure TSlavaSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
var
  I: Integer;
begin
  inherited MouseDown(Button, Shift, X, Y);
  if Button = mbLeft then
  begin
    case Align of
      alLeft   : FControl := ctrl1;
      alRight  : FControl := ctrl2;
      alTop    : FControl := ctrl1;
      alBottom : FControl := ctrl2;
    end;
    FDownPos := Point(X, Y);
    if Assigned(FControl) then
    begin
      if Align in [alLeft, alRight] then
      begin
        FMaxSize := Parent.ClientWidth - FMinSize;
        for I := 0 to Parent.ControlCount - 1 do
          with Parent.Controls[I] do
            if Align in [alLeft, alRight] then Dec(FMaxSize, Width);
        Inc(FMaxSize, FControl.Width);
      end
      else
      begin
        FMaxSize := Parent.ClientHeight - FMinSize;
        for I := 0 to Parent.ControlCount - 1 do
          with Parent.Controls[I] do
            if Align in [alTop, alBottom] then Dec(FMaxSize, Height);
        Inc(FMaxSize, FControl.Height);
      end;
      UpdateSize(X, Y);
      AllocateLineDC;
      with ValidParentForm(Self) do
        if ActiveControl <> nil then
        begin
          FActiveControl := ActiveControl;
          FOldKeyDown := TWinControlAccess(FActiveControl).OnKeyDown;
          TWinControlAccess(FActiveControl).OnKeyDown := FocusKeyDown;
        end;
      if ResizeStyle in [rsLine, rsPattern] then DrawLine;
    end;
  end;
end;

procedure TSlavaSplitter.UpdateControlSize;
begin
  if FNewSize <> FOldSize then
  begin
    case Align of
      alLeft: begin
                FControl.Width := FNewSize;
                Left := FControl.Width + 1;
              end;
      alTop: begin
               FControl.Height := FNewSize;
               Top := FControl.Height + 1;
             end;
      alRight:
        begin
//          Parent.DisableAlign;
          try
            FControl.Left := FControl.Left + (FControl.Width - FNewSize);
            FControl.Width := FNewSize;
          finally
//            Parent.EnableAlign;
          end;
          {$IFNDEF VER120}
          if FControl.Width <> 0
          then begin
                 Left := FControl.Left;
                 FControl.Left := Left + 1;
               end;
          {$ENDIF}
        end;
      alBottom:
        begin
//          Parent.DisableAlign;
          try
            FControl.Top := FControl.Top + (FControl.Height - FNewSize);
            FControl.Height := FNewSize;
          finally
//            Parent.EnableAlign;
          end;
          {$IFNDEF VER120}
          if FControl.Height <> 0
          then begin
                 Top := FControl.Top;
                 FControl.Top := Top + 1;
               end;
          {$ENDIF}
        end;
    end;
    Update;
    if Assigned(FOnMoved) then FOnMoved(Self);
    if FOldSize = 0
    then case Align of
           alLeft    : ClickOrientation := coLeft;
           alBottom  : ClickOrientation := coDown;
           alRight   : ClickOrientation := coRight;
           alTop     : ClickOrientation := coUp;
         end;
    FOldSize := FNewSize;
  end;
end;

procedure TSlavaSplitter.CalcSplitSize(X, Y: Integer; var NewSize, Split: Integer);
var
  S: Integer;
begin
  if Align in [alLeft, alRight] then
    Split := X - FDownPos.X
  else
    Split := Y - FDownPos.Y;
  S := 0;
  case Align of
    alLeft: S := FControl.Width + Split;
    alRight: S := FControl.Width - Split;
    alTop: S := FControl.Height + Split;
    alBottom: S := FControl.Height - Split;
  end;
  NewSize := S;
  if S < FMinSize then
    NewSize := FMinSize
  else if S > FMaxSize then
    NewSize := FMaxSize;
  if S <> NewSize then
  begin
    if Align in [alRight, alBottom] then
      S := S - NewSize else
      S := NewSize - S;
    Inc(Split, S);
  end;
end;

procedure TSlavaSplitter.UpdateSize(X, Y: Integer);
begin
  CalcSplitSize(X, Y, FNewSize, FSplit);
end;

procedure TSlavaSplitter.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  NewSize, Split: Integer;
begin
  inherited;
  if MouseInHandle then
  begin
   Cursor:=FHandleCursor;
   if not bOver then
   begin
    bOver:=true;
    Invalidate;
   end;
  end
  else
  begin
   Cursor := FSplitCursor;
   if bOver then
   begin
    bOver:=false;
    Invalidate;
   end;
  end;
  MouseX := x;
  MouseY := y;
  if (ssLeft in Shift) and Assigned(FControl) then
  begin
    CalcSplitSize(X, Y, NewSize, Split);
    if DoCanResize(NewSize) then
    begin
      if ResizeStyle in [rsLine, rsPattern] then DrawLine;
      FNewSize := NewSize;
      FSplit := Split;
      if ResizeStyle = rsUpdate then UpdateControlSize;
      if ResizeStyle in [rsLine, rsPattern] then DrawLine;
    end;
  end;
end;

procedure TSlavaSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
begin
  inherited;
  if Assigned(FControl) then
  begin
    if ResizeStyle in [rsLine, rsPattern] then DrawLine;
    if MouseInHandle
    then begin
           if FOldSize = -1 // first time
           then begin
                  FNewSize := 0;
                  if ClickOrientation in [coUp, coDown]
                  then FOldControlSize := FControl.Height
                  else FOldControlSize := FControl.Width;
                end
           else if FOldSize > 0
                then begin
                       FNewSize := 0;//
                       FOldControlSize := FOldSize;
                     end
                else begin
                       FNewSize := FOldControlSize;
                     end;
           case ClickOrientation of
             coUp    : ClickOrientation := coDown;
             coDown  : ClickOrientation := coUp;
             coLeft  : ClickOrientation := coRight;
             coRight : ClickOrientation := coLeft;
           end;
         end;
    UpdateControlSize;
    StopSizing;
  end;
end;

procedure TSlavaSplitter.FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_ESCAPE then
    StopSizing
  else if Assigned(FOldKeyDown) then
    FOldKeyDown(Sender, Key, Shift);
end;

procedure TSlavaSplitter.SetHandled(Value: Boolean);
begin
  FHandled := Value;
  case Align of
    alLeft, alRight : if Width < cMinHandledSize
                      then Width := cMinHandledSize;
    alBottom, alTop : if Height < cMinHandledSize
                      then Height := cMinHandledSize;
  end;                                      
  RePaint;
end;

procedure TSlavaSplitter.StopSizing;
begin
  if Assigned(FControl) then
  begin
    if FLineVisible then DrawLine;
    FControl := nil;
    ReleaseLineDC;
    if Assigned(FActiveControl) then
    begin
      TWinControlAccess(FActiveControl).OnKeyDown := FOldKeyDown;
      FActiveControl := nil;
    end;
  end;
  if Assigned(FOnMoved) then
    FOnMoved(Self);
end;

procedure TSlavaSplitter.SetClickOrientation(
  const Value: TClickOrientation);
begin
  FClickOrientation := Value;
  Invalidate;
end;


procedure TSlavaSplitter.Loaded;
begin
  inherited Loaded;
  FSplitCursor := Cursor;
  if Align in [alLeft, alRight]
  then begin
         ctrl1 := FindControl(diLeft);
         ctrl2 := FindControl(diRight);
       end;
  if Align in [alTop, alBottom]
  then begin
         ctrl1 := FindControl(diUp);
         ctrl2 := FindControl(diDown);
       end;
end;

function TSlavaSplitter.MouseInHandle: Boolean;
begin
  if Align in [alLeft, alRight]
  then Result := Handled and PtInRect(Rect(0, ctop, Width, cbottom), Point(MouseX, MouseY))
  else Result := Handled and PtInRect(Rect(cleft, 0, cright, Height), Point(MouseX, MouseY));
end;

function TSlavaSplitter.GetAlign: TAlign;
begin
  Result := inherited Align;
end;

procedure TSlavaSplitter.SetAlign(const Value: TAlign);
var aValue: TClickOrientation;
begin
  if Value in [alNone, alClient]
  then raise Exception.Create('Value not allowed for ' + ClassName + ' component.');
  inherited Align := Value;
  aValue := coLeft;
  case Align of
    alLeft   : aValue := coLeft;
    alRight  : aValue := coRight;
    alTop    : aValue := coUp;
    alBottom : aValue := coDown;
  end;
  ClickOrientation := aValue;
end;

procedure TSlavaSplitter.SetHandleSize(const Value: NaturalNumber);
begin
  FHandleSize := Value;
  Invalidate;
end;

procedure TSlavaSplitter.SetHandleAlign(const Value: THandleAlign);
begin
  FHandleAlign := Value;
  Invalidate;
end;


function TSlavaSplitter.GetWidth: Integer;
begin
  Result := inherited Width;
end;

procedure TSlavaSplitter.SetWidth(const Value: Integer);
begin
  if Handled and (Align in [alLeft, alRight]) and (Value < cMinHandledSize)
  then raise Exception.Create('Min. width for a handled TSlavaSplitter component is ' + IntToStr(cMinHandledSize));
  inherited Width := Value;
end;

procedure TSlavaSplitter.SetHeight(Value: Integer);
begin
  if Handled and (Align in [alTop, alBottom]) and (Value < cMinHandledSize)
  then raise Exception.Create('Min. height for a handled TSlavaSplitter component is ' + IntToStr(cMinHandledSize));
  inherited Height := Value;
end;

function TSlavaSplitter.GetHeight: Integer;
begin
  Result := inherited Height;
end;

procedure TSlavaSplitter.SetCursor(Value: TCursor);
begin
 FSplitCursor:=Value;
end;

procedure TSlavaSplitter.SetHandleCursor(Value: TCursor);
begin
 FHandleCursor:=Value;
end;

procedure TSlavaSplitter.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  if bOver then
  begin
   bOver:=false;
   Invalidate;
  end;
end;

function TSlavaSplitter.isValidBitmap(bmp:TBitmap):Boolean;
begin
 isValidBitmap:=false;
 if bmp=nil then exit;
 if not Assigned(bmp) then exit;
 if bmp.Width<3 then exit;
 if bmp.Height<3 then exit;
 isValidBitmap:=true;
end;

procedure TSlavaSplitter.SetBmDown(Value: TBitmap);
begin
 bmDown.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmDownOver(Value: TBitmap);
begin
 bmDownOver.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmLeft(Value: TBitmap);
begin
 bmLeft.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmLeftOver(Value: TBitmap);
begin
 bmLeftOver.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmRight(Value: TBitmap);
begin
 BmRight.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmRightOver(Value: TBitmap);
begin
 BmRightOver.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmUp(Value: TBitmap);
begin
 BmUp.Assign(Value);
 Invalidate;
end;

procedure TSlavaSplitter.SetBmUpOver(Value: TBitmap);
begin
 BmUpOver.Assign(Value);
 Invalidate;
end;

end.
