zooming and dragging by code lazarus / 55-TAChart ---------------------------------------------------------------------- frederic · 2015-03-25 11:50 wp in the other thread "proper  xaxis'  we have defined a Xaxis minimum and an Xaxis maximum   . By zooming and dragging the area < X-axis min and /or  > Xaxismax becomes visible . I want to avoid that and i want to code following setup I am in the Xzoom mode.When i zoom my mousewheelup then we unzoom . When for instance a xaxis minimum is reached then there will be no zooming but a panning should start so that the xminimum is not there anymore.  This means that with the next movement of the mousewheel a zoom step will be done . So panning and zooming will follow after each other; that should be part of the Xzoom operation. The same setup can be used  for the Xaxismax When you are in the panningmode this stepwise changing between zooming and panning can be used as well This all needs panning and zooming ,now by coding My question is is this setup correct? Has this been tried before ( it is rather universal)  or am i trying to re-invent the wheel again. can i use the code from tatools for that without introducing other problems? frederic ---------------------------------------------------------------------- wp · 2015-03-25 12:28 Just try, I don't know. Chart tools do not fully prevent zooming/panning out of the data range (PanDragTool and PanClickTool: LimitToExtent). I would check the OnAfterXXXX events whether the full extent of the chart has been left and bring the extent back into the allowed range. Something like this (not tested...) Code: [Select]procedure TForm1.EnsureExtent; // This procedure makes sure that no edge of the currently visible window ("LogicalExtent") can leave the window defined by the unzoomed/unpanned data range ("FullExtent") var   ext, fullext: TDoubleRect;   delta: Double; begin   ext := Chart.LogicalExtent;   fullext := Chart.GetFullExtent;   if ext.a.x < fullext.a.x then begin     delta := ext.b.x - ext.a.x;     ext.a.x := fullext.a.x;     ext.b.x := ext.a.x + delta;   end;   if ext.b.x > fullext.b.x then begin     delta := ext.b.x - ext.a.x;     ext.b.x := fullext.b.x;     ext.a.x := ext.b.x - delta;   end;   // ... the same with the y coordinates...   Chart.LogicalExtent := ext; end; procedure TForm1.MouseWheelZoomToolAfterMouseWheelUp(...); begin   // ... your code   EnsureExtent; end; ---------------------------------------------------------------------- frederic · 2015-03-25 15:33 wp QuoteI would check the OnAfterXXXX events whetherWhat did mean here? your setup looked a lot less complicated then the mine for panning it was oke. With zooming however you have to prevent that the correction of ,for instance the maxextent  ,stops long before you have a violation of the minextent . the corrected code: Code: [Select]procedure TForm1.EnsureExtent; // This procedure makes sure that no edge of the currently visible window ("LogicalExtent") can leave the window defined by the unzoomed/unpanned data range ("FullExtent") var   ext: TDoubleRect;   delta, correctionstepsmin,correctionstepsmax:Double;   Ffullext,fullwidth:double; begin   ext := Chart1.LogicalExtent;   Ffullext := Chart1.GetFullExtent;   fullwidth:= Ffullext.b.x  -   Ffullext.a.x ;   if ext.a.x < Ffullext.a.x then begin      delta := ext.b.x - ext.a.x;      ext.a.x := Ffullext.a.x;     if delta fullwidth/4 ') ;       ext.b.x := Ffullext.a.x + delta;     end ;//else correctminimum:=false;   end ;   if ext.b.x > Ffullext.b.x then begin   delta := ext.b.x - ext.a.x;   ext.b.x := Ffullext.b.x;     if delta < fullwidth/4 then  // we correct till  we have an overshoot of 1/4 the full size     begin          memo1.lines.add('maximum violated delta< fullwidth/4') ;         ext.a.x := Ffullext.b.x - delta;     end;   end; end;          and that worked frederic ---------------------------------------------------------------------- wp · 2015-03-25 15:41 Quote from: frederic on March 25, 2015, 04:33:10 pmQuoteI would check the OnAfterXXXX events whetherWhat did mean here? When you are panning/zooming with the scrollbar, then you use the ScrollbarPan/ZoomTools. They have events OnAfterMouseWheelUp/Down where you call the EnsureExtent method. Or, in case of the PanDrag/ZoomTools you use the event OnAfterMouseMove, etc. Quote from: frederic on March 25, 2015, 04:33:10 pmand that workedFine ---------------------------------------------------------------------- frederic · 2015-03-26 09:27 wp Strange situation. Yesterday i did test the above code a number of times and it worked perfectly as i reported. I transferred it to other projects and it was not functioning anymore especially with zooming. there is  one is issue and that is when you start with the chart in fullextent then the code is stuck .So you need to start with a fraction of the fullextent on an chosen or arbritrary position. The other applications have charts besides each other ,so not full screen as i tested. So i decided to retest this morning the project from whch i reported that it was oke. Same settings ,just start and it didn't function anymore !.........??? any idea where to look after? frederic ---------------------------------------------------------------------- wp · 2015-03-26 10:04 Quoteany idea where to look after?What else did you change? ---------------------------------------------------------------------- frederic · 2015-03-26 14:28 wp In the testproject, i used yesterday to test the code i presented ,nothing(i am awareof) has changed. I copied the EnsureExtent procedure and closed the testproject .This morning i started  it up and ran it. But of course something must have change to cause this difference in behaviour. Therefore i looked further and tried rebuild again on the basis of the latest testproject. There is something peculiar happening with the size of the fullextent of the X-axis  while setting of the separation lines of the pane . see the attached screenpicture .I loaded the testproject ---------------------------------------------------------------------- frederic · 2015-03-26 14:31 oh ,i forgot the printtscreen frederic ---------------------------------------------------------------------- wp · 2015-03-26 21:48 Mysterious, I do not know why it worked in the old version... Anyway, it must be related to the "SetLower/UpperSeparatorLines" which sets up the pane infrastructure. The chart displays fine again, if "UpdateAxisLabels" is called at least after the first one of these two methods - just put "UpdateAxisLabels" at the end of "makeChart", that's where I would expect it anyway (in "makechartBtnClick" it is called after the "SetXXXSeparatorLines"). I saw with heaptrc that your program creates a memory leak because the ZoomHistory is not destroyed. Add an OnDestroy handler to the form in which you call "ZoomHistory.Free". (Sorry - this bug was introduced in my own code in the other thread). Next time when you upload projects please add also the lpi file to the zip package, it is easier for me to start the project if it is complete, and there may be errors in there as well. [EDIT] I see now that the old version had a similar issue (a lot of vertical grid lines) which went away after adding "UpdateAxisLabels" to the end of "makechart". I still don't understand how it relates to the "SetXXXSeparatorLines", but I won't investigate much because it is not related directly to TAChart code. ---------------------------------------------------------------------- frederic · 2015-03-27 08:05 thanks wp, we investigate further,till next time frederic ---------------------------------------------------------------------- frederic · 2015-03-27 15:27 wp another strange thing ,now the other way round in my application i changed the code in the procedure 'prepareaxis' by using yhe extentlimit properties and it worked .I could even do  without the 'ensureextent' procedure. so i wanted to show it to this forum : Code: [Select]procedure TForm1.PrepareAxis; var   extent: TDoubleRect;  // needs TAChartUtils begin   // Properties of ChartNavScrollbar (can be set also in Object Inspector)   ChartNavScrollbar1.Align := alBottom;   ChartNavScrollbar1.Min := 0;   ChartNavScrollbar1.Max := 1000;  // determines smoothness of zooming   ChartNavScrollbar1.AutoPageSize := true;  // avoid scrolling past the end of the data   chart1.prepare;   // Zoom in such that 5 working days are visible   Chart1.extentsizelimit.UseXMax:=true;   Chart1.extentsizelimit.UseXmin:=true;   Chart1.extentsizelimit.XMax:=ConvertBARNumberToDaysPassed(TOTNUMLINE S);   Chart1.extentsizelimit.Xmin:=0;   extent.a.X := ConvertBARNumberToDaysPassed(NUM_LINES-200); arbritrary position   extent.b.X := ConvertBARNumberToDaysPassed(NUM_LINES-1);   //extent := Chart1.GetFullExtent;  // unzoomed data rectangle   //extent.a.X := extent.b.X - 1;    // move 5 days before the end of the x axis   Chart1.LogicalExtent := extent;   Chart1.Prepare; end;                  but this didn't work in the last uploaded project . I leave it now for the moment and wait for the  lazarus 1.4 release ( which should be there within a month ) . frederic ---------------------------------------------------------------------- wp · 2015-03-27 16:11 Of course, this cannot work because you have a local variable "extent" which is not initialized properly: you do assign values to the a.x and b.x elements, but the y elements are unassigned. You must call Chart.GetFullExtent first. And you must do this after data are loaded into the series (i.e. after "makeChart") because otherwise the chart does not know the y values... The sequence of operations in your program for chart creation (data loading -> xaxis creating -> y axis actions -> series creation ...) is a bit weird and probably causes a lot of your trouble. Why don't you do it like this: - load file into arrays - add series to the chart - construct the x labels - construct the y panes - prepare visible window (LogicalExtent) Be careful with "ExtentSizeLimit". Look at the "Size" in this name: it means that the *Size* of the extent cannot be greater than these limits, but if the extent is smaller it is still possible to pan the logical extent out of the full extent range! ---------------------------------------------------------------------- frederic · 2015-03-27 21:09 wp the original reason this sequence was chosen was the requirement to have an x-axis would go beyond the x values of the index and stoch1/stoch2 graphs. In fact the X-axisseries was created first with an Y value of 0 and now added up with the other series  in the procedure makeXaxis. PrepareAxis is deleted  and that works and looks far more stable than before! QuoteBe careful with "ExtentSizeLimit". Look at the "Size" in this name: it means that the *Size* of the extent cannot be greater than these limits, but if the extent is smaller it is still possible to pan the logical extent out of the full extent range oh, i  misinterpreted this thanks again we keep learning frederic ---------------------------------------------------------------------- wp · 2015-03-27 21:24 BTW: What is the xaxisseries for? In my opinion it is not needed,  the axis labels are stored in dedicated ListChartSources (TimeChartSource, DateTimeSource) from which the two bottom axes get them. QuoteExtentSizeLimitYou're not alone, I myself got caught in this trap many times. ---------------------------------------------------------------------- frederic · 2015-03-28 11:21 wp QuoteBTW: What is the xaxisseries for? In my opinion it is not needed,  the axis labels are stored in dedicated ListChartSources (TimeChartSource, DateTimeSource) from which the two bottom axes get them. but I want to see the axis labels also beyond the max X-axis value of all the other series.Therefore I constructed this "Ghost- series" . Code: [Select] Xaxisseries.AddXY(days, y, s); but it artificial but i could't find a more elegant way frederic