P&F Chart- function Series.Clicked always returns -1

TeeChart for ActiveX, COM and ASP
Post Reply
guilz2010
Newbie
Newbie
Posts: 63
Joined: Thu Nov 25, 2010 12:00 am
Location: Paris, France

P&F Chart- function Series.Clicked always returns -1

Post by guilz2010 » Fri Nov 04, 2011 1:58 pm

Hi
we are using Point and Figure Chart in our application
when the mouse is over a point, we want to display the X and Y series values of that point
we tryied to use the function AxTChart.Series(0).Clicked(e.x, e.y) in the AxTChart_OnMouseMove event
which should return the index of the point under the mouse, it works with fastline charts but it always return -1 with P&F charts

we also tried to use the event AxTChart_OnClickSeries but it is never raised with P&F chart
could you help?

thanks in advance

Yeray
Site Admin
Site Admin
Posts: 9602
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: P&F Chart- function Series.Clicked always returns -1

Post by Yeray » Fri Nov 04, 2011 3:32 pm

Hello,

I'm afraid there is not an override of the Clicked function for this series type so using it you are calling the Line series Clicked function.
I've added the possibility to add this override in the wish list to be implemented in future releases (TV52015818).
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

guilz2010
Newbie
Newbie
Posts: 63
Joined: Thu Nov 25, 2010 12:00 am
Location: Paris, France

Re: P&F Chart- function Series.Clicked always returns -1

Post by guilz2010 » Fri Nov 04, 2011 4:39 pm

Hi Yeray
thanks for your reply
can you provide us an alternative to the Clicked function? is there another way to display point detail using mouse events?

thanks in advance

Yeray
Site Admin
Site Admin
Posts: 9602
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: P&F Chart- function Series.Clicked always returns -1

Post by Yeray » Tue Nov 08, 2011 10:46 am

Hello,

Note this series has a quite particular drawing procedure and as things are right now, the points are drawn "on the fly" and not stored so a clicked method would repeat the majority of the code used to draw the series:

Code: Select all

var PointFigure1: TPointFigureSeries;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.View3D:=false;
  PointFigure1:=Chart1.AddSeries(TPointFigureSeries) as TPointFigureSeries;
  PointFigure1.FillSampleValues();
end;

function TForm1.Clicked(ASeries: TPointFigureSeries; XPos, YPos: Integer): Integer;
var tmpX, t, tmpCol, tmpColGroup: Integer;
    tmpDistance, tmpLow, tmpHigh, tmp: Double;
    tmpIsDown: Boolean;

  function calcRect(tmpX: Integer; tmpLow, tmpHigh: Double): TRect;
  begin
    with ASeries do
    begin
      Result.Left:=tmpX-Pointer.HorizSize;
      Result.Right:=tmpX+Pointer.HorizSize;
      Result.Top:=CalcYPosValue(tmpHigh)-Pointer.VertSize;
      Result.Bottom:=CalcYPosValue(tmpLow)+Pointer.VertSize;
    end;
  end;

begin
  result:=-1;

  with ASeries do
  begin
    tmpDistance:=ReversalAmount*BoxSize;

    tmpLow:=LowValues.Value[0];
    tmpHigh:=HighValues.Value[0];
    tmpCol:=0;
    tmpColGroup:=0;

    tmpX:=CalcXPosValue(tmpCol);
    if (PointInRect(calcRect(tmpX,tmpLow,tmpHigh), XPos, YPos)) then
    begin
      result:=0;
      exit;
    end;

    tmpIsDown:=True;

    for t:=1 to Count-1 do
    begin
      if tmpIsDown then
      begin
        tmp:=LowValues.Value[t];

        if tmp<=(tmpLow-BoxSize) then
        begin
          if (PointInRect(calcRect(tmpX,tmp,tmpLow-BoxSize), XPos, YPos)) then
          begin
            result:=t;
            exit;
          end;
          tmpLow:=tmp;
        end
        else
        begin
          tmp:=HighValues.Value[t];

          if tmp>=(tmpLow+tmpDistance) then
          begin
            Inc(tmpCol);
            tmpHigh:=tmp;
            tmpX:=CalcXPosValue(tmpCol);
            if (PointInRect(calcRect(tmpX,tmpLow+BoxSize,tmpHigh), XPos, YPos)) then
            begin
              result:=t;
              exit;
            end;
            tmpIsDown:=False;
            Inc(tmpColGroup);
          end;
        end;
      end
      else
      begin
        tmp:=HighValues.Value[t];
        if tmp>=(tmpHigh+BoxSize) then
        begin
          if (PointInRect(calcRect(tmpX,tmpHigh+BoxSize,tmp), XPos, YPos)) then
          begin
            result:=t;
            exit;
          end;
          tmpHigh:=tmp;
        end
        else
        begin
          tmp:=LowValues.Value[t];

          if tmp<=(tmpHigh-tmpDistance) then
          begin
            Inc(tmpCol);
            tmpLow:=tmp;
            tmpX:=CalcXPosValue(tmpCol);
            if (PointInRect(calcRect(tmpX,tmpLow,tmpHigh-BoxSize), XPos, YPos)) then
            begin
              result:=t;
              exit;
            end;
            tmpIsDown:=True;
            Inc(tmpColGroup);
          end;
        end;
      end;
    end;
  end;
