Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make charts interactive #18

Open
iwbnwif opened this issue Apr 18, 2017 · 5 comments
Open

Make charts interactive #18

iwbnwif opened this issue Apr 18, 2017 · 5 comments
Assignees
Milestone

Comments

@iwbnwif
Copy link
Owner

iwbnwif commented Apr 18, 2017

There has been some work on making charts interactive, but this needs to be completed.
The minimum requirement is to show a tooltip with the precise values when the user hovers the mouse over a specific data point.

@iwbnwif iwbnwif self-assigned this Apr 18, 2017
@iwbnwif iwbnwif added this to the 2.0 milestone Apr 18, 2017
iwbnwif added a commit that referenced this issue Apr 18, 2017
…rder. Fixes #14.

Also, some minor changes to axis label presentation as part of the work to addres #18.
iwbnwif added a commit that referenced this issue Apr 19, 2017
…onjunction with dc.DrawRectangle, 1 needs to be subtracted.

This is because rect.x + rect.width != rect.right (in fact it equals rect.right + 1)

A better fix for #18.
@psychegr
Copy link

I see that you have changed the mousevents handling in the code. Do you have a code example to enable tooltips? I would like to give it a go with changing the points on the plot using the mouse.

@iwbnwif
Copy link
Owner Author

iwbnwif commented May 27, 2017

I had a very simple version working, but it is disable for now due to the change in the dataset structure.

Look at the bottom of axisplot.cpp and you will see the code I had in before. You simply need to override OnMouseMove in any class derived from Plot to start getting mouse events (hopefully!).

My code did a brute force search of all datasets to see if any datapoint is near the mouse cursor. As soon as it found one that was within a threshold, the handler called SetTipData with the text to be displayed.

@psychegr
Copy link

Following your old method, i adapted it to work with the new dataset. Here is the new code :

void XYPlot::OnMouseMove(wxMouseEvent& event)
{
	for (size_t set = 0; set < GetDatasetCount(); set++)
    {
    	BiDataSet* dataset = wxDynamicCast(GetDataset(set), BiDataSet);

        NumberAxis* xAxis = static_cast<NumberAxis*>(GetDatasetAxis(dataset, false));
        NumberAxis* yAxis = static_cast<NumberAxis*>(GetDatasetAxis(dataset, true));

        for (size_t ser = 0; ser < dataset->GetSeriesCount(); ser++)
        {
            DataSeries* series = dataset->GetSeries(ser).get();

            wxMemoryDC dummy;

            double x = xAxis->ToData(dummy, m_rect.x, m_rect.GetWidth(), event.GetPosition().x);
            double y = yAxis->ToData(dummy, m_rect.y, m_rect.GetHeight(), event.GetPosition().y);

            for (size_t pt = 0; pt < series->GetSize(); pt++)
            {
                BiDataPoint* point = wxDynamicCast(series->GetPoint(pt).get(), BiDataPoint);
                double fi = point->first.As<double>();
                double se =  point->second.As<double>();
                if (fi < x + 5 && fi > x - 5 &&
                    se < y + 5 && se > y - 5)
                {
                	wxLogMessage("Got a point in Dataset: %d, Series: %d, Point Index: %d, at Point (x,y): %g, %g",set, ser, pt, fi, se);

			SetTipData(wxString::Format("x : %g\ny : %g", fi, se));
			return;
                }
            }
        }
    }
}

It seems to work quite nice, but it seems that there is an "offset" on the points that the tooltips are displayed. Maybe it is that the +5, -5 values are too high? I will do some more tests and report back. Also the when moving the mouse around the tooltip flickers. Maybe it has to do with the wxMemoryDC or something.

@psychegr
Copy link

Working a little bit more on the "interactivity" here is a code snippet that i use to drag points.
I am using it in the OnMouseMove event and i check if the event.Dragging is true.

if (event.Dragging())
{
	for (size_t set = 0; set < GetDatasetCount(); set++)
	{
		BiDataSet* dataset = wxDynamicCast(GetDataset(set), BiDataSet);

		NumberAxis* xAxis = static_cast<NumberAxis*>(GetDatasetAxis(dataset, false));
		NumberAxis* yAxis = static_cast<NumberAxis*>(GetDatasetAxis(dataset, true));

		for (size_t ser = 0; ser < dataset->GetSeriesCount(); ser++)
		{
			DataSeries* series = dataset->GetSeries(ser).get();

			wxMemoryDC dummy;

			double x = xAxis->ToData(dummy, m_rect.x, m_rect.GetWidth(), event.GetPosition().x);
			double y = yAxis->ToData(dummy, m_rect.y, m_rect.GetHeight(), event.GetPosition().y);

			for (size_t pt = 0; pt < series->GetSize(); pt++)
			{
				BiDataPoint* point = wxDynamicCast(series->GetPoint(pt).get(), BiDataPoint);
				double fi = point->first.As<double>();
				double se = point->second.As<double>();
				
				// drag a point vertically
				// maybe add a couple flags to enable dragging horizontaly or vertically or both
				if ((fi > x - 0.5) && (fi < x + 0.5))
				{
					point->SetValues(fi, y);
					dataset->DatasetChanged();
					return;
				}
			}
		}
	}
}

I hope that this will help enough to properly implement a "dragging" feature.

@iwbnwif
Copy link
Owner Author

iwbnwif commented Jun 2, 2017

Hi, I think that this is okay, but it would be better to somehow capture the point once dragging has started otherwise if you drag the point near another point it may jump and start dragging the other point instead. Also, this would avoid searching all the datasets on every mouse move.

Therefore, I would suggest using both OnMouseDown (not yet implemented!!) and OnMouseMove in future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants