Recent

Author Topic: TChartGrid  (Read 18176 times)

wp

  • Hero Member
  • *****
  • Posts: 13630
TChartGrid
« on: November 18, 2011, 12:50:25 am »
In the attachment I am contributing an early version of a new component to the TAChart project, TChartGrid. This is a grid component that displays the data shown in the chart series. Usage is simple: add the grid to the form and assign its Chart property to the chart to be displayed. The grid will automatically construct columns. For changing the layout or formatting, modify the columns' properties in the object inspector (but: see below!), or, at runtime, use the OnPopulate event.

The attachment contains a runtime version which avoids installation of this component into the TAChart package. Several options of the user interface are available for playing around.

There is also a designtime demo project which, of course, requires the component to be installed.

Unfortunately, I am stuck with streaming issues which are responsible that the designtime demo does not work well. Nevertheless, I am posting this component at this buggy stage, because I hope that somebody is out there who knows more about the internals of the LCL than me.

The issue is as follows: The TChartGrid uses descendants of TGridColumn to display the series data (TChartGridColumn). Each column gets its data from the series via a descendant of "TCustomChartSeriesColumnLink" which knows about the data structure of the series and passes the data to the series in a standardized way. This "SeriesLink" is a polymorphic property of the column, i.e. depending on which type of series is selected, a different series-column-link class is created.

While this works well at run-time, the SeriesLink is not handled correctly by the object inspector, probably because the SeriesLink obviously is not streamed into the lfm file. I thought that it would be sufficient to derive a class from TPersistent or TComponent, and the LCL would take care of everything. Obviously, the LCL is confused by the fact that the class of the SeriesLink depends on the class of the corresponding series. Can anybody help me with that?

Another question concerns the display of the series icons. The ChartGrid unit contains a define USE_CHARTIMAGELIST which activates a TChartImageList that was recently added to TAChart. There were some concerns on performance issues due to unnecessary and frequent creation of bitmaps during population of the series. Therefore, I alternatively used TChartLegendItems to draw the icons onto the canvas directly -- deactivate USE_CHARTIMAGELIST to select this feature. However, the LegendItems's Draw method paints the icon along with the series name which does not allow positioning icon and title independently. So, how can I get the LegendItem to draw the series icon alone?

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TChartGrid
« Reply #1 on: November 19, 2011, 07:20:44 am »
My schedule is still extremely tight -- I have just returned from one conference and
will depart to another next week.
I have taken a very brief look at your code, even without compiling it yet.

Few notes:

1) This is rather large unit. In the current state, it is more than twice the size
of the largest TAChart unit. Please consider splitting it both space-wise (i.e. into maybe two units)
and time-wise (i.e. maybe first submit some simpler version with minimal functionality, and
then full version -- this will simplify review).

2) Part of the modifications you made may be ported to the basic grid code, or simplified by
changing it. Maybe those changes should be submitted there.

3) Continuing our discussion on TChartGrid vs TChartGridLink approaches, I see now that
you method is more powerful (for example, you can modify grid behavior), but mine
is probably simpler to implement.

Quote
This "SeriesLink" is a polymorphic property of the column, i.e. depending on which type of series is selected, a different series-column-link class is created.
This is a known limitation of LCL streaming methods. It can be circumvented by grouping
polymorphic objects into a separate collection class, overriding a few virtual methods
and providing custom design-time editor.
You can look, for example, at TChart itself -- it contains a list of polymorphic series.
Another example is chart transformations.


wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #2 on: November 27, 2011, 12:19:43 am »
Quote
This is rather large unit.
Yes it is. Lots of typing...

Now I split it into three units:
- TAChartAccess: implements the ancestor of all series links (TBasicSeriesLink) which interfaces to the series data. The links are collected by the TChartAccess component (is there a better name?). There is also a SeriesLinkfactory in the implementation part which stores information on how to create the correct series link for each series class. Note that this unit does not use anything of the ChartGrid. Therefore, it may be a basis for future data interfacing tasks.
- TAChartSeriesLinks: overrides the virtual methods introduced in TBasicSeriesLink to interface to the ChartSeries from which most of the TAChart series are derived. A link to TFuncSeries etc. which directly inherits from TCustomChartSeries might be handled accordingly, call RegisterSeriesLink to add it to the SeriesLinkFactory.
- TAChartGrid, finally. It's still quite long, though... I had split off a TBasicChartGrid into a separate unit which would handle the series links, but not the columns. But this saved only a few lines and added some additional complexity, so I put that functionality back.

