Recent

Author Topic: TAChart: Series icons  (Read 15157 times)

wp

  • Hero Member
  • *****
  • Posts: 11923
TAChart: Series icons
« on: June 18, 2011, 09:41:52 pm »
@ask:
Could you please add a the following public method to TBasicChartSeries? This method, DrawSeriesIcon, would enable population of an TImageList with the icon of each series. The imagelist could be used in further controls for series selection (Listbox, Listview etc.).

This is my proposed code:
Code: [Select]
procedure TBasicChartSeries.DrawSeriesIcon(ADrawer:IChartDrawer; const ARect:TRect);
var
  legItems : TChartLegendItems;
  i : integer;
begin
  legItems := TChartLegendItems.Create;
  try
    GetLegendItemsBasic(legItems);
    for i:=0 to legItems.Count-1 do
      (legItems[i] as TLegendItem).Draw(ADrawer, ARect);
  finally
    legItems.Free;
  end;
end; 

For those interested, this would be the code to populate the imagelist with the series icons:
Code: [Select]
procedure PopulateSeriesImageList(AChart: TChart; AImageList:TImageList);
var
  drawer: IChartDrawer;
  bmp : TBitmap;
  R : TRect;
  i : integer;
begin
  AImageList.Clear;
  bmp := TBitmap.Create;
  try
    bmp.Width := AImageList.Width;
    bmp.Height := AImageList.Height;
    R := Rect(0, 0, bmp.Width, bmp.Height);
    bmp.Canvas.Brush.Color := clWindow;
    drawer := TCanvasDrawer.Create(bmp.Canvas);
    for i:=0 to AChart.SeriesCount-1 do
    begin
      bmp.Canvas.FillRect(R);
      AChart.Series[i].DrawSeriesIcon(drawer, R);
      AImageList.Add(bmp, nil);
    end;
  finally
    bmp.Free;
  end;
end;       

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TAChart: Series icons
« Reply #1 on: June 22, 2011, 04:17:59 pm »
Sorry for delayed reply -- missed your post.
The method you propose is not quite correct, since there is no guarantee
that there is exactly one legend item per series.
Instead, I have implemented TChart.GetLegendItems function
(and TChartLegend.MeasureItem helper in case you need to estimate item size).
Also, I have added combobox with legend items to the legend demo since r31335

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #2 on: June 22, 2011, 04:43:21 pm »
Thank you - this helps a lot.

Quote
...there is no guarantee that there is exactly one legend item per series.
I'm a bit confused: how can this be? How can I create two legend entries for the same series? If I'd want to plot the same data twice my understanding was to use a datasource attached to both series.

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TAChart: Series icons
« Reply #3 on: June 22, 2011, 06:37:25 pm »
How can I create two legend entries for the same series?

Currently -- by either setting Legend.Multiplicity to lmPoint or using user-drawn legend,
both of which are demonstrated in legend demo. I plan to add other multiplicity values --
for example, an item per stack level in stacked series.


wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #4 on: June 23, 2011, 12:06:43 pm »
Thanks again. I am impressed by the complexity of TAChart.

Maybe I am wrong, but there seems to be a weakness of legenditems being independent of series: how can I get the icon of a series which is inactive and therefore not displayed in the legend? One reason for wanting to do this could be using the series icons in a TCheckedListbox for quickly turning on and off of series, such as Delphi's TChartListbox. Of course, I could temporarily turn on all series, extract the icon of the hidden series and then turn the inactive series back off again. But this seems to be a bit cumbersome. Wouldn't it be better to have the LegendItems as a member of TBasicSeries?

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #5 on: June 24, 2011, 02:12:10 pm »
Please ignore my previous post - after looking into the sources in more detail I found out that the LegendItems are defined by the series, just as I though it should be.

But the issue with the inactive series still is still existing. Could you add a parameter "AllSeries:boolean=false" to the new method TChart.GetLegendItems in order to be able to include all series in the legend items list?

Code: [Select]
function TChart.GetLegendItems(AllSeries:boolean=false): TChartLegendItems;
var
  i: Integer;
