Unify common canvas manipulation functions

This commit is contained in:
Charles J. Cliffe 2015-01-02 21:32:24 -05:00
parent 6f5f97d26f
commit 8f8dd01341
7 changed files with 228 additions and 173 deletions

View File

@ -136,6 +136,7 @@ SET (cubicsdr_sources
src/util/MouseTracker.cpp
src/util/GLFont.cpp
src/visual/PrimaryGLContext.cpp
src/visual/InteractiveCanvas.cpp
src/visual/MeterCanvas.cpp
src/visual/MeterContext.cpp
src/visual/ScopeCanvas.cpp
@ -167,6 +168,7 @@ SET (cubicsdr_headers
src/util/MouseTracker.h
src/util/GLFont.h
src/visual/PrimaryGLContext.h
src/visual/InteractiveCanvas.h
src/visual/MeterCanvas.h
src/visual/MeterContext.h
src/visual/ScopeCanvas.h

View File

@ -0,0 +1,125 @@
#include "InteractiveCanvas.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#if !wxUSE_GLCANVAS
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
#endif
#include "CubicSDR.h"
#include "CubicSDRDefs.h"
#include "AppFrame.h"
#include <algorithm>
#include <wx/numformatter.h>
InteractiveCanvas::InteractiveCanvas(wxWindow *parent, int *attribList) :
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
wxFULL_REPAINT_ON_RESIZE), parent(parent), shiftDown(false), altDown(false), ctrlDown(false), center_freq(0), bandwidth(0), last_bandwidth(0), isView(
false) {
mTracker.setTarget(this);
}
InteractiveCanvas::~InteractiveCanvas() {
}
void InteractiveCanvas::SetView(int center_freq_in, int bandwidth_in) {
isView = true;
center_freq = center_freq_in;
bandwidth = bandwidth_in;
last_bandwidth = 0;
}
void InteractiveCanvas::DisableView() {
isView = false;
center_freq = wxGetApp().getFrequency();
bandwidth = SRATE;
last_bandwidth = 0;
}
int InteractiveCanvas::GetFrequencyAt(float x) {
int iqCenterFreq = GetCenterFrequency();
int iqBandwidth = GetBandwidth();
int freq = iqCenterFreq - (int) (0.5 * (float) iqBandwidth) + (int) ((float) x * (float) iqBandwidth);
return freq;
}
void InteractiveCanvas::SetCenterFrequency(unsigned int center_freq_in) {
center_freq = center_freq_in;
}
unsigned int InteractiveCanvas::GetCenterFrequency() {
if (isView) {
return center_freq;
} else {
return (unsigned int) wxGetApp().getFrequency();
}
}
void InteractiveCanvas::SetBandwidth(unsigned int bandwidth_in) {
bandwidth = bandwidth_in;
}
unsigned int InteractiveCanvas::GetBandwidth() {
if (isView) {
return bandwidth;
} else {
return SRATE;
}
}
void InteractiveCanvas::OnKeyUp(wxKeyEvent& event) {
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
}
void InteractiveCanvas::OnKeyDown(wxKeyEvent& event) {
float angle = 5.0;
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
}
void InteractiveCanvas::mouseMoved(wxMouseEvent& event) {
mTracker.OnMouseMoved(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
}
void InteractiveCanvas::mouseDown(wxMouseEvent& event) {
mTracker.OnMouseDown(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
}
void InteractiveCanvas::mouseWheelMoved(wxMouseEvent& event) {
mTracker.OnMouseWheelMoved(event);
}
void InteractiveCanvas::mouseReleased(wxMouseEvent& event) {
mTracker.OnMouseReleased(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
}
void InteractiveCanvas::mouseLeftWindow(wxMouseEvent& event) {
mTracker.OnMouseLeftWindow(event);
}
void InteractiveCanvas::mouseEnterWindow(wxMouseEvent& event) {
mTracker.OnMouseEnterWindow(event);
}

View File

@ -0,0 +1,48 @@
#pragma once
#include "wx/glcanvas.h"
#include "wx/timer.h"
#include "MouseTracker.h"
class InteractiveCanvas: public wxGLCanvas {
public:
InteractiveCanvas(wxWindow *parent, int *attribList = NULL);
~InteractiveCanvas();
int GetFrequencyAt(float x);
void SetView(int center_freq_in, int bandwidth_in);
void DisableView();
void SetCenterFrequency(unsigned int center_freq_in);
unsigned int GetCenterFrequency();
void SetBandwidth(unsigned int bandwidth_in);
unsigned int GetBandwidth();
protected:
void OnKeyDown(wxKeyEvent& event);
void OnKeyUp(wxKeyEvent& 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;
MouseTracker mTracker;
bool shiftDown;
bool altDown;
bool ctrlDown;
unsigned int center_freq;
unsigned int bandwidth;
unsigned int last_bandwidth;
bool isView;
};

View File

@ -27,13 +27,11 @@ EVT_MOUSEWHEEL(SpectrumCanvas::mouseWheelMoved)
wxEND_EVENT_TABLE()
SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) :
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
wxFULL_REPAINT_ON_RESIZE), parent(parent), fft_size(0), in(NULL), out(NULL), plan(NULL), waterfallCanvas(NULL), center_freq(0), bandwidth(0), isView(
0) {
InteractiveCanvas(parent, attribList), fft_size(0), in(NULL), out(NULL), plan(NULL), fft_ceil_ma(1), fft_ceil_maa(1), fft_floor_ma(0), fft_floor_maa(
0), waterfallCanvas(NULL) {
glContext = new SpectrumContext(this, &wxGetApp().GetContext(this));
mTracker.setTarget(this);
mTracker.setVertDragLock(true);
SetCursor(wxCURSOR_SIZEWE);
@ -131,7 +129,6 @@ void SpectrumCanvas::setData(DemodulatorThreadIQData *input) {
double b = out[n][1];
double c = sqrt(a * a + b * b);
// n = (i == FFT_SIZE / 2) ? (FFT_SIZE / 2 + 1) : i;
double x = out[fft_size / 2 + n][0];
double y = out[fft_size / 2 + n][1];
double z = sqrt(x * x + y * y);
@ -172,48 +169,12 @@ void SpectrumCanvas::setData(DemodulatorThreadIQData *input) {
}
}
void SpectrumCanvas::SetView(int center_freq_in, int bandwidth_in) {
isView = true;
center_freq = center_freq_in;
bandwidth = bandwidth_in;
}
void SpectrumCanvas::DisableView() {
isView = false;
center_freq = wxGetApp().getFrequency();
bandwidth = SRATE;
}
void SpectrumCanvas::SetCenterFrequency(unsigned int center_freq_in) {
center_freq = center_freq_in;
}
unsigned int SpectrumCanvas::GetCenterFrequency() {
if (isView) {
return center_freq;
} else {
return (unsigned int) wxGetApp().getFrequency();
}
}
void SpectrumCanvas::SetBandwidth(unsigned int bandwidth_in) {
bandwidth = bandwidth_in;
}
unsigned int SpectrumCanvas::GetBandwidth() {
if (isView) {
return bandwidth;
} else {
return SRATE;
}
}
void SpectrumCanvas::OnIdle(wxIdleEvent &event) {
Refresh(false);
}
void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
mTracker.OnMouseMoved(event);
InteractiveCanvas::mouseMoved(event);
if (mTracker.mouseDown()) {
int freqChange = mTracker.getDeltaMouseX() * GetBandwidth();
@ -226,12 +187,12 @@ void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
waterfallCanvas->SetCenterFrequency(center_freq);
}
int bw = (int)bandwidth;
int bwOfs = ((int)center_freq>freq)?((int)bandwidth/2):(-(int)bandwidth/2);
int freqEdge = ((int)center_freq+bwOfs);
int bw = (int) bandwidth;
int bwOfs = ((int) center_freq > freq) ? ((int) bandwidth / 2) : (-(int) bandwidth / 2);
int freqEdge = ((int) center_freq + bwOfs);
if (abs(freq-freqEdge) > (SRATE/2)) {
freqChange = -(((int)center_freq>freq)?(freqEdge-freq-(SRATE/2)):(freqEdge-freq+(SRATE/2)));
if (abs(freq - freqEdge) > (SRATE / 2)) {
freqChange = -(((int) center_freq > freq) ? (freqEdge - freq - (SRATE / 2)) : (freqEdge - freq + (SRATE / 2)));
} else {
freqChange = 0;
}
@ -250,28 +211,25 @@ void SpectrumCanvas::mouseMoved(wxMouseEvent& event) {
}
void SpectrumCanvas::mouseDown(wxMouseEvent& event) {
mTracker.OnMouseDown(event);
InteractiveCanvas::mouseDown(event);
SetCursor(wxCURSOR_CROSS);
}
void SpectrumCanvas::mouseWheelMoved(wxMouseEvent& event) {
mTracker.OnMouseWheelMoved(event);
InteractiveCanvas::mouseWheelMoved(event);
}
void SpectrumCanvas::mouseReleased(wxMouseEvent& event) {
mTracker.OnMouseReleased(event);
InteractiveCanvas::mouseReleased(event);
SetCursor(wxCURSOR_SIZEWE);
}
void SpectrumCanvas::mouseLeftWindow(wxMouseEvent& event) {
mTracker.OnMouseLeftWindow(event);
InteractiveCanvas::mouseLeftWindow(event);
SetCursor(wxCURSOR_SIZEWE);
}
void SpectrumCanvas::attachWaterfallCanvas(WaterfallCanvas* canvas_in) {
waterfallCanvas = canvas_in;
}
//void SpectrumCanvas::rightClick(wxMouseEvent& event) {}
//void SpectrumCanvas::keyPressed(wxKeyEvent& event) {}
//void SpectrumCanvas::keyReleased(wxKeyEvent& event) {}

View File

@ -6,6 +6,7 @@
#include <vector>
#include <queue>
#include "InteractiveCanvas.h"
#include "SpectrumContext.h"
#include "fftw3.h"
@ -13,7 +14,7 @@
class WaterfallCanvas;
class SpectrumCanvas: public wxGLCanvas {
class SpectrumCanvas: public InteractiveCanvas {
public:
std::vector<float> spectrum_points;
@ -22,16 +23,6 @@ public:
~SpectrumCanvas();
void setData(DemodulatorThreadIQData *input);
void SetView(int center_freq_in, int bandwidth_in);
void DisableView();
void SetCenterFrequency(unsigned int center_freq_in);
unsigned int GetCenterFrequency();
void SetBandwidth(unsigned int bandwidth_in);
unsigned int GetBandwidth();
void attachWaterfallCanvas(WaterfallCanvas *canvas_in);
private:
@ -47,8 +38,6 @@ private:
// void rightClick(wxMouseEvent& event);
void mouseLeftWindow(wxMouseEvent& event);
wxWindow *parent;
fftw_complex *in, *out;
fftw_plan plan;
@ -62,13 +51,6 @@ private:
SpectrumContext *glContext;
WaterfallCanvas *waterfallCanvas;
int fft_size;
unsigned int center_freq;
unsigned int bandwidth;
bool isView;
MouseTracker mTracker;
// event table
wxDECLARE_EVENT_TABLE();
};

View File

@ -31,11 +31,9 @@ EVT_ENTER_WINDOW(WaterfallCanvas::mouseEnterWindow)
wxEND_EVENT_TABLE()
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
wxFULL_REPAINT_ON_RESIZE), parent(parent), spectrumCanvas(NULL), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState(
WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown(false), altDown(false), ctrlDown(false), fft_size(0), waterfall_lines(0), plan(
NULL), in(NULL), out(NULL), center_freq(0), bandwidth(0), isView(false), resampler(NULL), resample_ratio(0), last_bandwidth(0), last_input_bandwidth(
0), zoom(0) {
InteractiveCanvas(parent, attribList), spectrumCanvas(NULL), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState(
WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0), plan(
NULL), in(NULL), out(NULL), resampler(NULL), resample_ratio(0), last_input_bandwidth(0), zoom(0) {
glContext = new WaterfallContext(this, &wxGetApp().GetContext(this));
@ -45,7 +43,6 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
fft_ceil_ma = fft_ceil_maa = 100.0;
fft_floor_ma = fft_floor_maa = 0.0;
mTracker.setTarget(this);
SetCursor(wxCURSOR_CROSS);
}
@ -53,20 +50,6 @@ WaterfallCanvas::~WaterfallCanvas() {
nco_crcf_destroy(nco_shift);
}
void WaterfallCanvas::SetView(int center_freq_in, int bandwidth_in) {
isView = true;
center_freq = center_freq_in;
bandwidth = bandwidth_in;
last_bandwidth = 0;
}
void WaterfallCanvas::DisableView() {
isView = false;
center_freq = wxGetApp().getFrequency();
bandwidth = SRATE;
last_bandwidth = 0;
}
void WaterfallCanvas::Setup(int fft_size_in, int waterfall_lines_in) {
if (fft_size == fft_size_in && waterfall_lines_in == waterfall_lines) {
return;
@ -90,38 +73,6 @@ void WaterfallCanvas::Setup(int fft_size_in, int waterfall_lines_in) {
glContext->Setup(fft_size, waterfall_lines);
}
int WaterfallCanvas::GetFrequencyAt(float x) {
int iqCenterFreq = GetCenterFrequency();
int iqBandwidth = GetBandwidth();
int freq = iqCenterFreq - (int) (0.5 * (float) iqBandwidth) + (int) ((float) x * (float) iqBandwidth);
return freq;
}
void WaterfallCanvas::SetCenterFrequency(unsigned int center_freq_in) {
center_freq = center_freq_in;
}
unsigned int WaterfallCanvas::GetCenterFrequency() {
if (isView) {
return center_freq;
} else {
return (unsigned int) wxGetApp().getFrequency();
}
}
void WaterfallCanvas::SetBandwidth(unsigned int bandwidth_in) {
bandwidth = bandwidth_in;
}
unsigned int WaterfallCanvas::GetBandwidth() {
if (isView) {
return bandwidth;
} else {
return SRATE;
}
}
WaterfallCanvas::DragState WaterfallCanvas::getDragState() {
return dragState;
}
@ -221,6 +172,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
}
void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) {
InteractiveCanvas::OnKeyUp(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
@ -235,12 +187,9 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) {
}
void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
InteractiveCanvas::OnKeyDown(event);
float angle = 5.0;
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
unsigned int freq;
@ -256,8 +205,20 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
freq = wxGetApp().getFrequency();
if (shiftDown) {
freq += SRATE * 10;
if (isView) {
SetView(center_freq + SRATE * 10, GetBandwidth());
if (spectrumCanvas) {
spectrumCanvas->SetView(GetCenterFrequency(), GetBandwidth());
}
}
} else {
freq += SRATE / 2;
if (isView) {
SetView(center_freq + SRATE / 2, GetBandwidth());
if (spectrumCanvas) {
spectrumCanvas->SetView(GetCenterFrequency(), GetBandwidth());
}
}
}
wxGetApp().setFrequency(freq);
((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq));
@ -266,11 +227,23 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
freq = wxGetApp().getFrequency();
if (shiftDown) {
freq -= SRATE * 10;
if (isView) {
SetView(center_freq - SRATE * 10, GetBandwidth());
if (spectrumCanvas) {
spectrumCanvas->SetView(GetCenterFrequency(), GetBandwidth());
}
}
} else {
freq -= SRATE / 2;
if (isView) {
SetView(center_freq - SRATE / 2, GetBandwidth());
if (spectrumCanvas) {
spectrumCanvas->SetView(GetCenterFrequency(), GetBandwidth());
}
}
}
wxGetApp().setFrequency(freq);
((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq));
((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequenfcy: %i"), freq));
break;
case 'D':
case WXK_DELETE:
@ -542,12 +515,7 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
}
void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
mTracker.OnMouseMoved(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
InteractiveCanvas::mouseMoved(event);
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator();
if (mTracker.mouseDown()) {
@ -670,12 +638,9 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) {
}
void WaterfallCanvas::mouseDown(wxMouseEvent& event) {
mTracker.OnMouseDown(event);
dragState = nextDragState;
InteractiveCanvas::mouseDown(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
dragState = nextDragState;
if (dragState && dragState != WF_DRAG_RANGE) {
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false);
@ -686,15 +651,11 @@ void WaterfallCanvas::mouseDown(wxMouseEvent& event) {
}
void WaterfallCanvas::mouseWheelMoved(wxMouseEvent& event) {
mTracker.OnMouseWheelMoved(event);
InteractiveCanvas::mouseWheelMoved(event);
}
void WaterfallCanvas::mouseReleased(wxMouseEvent& event) {
mTracker.OnMouseReleased(event);
shiftDown = event.ShiftDown();
altDown = event.AltDown();
ctrlDown = event.ControlDown();
InteractiveCanvas::mouseReleased(event);
bool isNew = shiftDown
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
@ -819,13 +780,13 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) {
}
void WaterfallCanvas::mouseLeftWindow(wxMouseEvent& event) {
mTracker.OnMouseLeftWindow(event);
InteractiveCanvas::mouseLeftWindow(event);
SetCursor(wxCURSOR_CROSS);
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
}
void WaterfallCanvas::mouseEnterWindow(wxMouseEvent& event) {
mTracker.OnMouseEnterWindow(event);
InteractiveCanvas::mouseEnterWindow(event);
SetCursor(wxCURSOR_CROSS);
}

View File

@ -6,13 +6,14 @@
#include <vector>
#include <queue>
#include "InteractiveCanvas.h"
#include "WaterfallContext.h"
#include "MouseTracker.h"
#include "SpectrumCanvas.h"
#include "fftw3.h"
class WaterfallCanvas: public wxGLCanvas {
class WaterfallCanvas: public InteractiveCanvas {
public:
enum DragState {
WF_DRAG_NONE, WF_DRAG_BANDWIDTH_LEFT, WF_DRAG_BANDWIDTH_RIGHT, WF_DRAG_FREQUENCY, WF_DRAG_RANGE
@ -23,16 +24,6 @@ public:
~WaterfallCanvas();
void setData(DemodulatorThreadIQData *input);
int GetFrequencyAt(float x);
void SetView(int center_freq_in, int bandwidth_in);
void DisableView();
void SetCenterFrequency(unsigned int center_freq_in);
unsigned int GetCenterFrequency();
void SetBandwidth(unsigned int bandwidth_in);
unsigned int GetBandwidth();
DragState getDragState();
DragState getNextDragState();
@ -53,7 +44,6 @@ private:
void mouseEnterWindow(wxMouseEvent& event);
void mouseLeftWindow(wxMouseEvent& event);
wxWindow *parent;
SpectrumCanvas *spectrumCanvas;
std::vector<float> spectrum_points;
@ -68,7 +58,6 @@ private:
std::vector<double> fft_result_maa;
WaterfallContext *glContext;
MouseTracker mTracker;
int activeDemodulatorBandwidth;
int activeDemodulatorFrequency;
@ -76,25 +65,15 @@ private:
DragState dragState;
DragState nextDragState;
bool shiftDown;
bool altDown;
bool ctrlDown;
int fft_size;
int waterfall_lines;
unsigned int center_freq;
unsigned int bandwidth;
bool isView;
msresamp_crcf resampler;
double resample_ratio;
nco_crcf nco_shift;
int shift_freq;
int last_input_bandwidth;
int last_bandwidth;
int zoom;
std::vector<liquid_float_complex> shift_buffer;