Mode selector widget to replace menu

+ OSX keyboard focus fix
This commit is contained in:
Charles J. Cliffe 2015-01-06 00:29:33 -05:00
parent 082c8fbd12
commit 726113e9ea
7 changed files with 120 additions and 53 deletions

View File

@ -40,6 +40,10 @@ AppFrame::AppFrame() :
demodModeSelector = new ModeSelectorCanvas(this, NULL); demodModeSelector = new ModeSelectorCanvas(this, NULL);
demodModeSelector->addChoice(DEMOD_TYPE_FM,"FM");
demodModeSelector->addChoice(DEMOD_TYPE_AM,"AM");
demodModeSelector->addChoice(DEMOD_TYPE_LSB,"LSB");
demodModeSelector->addChoice(DEMOD_TYPE_USB,"USB");
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0); demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
// demodTray->AddSpacer(2); // demodTray->AddSpacer(2);
@ -94,20 +98,21 @@ AppFrame::AppFrame() :
this->SetSizer(vbox); this->SetSizer(vbox);
waterfallCanvas->SetFocusFromKbd(); // waterfallCanvas->SetFocusFromKbd();
waterfallCanvas->SetFocus(); waterfallCanvas->SetFocus();
// SetIcon(wxICON(sample)); // SetIcon(wxICON(sample));
// Make a menubar // Make a menubar
// wxMenu *menu = new wxMenu; wxMenuBar *menuBar = new wxMenuBar;
wxMenu *menu = new wxMenu;
// menu->Append(wxID_NEW); // menu->Append(wxID_NEW);
// menu->AppendSeparator(); // menu->AppendSeparator();
// menu->Append(wxID_CLOSE); menu->Append(wxID_CLOSE);
// wxMenuBar *menuBar = new wxMenuBar;
// menuBar->Append(menu, wxT("&File"));
wxMenu *menu = new wxMenu; menuBar->Append(menu, wxT("&File"));
menu = new wxMenu;
std::vector<RtAudio::DeviceInfo>::iterator devices_i; std::vector<RtAudio::DeviceInfo>::iterator devices_i;
std::map<int, RtAudio::DeviceInfo>::iterator mdevices_i; std::map<int, RtAudio::DeviceInfo>::iterator mdevices_i;
@ -136,17 +141,8 @@ AppFrame::AppFrame() :
outputDeviceMenuItems[mdevices_i->first] = itm; outputDeviceMenuItems[mdevices_i->first] = itm;
} }
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menu, wxT("Active Demodulator &Output")); menuBar->Append(menu, wxT("Active Demodulator &Output"));
wxMenu *demodMenu = new wxMenu;
demodMenuItems[DEMOD_TYPE_FM] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_FM, wxT("FM"), wxT("Description?"));
demodMenuItems[DEMOD_TYPE_AM] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_AM, wxT("AM"), wxT("Description?"));
demodMenuItems[DEMOD_TYPE_LSB] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_LSB, wxT("LSB"), wxT("Description?"));
demodMenuItems[DEMOD_TYPE_USB] = demodMenu->AppendRadioItem(wxID_DEMOD_TYPE_USB, wxT("USB"), wxT("Description?"));
menuBar->Append(demodMenu, wxT("Active Demodulator &Type"));
SetMenuBar(menuBar); SetMenuBar(menuBar);
CreateStatusBar(); CreateStatusBar();
@ -172,22 +168,6 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
activeDemodulator = NULL; activeDemodulator = NULL;
} }
} }
if (activeDemodulator) {
if (event.GetId() == wxID_DEMOD_TYPE_FM) {
activeDemodulator->setDemodulatorType(DEMOD_TYPE_FM);
activeDemodulator = NULL;
} else if (event.GetId() == wxID_DEMOD_TYPE_AM) {
activeDemodulator->setDemodulatorType(DEMOD_TYPE_AM);
activeDemodulator = NULL;
} else if (event.GetId() == wxID_DEMOD_TYPE_LSB) {
activeDemodulator->setDemodulatorType(DEMOD_TYPE_LSB);
activeDemodulator = NULL;
} else if (event.GetId() == wxID_DEMOD_TYPE_USB) {
activeDemodulator->setDemodulatorType(DEMOD_TYPE_USB);
activeDemodulator = NULL;
}
}
} }
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) { void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
@ -219,13 +199,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
scopeCanvas->setDeviceName(outputDevices[outputDevice].name); scopeCanvas->setDeviceName(outputDevices[outputDevice].name);
outputDeviceMenuItems[outputDevice]->Check(true); outputDeviceMenuItems[outputDevice]->Check(true);
int dType = demod->getDemodulatorType(); int dType = demod->getDemodulatorType();
demodMenuItems[dType]->Check(true); demodModeSelector->setSelection(dType);
} }
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) { if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
if (demod->getParams().frequency != demodWaterfallCanvas->getCenterFrequency()) { if (demod->getParams().frequency != demodWaterfallCanvas->getCenterFrequency()) {
demodWaterfallCanvas->setCenterFrequency(demod->getFrequency()); demodWaterfallCanvas->setCenterFrequency(demod->getFrequency());
demodSpectrumCanvas->setCenterFrequency(demod->getFrequency()); demodSpectrumCanvas->setCenterFrequency(demod->getFrequency());
} }
int dSelection = demodModeSelector->getSelection();
if (dSelection != -1 && dSelection != demod->getDemodulatorType()) {
demod->setDemodulatorType(dSelection);
}
unsigned int demodBw = (unsigned int) ceil((float) demod->getParams().bandwidth * 2.5); unsigned int demodBw = (unsigned int) ceil((float) demod->getParams().bandwidth * 2.5);
if (demodBw > SRATE / 2) { if (demodBw > SRATE / 2) {
demodBw = SRATE / 2; demodBw = SRATE / 2;
@ -280,6 +265,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
work_done = true; work_done = true;
} }
if (!waterfallCanvas->HasFocus()) {
waterfallCanvas->SetFocus();
}
if (!work_done) { if (!work_done) {
event.Skip(); event.Skip();
} }

View File

@ -13,10 +13,6 @@
#include <map> #include <map>
#define wxID_RT_AUDIO_DEVICE 1000 #define wxID_RT_AUDIO_DEVICE 1000
#define wxID_DEMOD_TYPE_FM 2000
#define wxID_DEMOD_TYPE_AM 2001
#define wxID_DEMOD_TYPE_LSB 2002
#define wxID_DEMOD_TYPE_USB 2003
// Define a new frame type // Define a new frame type
class AppFrame: public wxFrame { class AppFrame: public wxFrame {
@ -49,7 +45,5 @@ private:
std::map<int,RtAudio::DeviceInfo> outputDevices; std::map<int,RtAudio::DeviceInfo> outputDevices;
std::map<int,wxMenuItem *> outputDeviceMenuItems; std::map<int,wxMenuItem *> outputDeviceMenuItems;
std::map<int,wxMenuItem *> demodMenuItems;
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();
}; };

View File

@ -149,6 +149,14 @@ void MouseTracker::setHorizDragLock(bool dragLock) {
horizDragLock = dragLock; horizDragLock = dragLock;
} }
bool MouseTracker::getVertDragLock() {
return vertDragLock;
}
bool MouseTracker::getHorizDragLock() {
return horizDragLock;
}
bool MouseTracker::mouseDown() { bool MouseTracker::mouseDown() {
return isMouseDown; return isMouseDown;
} }

View File

@ -29,6 +29,8 @@ public:
void setVertDragLock(bool dragLock); void setVertDragLock(bool dragLock);
void setHorizDragLock(bool dragLock); void setHorizDragLock(bool dragLock);
bool getVertDragLock();
bool getHorizDragLock();
bool mouseDown(); bool mouseDown();
bool mouseRightDown(); bool mouseRightDown();
bool mouseInView(); bool mouseInView();

View File

@ -25,7 +25,7 @@ EVT_ENTER_WINDOW(ModeSelectorCanvas::OnMouseEnterWindow)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
ModeSelectorCanvas::ModeSelectorCanvas(wxWindow *parent, int *attribList) : ModeSelectorCanvas::ModeSelectorCanvas(wxWindow *parent, int *attribList) :
InteractiveCanvas(parent, attribList) { InteractiveCanvas(parent, attribList), currentSelection(-1), numChoices(0) {
glContext = new ModeSelectorContext(this, &wxGetApp().GetContext(this)); glContext = new ModeSelectorContext(this, &wxGetApp().GetContext(this));
} }
@ -34,6 +34,17 @@ ModeSelectorCanvas::~ModeSelectorCanvas() {
} }
int ModeSelectorCanvas::getHoveredSelection() {
if (!mouseTracker.mouseInView()) {
return -1;
}
float ypos = 1.0 - (mouseTracker.getMouseY() * 2.0);
float yval = (int) (((ypos + 1.0) / 2.0) * (float) numChoices);
return yval;
}
void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
wxPaintDC dc(this); wxPaintDC dc(this);
const wxSize ClientSize = GetClientSize(); const wxSize ClientSize = GetClientSize();
@ -43,10 +54,18 @@ void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glContext->DrawBegin(); glContext->DrawBegin();
glContext->DrawSelector("FM", 1, 4, true, 0.75, 0.75, 0.75, 1.0); DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
glContext->DrawSelector("AM", 2, 4, true, 0.75, 0.75, 0.75, 1.0);
glContext->DrawSelector("LSB", 3, 4, true, 0.75, 0.75, 0.75, 1.0); int demodType = 0;
glContext->DrawSelector("USB", 4, 4, true, 0.75, 0.75, 0.75, 1.0); if (demod) {
demodType = demod->getDemodulatorType();
}
int yval = getHoveredSelection();
for (int i = 0; i < numChoices; i++) {
glContext->DrawSelector(selections[i].label, i, numChoices, i == currentSelection || yval == i, (yval == i)?0.9:0.75, (yval == i)?0.9:0.75, (yval == i)?0.2:0.75, 1.0);
}
glContext->DrawEnd(); glContext->DrawEnd();
@ -75,19 +94,54 @@ void ModeSelectorCanvas::OnMouseReleased(wxMouseEvent& event) {
InteractiveCanvas::OnMouseReleased(event); InteractiveCanvas::OnMouseReleased(event);
mouseTracker.setHorizDragLock(false); mouseTracker.setHorizDragLock(false);
mouseTracker.setVertDragLock(false); mouseTracker.setVertDragLock(false);
SetCursor(wxCURSOR_ARROW);
const wxSize ClientSize = GetClientSize();
if (mouseTracker.getOriginDeltaMouseX() < 2.0 / ClientSize.y) {
currentSelection = getHoveredSelection();
}
SetCursor (wxCURSOR_ARROW);
} }
void ModeSelectorCanvas::OnMouseLeftWindow(wxMouseEvent& event) { void ModeSelectorCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
InteractiveCanvas::OnMouseLeftWindow(event); InteractiveCanvas::OnMouseLeftWindow(event);
SetCursor(wxCURSOR_CROSS); SetCursor (wxCURSOR_CROSS);
} }
void ModeSelectorCanvas::OnMouseEnterWindow(wxMouseEvent& event) { void ModeSelectorCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event); InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
SetCursor(wxCURSOR_ARROW); SetCursor (wxCURSOR_ARROW);
} }
void ModeSelectorCanvas::setHelpTip(std::string tip) { void ModeSelectorCanvas::setHelpTip(std::string tip) {
helpTip = tip; helpTip = tip;
} }
void ModeSelectorCanvas::setNumChoices(int numChoices_in) {
numChoices = numChoices_in;
}
void ModeSelectorCanvas::addChoice(int value, std::string label) {
selections.push_back(ModeSelectorMode(value, label));
numChoices = selections.size();
}
void ModeSelectorCanvas::setSelection(int value) {
for (int i = 0; i < numChoices; i++) {
if (selections[i].value == value) {
currentSelection = i;
return;
}
}
currentSelection = -1;
}
int ModeSelectorCanvas::getSelection() {
if (currentSelection == -1) {
return -1;
}
return selections[currentSelection].value;
}

