diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d80c3f..c6518a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,6 +257,7 @@ SET (cubicsdr_sources src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp src/visual/WaterfallContext.cpp + src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp external/tinyxml/tinyxml.cpp @@ -302,6 +303,11 @@ SET (cubicsdr_headers src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h src/visual/WaterfallContext.h + src/ui/GLPanel.h + src/ui/UITestCanvas.cpp + src/ui/UITestCanvas.h + src/ui/UITestContext.cpp + src/ui/UITestContext.h external/rtaudio/RtAudio.h external/lodepng/lodepng.h external/tinyxml/tinyxml.h @@ -314,6 +320,7 @@ include_directories ( ${PROJECT_SOURCE_DIR}/src/audio ${PROJECT_SOURCE_DIR}/src/util ${PROJECT_SOURCE_DIR}/src/visual + ${PROJECT_SOURCE_DIR}/src/ui ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/external/rtaudio ${PROJECT_SOURCE_DIR}/external/lodepng diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index b659b0f..e94783f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -119,6 +119,11 @@ AppFrame::AppFrame() : spectrumCanvas->attachWaterfallCanvas(waterfallCanvas); vbox->Add(waterfallCanvas, 20, wxEXPAND | wxALL, 0); + + vbox->AddSpacer(1); + testCanvas = new UITestCanvas(this, attribList); + vbox->Add(testCanvas, 20, wxEXPAND | wxALL, 0); + this->SetSizer(vbox); // waterfallCanvas->SetFocusFromKbd(); diff --git a/src/AppFrame.h b/src/AppFrame.h index 5788bb7..e3fcc5b 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -9,6 +9,7 @@ #include "MeterCanvas.h" #include "TuningCanvas.h" #include "ModeSelectorCanvas.h" +#include "UITestCanvas.h" #include @@ -77,6 +78,7 @@ private: MeterCanvas *demodSignalMeter; MeterCanvas *demodGainMeter; TuningCanvas *demodTuner; + UITestCanvas *testCanvas; DemodulatorInstance *activeDemodulator; diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp new file mode 100644 index 0000000..79f9ac8 --- /dev/null +++ b/src/ui/GLPanel.cpp @@ -0,0 +1,121 @@ + +#include "GLPanel.h" + + + +GLPanel::GLPanel() : fill(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE), contentsVisible(true) { + pos[0] = 0.0f; + pos[1] = 0.0f; + size[0] = 1.0f; + size[1] = 1.0f; + + genArrays(); +} + +void GLPanel::setViewport() { + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + + view[0] = vp[2]; + view[1] = vp[3]; +} + +void GLPanel::setPosition(float x, float y) { + pos[0] = x; + pos[1] = y; +} + +void GLPanel::setSize(float w, float h) { + size[0] = w; + size[1] = h; +} + +float GLPanel::getWidthPx() { + return size[0]*view[0]; +} + +float GLPanel::getHeightPx() { + return size[1]*view[0]; +} + +void GLPanel::setFill(GLPanelFillType fill_mode) { + fill = fill_mode; +} + +void GLPanel::setMargin(float marg) { + margin.left = margin.right = margin.top = margin.bottom = marg; +} + +void GLPanel::setMargin(float margl, float margr, float margt, float margb) { + margin.left = margl; + margin.right = margr; + margin.top = margt; + margin.bottom = margb; +} + + +void GLPanel::addChild(GLPanel *childPanel) { + children.push_back(childPanel); +} + +void GLPanel::drawChildren() { + if (children.size()) { + std::vector::iterator panel_i; + + for (panel_i = children.begin(); panel_i != children.end(); panel_i++) { + (*panel_i)->draw(this); + } + } +} + +void GLPanel::drawPanelContents() { + drawChildren(); +} + +void GLPanel::draw(GLPanel *parent) { + if (!parent) { + if (coord == GLPANEL_Y_DOWN_ZERO_ONE) { + glPushMatrix(); + glTranslatef(-1.0f, 1.0f, 0.0f); + glScalef(2.0f, -2.0f, 2.0f); + } + if (coord == GLPANEL_Y_UP_ZERO_ONE) { + glPushMatrix(); + glTranslatef(-1.0f, -1.0f, 0.0f); + glScalef(2.0f, 2.0f, 2.0f); + } + if (coord == GLPANEL_Y_DOWN) { + glPushMatrix(); + glScalef(1.0f, -1.0f, 1.0f); + } + if (coord == GLPANEL_Y_UP) { + glPushMatrix(); + } + } + glPushMatrix(); + glTranslatef(pos[0]+margin.left, pos[1]+margin.top, 0); + glScalef(size[0]-(margin.left+margin.right), size[1]-(margin.top+margin.bottom), 0); + + if (fill != GLPANEL_FILL_NONE) { + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, &glPoints[0]); + glColorPointer(3, GL_FLOAT, 0, &glColors[0]); + + glDrawArrays(GL_QUADS, 0, glPoints.size() / 2); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } + + if (contentsVisible) { + glPushMatrix(); + drawPanelContents(); + glPopMatrix(); + } + + glPopMatrix(); + if (!parent) { + glPopMatrix(); + } +} diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h new file mode 100644 index 0000000..1d31bb7 --- /dev/null +++ b/src/ui/GLPanel.h @@ -0,0 +1,109 @@ +#pragma once + +#include +#include "GLExt.h" + +class GLPanelEdges { +public: + float left; + float right; + float top; + float bottom; + + GLPanelEdges(): left(0), right(0), top(0), bottom(0) { + } + + GLPanelEdges(float l, float r, float t, float b) { + left = l; + right = r; + top = t; + bottom = b; + } +}; + +class GLPanel { +private: + std::vector glPoints; + std::vector glColors; + + void genArrays() { + if (!glPoints.size()) { + glPoints.resize(2 * 4); + glColors.resize(3 * 4); + } + + float pts[2 * 4] = { + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f + }; + + float clr[3 * 4] = { + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 1.0, 1.0 + }; + + glPoints.reserve(2 * 4); + glColors.reserve(3 * 4); + glPoints.assign(pts, pts + (2 * 4)); + glColors.assign(clr, clr + (3 * 4)); + } + +public: + typedef enum GLPanelFillType { GLPANEL_FILL_NONE, GLPANEL_FILL_SOLID } GLPanelFillType; + typedef enum GLPanelCoordinateSystem { GLPANEL_Y_DOWN_ZERO_ONE, GLPANEL_Y_UP_ZERO_ONE, GLPANEL_Y_UP, GLPANEL_Y_DOWN } GLPanelCoordinateSystem; + float pos[2]; + float size[2]; + float view[2]; + GLPanelFillType fill; + GLPanelCoordinateSystem coord; + GLPanelEdges margin; + GLPanelEdges border; + bool contentsVisible; + + std::vector children; + + GLPanel(); + + void setViewport(); + void setPosition(float x, float y); + void setSize(float w, float h); + float getWidthPx(); + float getHeightPx(); + + void setFill(GLPanelFillType fill_mode); + void setMargin(float marg); + void setMargin(float margl, float margr, float margt, float margb); + + void addChild(GLPanel *childPanel); + + void drawChildren(); + virtual void drawPanelContents(); + void draw(GLPanel *parent=NULL); +}; + + +class GLTestPanel : public GLPanel { +public: + GLTestPanel() : GLPanel() { + + } + + void drawPanelContents() { + glColor3f(1.0,1.0,1.0); + glBegin(GL_LINES); + glVertex2f(0, 0.5); + glVertex2f(1, 0.5); + glVertex2f(0.5, 0); + glVertex2f(0.5, 1); + + glVertex2f(0.5, 1); + glVertex2f(0.48, 0.80); + glVertex2f(0.5, 1); + glVertex2f(0.52, 0.80); + glEnd(); + } +}; diff --git a/src/ui/UITestCanvas.cpp b/src/ui/UITestCanvas.cpp new file mode 100644 index 0000000..e94a993 --- /dev/null +++ b/src/ui/UITestCanvas.cpp @@ -0,0 +1,85 @@ +#include "UITestCanvas.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 + +wxBEGIN_EVENT_TABLE(UITestCanvas, wxGLCanvas) EVT_PAINT(UITestCanvas::OnPaint) +EVT_IDLE(UITestCanvas::OnIdle) +EVT_MOTION(UITestCanvas::OnMouseMoved) +EVT_LEFT_DOWN(UITestCanvas::OnMouseDown) +EVT_LEFT_UP(UITestCanvas::OnMouseReleased) +EVT_LEAVE_WINDOW(UITestCanvas::OnMouseLeftWindow) +EVT_ENTER_WINDOW(UITestCanvas::OnMouseEnterWindow) +wxEND_EVENT_TABLE() + +UITestCanvas::UITestCanvas(wxWindow *parent, int *attribList) : +InteractiveCanvas(parent, attribList) { + + glContext = new UITestContext(this, &wxGetApp().GetContext(this)); +} + +UITestCanvas::~UITestCanvas() { + +} + +void UITestCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { + wxPaintDC dc(this); +#ifdef __APPLE__ // force half-rate? + glFinish(); +#endif + const wxSize ClientSize = GetClientSize(); + + glContext->SetCurrent(*this); + initGLExtensions(); + + glViewport(0, 0, ClientSize.x, ClientSize.y); + + glContext->DrawBegin(); + + glContext->Draw(); + + glContext->DrawEnd(); + + SwapBuffers(); +} + +void UITestCanvas::OnIdle(wxIdleEvent &event) { + Refresh(false); +} + +void UITestCanvas::OnMouseMoved(wxMouseEvent& event) { + InteractiveCanvas::OnMouseMoved(event); + +} + +void UITestCanvas::OnMouseDown(wxMouseEvent& event) { + InteractiveCanvas::OnMouseDown(event); +} + +void UITestCanvas::OnMouseWheelMoved(wxMouseEvent& event) { + InteractiveCanvas::OnMouseWheelMoved(event); +} + +void UITestCanvas::OnMouseReleased(wxMouseEvent& event) { + InteractiveCanvas::OnMouseReleased(event); +} + +void UITestCanvas::OnMouseLeftWindow(wxMouseEvent& event) { + InteractiveCanvas::OnMouseLeftWindow(event); +} + +void UITestCanvas::OnMouseEnterWindow(wxMouseEvent& event) { + InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event); +} diff --git a/src/ui/UITestCanvas.h b/src/ui/UITestCanvas.h new file mode 100644 index 0000000..29e042c --- /dev/null +++ b/src/ui/UITestCanvas.h @@ -0,0 +1,36 @@ +#pragma once + +#include "wx/glcanvas.h" +#include "wx/timer.h" + +#include +#include + +#include "InteractiveCanvas.h" +#include "UITestContext.h" +#include "MouseTracker.h" + +#include "fftw3.h" +#include "Timer.h" + +class UITestCanvas: public InteractiveCanvas { +public: + UITestCanvas(wxWindow *parent, int *attribList = NULL); + ~UITestCanvas(); + +private: + void OnPaint(wxPaintEvent& event); + void OnIdle(wxIdleEvent &event); + + void OnMouseMoved(wxMouseEvent& event); + void OnMouseDown(wxMouseEvent& event); + void OnMouseWheelMoved(wxMouseEvent& event); + void OnMouseReleased(wxMouseEvent& event); + void OnMouseEnterWindow(wxMouseEvent& event); + void OnMouseLeftWindow(wxMouseEvent& event); + + UITestContext *glContext; + + wxDECLARE_EVENT_TABLE(); +}; + diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp new file mode 100644 index 0000000..f7c5e2a --- /dev/null +++ b/src/ui/UITestContext.cpp @@ -0,0 +1,42 @@ +#include "UITestContext.h" +#include "UITestCanvas.h" +#include "ColorTheme.h" + +UITestContext::UITestContext(UITestCanvas *canvas, wxGLContext *sharedContext) : +PrimaryGLContext(canvas, sharedContext) { + testPanel.setPosition(0.0, 0.0); + testPanel.setSize(1.0, 1.0); + testPanel.setMargin(0.02, 0.02, 0.1, 0.1); + testChildPanel.setPosition(0.0, 0.0); + testChildPanel.setMargin(0.05); + testChildPanel.setSize(1.0, 0.3); + testChildPanel2.setPosition(0.0, 0.3); + testChildPanel2.setSize(1.0, 0.3); + testChildPanel2.setMargin(0.05); + testPanel.addChild(&testChildPanel); + testPanel.addChild(&testChildPanel2); +} + +void UITestContext::DrawBegin() { + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glClearColor(ThemeMgr::mgr.currentTheme->generalBackground.r, ThemeMgr::mgr.currentTheme->generalBackground.g, ThemeMgr::mgr.currentTheme->generalBackground.b, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_TEXTURE_2D); +} + +void UITestContext::Draw() { + testPanel.draw(); +} + +void UITestContext::DrawEnd() { + glFlush(); + + CheckGLError(); +} + diff --git a/src/ui/UITestContext.h b/src/ui/UITestContext.h new file mode 100644 index 0000000..9ac27bb --- /dev/null +++ b/src/ui/UITestContext.h @@ -0,0 +1,20 @@ +#pragma once + +#include "PrimaryGLContext.h" +#include "GLPanel.h" + +class UITestCanvas; + +class UITestContext: public PrimaryGLContext { +public: + UITestContext(UITestCanvas *canvas, wxGLContext *sharedContext); + + void DrawBegin(); + void Draw(); + void DrawEnd(); + +private: + GLPanel testPanel; + GLTestPanel testChildPanel; + GLPanel testChildPanel2; +};