unit Settings;

interface

uses
  Classes, SysUtils, FileUtil, Dialogs, LCLProc, ScreenTools, Messg, ButtonA,
  Directories, DrawDlg, ButtonC, KeyBindings, Languages, ListBoxEx,
  {$IFDEF DPI}Dpi.Forms, Dpi.Controls, Dpi.Graphics, Dpi.StdCtrls{$ELSE}
  Forms, Controls, Graphics, StdCtrls{$ENDIF}, Controls;

type
  { TSettingsDlg }

  TSettingsDlg = class(TDrawDlg)
    ButtonMusic: TButtonC;
    ButtonMusicVolumeDown: TButtonC;
    ButtonMusicVolumeUp: TButtonC;
    ButtonFullscreen: TButtonC;
    ButtonCustomDpi: TButtonC;
    ButtonGammaDown: TButtonC;
    ButtonDpiDown: TButtonC;
    EditShortCutPrimary: TEdit;
    EditShortCutSecondary: TEdit;
    ListLanguages: TListBoxEx;
    ListKeyBindings: TListBoxEx;
    ButtonOk: TButtonA;
    ButtonCancel: TButtonA;
    ButtonReset: TButtonA;
    ButtonGammaUp: TButtonC;
    ButtonDpiUp: TButtonC;
    procedure ButtonCustomDpiClick(Sender: TObject);
    procedure ButtonDpiDownClick(Sender: TObject);
    procedure ButtonDpiUpClick(Sender: TObject);
    procedure ButtonFullscreenClick(Sender: TObject);
    procedure ButtonCancelClick(Sender: TObject);
    procedure ButtonMusicClick(Sender: TObject);
    procedure ButtonMusicVolumeDownClick(Sender: TObject);
    procedure ButtonMusicVolumeUpClick(Sender: TObject);
    procedure ButtonResetClick(Sender: TObject);
    procedure ButtonGammaDownClick(Sender: TObject);
    procedure EditShortCutPrimaryKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure EditShortCutSecondaryKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure ListKeyBindingsKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure ListKeyBindingsSelectionChange(Sender: TObject; User: Boolean);
    procedure ButtonOkClick(Sender: TObject);
    procedure ButtonGammaUpClick(Sender: TObject);
  private
    LocalGamma: Integer;
    LocalKeyBindings: TKeyBindings;
    LocalMusicVolume: Integer;
    CurrentKeyBinding: TKeyBinding;
    LocalDpi: Integer;
    procedure UpdateShortCutItem;
    function GetLocalCustomDpiEnabled: Boolean;
    function GetLocalMusicEnabled: Boolean;
    procedure UpdateInterface;
  public
    procedure LoadData;
    procedure SaveData;
  end;


const
  DpiMin = 100;
  DpiMax = 500;
  DpiStep = 25;
  MusicVolumeMin = 0;
  MusicVolumeMax = 100;
  MusicVolumeStep = 10;


implementation

{$R *.lfm}

uses
  Start;

var
  SFullScreen, SGamma, SRestartMsg, SShortCutPrimary, SShortCutSecondary,
  SLanguages, SKeyBindings, SCustomDpi, SDpi, SMusic, SMusicVolume: string;

procedure ReloadLanguages;
begin
  SFullScreen := Phrases.Lookup('SETTINGS', 0);
  SGamma := Phrases.Lookup('SETTINGS', 1);
  SRestartMsg := Phrases.Lookup('SETTINGS', 2);
  SShortCutPrimary := Phrases.Lookup('SETTINGS', 3);
  SShortCutSecondary := Phrases.Lookup('SETTINGS', 4);
  SLanguages := Phrases.Lookup('SETTINGS', 5);
  SKeyBindings := Phrases.Lookup('SETTINGS', 6);
  SCustomDpi := Phrases.Lookup('SETTINGS', 7);
  SDpi := Phrases.Lookup('SETTINGS', 8);
  SMusic := Phrases.Lookup('SETTINGS', 9);
  SMusicVolume := Phrases.Lookup('SETTINGS', 10);
