mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-25 21:28:38 -05:00
Merge pull request #10 from cjcliffe/canvas_interaction
Canvas interaction
This commit is contained in:
commit
d33ef25a79
@ -95,6 +95,7 @@ SET (cubicsdr_sources
|
||||
src/audio/AudioThread.cpp
|
||||
src/util/Gradient.cpp
|
||||
src/util/Timer.cpp
|
||||
src/util/MouseTracker.cpp
|
||||
src/visual/PrimaryGLContext.cpp
|
||||
src/visual/ScopeCanvas.cpp
|
||||
src/visual/ScopeContext.cpp
|
||||
@ -115,6 +116,7 @@ SET (cubicsdr_headers
|
||||
src/util/Gradient.h
|
||||
src/util/Timer.h
|
||||
src/util/ThreadQueue.h
|
||||
src/util/MouseTracker.h
|
||||
src/visual/PrimaryGLContext.h
|
||||
src/visual/ScopeCanvas.h
|
||||
src/visual/ScopeContext.h
|
||||
|
@ -36,6 +36,10 @@ public:
|
||||
return iqVisualQueue;
|
||||
}
|
||||
|
||||
DemodulatorInstance *getDemodTest() {
|
||||
return demodulatorTest;
|
||||
}
|
||||
|
||||
private:
|
||||
PrimaryGLContext *m_glContext;
|
||||
|
||||
|
118
src/util/MouseTracker.cpp
Normal file
118
src/util/MouseTracker.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include "MouseTracker.h"
|
||||
#include <iostream>
|
||||
|
||||
void MouseTracker::OnMouseMoved(wxMouseEvent& event) {
|
||||
if (target == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wxSize ClientSize = target->GetClientSize();
|
||||
|
||||
mouseX = (float) event.m_x / (float) ClientSize.x;
|
||||
mouseY = (float) event.m_y / (float) ClientSize.y;
|
||||
|
||||
deltaMouseX = mouseX - lastMouseX;
|
||||
deltaMouseY = mouseY - lastMouseY;
|
||||
|
||||
if (isMouseDown) {
|
||||
lastMouseX = mouseX;
|
||||
|
||||
if (vertDragLock && mouseY != lastMouseY) {
|
||||
target->WarpPointer(event.m_x, lastMouseY * ClientSize.y);
|
||||
} else {
|
||||
lastMouseY = mouseY;
|
||||
}
|
||||
} else {
|
||||
lastMouseY = mouseY;
|
||||
lastMouseX = mouseX;
|
||||
}
|
||||
}
|
||||
|
||||
void MouseTracker::OnMouseDown(wxMouseEvent& event) {
|
||||
if (target == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wxSize ClientSize = target->GetClientSize();
|
||||
|
||||
mouseX = lastMouseX = (float) event.m_x / (float) ClientSize.x;
|
||||
mouseY = lastMouseY = (float) event.m_y / (float) ClientSize.y;
|
||||
|
||||
originMouseX = mouseX;
|
||||
originMouseY = mouseY;
|
||||
|
||||
isMouseDown = true;
|
||||
}
|
||||
|
||||
void MouseTracker::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||
// std::cout << "wheel?" << std::endl;
|
||||
}
|
||||
|
||||
void MouseTracker::OnMouseReleased(wxMouseEvent& event) {
|
||||
isMouseDown = false;
|
||||
}
|
||||
|
||||
void MouseTracker::OnMouseEnterWindow(wxMouseEvent& event) {
|
||||
isMouseInView = true;
|
||||
}
|
||||
|
||||
void MouseTracker::OnMouseLeftWindow(wxMouseEvent& event) {
|
||||
isMouseDown = false;
|
||||
isMouseInView = false;
|
||||
}
|
||||
|
||||
float MouseTracker::getOriginMouseX() {
|
||||
return originMouseX;
|
||||
}
|
||||
|
||||
float MouseTracker::getOriginMouseY() {
|
||||
return originMouseY;
|
||||
}
|
||||
|
||||
float MouseTracker::getOriginDeltaMouseX() {
|
||||
return mouseX - originMouseX;
|
||||
}
|
||||
|
||||
float MouseTracker::getOriginDeltaMouseY() {
|
||||
return mouseY - originMouseY;
|
||||
}
|
||||
|
||||
float MouseTracker::getDeltaMouseX() {
|
||||
return deltaMouseX;
|
||||
}
|
||||
|
||||
float MouseTracker::getDeltaMouseY() {
|
||||
return deltaMouseY;
|
||||
}
|
||||
|
||||
float MouseTracker::getLastMouseX() {
|
||||
return lastMouseX;
|
||||
}
|
||||
|
||||
float MouseTracker::getLastMouseY() {
|
||||
return lastMouseY;
|
||||
}
|
||||
|
||||
float MouseTracker::getMouseX() {
|
||||
return mouseX;
|
||||
}
|
||||
|
||||
float MouseTracker::getMouseY() {
|
||||
return mouseY;
|
||||
}
|
||||
|
||||
void MouseTracker::setVertDragLock(bool dragLock) {
|
||||
vertDragLock = dragLock;
|
||||
}
|
||||
|
||||
bool MouseTracker::mouseDown() {
|
||||
return isMouseDown;
|
||||
}
|
||||
|
||||
bool MouseTracker::mouseInView() {
|
||||
return isMouseInView;
|
||||
}
|
||||
|
||||
void MouseTracker::setTarget(wxWindow *target_in) {
|
||||
target = target_in;
|
||||
}
|
51
src/util/MouseTracker.h
Normal file
51
src/util/MouseTracker.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "wx/window.h"
|
||||
|
||||
class MouseTracker {
|
||||
public:
|
||||
MouseTracker(wxWindow *target) :
|
||||
target(target), mouseX(0), mouseY(0), lastMouseX(0), lastMouseY(0), originMouseX(0), originMouseY(0), deltaMouseX(0), deltaMouseY(0), isMouseDown(
|
||||
false), vertDragLock(false), isMouseInView(false) {
|
||||
|
||||
}
|
||||
|
||||
MouseTracker() :
|
||||
target(NULL), mouseX(0), mouseY(0), lastMouseX(0), lastMouseY(0), originMouseX(0), originMouseY(0), deltaMouseX(0), deltaMouseY(0), isMouseDown(
|
||||
false), vertDragLock(false), isMouseInView(false) {
|
||||
|
||||
}
|
||||
|
||||
void OnMouseMoved(wxMouseEvent& event);
|
||||
void OnMouseDown(wxMouseEvent& event);
|
||||
void OnMouseWheelMoved(wxMouseEvent& event);
|
||||
void OnMouseReleased(wxMouseEvent& event);
|
||||
void OnMouseEnterWindow(wxMouseEvent& event);
|
||||
void OnMouseLeftWindow(wxMouseEvent& event);
|
||||
|
||||
float getOriginMouseX();
|
||||
float getOriginMouseY();
|
||||
float getOriginDeltaMouseX();
|
||||
float getOriginDeltaMouseY();
|
||||
float getDeltaMouseX();
|
||||
float getDeltaMouseY();
|
||||
float getLastMouseX();
|
||||
float getLastMouseY();
|
||||
float getMouseX();
|
||||
float getMouseY();
|
||||
|
||||
void setVertDragLock(bool dragLock);
|
||||
bool mouseDown();
|
||||
bool mouseInView();
|
||||
void setTarget(wxWindow *target_in);
|
||||
|
||||
private:
|
||||
float mouseX, mouseY;
|
||||
float lastMouseX, lastMouseY;
|
||||
float deltaMouseX, deltaMouseY;
|
||||
float originMouseX, originMouseY;
|
||||
|
||||
bool isMouseDown, isMouseInView;
|
||||
bool vertDragLock;
|
||||
wxWindow *target;
|
||||
};
|
@ -29,7 +29,7 @@ wxEND_EVENT_TABLE()
|
||||
|
||||
SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) :
|
||||
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), isMouseDown(false) {
|
||||
wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0) {
|
||||
|
||||
int in_block_size = BUF_SIZE / 2;
|
||||
int out_block_size = FFT_SIZE;
|
||||
@ -44,6 +44,9 @@ SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) :
|
||||
glContext = new SpectrumContext(this, &wxGetApp().GetContext(this));
|
||||
timer.start();
|
||||
|
||||
mTracker.setTarget(this);
|
||||
mTracker.setVertDragLock(true);
|
||||
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
@ -172,57 +175,39 @@ void SpectrumCanvas::OnIdle(wxIdleEvent &event) {
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
|
||||
if (isMouseDown) {
|
||||
const wxSize ClientSize = GetClientSize();
|
||||
float mouseX = (float)event.m_x/(float)ClientSize.x;
|
||||
float mouseY = (float)event.m_y/(float)ClientSize.y;
|
||||
|
||||
|
||||
deltaMouseX = mouseX-lastMouseX;
|
||||
deltaMouseY = mouseY-lastMouseY;
|
||||
|
||||
lastMouseX = mouseX;
|
||||
// lastMouseY = mouseY;
|
||||
|
||||
int freqChange = deltaMouseX*SRATE;
|
||||
mTracker.OnMouseMoved(event);
|
||||
if (mTracker.mouseDown()) {
|
||||
int freqChange = mTracker.getDeltaMouseX() * SRATE;
|
||||
|
||||
if (freqChange != 0) {
|
||||
int freq = wxGetApp().getFrequency();
|
||||
freq -= freqChange;
|
||||
wxGetApp().setFrequency(freq);
|
||||
|
||||
((wxFrame*)parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %s"),wxNumberFormatter::ToString((long)freq,wxNumberFormatter::Style_WithThousandsSep)));
|
||||
|
||||
if (mouseY != lastMouseY) {
|
||||
WarpPointer(event.m_x,lastMouseY*ClientSize.y);
|
||||
((wxFrame*) parent)->GetStatusBar()->SetStatusText(
|
||||
wxString::Format(wxT("Set center frequency: %s"),
|
||||
wxNumberFormatter::ToString((long) freq, wxNumberFormatter::Style_WithThousandsSep)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpectrumCanvas::mouseDown(wxMouseEvent& event) {
|
||||
const wxSize ClientSize = GetClientSize();
|
||||
lastMouseX = (float)event.m_x/(float)ClientSize.x;
|
||||
lastMouseY = (float)event.m_y/(float)ClientSize.y;
|
||||
|
||||
isMouseDown = true;
|
||||
mTracker.OnMouseDown(event);
|
||||
SetCursor(wxCURSOR_CROSS);
|
||||
}
|
||||
|
||||
void SpectrumCanvas::mouseWheelMoved(wxMouseEvent& event) {
|
||||
std::cout << "wheel?" << std::endl;
|
||||
mTracker.OnMouseWheelMoved(event);
|
||||
}
|
||||
|
||||
void SpectrumCanvas::mouseReleased(wxMouseEvent& event) {
|
||||
isMouseDown = false;
|
||||
mTracker.OnMouseReleased(event);
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
void SpectrumCanvas::mouseLeftWindow(wxMouseEvent& event) {
|
||||
isMouseDown = false;
|
||||
mTracker.OnMouseLeftWindow(event);
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "fftw3.h"
|
||||
#include "Timer.h"
|
||||
#include "MouseTracker.h"
|
||||
|
||||
class SpectrumCanvas: public wxGLCanvas {
|
||||
public:
|
||||
@ -48,9 +49,7 @@ private:
|
||||
Timer timer;
|
||||
float frameTimer;
|
||||
|
||||
float lastMouseX, lastMouseY;
|
||||
float deltaMouseX, deltaMouseY;
|
||||
bool isMouseDown;
|
||||
MouseTracker mTracker;
|
||||
// event table
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
@ -15,9 +15,16 @@
|
||||
#include "AppFrame.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include <wx/numformatter.h>
|
||||
|
||||
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas) EVT_PAINT(WaterfallCanvas::OnPaint)
|
||||
EVT_KEY_DOWN(WaterfallCanvas::OnKeyDown)
|
||||
EVT_IDLE(WaterfallCanvas::OnIdle)
|
||||
EVT_MOTION(WaterfallCanvas::mouseMoved)
|
||||
EVT_LEFT_DOWN(WaterfallCanvas::mouseDown)
|
||||
EVT_LEFT_UP(WaterfallCanvas::mouseReleased)
|
||||
EVT_LEAVE_WINDOW(WaterfallCanvas::mouseLeftWindow)
|
||||
EVT_ENTER_WINDOW(WaterfallCanvas::mouseEnterWindow)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||
@ -37,6 +44,8 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||
glContext = new WaterfallContext(this, &wxGetApp().GetContext(this));
|
||||
timer.start();
|
||||
|
||||
mTracker.setTarget(this);
|
||||
|
||||
SetCursor(wxCURSOR_CROSS);
|
||||
}
|
||||
|
||||
@ -51,8 +60,14 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
glContext->SetCurrent(*this);
|
||||
glViewport(0, 0, ClientSize.x, ClientSize.y);
|
||||
|
||||
glContext->BeginDraw();
|
||||
glContext->Draw(spectrum_points);
|
||||
|
||||
if (mTracker.mouseInView()) {
|
||||
glContext->DrawFreqSelector(mTracker.getMouseX());
|
||||
}
|
||||
glContext->EndDraw();
|
||||
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
@ -162,3 +177,60 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
||||
// frameTimer = 0;
|
||||
// }
|
||||
}
|
||||
|
||||
void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
|
||||
mTracker.OnMouseMoved(event);
|
||||
if (mTracker.mouseDown()) {
|
||||
int freqChange = mTracker.getDeltaMouseX() * SRATE;
|
||||
|
||||
if (freqChange != 0) {
|
||||
int freq = wxGetApp().getFrequency();
|
||||
freq -= freqChange;
|
||||
wxGetApp().setFrequency(freq);
|
||||
|
||||
((wxFrame*) parent)->GetStatusBar()->SetStatusText(
|
||||
wxString::Format(wxT("Set center frequency: %s"),
|
||||
wxNumberFormatter::ToString((long) freq, wxNumberFormatter::Style_WithThousandsSep)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WaterfallCanvas::mouseDown(wxMouseEvent& event) {
|
||||
mTracker.OnMouseDown(event);
|
||||
SetCursor(wxCURSOR_CROSS);
|
||||
}
|
||||
|
||||
void WaterfallCanvas::mouseWheelMoved(wxMouseEvent& event) {
|
||||
mTracker.OnMouseWheelMoved(event);
|
||||
}
|
||||
|
||||
void WaterfallCanvas::mouseReleased(wxMouseEvent& event) {
|
||||
mTracker.OnMouseReleased(event);
|
||||
|
||||
if (mTracker.getOriginDeltaMouseX() == 0 && mTracker.getOriginDeltaMouseX() == 0) {
|
||||
|
||||
float pos = mTracker.getMouseX();
|
||||
|
||||
int freq = wxGetApp().getFrequency();
|
||||
|
||||
freq += (pos - 0.5) * SRATE;
|
||||
|
||||
wxGetApp().setFrequency(freq);
|
||||
|
||||
((wxFrame*) parent)->GetStatusBar()->SetStatusText(
|
||||
wxString::Format(wxT("Set center frequency: %s"),
|
||||
wxNumberFormatter::ToString((long) freq, wxNumberFormatter::Style_WithThousandsSep)));
|
||||
}
|
||||
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
void WaterfallCanvas::mouseLeftWindow(wxMouseEvent& event) {
|
||||
mTracker.OnMouseLeftWindow(event);
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
void WaterfallCanvas::mouseEnterWindow(wxMouseEvent& event) {
|
||||
mTracker.OnMouseEnterWindow(event);
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <queue>
|
||||
|
||||
#include "WaterfallContext.h"
|
||||
#include "MouseTracker.h"
|
||||
|
||||
#include "fftw3.h"
|
||||
#include "Timer.h"
|
||||
@ -23,6 +24,13 @@ private:
|
||||
|
||||
void OnIdle(wxIdleEvent &event);
|
||||
|
||||
void mouseMoved(wxMouseEvent& event);
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseWheelMoved(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent& event);
|
||||
void mouseEnterWindow(wxMouseEvent& event);
|
||||
void mouseLeftWindow(wxMouseEvent& event);
|
||||
|
||||
wxWindow *parent;
|
||||
std::vector<float> spectrum_points;
|
||||
|
||||
@ -39,6 +47,8 @@ private:
|
||||
WaterfallContext *glContext;
|
||||
Timer timer;
|
||||
float frameTimer;
|
||||
MouseTracker mTracker;
|
||||
|
||||
// event table
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "WaterfallContext.h"
|
||||
#include "WaterfallCanvas.h"
|
||||
#include "CubicSDR.h"
|
||||
|
||||
WaterfallContext::WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext) :
|
||||
PrimaryGLContext(canvas, sharedContext) {
|
||||
@ -36,11 +37,14 @@ WaterfallContext::WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedC
|
||||
glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, &(grad.getBlue())[0]);
|
||||
}
|
||||
|
||||
void WaterfallContext::Draw(std::vector<float> &points) {
|
||||
void WaterfallContext::BeginDraw() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void WaterfallContext::Draw(std::vector<float> &points) {
|
||||
|
||||
if (points.size()) {
|
||||
memmove(waterfall_tex + FFT_SIZE, waterfall_tex, (NUM_WATERFALL_LINES - 1) * FFT_SIZE);
|
||||
@ -57,15 +61,13 @@ void WaterfallContext::Draw(std::vector<float> &points) {
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, waterfall);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FFT_SIZE, NUM_WATERFALL_LINES, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_tex);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
// glEnable(GL_COLOR_TABLE);
|
||||
glBindTexture(GL_TEXTURE_2D, waterfall);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
@ -78,6 +80,37 @@ void WaterfallContext::Draw(std::vector<float> &points) {
|
||||
glVertex3f(-1.0, 1.0, 0.0);
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
void WaterfallContext::DrawFreqSelector(float uxPos) {
|
||||
DemodulatorInstance *demod = wxGetApp().getDemodTest();
|
||||
|
||||
if (!demod) {
|
||||
return;
|
||||
}
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0);
|
||||
glVertex3f((uxPos - 0.5) * 2.0, -1.0, 0.0);
|
||||
|
||||
float ofs = ((float) demod->params.inputResampleRate) / (float) SRATE;
|
||||
|
||||
glVertex3f((uxPos - 0.5) * 2.0 - ofs, 1.0, 0.0);
|
||||
glVertex3f((uxPos - 0.5) * 2.0 - ofs, -1.0, 0.0);
|
||||
|
||||
glVertex3f((uxPos - 0.5) * 2.0 + ofs, 1.0, 0.0);
|
||||
glVertex3f((uxPos - 0.5) * 2.0 + ofs, -1.0, 0.0);
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
void WaterfallContext::EndDraw() {
|
||||
glFlush();
|
||||
|
||||
CheckGLError();
|
||||
|
@ -11,7 +11,10 @@ class WaterfallContext: public PrimaryGLContext {
|
||||
public:
|
||||
WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext);
|
||||
|
||||
void BeginDraw();
|
||||
void Draw(std::vector<float> &points);
|
||||
void DrawFreqSelector(float uxPos);
|
||||
void EndDraw();
|
||||
|
||||
private:
|
||||
Gradient grad;
|
||||
|
Loading…
Reference in New Issue
Block a user