unit dgui_simple;

interface

uses
  dvector2i,
  dvector2f,
  drect2i,
  drect2f,
  dcolors,
  dstream,
  deng,
  dgui3,
  DDrawFont;

const
  STATE_NORMAL = 0;
  STATE_HOVER = 1;
  STATE_DISABLED = 2;
  STATE_PRESSED = 3;

type
PGuiThemeSimple = ^TGuiThemeSimple;
PGuiStyleSimple = ^TGuiStyleSimple;

TStateColors = array[0..3] of TColor;

TGuiStyleSimple = object(TGuiStyle)
protected
  FTheme: PGuiThemeSimple;
  FMain: TStateColors;
  FBg: TStateColors;
  function GetMainNormal: TColor; inline;
  procedure SetMainNormal(Color: TColor); inline;
  function GetMainHover: TColor; inline;
  procedure SetMainHover(Color: TColor); inline;
  function GetMainDisabled: TColor; inline;
  procedure SetMainDisabled(Color: TColor); inline;
  function GetMainPressed: TColor; inline;
  procedure SetMainPressed(Color: TColor); inline;
public
  constructor Init(const aWidgetName: AnsiString; Theme: PGuiThemeSimple);

  procedure RectRender(Widget: PWidget); virtual;

  procedure ButtonRender(Widget: PWidget; ButtonState: PGUIButtonState); virtual;

  procedure HSliderRender(Widget: PWidget; SliderState: PGUISliderState); virtual;
  function HSliderIsPointInThumb(Widget: PWidget;
                                 SliderState: PGUISliderState;
                                 const V: TVec2i): Boolean; virtual;

  property MainNormal: TColor read GetMainNormal write SetMainNormal;
  property MainHover: TColor read GetMainHover write SetMainHover;
  property MainDisabled: TColor read GetMainDisabled write SetMainDisabled;
  property MainPressed: TColor read GetMainPressed write SetMainPressed;
public type
end;

TGuiThemeSimple = object(TGuiTheme)
private
  FFont: TFont;
  FSimpleStyle: TGuiStyleSimple;
  FButton: TGuiStyleSimple;
  FRect: TGuiStyleSimple;
  FHorSlider: TGuiStyleSimple;
public
  constructor Init(FontData: TData);
  destructor Done; virtual;
end;

implementation

function TGuiStyleSimple.GetMainNormal: TColor;
begin
  Result := FMain[STATE_NORMAL];
end;

procedure TGuiStyleSimple.SetMainNormal(Color: TColor);
begin
  FMain[STATE_NORMAL] := Color;
end;

function TGuiStyleSimple.GetMainHover: TColor;
begin
  Result := FMain[STATE_HOVER];
end;

procedure TGuiStyleSimple.SetMainHover(Color: TColor);
begin
  FMain[STATE_HOVER] := Color;
end;

function TGuiStyleSimple.GetMainDisabled: TColor;
begin
  Result := FMain[STATE_DISABLED];
end;

procedure TGuiStyleSimple.SetMainDisabled(Color: TColor);
begin
  FMain[STATE_DISABLED] := Color;
end;

function TGuiStyleSimple.GetMainPressed: TColor;
begin
  Result := FMain[STATE_PRESSED];
end;

procedure TGuiStyleSimple.SetMainPressed(Color: TColor);
begin
  FMain[STATE_PRESSED] := Color;
end;

constructor TGuiStyleSimple.Init(const aWidgetName: AnsiString; Theme: PGuiThemeSimple);
var
  I: LongInt;
begin
  inherited Init(aWidgetName);
  FTheme := Theme;
  for I := 0 to 3 do begin
    FMain[I] := RGBA(128, 128, 128, 255);
    FBg[I] := RGBA(0, 0, 0, 255);
  end;
  FMain[STATE_HOVER] := RGBA(192, 0, 0, 255);
  FBg[STATE_HOVER] := RGBA(128, 0, 0, 255);
  FMain[STATE_PRESSED] := RGBA(192, 0, 0, 255);
end;

procedure TGuiStyleSimple.RectRender(Widget: PWidget);
begin
  Eng.Draw.Color(Self.FBg[STATE_NORMAL]);
  Eng.Draw.Color(RGBA($ff, $00, $00, $ff));
  Eng.Draw.RectFilled(drect2i.Rect2i(Widget^.GlobalPos, Widget^.Size));
  Eng.Draw.Color(RGBA($ff, $ff, $ff, $ff));