end;

{ TSettingsDlg }

procedure TSettingsDlg.FormCreate(Sender: TObject);
begin
  Color := clBlack;
  LocalKeyBindings := TKeyBindings.Create;

  Canvas.Font.Assign(UniFont[ftNormal]);
  Canvas.Brush.Style := TBrushStyle.bsClear;

  ButtonOk.Caption := Phrases.Lookup('BTN_OK');
  ButtonCancel.Caption := Phrases.Lookup('BTN_CANCEL');
  ButtonReset.Caption := Phrases.Lookup('BTN_RESET');
  InitButtons;
end;

procedure TSettingsDlg.ButtonCancelClick(Sender: TObject);
begin
  ModalResult := mrCancel;
end;

procedure TSettingsDlg.ButtonMusicClick(Sender: TObject);
begin
  ButtonMusic.ButtonIndex := ButtonMusic.ButtonIndex xor 1;
  UpdateInterface;
end;

procedure TSettingsDlg.ButtonMusicVolumeDownClick(Sender: TObject);
begin
  Dec(LocalMusicVolume, MusicVolumeStep);
  if LocalMusicVolume < MusicVolumeMin then LocalMusicVolume := MusicVolumeMin;
  Invalidate;
end;

procedure TSettingsDlg.ButtonMusicVolumeUpClick(Sender: TObject);
begin
  Inc(LocalMusicVolume, MusicVolumeStep);
  if LocalMusicVolume > MusicVolumeMax then LocalMusicVolume := MusicVolumeMax;
  Invalidate;
end;

procedure TSettingsDlg.ButtonResetClick(Sender: TObject);
begin
  // TODO: Better to have default values on single place
  ListLanguages.ItemIndex := 0;
  ButtonFullscreen.ButtonIndex := 3;
  ButtonMusic.ButtonIndex := 3;
  LocalMusicVolume := 50;
  ButtonCustomDpi.ButtonIndex := 2;
  LocalDpi := 100;
  LocalGamma := 100;
  ListKeyBindings.ItemIndex := -1;
  ListKeyBindingsSelectionChange(nil, False);
  LocalKeyBindings.ResetToDefault;
  LocalKeyBindings.LoadToStrings(ListKeyBindings.Items);
  UpdateInterface;
  Repaint;
end;

procedure TSettingsDlg.ButtonGammaDownClick(Sender: TObject);
begin
  if LocalGamma > 50 then
  begin
    Dec(LocalGamma);
    Invalidate;
  end;
end;

procedure TSettingsDlg.EditShortCutPrimaryKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Sender is TEdit) and Assigned(CurrentKeyBinding) and not (Key in [16..18]) then begin
    CurrentKeyBinding.ShortCut := Key or
      (scShift * Integer(ssShift in Shift)) or
      (scCtrl * Integer(ssCtrl in Shift)) or
      (scAlt * Integer(ssAlt in Shift));
    EditShortCutPrimary.Text := ShortCutToText(CurrentKeyBinding.ShortCut);
    Key := 0;
    UpdateShortCutItem;
  end;
end;

