Page 1 of 1

Is it possible to define a legend as a grid of Rows and Cols

Posted: Mon Mar 18, 2013 10:40 am
by 16464672
Hi

I am using the latest version of TeeChart Pro 2012 VCL on Delphi XE3.

Is it possible to define a legend as a grid of Rows and Cols. The text is too great and so I have to use a small font which is hard to read. Additionally if the application is resized the legend layout is lost and sprawls poorly across several lines (see images attached)

I was hoping to be able to define row and column headers and just have the appropriate coloured checkbox within; is this possible?

Many thanks in advance

Rob

Re: Is it possible to define a legend as a grid of Rows and Cols

Posted: Mon Mar 18, 2013 12:20 pm
by narcis
Hi Rob,

I'm not sure about what you mean with this:
I was hoping to be able to define row and column headers and just have the appropriate coloured checkbox within; is this possible?
Anyway, I'd recommend you to look at the custom legend tool demoed at the What's New?\Welcome!\New Chart Tools\Custom Legend example in the features demo, available at TeeChart's program group or the TChartGrid component at All Features\Welcome\Components\Chart Grid in the same demo.

If this doesn't fit your needs please give us more detailed information about what you are trying to achieve.

Thanks in advance.

Re: Is it possible to define a legend as a grid of Rows and Cols

Posted: Mon Mar 18, 2013 2:47 pm
by 16464672
Hi Narcis,

I was hoping to achieve something akin to this

Re: Is it possible to define a legend as a grid of Rows and Cols

Posted: Tue Mar 19, 2013 10:55 am
by 16464672
As can be seen in the very first image, the legend loses its neat layout with all associated legends no longer in a straight vertical line down (effectively a column), which is represented in the second image.

However there is a lot of repeated text, and I wondered if it was possible to combine a consistent fixed number of rows and columns with the checkbox to switch on graphed datasets.

Please advise if this is possible.

Many thanks

Rob

Re: Is it possible to define a legend as a grid of Rows and Cols

Posted: Wed Mar 20, 2013 5:01 pm
by yeray
Hi Rob,

Have you tried using the TCustomLegendTool as NarcĂ­s indicated?
I've made a quite complete example:

Code: Select all

  private
    { Private declarations }
    procedure DrawCustomLegend();
    procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
                                  Rect: TRect; State: TGridDrawState);
    procedure ClickTool(Sender:TAnnotationTool; Button:TMouseButton; Shift: TShiftState; X, Y: Integer);
//...
var
  CustomLegendTool : TCustomLegendTool;

  jobs  : Array[0..4] of string = ('Builders', 'Electricians', 'Gardeners', 'Mechanical', 'Painters');
  days  : Array[0..3] of string = ('Within 1 Day', 'Within 3 Day', 'Within 7 Day', 'More than 7 Days');
  colors: Array[0..4] of TColor;

procedure TForm1.FormCreate(Sender: TObject);
var
  i, j, d: Integer;
begin
  colors[0]:=rgb(226, 108, 10);
  colors[1]:=rgb(49, 133, 157);
  colors[2]:=rgb(118, 147, 57);
  colors[3]:=rgb(149, 54, 52);
  colors[4]:=rgb(128, 128, 128);

  CustomLegendTool := TCustomLegendTool.Create(Chart1);
  DrawCustomLegend();

  for j:=0 to length(jobs)-1 do
    for d:=0 to length(days)-1 do
    begin
      with Chart1.AddSeries(TBarSeries) as TBarSeries do
      begin
        Color:=ApplyBright(colors[j], 80-(d*20));
        XValues.DateTime:=true;
        BarStyle := bsBevel;

        Active:=j=1;

        for i:=0 to 3 do
          AddXY(IncMonth(MonthOf(Today), i) , 30 + random*130)
      end;
    end;

  CustomLegendTool.Height := 120;

  with Chart1 do
  begin
    Legend.Visible:=false;
    Title.Visible:=false;
    Axes.Bottom.DateTimeFormat:='MMMM';
    Axes.Bottom.LabelStyle:=talPointValue;
    MarginUnits:=muPixels;
    MarginTop:=CustomLegendTool.Height + 20;
  end;

  Chart1.Draw;
  CustomLegendTool.Left := (Chart1.Width div 2) - (CustomLegendTool.Width div 2);