end;

procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Chart1.Title.Text.Text:=IntToStr(Clicked(PointFigure1,X,Y));
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

guilz2010
Newbie
Newbie
Posts: 63
Joined: Thu Nov 25, 2010 12:00 am
Location: Paris, France

Re: P&F Chart- function Series.Clicked always returns -1

Post by guilz2010 » Tue Nov 22, 2011 10:48 am

Hi Yeray

Thanks for your reply
I actually implemented you Code in a VB.Net application:

Code: Select all

Private Function ClickedPF(ByVal Chart As AxTeeChart.AxTChart, ByVal XPos As Integer, ByVal YPos As Integer, ByRef text As String) As Integer

        Dim tmpX, i, tmpCol, tmpColGroup As Integer
        Dim tmpDistance, tmpLow, tmpHigh, tmp As Double
        Dim tmpIsDown As Boolean
        Dim result As Integer = -1

        Try

        
            With AxTChart.Series(0).asPointFigure

                tmpDistance = .ReversalAmount * .BoxSize
                tmpLow = .LowValues.First
                tmpHigh = .HighValues.First
                tmpCol = 0
                tmpColGroup = 0
                tmpX = AxTChart.Series(0).CalcXPosValue(tmpCol)
                If calcRect(tmpX, tmpLow, tmpHigh).Contains(XPos, YPos) Then
                    text = CStr(.HighValues.Value(0))
                    Return 0
                End If

                tmpIsDown = True
                For i = 1 To .DateValues.Count - 1
                    If tmpIsDown Then
                        tmp = .LowValues.Value(i)
                        If tmp <= (tmpLow - .BoxSize) Then
                            If calcRect(tmpX, tmp, tmpLow - .BoxSize).Contains(XPos, YPos) Then
                                text = CStr(.LowValues.Value(i))
                                Return i
                            End If
                            tmpLow = tmp
                        Else
                            tmp = .HighValues.Value(i)
                            If tmp >= (tmpLow + tmpDistance) Then
                                tmpCol = tmpCol + 1
                                tmpHigh = tmp
                                tmpX = AxTChart.Series(0).CalcXPosValue(tmpCol)
                                If calcRect(tmpX, tmpLow + .BoxSize, tmpHigh).Contains(XPos, YPos) Then
                                    text = CStr(.HighValues.Value(i))
                                    Return i
                                End If
                                tmpIsDown = False
                                tmpColGroup = tmpColGroup + 1

                            End If
                        End If
                    Else
                        tmp = .HighValues.Value(i)
                        If tmp >= (tmpHigh + .BoxSize) Then
                            If calcRect(tmpX, tmpHigh + .BoxSize, tmp).Contains(XPos, YPos) Then
                                text = CStr(.HighValues.Value(i))
                                Return i
                            End If
                            tmpHigh = tmp
                        Else
                            tmp = .LowValues.Value(i)
                            If tmp <= (tmpHigh - tmpDistance) Then
                                tmpCol = tmpCol + 1
                                tmpLow = tmp
                                tmpX = AxTChart.Series(0).CalcXPosValue(tmpCol)
                                If calcRect(tmpX, tmpLow, tmpHigh - .BoxSize).Contains(XPos, YPos) Then
                                    text = CStr(.LowValues.Value(i))
                                    Return i
                                End If
                                tmpIsDown = True
                                tmpColGroup = tmpColGroup + 1
                            End If
                        End If
                    End If


                Next
            End With
            Return result
        Catch ex As Exception

        End Try
    End Function


    Private Function calcRect(ByVal tmpX As Integer, ByVal tmpLow As Double, ByVal tmpHigh As Double) As Rectangle
        Dim size As Size
        Dim location As Point

        With AxTChart
            location.X = tmpX - Cursor.Size.Width
            location.Y = .Series(0).CalcYPosValue(tmpHigh) - Cursor.Size.Height
            size.Height = .Series(0).CalcYPosValue(tmpLow) - .Series(0).CalcYPosValue(tmpHigh) + 2 * Cursor.Size.Width
            size.Width = 2 * Cursor.Size.Width
        End With
        Return New Rectangle(location, size)

    End Function