procedure TSettingsDlg.EditShortCutSecondaryKeyUp(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  if (Sender is TEdit) and Assigned(CurrentKeyBinding) and not (Key in [16..18]) then begin
    CurrentKeyBinding.ShortCut2 := Key or
      (scShift * Integer(ssShift in Shift)) or
      (scCtrl * Integer(ssCtrl in Shift)) or
      (scAlt * Integer(ssAlt in Shift));
    EditShortCutSecondary.Text := ShortCutToText(CurrentKeyBinding.ShortCut2);
    Key := 0;
    UpdateShortCutItem;
  end;
end;

procedure TSettingsDlg.FormClose(Sender: TObject; var CloseAction: TCloseAction
  );
begin
  ListKeyBindings.ItemIndex := -1;
end;

procedure TSettingsDlg.ButtonFullscreenClick(Sender: TObject);
begin
  ButtonFullscreen.ButtonIndex := ButtonFullscreen.ButtonIndex xor 1;
end;

procedure TSettingsDlg.ButtonDpiDownClick(Sender: TObject);
begin
  Dec(LocalDpi, DpiStep);
  if LocalDpi < DpiMin then LocalDpi := DpiMin;
  Invalidate;
end;

procedure TSettingsDlg.ButtonCustomDpiClick(Sender: TObject);
begin
  ButtonCustomDpi.ButtonIndex := ButtonCustomDpi.ButtonIndex xor 1;
  UpdateInterface;
end;

procedure TSettingsDlg.ButtonDpiUpClick(Sender: TObject);
begin
  Inc(LocalDpi, DpiStep);
  if LocalDpi > DpiMax then LocalDpi := DpiMax;
  Invalidate;
end;

procedure TSettingsDlg.FormDestroy(Sender: TObject);
begin
  FreeAndNil(LocalKeyBindings);
end;

procedure TSettingsDlg.FormPaint(Sender: TObject);
const
  TextDistanceX = 20;
  UpDownTextWidth = 120;
begin
  PaintBackground(Canvas, 3, 3, ClientWidth - 6, ClientHeight - 6,
    ClientWidth, ClientHeight);
  Frame(Canvas, 0, 0, ClientWidth - 1, ClientHeight - 1, 0, 0);
  Frame(Canvas, 1, 1, ClientWidth - 2, ClientHeight - 2,
    MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
  Frame(Canvas, 2, 2, ClientWidth - 3, ClientHeight - 3,
    MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
  EditFrame(Canvas, EditShortCutPrimary.BoundsRect, MainTexture);
  EditFrame(Canvas, EditShortCutSecondary.BoundsRect, MainTexture);
  EditFrame(Canvas, ListLanguages.BoundsRect, MainTexture);
  BtnFrame(Canvas, ButtonOk.BoundsRect, MainTexture);
  BtnFrame(Canvas, ButtonCancel.BoundsRect, MainTexture);

  RFrame(Canvas, ButtonFullscreen.Left - 1, ButtonFullscreen.Top - 1,
    ButtonFullscreen.Left + 12, ButtonFullscreen.Top + 12, MainTexture.ColorBevelShade,
    MainTexture.ColorBevelLight);
  {$IFDEF DPI}
  RFrame(Canvas, ButtonCustomDpi.Left - 1, ButtonCustomDpi.Top - 1,
    ButtonCustomDpi.Left + 12, ButtonCustomDpi.Top + 12, MainTexture.ColorBevelShade,
    MainTexture.ColorBevelLight);
  LoweredTextOut(Canvas, -2, MainTexture, ButtonCustomDpi.Left + TextDistanceX,
    ButtonCustomDpi.Top - 4, SCustomDpi);
  UnderlinedTitleValue(Canvas, SDpi, IntToStr(LocalDpi) + '%',
    ButtonDpiUp.Left - UpDownTextWidth - 4, ButtonDpiUp.Top + 2, UpDownTextWidth);
  {$ENDIF}

  RFrame(Canvas, ButtonMusic.Left - 1, ButtonMusic.Top - 1,
    ButtonMusic.Left + 12, ButtonMusic.Top + 12, MainTexture.ColorBevelShade,
    MainTexture.ColorBevelLight);
  LoweredTextOut(Canvas, -2, MainTexture, ButtonMusic.Left + TextDistanceX,
    ButtonMusic.Top - 4, SMusic);
  UnderlinedTitleValue(Canvas, SMusicVolume, IntToStr(LocalMusicVolume) + '%',
    ButtonMusicVolumeUp.Left - UpDownTextWidth - 4, ButtonMusicVolumeUp.Top + 2, UpDownTextWidth);

  LoweredTextOut(Canvas, -2, MainTexture, ListLanguages.Left,
    ListLanguages.Top - 26, SLanguages);
  LoweredTextOut(Canvas, -2, MainTexture, ListKeyBindings.Left,
    ListKeyBindings.Top - 26, SKeyBindings);
  LoweredTextOut(Canvas, -2, MainTexture, ButtonFullscreen.Left + TextDistanceX,
    ButtonFullscreen.Top - 4, SFullScreen);
  UnderlinedTitleValue(Canvas, SGamma, IntToStr(LocalGamma) + '%',
    ButtonGammaUp.Left - UpDownTextWidth - 4, ButtonGammaUp.Top + 2, UpDownTextWidth);
  LoweredTextOut(Canvas, -2, MainTexture, EditShortCutPrimary.Left,
    EditShortCutPrimary.Top - 26, SShortCutPrimary);
  LoweredTextOut(Canvas, -2, MainTexture, EditShortCutSecondary.Left,
    EditShortCutSecondary.Top - 26, SShortCutSecondary);
end;

procedure TSettingsDlg.FormShow(Sender: TObject);
begin
  Caption := Phrases2.Lookup('ACTIONHEADER_CONFIG');
  ReloadLanguages;
  StartDlg.Translator.LanguageListToStrings(ListLanguages.Items);
  ListLanguages.Font.Color := MainTexture.ColorMark;
  ListKeyBindings.Font.Color := MainTexture.ColorMark;
  LoadData;
  LocalKeyBindings.LoadToStrings(ListKeyBindings.Items);
  EditShortCutPrimary.Font.Color := MainTexture.ColorMark;
  EditShortCutSecondary.Font.Color := MainTexture.ColorMark;
  {$IFDEF DPI}
  ButtonCustomDpi.Visible := True;
  ButtonDpiDown.Visible := True;
  ButtonDpiUp.Visible := True;
  {$ELSE}
  ButtonCustomDpi.Visible := False;
  ButtonDpiDown.Visible := False;
  ButtonDpiUp.Visible := False;
  {$ENDIF}
  UpdateInterface;
  Gtk2DisableControlStyling(EditShortCutPrimary);
  Gtk2DisableControlStyling(EditShortCutSecondary);
end;

procedure TSettingsDlg.ListKeyBindingsKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  KeyDown(Key, Shift);
end;

procedure TSettingsDlg.ListKeyBindingsSelectionChange(Sender: TObject;
  User: Boolean);
begin
  if Assigned(CurrentKeyBinding) then begin
    CurrentKeyBinding.ShortCut := TextToShortCut(EditShortCutPrimary.Text);
    CurrentKeyBinding.ShortCut2 := TextToShortCut(EditShortCutSecondary.Text);
  end;

  if ListKeyBindings.ItemIndex >= 0 then
    CurrentKeyBinding := LocalKeyBindings[ListKeyBindings.ItemIndex]
    else CurrentKeyBinding := nil;

  if Assigned(CurrentKeyBinding) then begin
    if CurrentKeyBinding.ShortCut <> 0 then
      EditShortCutPrimary.Text := ShortCutToText(CurrentKeyBinding.ShortCut)
      else EditShortCutPrimary.Text := '';
    EditShortCutPrimary.Enabled := True;
    if CurrentKeyBinding.ShortCut2 <> 0 then
      EditShortCutSecondary.Text := ShortCutToText(CurrentKeyBinding.ShortCut2)
      else EditShortCutSecondary.Text := '';
    EditShortCutSecondary.Enabled := True;
  end else begin
    EditShortCutPrimary.Text := '';
    EditShortCutPrimary.Enabled := False;
    EditShortCutSecondary.Text := '';
    EditShortCutSecondary.Enabled := False;
  end;
end;

procedure TSettingsDlg.ButtonOkClick(Sender: TObject);
begin
  SaveData;
  ModalResult := mrOk;
end;

procedure TSettingsDlg.ButtonGammaUpClick(Sender: TObject);
begin
  if LocalGamma < 150 then begin
    Inc(LocalGamma);
    Invalidate;
  end;
end;

procedure TSettingsDlg.UpdateShortCutItem;
begin
  if Assigned(CurrentKeyBinding) then begin
    if CurrentKeyBinding.ShortCut > 0 then
      LocalKeyBindings.RemoveShortCut(CurrentKeyBinding.ShortCut);
    if CurrentKeyBinding.ShortCut2 > 0 then
      LocalKeyBindings.RemoveShortCut(CurrentKeyBinding.ShortCut2);
    CurrentKeyBinding.ShortCut := TextToShortCut(EditShortCutPrimary.Text);
    CurrentKeyBinding.ShortCut2 := TextToShortCut(EditShortCutSecondary.Text);
    LocalKeyBindings.LoadToStrings(ListKeyBindings.Items);
  end;
end;

function TSettingsDlg.GetLocalCustomDpiEnabled: Boolean;
begin
  Result := (ButtonCustomDpi.ButtonIndex and 1) = 1;
end;

function TSettingsDlg.GetLocalMusicEnabled: Boolean;
begin
  Result := (ButtonMusic.ButtonIndex and 1) = 1;
end;

procedure TSettingsDlg.UpdateInterface;
begin
  ButtonDpiUp.Enabled := GetLocalCustomDpiEnabled;
  ButtonDpiDown.Enabled := GetLocalCustomDpiEnabled;
  ButtonMusicVolumeDown.Enabled := GetLocalMusicEnabled;
  ButtonMusicVolumeUp.Enabled := GetLocalMusicEnabled;
end;

procedure TSettingsDlg.LoadData;
begin
  StartDlg.Translator.Language := StartDlg.Translator.Languages.SearchByCode(LocaleCode);
  StartDlg.Translator.LanguageListToStrings(ListLanguages.Items, False);
  ListLanguages.ItemIndex := ListLanguages.Items.IndexOfObject(StartDlg.Translator.Language);
  if ListLanguages.ItemIndex = -1 then ListLanguages.ItemIndex := 0;
  if FullScreen then ButtonFullscreen.ButtonIndex := 3
    else ButtonFullscreen.ButtonIndex := 2;
  if MusicEnabled then ButtonMusic.ButtonIndex := 3
    else ButtonMusic.ButtonIndex := 2;
  LocalMusicVolume := Round(MusicVolume * 100);
  LocalGamma := Gamma;
  LocalKeyBindings.Assign(KeyBindings.KeyBindings);
  {$IFDEF DPI}
  if CustomDpiEnabled then ButtonCustomDpi.ButtonIndex := 3
    else ButtonCustomDpi.ButtonIndex := 2;
  LocalDpi := Round(CustomDpi * 100 / 96);
  {$ENDIF}
end;

procedure TSettingsDlg.SaveData;
var
  NeedRestart: Boolean;
begin
  NeedRestart := (Gamma <> LocalGamma) or (CustomDpiEnabled <> GetLocalCustomDpiEnabled) or
    ((GetLocalCustomDpiEnabled and (LocalDpi <> CustomDpi)));
  if ListLanguages.ItemIndex <> -1 then begin
    StartDlg.Translator.Language := TLanguage(ListLanguages.Items.Objects[ListLanguages.ItemIndex]);
    LocaleCode := StartDlg.Translator.Language.Code;
  end else begin
    StartDlg.Translator.Language := nil;
    LocaleCode := '';
  end;
  FullScreen := (ButtonFullscreen.ButtonIndex and 1) = 1;
  MusicEnabled := GetLocalMusicEnabled;
  MusicVolume := LocalMusicVolume / 100;
  Gamma := LocalGamma;
  ScreenTools.CustomDpiEnabled := CustomDpiEnabled;
  if NeedRestart then SimpleMessage(SRestartMsg);
  KeyBindings.KeyBindings.Assign(LocalKeyBindings);
  {$IFDEF DPI}
  CustomDpiEnabled := GetLocalCustomDpiEnabled;
  CustomDpi := Round(LocalDpi * 96 / 100);
  {$ENDIF}
end;

end.