begin
  Result := TChartLegendItems.Create;
  try
    for i := 0 to SeriesCount - 1 do
      with Series[i] do
        if (Active and GetShowInLegend)
           or AllSeries // new
        then
          GetLegendItemsBasic(Result);
  except
    FreeAndNil(Result);
    raise;
  end;
end;

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TAChart: Series icons
« Reply #6 on: June 24, 2011, 03:42:28 pm »
Heh, I have almost added this parameter first time -- then decided to wait for feedback.
Turns out my plan was correct ;-)

Added in r31359.
I have credited you in the commit message as "Werner",
since this is how you signed some of you messages.
If you want different name, please let me know.

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #7 on: June 24, 2011, 03:46:41 pm »
Thank you

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #8 on: July 04, 2011, 12:09:29 pm »
Hi, beginning to implement a TChartListbox (a TCheckListbox descendant for turning on and off of series) I got stuck since I do not know the series to which a LegendItem belongs.

Code: [Select]
procedure TChartListbox.Populate;
var
  i : integer;
begin
  try
    FreeAndNil(FLegendItems);
    Items.BeginUpdate;
    Items.Clear;
    if (FChart <> nil) then begin
      FLegendItems := FChart.GetLegendItems(true);
      for i:=0 to FLegendItems.Count-1 do begin
        Items.AddObject(FLegendItems[i].Text, FLegendItems[i]);
        //Checked[i] := FLegendItems[i].Series.Visible;
        // not possible, since TLegendItem forgot the series where it came from
      end;
    end;
  finally
    Items.EndUpdate;
  end;
end;

Could you add a series field to the definition of TLegendItem? Or is there another way to get the series which belongs to a given LegendItem?

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TAChart: Series icons
« Reply #9 on: July 04, 2011, 02:01:32 pm »
Quote
Could you add a series field to the definition of TLegendItem?

Added Owner field in r31557. It is of the base type, since otherwise
a circular reference would be introduced.

However, with multiple items per legend, TChartListBox would look strange.
I have implemented TCustomChartSeries.GetSingleLegendItem in r31556.

If you are planning to submit TChartListBox for inclusion, please consider the possibility
of using it in design-time series editor.

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #10 on: July 05, 2011, 12:32:44 pm »
Thank you.

Now I have to assign the series to the new owner property. Is this the correct place?

Code: [Select]
procedure TCustomChartSeries.GetLegendItemsBasic(AItems: TChartLegendItems);
var
  i, oldCount: Integer;
begin
  oldCount := AItems.Count;
  if Assigned(Legend.OnDraw) then
    for i := 0 to Legend.UserItemsCount - 1 do
      AItems.Add(TLegendItemUserDrawn.Create(i, Legend.OnDraw, Title))
  else
    GetLegendItems(AItems);
  for i := oldCount to AItems.Count - 1 do begin
    AItems[i].Owner := self;              // <---  new
    Legend.InitItem(AItems[i], i - oldCount, FChart.Legend);
  end;
end;   

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TAChart: Series icons
« Reply #11 on: July 05, 2011, 04:14:39 pm »
I do not quite understand. Does it not work already?

Also, since you can now get a single item from series, you can write a loop
over series, like you wanted at the beginning.

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #12 on: July 05, 2011, 06:09:14 pm »
Thank you once more - I did not understand why you introduced the GetSingleLegendItem because you had discussed multiple legend items before. This is working now. However, there's another issue with notification - but I'll open a separate thread for that.

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TAChart: Series icons
« Reply #13 on: July 05, 2011, 09:11:29 pm »
Going back to your answer of July 04: yes - I'd like to donate the component once it is finished. There are some issues left, though.

Anyway: why should the component be used in the design-time series editor? It is just a supplementary component, e.g. like the TChartLegendPanel.

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TAChart: Series icons
« Reply #14 on: July 06, 2011, 07:00:13 am »
Quote
Anyway: why should the component be used in the design-time series editor?

It is not a requirement, of course, but I think it would be logical.
See, for example, documentation for similar Delphi/TeeChart component:
http://www.berneda.com/TeeChart6Docs/TCHARTLISTBOX.html

Note that I am NOT asking you to modify series editor,
just to consider it and design your API with this possibility in mind.

 

TinyPortal © 2005-2018