end;

procedure TForm1.DrawCustomLegend();
var i: Integer;
begin
  with CustomLegendTool do
  begin
    ParentChart := Chart1;

    AllowDrag:=false;
    AllowResize:=false;

    with Shape do
    begin
      RoundSize := 15;
      Pen.Width:= 2;
      Font.Style := [fsItalic];
      ShapeStyle:=fosRectangle;
    end;

    Grid.OnDrawCell:=StringGrid1DrawCell;
    OnClick:=ClickTool;

    with Grid do
    begin
      ColCount := length(jobs)+1;
      RowCount := length(days)+1;
      for i:=0 to RowCount-1 do
        RowHeights[i] := 20;

      ColWidths[0] := 120;
      for i:=1 to ColCount-1 do
        ColWidths[i] := 80;

      Height := 105;
      Width := 526;
    end;
  end;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  seriesIndex: Integer;
begin
  if (ACol = 0) then
  begin
    if (ARow > 0) then
    begin
      with CustomLegendTool.Grid.Canvas.Font do
      begin
        Name := 'Arial';
        Size := 10;
      end;
      CustomLegendTool.Grid.Canvas.TextRect(Rect, Rect.Left+60, Rect.Top+1, days[ARow-1]);
    end;
  end
  else
  begin
    if (ARow = 0) then
    begin
      with CustomLegendTool.Grid.Canvas.Font do
      begin
        Name := 'Arial';
        Size := 10;
      end;
      CustomLegendTool.Grid.Canvas.TextRect(Rect, Rect.Left+35, Rect.Top+3, jobs[ACol-1]);
    end
    else
    begin
      seriesIndex:=(ARow-1) + length(days)*(ACol-1);
      CustomLegendTool.Grid.Canvas.Pen.Style:=psClear;
      CustomLegendTool.Grid.Canvas.Brush.Color:=Chart1[seriesIndex].Color;
      CustomLegendTool.Grid.Canvas.Rectangle(Rect);
      TeeDrawCheckBox(Rect.Left+39, rect.Top+3, CustomLegendTool.Grid.Canvas, Chart1[seriesIndex].Active, clWhite);
      CustomLegendTool.Grid.Canvas.Pen.Style:=psSolid;
      CustomLegendTool.Grid.Canvas.Brush.Color:=clNone;
    end;
  end;
end;

procedure TForm1.ClickTool(Sender:TAnnotationTool; Button:TMouseButton; Shift: TShiftState; X, Y: Integer);
var seriesIndex, nCol, nRow: Integer;
begin
  with CustomLegendTool.Grid do
    MouseToCell(X-ColWidths[0], Y-RowHeights[0], nCol, nRow);

  if (nCol > 0) and (nCol<CustomLegendTool.Grid.ColCount) and
     (nRow > 0) and (nRow<CustomLegendTool.Grid.RowCount) then
  begin
    seriesIndex:=(nRow-1) + length(days)*(nCol-1);
    Chart1[seriesIndex].Active:=not Chart1[seriesIndex].Active;
  end;
end;
customlegend.png
customlegend.png (21.33 KiB) Viewed 6834 times

Re: Is it possible to define a legend as a grid of Rows and Cols

Posted: Thu Mar 21, 2013 2:31 pm
by 16464672
:D My word Yeray, I think that is one of the most beautiful things I have ever seen, you should add that to your demos.

I will take your sample code and seek to make the same work in my applications.

Many many thanks

Rob

Re: Is it possible to define a legend as a grid of Rows and Cols

Posted: Thu Mar 21, 2013 2:45 pm
by yeray
Hi Rob,
redgar wrote::D My word Yeray, I think that is one of the most beautiful things I have ever seen, you should add that to your demos.
Thanks for the compliments, but the idea is actually yours :P
We'll take your word and we'll add it to the demos.