Quote
This is a known limitation of LCL streaming methods. It can be circumvented by grouping polymorphic objects into a separate collection class, overriding a few virtual methods and providing custom design-time editor.
I took this advice and collected the series links in the ChartAccess component mentioned above. The TBasicSeriesLink class inherits from TIndexedComponent. I followed the examples in TATranformations and TATools, but still the streaming is not yet working. Everything works fine at run-time. But at design-time, the series links do not show up in the Object Inspector. In a previous version I had switched to TCollection and TCollectionItem which worked fine in the Object Inspector, but there were streaming errors as well since TCollection seems to create only a single class of items when reading the lfm. I failed to override the streaming mechanism of the collection. Therefore, I came back to TIndexedComponent and TIndexedComponentList. I must be overlooking something. Are there any methods that I forgot to override? Do I really need a design-time editor? I don't think so because the series links are not created by the user, but automatically when the chart is assigned to the ChartAccess component.

Any ideas would be gratefully appreciated.


wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #3 on: December 02, 2011, 12:09:37 am »
I am still fighting against the object inspector...

In the meantime, I found a missing call to RegisterClass for the descendants of TBasicSeriesLink. But still the same problem. I'll keep on fighting...

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TChartGrid
« Reply #4 on: December 03, 2011, 12:24:36 pm »
Yep, and I am still fighting to find some time to work on Lazarus :(

I can see you have submitted some changes to generic grids -- good work.

wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #5 on: December 04, 2011, 06:17:35 pm »
How can I trace into the code of TWriter? It is located in $(FPCSRCDIR)\rtl\objpas\classes\classesh.inc. I can see the code, but during run-time the debugger does not allow me to get there. What is the easiest way to temporarily compile the rtl with debug info?

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TChartGrid
« Reply #6 on: December 05, 2011, 06:33:43 am »
I am afraid you'll have to build debug versions yourself -- that is what I do.
Perhaps somebody has published pre-built debug units,
but I was unable to find them with a quick Google search.

wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #7 on: December 06, 2011, 12:45:54 pm »
Sorry to bother you again: How do I do that? In which package is Classes?

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687

wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #9 on: December 07, 2011, 10:46:18 pm »
Thank you. I knew this link before, but now decided to follow its instructions exactly. After some fails (the link ftp://ftp.freepascal.org/pub/fpc/dist/2.4.4/bootstrap/i386-win32-ppc386.zip mentioned points to nowhere) I managed to compile both fpc and lazarus from svn. Then I re-built fpc with the option -glw2 for the make command, hoping that this finally opens access to the debug info.

Code: [Select]
make clean all install INSTALL_PREFIX=%myFPC% PP=%mybinutils%\ppc386.exe DATA2INC=%myFPC%\utils\data2inc.exe -OPT="-glw2"

I do see that the size of classes.o has increased, but in my simple Lazarus test program I still cannot trace into the writer class.

What am I doing wrong?

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TChartGrid
« Reply #10 on: December 07, 2011, 10:59:59 pm »
You have specified dwarf2 debug info format.
Are you using this format for your test project as well?
Does "FPC source directory" from Lazarus options point
to the right version of FPC?

If the above does not help, I am afraid I do not know what is wrong --
maybe you can get more help by repeating this question on a separate thread.

wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #11 on: December 07, 2011, 11:37:18 pm »

wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #12 on: December 09, 2011, 11:57:45 pm »
After having made some progress with the fpc debugging issue I come back to the main streaming problem. Unfortunately, I can work on this topc only occasionally, so progress is quite slow...

I see now that the WriteState procedure of my TBasicSeriesLinks is never called when I stream the entire form; it is called, however, when I stream the ChartLink directly (that's the new name for the TChartAccess of a previous posting).

I think I follow your examples quite closely now. But still something is missing. I don't understand which mechanism causes streaming of the TIndexedComponentLists -- these are lists, no components, and therefore omitted by the usual streaming mechanism. Also, I don't understand why the series and tools behave differently in the Object Inspector: the series are children of the form, but the tools are children of the ToolSet.

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: TChartGrid
« Reply #13 on: December 10, 2011, 10:38:47 am »
Please post your latest code. I hope I'll have some time on Sunday.

wp

  • Hero Member
  • *****
  • Posts: 13630
Re: TChartGrid
« Reply #14 on: December 10, 2011, 01:28:07 pm »
Here it is - thank you.

 

TinyPortal © 2005-2018