View File

@ -13,14 +13,31 @@
#include "fftw3.h" #include "fftw3.h"
#include "Timer.h" #include "Timer.h"
class ModeSelectorMode {
public:
int value;
std::string label;
ModeSelectorMode(int value, std::string label) : value(value), label(label) {
}
};
class ModeSelectorCanvas: public InteractiveCanvas { class ModeSelectorCanvas: public InteractiveCanvas {
public: public:
ModeSelectorCanvas(wxWindow *parent, int *attribList = NULL); ModeSelectorCanvas(wxWindow *parent, int *attribList = NULL);
~ModeSelectorCanvas(); ~ModeSelectorCanvas();
int getHoveredSelection();
void setHelpTip(std::string tip); void setHelpTip(std::string tip);
void addChoice(int value, std::string label);
void setSelection(int value);
int getSelection();
private: private:
void setNumChoices(int numChoices_in);
void OnPaint(wxPaintEvent& event); void OnPaint(wxPaintEvent& event);
void OnIdle(wxIdleEvent &event); void OnIdle(wxIdleEvent &event);
@ -34,6 +51,9 @@ private:
ModeSelectorContext *glContext; ModeSelectorContext *glContext;
std::string helpTip; std::string helpTip;
int numChoices;
int currentSelection;
std::vector<ModeSelectorMode> selections;
// //
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();
}; };

View File

@ -37,23 +37,23 @@ void ModeSelectorContext::DrawSelector(std::string label, int c, int cMax, bool
glColor4f(r, g, b, a); glColor4f(r, g, b, a);
float y = 1.0 - ((float) c / (float) cMax * 2.0); float y = 1.0 - ((float) (c+1) / (float) cMax * 2.0);
float height = (2.0 / (float) cMax); float height = (2.0 / (float) cMax);
float padX = (4.0 / viewWidth); float padX = (4.0 / viewWidth);
float padY = (4.0 / viewHeight); float padY = (4.0 / viewHeight);
glBegin(GL_LINE_LOOP);
glBegin(on?GL_QUADS:GL_LINE_LOOP);
glVertex2f(-1.0 + padX, y + padY); glVertex2f(-1.0 + padX, y + padY);
glVertex2f(1.0 - padX, y + padY); glVertex2f(1.0 - padX, y + padY);
glVertex2f(1.0 - padX, y + height - padY); glVertex2f(1.0 - padX, y + height - padY);
glVertex2f(-1.0 + padX, y + height - padY); glVertex2f(-1.0 + padX, y + height - padY);
glEnd(); glEnd();
if (on) {
glColor4f(1.0-r, 1.0-g, 1.0-b, a);
}
getFont(fontSize).drawString(label, 0.0, y + height / 2.0, fontHeight, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); getFont(fontSize).drawString(label, 0.0, y + height / 2.0, fontHeight, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER);
// glEnable(GL_BLEND);
// glBlendFunc(GL_ONE, GL_ONE);
// glColor4f(r, g, b, a);
} }
void ModeSelectorContext::DrawEnd() { void ModeSelectorContext::DrawEnd() {