unit FMXTee.Editor.DBChart;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMXTee.Editor.DB, FMX.Edit,
  FMX.Layouts, FMX.ListBox;

type
  TDBChartEditor = class(TDBSourceEditor)
    GroupFields: TLayout;
    LLabels: TLabel;
    CBLabelsField: TComboEdit;
    procedure CBLabelsFieldChange(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure BApplyClick(Sender: TObject);
    procedure CBSourcesChange(Sender: TObject);
  private
    { Private declarations }
    const MaxValueSources=16;
  private
    LabelValues : Array[0..MaxValueSources-1] of TLabel;
    CBDateTime  : Array[0..MaxValueSources-1] of TCheckBox;

    procedure CBValuesChange(Sender: TObject);
    procedure RefreshFields;
    Procedure SetFields;
    Procedure SetTextItemIndex(Combo:TComboEdit);
  protected
    Function IsValid(AComponent:TComponent):Boolean; override;
  public
    { Public declarations }
    CBValues : Array[0..MaxValueSources-1] of TComboEdit;

    procedure Translate; override;
  end;

implementation

{$R *.fmx}

uses
  FMXTee.Engine, FMXTee.DBChart, FMXTee.Editor.DBSource,
  FMXTee.Editor.DBSummary, FMXTee.Constants, Data.DB, FMXTee.Procs;

type
  TDataSetSeriesSource=class(TTeeSeriesDBSource)
  public
    class Function Description:String; override;
    class Function Editor:TComponentClass; override;
    class Function HasSeries(ASeries:TChartSeries):Boolean; override;
  end;

procedure TDBChartEditor.BApplyClick(Sender: TObject);

  Procedure CheckFieldIsBlank(Const AFieldName:String);
  begin
    if AFieldName<>'' then
       Raise ChartException.CreateFmt(TeeMsg_FieldNotFound,[AFieldName]);
  end;

  Procedure CheckValidFields;
  var t : Integer;
  begin
    for t:=0 to TheSeries.ValuesList.Count-1 do
    With CBValues[t] do
    begin
      SetTextItemIndex(CBValues[t]);

      if ItemIndex=-1 then
         CheckFieldIsBlank(Text);
    end;

    SetTextItemIndex(CBLabelsField);

    With CBLabelsField do
    if ItemIndex=-1 then CheckFieldIsBlank(Text);
  end;

var t : Integer;
begin
  inherited;

  if Assigned(TheSeries) then
  With TheSeries do
  begin
    DataSource:=nil;
    try
      CheckValidFields;

      for t:=0 to ValuesList.Count-1 do
      With ValuesList[t] do
      begin
        ValueSource:=CBValues[t].Text;
        DateTime:=CBDateTime[t].IsChecked;
      end;

      XLabelsSource:=CBLabelsField.Text;
    finally
      DataSource:=DataSet;
    end;
  end;

  BApply.Enabled:=False;
end;

procedure TDBChartEditor.CBLabelsFieldChange(Sender: TObject);
begin
  inherited;
  BApply.Enabled:=True;
end;

procedure TDBChartEditor.CBSourcesChange(Sender: TObject);
begin
  inherited;

  if not IChanging then
     SetFields;
end;

procedure TDBChartEditor.CBValuesChange(Sender: TObject);
var tmpField : TField;
begin
  With TComboEdit(Sender) do
  if ItemIndex<>-1 then
  begin
    tmpField:=DataSet.FindField(Items[ItemIndex]);
    CBDateTime[Tag].IsChecked:=Assigned(tmpField) and
                             (TeeFieldType(tmpField.DataType)=tftDateTime);
  end;

  BApply.Enabled:=True;
end;

procedure TDBChartEditor.FormActivate(Sender: TObject);
begin
  inherited;
  RefreshFields;
end;

procedure TDBChartEditor.RefreshFields;
var t       : Integer;
    tmpName : String;
begin
  inherited;

  if Assigned(TheSeries) then
  begin
    With TheSeries do
    for t:=0 to ValuesList.Count-1 do
    begin
      tmpName:=ValuesList[t].Name;

      CBValues[t]:=TComboEdit.Create(Self);

      With CBValues[t] do
      begin
        Position.X:=CBLabelsField.Position.X;
        HelpContext:=178;
        Width:=CBLabelsField.Width;
        Position.Y:=2+CBLabelsField.Position.Y+CBLabelsField.Height+((CBValues[t].Height+4)*t+1);
        OnChange:=CBValuesChange;
        Tag:=t;
        Parent:=GroupFields;
        Visible:=tmpName<>'';
      end;

      LabelValues[t]:=TLabel.Create(Self);

      With LabelValues[t] do
      begin
        TextAlign:=TTextAlign.taTrailing;
        Parent:=GroupFields;
        Position.Y:=CBValues[t].Position.Y+4;
        Text:=tmpName+':';  // Do not localize
        Visible:=tmpName<>'';

        //AutoSize:=False;  5.03 , Japanese
        AutoSize:=True; // 6.0 fix ""
        Position.X:=LLabels.Position.X; //+LLabels.Width-Width;

        if ValuesList[t]=MandatoryValueList then
           Font.Style:=[TFontStyle.fsBold];
      end;

      CBDateTime[t]:=TCheckBox.Create(Self);

      With CBDateTime[t] do
      begin
        Parent:=GroupFields;
        Position.X:=CBLabelsField.Position.X+CBLabelsField.Width+6;
        Position.Y:=CBValues[t].Position.Y;
        HelpContext:=178;
        Text:=TeeMsg_DateTime;
        Width:=Canvas.TextWidth(Text + 'www'); // Do not localize
        Tag:=t;
        Visible:=tmpName<>'';
        OnClick:=CBLabelsFieldChange;
      end;
    end;

    SetFields;
  end;

  BApply.Enabled:=False;
end;

Procedure TDBChartEditor.SetTextItemIndex(Combo:TComboEdit);
var tmp : Integer;
begin
  With Combo do
  begin
    tmp:=Items.IndexOf(Text);
    if tmp<>ItemIndex then ItemIndex:=tmp;
  end;
end;

procedure AddItem(ACombo:TComboEdit; const S:String);
begin
  ACombo.Items.Add(S);
end;

Procedure TDBChartEditor.SetFields;

  Procedure FillFields;

    Procedure AddField(Const tmpSt:String; tmpType:TFieldType);
    Var t : Integer;
    begin
      Case TeeFieldType(tmpType) of
      tftNumber,
     tftDateTime: begin
                    AddItem(CBLabelsField,tmpSt);
                    for t:=0 to TheSeries.ValuesList.Count-1 do
                        AddItem(CBValues[t],tmpSt);
                  end;
         tftText: AddItem(CBLabelsField,tmpSt);
      end;
    end;

  Var t : Integer;
  Begin
    With DataSet do
    if FieldCount>0 then
       for t:=0 to FieldCount-1 do
           AddField(Fields[t].FieldName,Fields[t].DataType)
    else
    begin
      FieldDefs.Update;
      for t:=0 to FieldDefs.Count-1 do
          AddField(FieldDefs[t].Name,FieldDefs[t].DataType);
    end;
  end;

var t : Integer;
begin
  CBLabelsField.ListBox.Clear;
  CBLabelsField.Enabled:=CBSources.ItemIndex<>-1;

  for t:=0 to TheSeries.ValuesList.Count-1 do
  With CBValues[t] do
  begin
    ListBox.Clear;
    Enabled:=CBLabelsField.Enabled;
  end;

  if CBSources.ItemIndex<>-1 then FillFields;

  With CBLabelsField do ItemIndex:=Items.IndexOf(TheSeries.XLabelsSource);

  With TheSeries.ValuesList do
  for t:=0 to Count-1 do
  begin
    With CBValues[t] do ItemIndex:=Items.IndexOf(ValueList[t].ValueSource);
    CBDateTime[t].IsChecked:=ValueList[t].DateTime;
  end;
end;

Function TDBChartEditor.IsValid(AComponent:TComponent):Boolean;
begin
  result:=AComponent is TDataSet;
end;

procedure TDBChartEditor.Translate;
var tmpArray : Array of TFmxObject;
    t        : Integer;
begin
  if Assigned(TheSeries) then
     SetLength(tmpArray, TheSeries.ValuesList.Count+1)
  else
     tmpArray:=nil;

  try
    if Assigned(TheSeries) then
    begin
      tmpArray[0]:=CBLabelsField;

      for t:=0 to TheSeries.ValuesList.Count-1 do
          tmpArray[t+1]:=CBValues[t];
    end;

    TeeTranslateControl(Self, tmpArray);
  finally
    tmpArray:=nil;
  end;
end;


{ TDataSetSeriesSource }
class function TDataSetSeriesSource.Description: String;
begin
  result:=TeeMsg_DataSet;
end;

class function TDataSetSeriesSource.Editor: TComponentClass;
begin
  result:=TDBChartEditor;
end;

class function TDataSetSeriesSource.HasSeries(ASeries: TChartSeries): Boolean;
begin
  result:=(ASeries.DataSource is TDataSet) and
          (Copy(ASeries.MandatoryValueList.ValueSource,1,1)<>'#'); // Do not localize
end;

initialization
  TeeSources.Add(TDataSetSeriesSource);
finalization
  TeeSources.Remove(TDataSetSeriesSource);
end.
