unit Vis2D_CategoryChartSettings;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, VisCtl2D, Vcl.ExtCtrls, Vcl.ComCtrls, System.ImageList,
  Vcl.ImgList, UITypes, UxPanel, TextEditor, ScrollBoxEx;

type
  TVis2D_CategoryChartSettingsFrm = class(TDrawableOptionsFrm)
    icons: TImageList;
    pnCategories: TPanel;
    lvCategories: TListView;
    Label1: TLabel;
    pnCatSettings: TPanel;
    pnGeneral: TPanel;
    btnApply: TUxButton;
    pnToolbar: TUxClient;
    btnGeneral: TUxButton;
    btnCategories: TUxButton;
    btnDetails: TUxButton;
    pnDetails: TPanel;
    ScrollBoxEx1: TScrollBoxEx;
    Label2: TLabel;
    Label12: TLabel;
    Label3: TLabel;
    imgLegendStyle: TImage;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    cbLegend: TCheckBox;
    btnLegendStyle: TUxButton;
    pnLegendFont: TPanel;
    btnLegendFont: TUxButton;
    cbLabelsVisible: TCheckBox;
    pnLabelFont: TPanel;
    btnLabelFont: TUxButton;
    eLabelPosition: TTextEditor;
    cbValueLabels: TCheckBox;
    pnValueLabelFont: TPanel;
    btnValueLabelFont: TUxButton;
    eValueLabelPosition: TTextEditor;
    eValueLabelFormat: TTextEditor;
    procedure lvCategoriesSelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);
    procedure CallUpdateDrawable(Sender: TObject);
    procedure btnLegendStyleClick(Sender: TObject);
    procedure btnLegendFontClick(Sender: TObject);
    procedure btnLabelFontClick(Sender: TObject);
    procedure btnValueLabelFontClick(Sender: TObject);
    procedure pnGeneralClick(Sender: TObject);
    procedure pnGeneralEnter(Sender: TObject);
    procedure pnGeneralExit(Sender: TObject);
    procedure SetPage(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  strict private
    FCatFrm: TDrawableOptionsFrm;
    FDetailsFrm: TDrawableOptionsFrm;
    FPageButtons: TArray<TUxButton>;
    procedure CategoryChanged(Sender: TObject);
  strict protected
    procedure Initialize; override;
    procedure UpdateDrawable; override;
  public

  end;

implementation

uses
  Vis2D_CategorySettings, Math, ASColors;

{$R *.dfm}

{ TVis2D_CategoryChartSettingsFrm }

function MakeIcon(AStyle: TElementStyle; AWidth: Integer = 0; AHeight: Integer = 0): TBitmap;
begin
  if AWidth = 0 then
    AWidth := 32;
  if AHeight = 0 then
    AHeight := 32;
  Result := TBitmap.Create;
  try
    Result.SetSize(AWidth, AHeight);
    Result.Canvas.Brush.Color := clWhite;
    Result.Canvas.Brush.Style := bsSolid;
    Result.Canvas.FillRect(Rect(0, 0, Result.Width, Result.Height));
    var f: Double := AStyle.Opacity / AStyle.Opacity.MaxValue;
    Result.Canvas.Brush.Color := f * TRGB(AStyle.Color) + (1 - f) * TRGB(clWhite);
    Result.Canvas.Pen.Color := AStyle.BorderColor;
    Result.Canvas.Pen.Width := Min(AStyle.BorderWidth, 6);
    if Result.Canvas.Pen.Width = 0 then
      Result.Canvas.Pen.Style := psClear
    else
      Result.Canvas.Pen.Style := psSolid;
    var w := Min(AStyle.BorderWidth, 6) div 2;
    Result.Canvas.Rectangle(w, w, Result.Width - w, Result.Height - w);
  except
    Result.Free;
    raise;
  end;
end;

procedure TVis2D_CategoryChartSettingsFrm.SetPage(Sender: TObject);
var
  B: TUxButton;
  P: TPanel;
begin
  LockDrawing;
  try
    for B in FPageButtons do
    begin
      if B.Tag = 0 then
        Continue;
      P := TObject(B.Tag) as TPanel;
      P.Align := alClient;
      P.Visible := B = Sender;
      B.Down := B = Sender;
      if (B = Sender) and Visible and P.Visible and P.CanFocus then
      begin
        if (P.ControlCount = 1) and (P.Controls[0] is TCustomForm) then
        begin
          P.Controls[0].ScaleForPPI(Self.CurrentPPI);
          P.Realign;
        end;
        P.SetFocus;
      end;
    end;
  finally
    UnlockDrawing;
  end;
end;

procedure TVis2D_CategoryChartSettingsFrm.btnLabelFontClick(Sender: TObject);
begin
  with TFontDialog.Create(nil) do
    try
      Font := pnLabelFont.Font;
      if Execute then
      begin
        pnLabelFont.Font := Font;
        pnLabelFont.Caption := Format('%s, %d pt', [Font.Name, Font.Size]);
        UpdateDrawable;
      end;
    finally
      Free;
    end;
end;

procedure TVis2D_CategoryChartSettingsFrm.btnLegendFontClick(Sender: TObject);
begin
  with TFontDialog.Create(nil) do
    try
      Font := pnLegendFont.Font;
      if Execute then
      begin
        pnLegendFont.Font := Font;
        pnLegendFont.Caption := Format('%s, %d pt', [Font.Name, Font.Size]);
        UpdateDrawable;
      end;
    finally
      Free;
    end;
end;

procedure TVis2D_CategoryChartSettingsFrm.btnLegendStyleClick(Sender: TObject);
begin
  (FDrawable as TCategoryChart).LegendStyle.ShowOptionsForm(Self);
  var bm := MakeIcon((FDrawable as TCategoryChart).LegendStyle, imgLegendStyle.Width, imgLegendStyle.Height);
  try
    imgLegendStyle.Picture.Bitmap := bm;
  finally
    bm.Free;
  end;
end;

procedure TVis2D_CategoryChartSettingsFrm.btnValueLabelFontClick(
  Sender: TObject);
begin
  with TFontDialog.Create(nil) do
    try
      Font := pnValueLabelFont.Font;
      if Execute then
      begin
        pnValueLabelFont.Font := Font;
        pnValueLabelFont.Caption := Format('%s, %d pt', [Font.Name, Font.Size]);
        UpdateDrawable;
      end;
    finally
      Free;
    end;
end;

procedure TVis2D_CategoryChartSettingsFrm.CallUpdateDrawable(Sender: TObject);
begin
  UpdateDrawable;
end;

procedure TVis2D_CategoryChartSettingsFrm.CategoryChanged(Sender: TObject);
begin

  if Sender is TVis2D_CategorySettingsFrm then
  begin
    var Cat := TVis2D_CategorySettingsFrm(Sender).Drawable as TCategoryElement;
    for var i := 0 to lvCategories.Items.Count - 1 do
      if Pointer(Cat) = lvCategories.Items[i].Data then
      begin
        lvCategories.Items[i].Caption := Cat.&Label;
        var bm := MakeIcon(Cat.Style);
        try
          icons.Replace(lvCategories.Items[i].ImageIndex, bm, nil);
        finally
          bm.Free;
        end;
      end;
  end;

end;

procedure TVis2D_CategoryChartSettingsFrm.FormCreate(Sender: TObject);
var
  CatChart: TCategoryChart;
begin

  CatChart := FDrawable as TCategoryChart;

  btnGeneral.Tag := NativeInt(pnGeneral);
  btnCategories.Tag := NativeInt(pnCategories);
  btnDetails.Tag := NativeInt(pnDetails);
  btnDetails.Visible := Assigned(CatChart.DetailsOptionsFormClass);
  FPageButtons := [btnGeneral, btnCategories, btnDetails];

  if Assigned(CatChart.DetailsOptionsFormClass) then
  begin
    FDetailsFrm := CatChart.DetailsOptionsFormClass.Create(Self, CatChart);
    FDetailsFrm.BorderStyle := bsNone;
    FDetailsFrm.Parent := pnDetails;
    FDetailsFrm.Align := alClient;
    FDetailsFrm.Show;
  end;

  SetPage(btnGeneral);

end;

procedure TVis2D_CategoryChartSettingsFrm.Initialize;
var
  CatChart: TCategoryChart;
begin

  inherited;

  CatChart := FDrawable as TCategoryChart;

  if CatChart.Name.IsEmpty then
    Caption := CatChart.ChartTypeName
  else
    Caption := CatChart.ChartTypeName + ': ' + CatChart.Name;

  cbLegend.Checked := CatChart.ShowLegend;

  pnLegendFont.Font := CatChart.LegendFont;
  pnLegendFont.Caption := Format('%s, %d pt', [pnLegendFont.Font.Name, pnLegendFont.Font.Size]);

  var bm := MakeIcon(CatChart.LegendStyle, imgLegendStyle.Width, imgLegendStyle.Height);
  try
    imgLegendStyle.Picture.Bitmap := bm;
  finally
    bm.Free;
  end;

  cbLabelsVisible.Checked := CatChart.LabelVisible;

  pnLabelFont.Font := CatChart.LabelFont;
  pnLabelFont.Caption := Format('%s, %d pt', [pnLabelFont.Font.Name, pnLabelFont.Font.Size]);

  eLabelPosition.PlainText := CatChart.LabelPosition.ToString;

  cbValueLabels.Checked := CatChart.ValueLabelVisible;
  pnValueLabelFont.Font := CatChart.ValueFont;
  pnValueLabelFont.Caption := Format('%s, %d pt', [pnValueLabelFont.Font.Name, pnValueLabelFont.Font.Size]);

  eValueLabelPosition.PlainText := CatChart.ValueLabelPosition.ToString;
  eValueLabelFormat.PlainText := CatChart.ValueFormat;

  Icons.BeginUpdate;
  try
    Icons.Clear;

    lvCategories.Items.BeginUpdate;
    try
      lvCategories.Clear;
      for var Cat in CatChart.Categories do
      begin
        with lvCategories.Items.Add do
        begin
          Caption := Cat.&Label;
          bm := MakeIcon(Cat.Style);
          try
            ImageIndex := Icons.Add(bm, nil);
          finally
            bm.Free;
          end;
          Data := Pointer(Cat);
        end;
      end;
    finally
      lvCategories.Items.EndUpdate;
    end;

  finally
    Icons.EndUpdate;
  end;

end;

procedure TVis2D_CategoryChartSettingsFrm.lvCategoriesSelectItem(
  Sender: TObject; Item: TListItem; Selected: Boolean);
begin

  LockDrawing;
  try

    if not Selected then
      Exit;

    if Item = nil then
      Exit;

    if not (TObject(Item.Data) is TDrawable) then
      Exit;

    if FCatFrm = nil then
    begin
      FCatFrm := TVis2D_CategorySettingsFrm.Create(Self, TDrawable(Item.Data));
      FCatFrm.BorderStyle := bsNone;
      FCatFrm.Parent := pnCatSettings;
      FCatFrm.Align := alClient;
      FCatFrm.OnChange := CategoryChanged;
      FCatFrm.Show;
    end
    else
      FCatFrm.Reassign(TDrawable(Item.Data));

    FCatFrm.ScaleForPPI(Self.CurrentPPI);
    pnCatSettings.Realign;

  finally
    UnlockDrawing;
  end;

end;

procedure TVis2D_CategoryChartSettingsFrm.pnGeneralClick(Sender: TObject);
begin
  if Visible and pnGeneral.Visible and pnGeneral.CanFocus then
    pnGeneral.SetFocus;
end;

procedure TVis2D_CategoryChartSettingsFrm.pnGeneralEnter(Sender: TObject);
begin
  btnApply.Default := True;
end;

procedure TVis2D_CategoryChartSettingsFrm.pnGeneralExit(Sender: TObject);
begin
  btnApply.Default := False;
end;

procedure TVis2D_CategoryChartSettingsFrm.UpdateDrawable;
var
  CatChart: TCategoryChart;
begin

  if not Initialized then
    Exit;

  CatChart := FDrawable as TCategoryChart;

  CatChart.ShowLegend := cbLegend.Checked;
  CatChart.LegendFont.Assign(pnLegendFont.Font);

  CatChart.LabelVisible := cbLabelsVisible.Checked;
  CatChart.LabelFont.Assign(pnLabelFont.Font);
  CatChart.LabelPosition := StrToFloat(eLabelPosition.PlainText);

  CatChart.ValueLabelVisible := cbValueLabels.Checked;
  CatChart.ValueFont.Assign(pnValueLabelFont.Font);
  CatChart.ValueLabelPosition := StrToFloat(eValueLabelPosition.PlainText);
  CatChart.ValueFormat := eValueLabelFormat.PlainText;

  inherited;

end;

end.
