Support mouse gestures when active tracing is enabled (#1064)
* Make the pointer follow the mouse * Only render when necessary * Move trace rendering to background thread
This commit is contained in:
		@@ -93,11 +93,19 @@ namespace GraphControl
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (auto renderer = m_graph->GetRenderer())
 | 
					            if (auto renderer = m_graph->GetRenderer())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                m_renderMain->GetCriticalSection().lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (SUCCEEDED(renderer->ScaleRange(centerX, centerY, scale)))
 | 
					                if (SUCCEEDED(renderer->ScaleRange(centerX, centerY, scale)))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
					                    m_renderMain->GetCriticalSection().unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    m_renderMain->RunRenderPass();
 | 
					                    m_renderMain->RunRenderPass();
 | 
				
			||||||
                    GraphViewChangedEvent(this, ref new RoutedEventArgs());
 | 
					                    GraphViewChangedEvent(this, ref new RoutedEventArgs());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    m_renderMain->GetCriticalSection().unlock();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -612,9 +620,33 @@ namespace GraphControl
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (m_renderMain)
 | 
					        if (m_renderMain)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            PointerPoint ^ currPoint = e->GetCurrentPoint(/* relativeTo */ this);
 | 
					            Point currPosition = e->GetCurrentPoint(/* relativeTo */ this)->Position;
 | 
				
			||||||
            m_renderMain->PointerLocation = currPoint->Position;
 | 
					
 | 
				
			||||||
            UpdateTracingChanged();
 | 
					            if (m_renderMain->ActiveTracing)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                PointerValueChangedEvent(currPosition);
 | 
				
			||||||
 | 
					                ActiveTraceCursorPosition = currPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (m_cachedCursor == nullptr)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    m_cachedCursor = ::CoreWindow::GetForCurrentThread()->PointerCursor;
 | 
				
			||||||
 | 
					                    ::CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (m_cachedCursor != nullptr)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                m_renderMain->PointerLocation = currPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ::CoreWindow::GetForCurrentThread()->PointerCursor = m_cachedCursor;
 | 
				
			||||||
 | 
					                m_cachedCursor = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                UpdateTracingChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                m_renderMain->PointerLocation = currPosition;
 | 
				
			||||||
 | 
					                UpdateTracingChanged();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            e->Handled = true;
 | 
					            e->Handled = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -628,6 +660,12 @@ namespace GraphControl
 | 
				
			|||||||
            TracingChangedEvent(false);
 | 
					            TracingChangedEvent(false);
 | 
				
			||||||
            e->Handled = true;
 | 
					            e->Handled = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_cachedCursor != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ::CoreWindow::GetForCurrentThread()->PointerCursor = m_cachedCursor;
 | 
				
			||||||
 | 
					            m_cachedCursor = nullptr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Grapher::OnPointerWheelChanged(PointerRoutedEventArgs ^ e)
 | 
					    void Grapher::OnPointerWheelChanged(PointerRoutedEventArgs ^ e)
 | 
				
			||||||
@@ -699,11 +737,15 @@ namespace GraphControl
 | 
				
			|||||||
                    translationX /= -width;
 | 
					                    translationX /= -width;
 | 
				
			||||||
                    translationY /= height;
 | 
					                    translationY /= height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    m_renderMain->GetCriticalSection().lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (FAILED(renderer->MoveRangeByRatio(translationX, translationY)))
 | 
					                    if (FAILED(renderer->MoveRangeByRatio(translationX, translationY)))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
					                        m_renderMain->GetCriticalSection().unlock();
 | 
				
			||||||
                        return;
 | 
					                        return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    m_renderMain->GetCriticalSection().unlock();
 | 
				
			||||||
                    needsRenderPass = true;
 | 
					                    needsRenderPass = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -717,11 +759,15 @@ namespace GraphControl
 | 
				
			|||||||
                    const auto& pos = e->Position;
 | 
					                    const auto& pos = e->Position;
 | 
				
			||||||
                    const auto [centerX, centerY] = PointerPositionToGraphPosition(pos.X, pos.Y, width, height);
 | 
					                    const auto [centerX, centerY] = PointerPositionToGraphPosition(pos.X, pos.Y, width, height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    m_renderMain->GetCriticalSection().lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (FAILED(renderer->ScaleRange(centerX, centerY, scale)))
 | 
					                    if (FAILED(renderer->ScaleRange(centerX, centerY, scale)))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
					                        m_renderMain->GetCriticalSection().unlock();
 | 
				
			||||||
                        return;
 | 
					                        return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    m_renderMain->GetCriticalSection().unlock();
 | 
				
			||||||
                    needsRenderPass = true;
 | 
					                    needsRenderPass = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -333,6 +333,7 @@ public
 | 
				
			|||||||
        bool m_KeysPressed[5];
 | 
					        bool m_KeysPressed[5];
 | 
				
			||||||
        bool m_Moving;
 | 
					        bool m_Moving;
 | 
				
			||||||
        Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer;
 | 
					        Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer;
 | 
				
			||||||
 | 
					        Windows::UI::Core::CoreCursor ^ m_cachedCursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        Windows::Storage::Streams::RandomAccessStreamReference ^ GetGraphBitmapStream();
 | 
					        Windows::Storage::Streams::RandomAccessStreamReference ^ GetGraphBitmapStream();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,12 @@ namespace GraphControl::DX
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                m_Tracing = false;
 | 
					                m_Tracing = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            RunRenderPass();
 | 
					
 | 
				
			||||||
 | 
					            bool wasPointRendered = m_Tracing;
 | 
				
			||||||
 | 
					            if (CanRenderPoint() || wasPointRendered)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                RunRenderPassAsync();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,7 +100,12 @@ namespace GraphControl::DX
 | 
				
			|||||||
        if (m_pointerLocation != location)
 | 
					        if (m_pointerLocation != location)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            m_pointerLocation = location;
 | 
					            m_pointerLocation = location;
 | 
				
			||||||
            RunRenderPass();
 | 
					
 | 
				
			||||||
 | 
					            bool wasPointRendered = m_Tracing;
 | 
				
			||||||
 | 
					            if (CanRenderPoint() || wasPointRendered)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                RunRenderPassAsync();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -104,7 +114,12 @@ namespace GraphControl::DX
 | 
				
			|||||||
        if (m_drawActiveTracing != value)
 | 
					        if (m_drawActiveTracing != value)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            m_drawActiveTracing = value;
 | 
					            m_drawActiveTracing = value;
 | 
				
			||||||
            RunRenderPass();
 | 
					
 | 
				
			||||||
 | 
					            bool wasPointRendered = m_Tracing;
 | 
				
			||||||
 | 
					            if (CanRenderPoint() || wasPointRendered)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                RunRenderPassAsync();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,6 +142,51 @@ namespace GraphControl::DX
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool RenderMain::CanRenderPoint()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (m_drawNearestPoint || m_drawActiveTracing)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Point trackPoint = m_pointerLocation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (m_drawActiveTracing)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                trackPoint = m_activeTracingPointerLocation;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!m_criticalSection.try_lock())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            m_criticalSection.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            critical_section::scoped_lock lock(m_criticalSection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int formulaId = -1;
 | 
				
			||||||
 | 
					            float nearestPointLocationX, nearestPointLocationY;
 | 
				
			||||||
 | 
					            double nearestPointValueX, nearestPointValueY, rhoValueOut, thetaValueOut, tValueOut;
 | 
				
			||||||
 | 
					            m_Tracing = m_graph->GetRenderer()->GetClosePointData(
 | 
				
			||||||
 | 
					                            trackPoint.X,
 | 
				
			||||||
 | 
					                            trackPoint.Y,
 | 
				
			||||||
 | 
					                            formulaId,
 | 
				
			||||||
 | 
					                            nearestPointLocationX,
 | 
				
			||||||
 | 
					                            nearestPointLocationY,
 | 
				
			||||||
 | 
					                            nearestPointValueX,
 | 
				
			||||||
 | 
					                            nearestPointValueY,
 | 
				
			||||||
 | 
					                            rhoValueOut,
 | 
				
			||||||
 | 
					                            thetaValueOut,
 | 
				
			||||||
 | 
					                            tValueOut)
 | 
				
			||||||
 | 
					                        == S_OK;
 | 
				
			||||||
 | 
					            m_Tracing = m_Tracing && !isnan(nearestPointLocationX) && !isnan(nearestPointLocationY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_Tracing = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return m_Tracing;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool RenderMain::RunRenderPass()
 | 
					    bool RenderMain::RunRenderPass()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Non async render passes cancel if they can't obtain the lock immediatly
 | 
					        // Non async render passes cancel if they can't obtain the lock immediatly
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,8 @@ namespace GraphControl::DX
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        void CreateWindowSizeDependentResources();
 | 
					        void CreateWindowSizeDependentResources();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool RenderMain::CanRenderPoint();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool RunRenderPass();
 | 
					        bool RunRenderPass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Windows::Foundation::IAsyncAction ^ RunRenderPassAsync(bool allowCancel = true);
 | 
					        Windows::Foundation::IAsyncAction ^ RunRenderPassAsync(bool allowCancel = true);
 | 
				
			||||||
@@ -78,7 +80,12 @@ namespace GraphControl::DX
 | 
				
			|||||||
                if (m_activeTracingPointerLocation != newValue)
 | 
					                if (m_activeTracingPointerLocation != newValue)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    m_activeTracingPointerLocation = newValue;
 | 
					                    m_activeTracingPointerLocation = newValue;
 | 
				
			||||||
                    RunRenderPass();
 | 
					
 | 
				
			||||||
 | 
					                    bool wasPointRendered = m_Tracing;
 | 
				
			||||||
 | 
					                    if (CanRenderPoint() || wasPointRendered)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        RunRenderPassAsync();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user