end;

procedure TGuiStyleSimple.ButtonRender(Widget: PWidget; ButtonState: PGUIButtonState);
var
  State: LongInt;
  S: TVec2i;
begin
  with Widget^ do begin
    if MouseHover then begin
      State := STATE_HOVER;
    end else
      State := STATE_NORMAL;
    Eng.Draw.Color(Self.FBg[State]);
    Eng.Draw.RectFilled(drect2i.Rect2i(GlobalPos, Size));
    Eng.Draw.Color(Self.FMain[State]);
    Eng.Draw.Rect(drect2i.Rect2i(GlobalPos, Size));
    S := Vec2i(FTheme.FFont.Width(Caption), FTheme.FFont.Height(Caption));
    FTheme.FFont.Draw(GlobalPos + Vec2i((Size.X - S.X) div 2, (Size.Y) div 2), Caption);
  end;
end;

procedure TGuiStyleSimple.HSliderRender(Widget: PWidget; SliderState: PGUISliderState);
var
  State: LongInt;
  Y, Left, Right, Height: Single;
  CursorX: Single;
begin
  if SliderState^.Dragging then begin
    State := STATE_PRESSED;
  end else if SliderState^.Hover then begin
    State := STATE_HOVER;
  end else
    State := STATE_NORMAL;
  Left := Widget^.GlobalPos.X;
  Right := Widget^.GlobalPos.X + Widget^.Size.X;
  Height := Widget^.Size.Y;
  Y := Widget^.GlobalPos.Y + Height / 2;
  CursorX := Left + SliderState^.Value * Widget^.Size.X;
  Eng.Draw.Color(Self.FMain[STATE_NORMAL]);
  Eng.Draw.Line(Vec2f(Left, Y), Vec2f(Right, Y));
  Eng.Draw.Color(Self.FMain[State]);
  Eng.Draw.RectFilled(drect2f.Rect2f(Vec2f(CursorX - 2, Widget^.GlobalPos.Y),
                                     Vec2f(4, Widget^.Size.Y)));
end;

function TGuiStyleSimple.HSliderIsPointInThumb(Widget: PWidget;
                                                        SliderState: PGUISliderState;
                                                        const V: TVec2i): Boolean;
var
  CursorX: Single;
begin
  CursorX := Widget^.GlobalPos.X + SliderState^.Value * Widget^.Size.X;
  Exit((CursorX - 2 <= V.X) and (V.X < CursorX + 2)
   and (Widget^.GlobalPos.Y <= V.Y) and (V.Y <= Widget^.GlobalPos.Y + Widget^.Size.Y));
end;

// TODO
//function TGuiStyleSimpleButton.GetMinSize(Widget: PWidget): TVec2i;
//begin
//  Exit(Vec2i(FTheme.FFont.Width(Widget^.Caption),
//             FTheme.FFont.Height(Widget^.Caption)));
//end;

function EndsWith(const S, E: AnsiString): Boolean;
begin
  if Length(S) < Length(E) then
    Exit(False);
  Result := Copy(S, Length(S) - Length(E) + 1, Length(E)) = E;
end;

constructor TGuiThemeSimple.Init(FontData: TData);
begin
  inherited Init;
  if EndsWith(FontData.Stream^.Name, '.bit') then begin
    // legacy -- much old code rely on this
    FFont.InitCP1251(nil, @Eng, FontData);
  end else
    FFont.InitFromJson(nil, @Eng, FontData);
  AddFont('default', @FFont);
  AddFont('console', @FFont);
  FSimpleStyle.Init(STYLE_DEFAULT, @Self);
  AddStyle(STYLE_DEFAULT, @FSimpleStyle);
  FButton.Init(WIDGET_BUTTON, @Self);
  AddStyle(WIDGET_BUTTON, @FButton);
  FRect.Init(WIDGET_RECT, @Self);
  AddStyle(WIDGET_RECT, @FRect);
  FHorSlider.Init(WIDGET_HORSLIDER, @Self);
  AddStyle(WIDGET_HORSLIDER, @FHorSlider);
end;

destructor TGuiThemeSimple.Done;
begin
  FFont.Done;
  inherited Done;
end;

end.