the clickedPF function is called when chart_dblclick event is raised:

Code: Select all

Public Class Form1

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

        With AxTChart
            .AddSeries(TeeChart.ESeriesClass.scPointFigure)
            .Series(0).FillSampleValues()
        End With


    End Sub

Private Sub AxTChart_OnDblClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles AxTChart.OnDblClick

        Dim text As String = ""
        Cursor = Cursors.WaitCursor
        Dim MousePosInchart As Point
        MousePosInchart = AxTChart.PointToClient(New Point(MousePosition.X, MousePosition.Y))
        Dim index As Integer = ClickedPF(AxTChart, MousePosInchart.X, MousePosInchart.Y, text)
        Cursor = Cursors.Arrow
        If index <> -1 Then

            AxTChart.Repaint()
            AxTChart.Canvas.BackColor = System.Drawing.ColorTranslator.ToOle(Color.White)
            AxTChart.Canvas.Brush.Style = TeeChart.EBrushStyle.bsSolid
            AxTChart.Canvas.Pen.Color = System.Drawing.ColorTranslator.ToOle(Color.Red)
            AxTChart.Canvas.Brush.Color = System.Drawing.ColorTranslator.ToOle(Color.White)
            AxTChart.Canvas.TextOut(MousePosInchart.X + 10, MousePosInchart.Y, CStr(AxTChart.Series(0).asPointFigure.DateValues.Value(index)) & "  " & text)
        Else
            AxTChart.Repaint()
        End If

    End Sub

End Class
but it still doesn't work fine: the displayed value is the same for the whole column, although different point where clicked
and sometimes i get a value displayed even when i click outside the serie
i attached a screenshot with an example of the result i get

do you have any suggestions?

thanks in advance
P&F.png
Point and figure sample
P&F.png (26.73 KiB) Viewed 11004 times

Yeray
Site Admin
Site Admin
Posts: 9602
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: P&F Chart- function Series.Clicked always returns -1

Post by Yeray » Wed Nov 23, 2011 8:55 am

Hi Guilz,
guilz2010 wrote:the displayed value is the same for the whole column, although different point where clicked
The Clicked function gives different indexes and thus the example shows different values in a same column for me with the Delphi example I posted.
I haven't seen what could be but I guess it has to be a difference that is affecting the behaviour.
guilz2010 wrote:and sometimes i get a value displayed even when i click outside the serie
i attached a screenshot with an example of the result i get
I've seen in your calcRect function you use the Cursor.Size to calculate the rectangle width and height. I see in ActiveX you can't access to the asPointFigure.Pointer property (I'll add it to the wish list for future releases) but the values given by Cursor.Size may be wrong. I'd try using hardcoded values, for example 5 pixels width and height.

Just one tip: To test the rectangles calculated, you could draw them at the end of the Clicked function:

Code: Select all

    Chart1.Canvas.Rectangle(Result);
And call the Clicked function at OnAfterDraw event to have a more stable draw:

Code: Select all

procedure TForm1.Chart1AfterDraw(Sender: TObject);
begin
  Clicked(PointFigure1,0,0); //just for the rectangles drawing, the X and Y are irrelevant
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply