From 0206b2089a005d29e315fab3452fc54c9d01a5ca Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Thu, 26 May 2022 14:54:21 -0400 Subject: [PATCH 01/15] Improve NavigationBar and related tests --- src/opengl/ButtonWidget.hh | 2 + src/opengl/Canvas.cc | 12 ++- src/opengl/Canvas.hh | 3 +- src/opengl/GLWin.cc | 12 ++- src/opengl/GLWin.hh | 2 + src/opengl/NavigationBar.cc | 69 +++++++++------- src/opengl/NavigationBar.hh | 45 +++++----- src/opengl/Widget2D.hh | 50 +++++------ test/CMakeLists.txt | 161 ++++++++++++++++++------------------ test/xp/test2Tabs.cc | 53 ++++++++++++ test/xp/testMultiTab.cc | 35 +++----- 11 files changed, 262 insertions(+), 182 deletions(-) create mode 100644 test/xp/test2Tabs.cc diff --git a/src/opengl/ButtonWidget.hh b/src/opengl/ButtonWidget.hh index 30e368f1..6a35c4a7 100644 --- a/src/opengl/ButtonWidget.hh +++ b/src/opengl/ButtonWidget.hh @@ -25,4 +25,6 @@ class ButtonWidget : public InteractiveWidget2D { void setAction(Func func) { this->func = func; } + + void updateCanvas(MainCanvas* canvas) { c = canvas; }; }; \ No newline at end of file diff --git a/src/opengl/Canvas.cc b/src/opengl/Canvas.cc index 58da4f3e..e6d5dad1 100644 --- a/src/opengl/Canvas.cc +++ b/src/opengl/Canvas.cc @@ -17,6 +17,13 @@ Canvas::Canvas(Tab* tab) : Canvas(tab->getParentWin(), tab) {} Canvas::~Canvas() { cleanup(); } +void MainCanvas::copy(const MainCanvas& orig) { + gui = orig.gui; + guiText = orig.guiText; + menu = orig.menu; + menuText = orig.menuText; +} + void Canvas::cleanup() { for (uint32_t i = 0; i < layers.size(); i++) delete layers[i]; layers.clear(); @@ -86,8 +93,9 @@ void MainCanvas::init() { menuText->init(); tab->registerCallback(Tab::Inputs::MOUSE0_PRESS, "Widget Callback- Press", Tab::Security::SAFE, bind(&MainCanvas::click, this)); - tab->registerCallback(Tab::Inputs::MOUSE0_RELEASE, "Widget Callback- Release", - Tab::Security::SAFE, bind(&MainCanvas::click, this)); + // tab->registerCallback(Tab::Inputs::MOUSE0_RELEASE, "Widget Callback- + // Release", + // Tab::Security::SAFE, bind(&MainCanvas::click, this)); } void MainCanvas::render() { diff --git a/src/opengl/Canvas.hh b/src/opengl/Canvas.hh index 6eaf6596..28a0b7dd 100644 --- a/src/opengl/Canvas.hh +++ b/src/opengl/Canvas.hh @@ -54,7 +54,7 @@ class Canvas { // z!=0 } ~Canvas(); - Canvas(const Canvas& orig) = delete; + Canvas(const Canvas&) = delete; Canvas& operator=(const Canvas& orig) = delete; uint32_t getWidth() const { return vpW; } uint32_t getHeight() const { return vpH; } @@ -126,6 +126,7 @@ class MainCanvas : public Canvas { ~MainCanvas(); MainCanvas(const MainCanvas&) = delete; MainCanvas& operator=(const MainCanvas&) = delete; + void copy(const MainCanvas&); StyledMultiShape2D* getGui() { return gui; } MultiText* getGuiText() { return guiText; } StyledMultiShape2D* getMenu() { return menu; } diff --git a/src/opengl/GLWin.cc b/src/opengl/GLWin.cc index feb3f7a3..b0c35c7c 100644 --- a/src/opengl/GLWin.cc +++ b/src/opengl/GLWin.cc @@ -94,6 +94,7 @@ void GLWin::keyCallback(GLFWwindow *win, int key, int scancode, int action, int mods) { uint32_t input = (mods << 11) | (action << 9) | key; cerr << "key: " << key << " mods: " << mods << " input=" << input << '\n'; + winMap[win]->sharedTab->doit(input); winMap[win]->currentTab()->doit(input); } @@ -107,6 +108,7 @@ void GLWin::mouseButtonCallback(GLFWwindow *win, int button, int action, uint32_t input = (mods << 9) | (action << 3) | button; fmt::print("mouse!{}, action={}, location=({}, {}), input={}\n", button, action, w->mouseX, w->mouseY, input); + winMap[win]->sharedTab->doit(input); winMap[win]->currentTab()->doit(input); } @@ -114,6 +116,7 @@ void GLWin::scrollCallback(GLFWwindow *win, double xoffset, double yoffset) { // cout << "xoffset=" << xoffset << " yoffset=" << yoffset << '\n'; // todo: we would have to copy offsets into the object given the way this is uint32_t input = 400; + winMap[win]->sharedTab->doit(input + int(yoffset)); winMap[win]->currentTab()->doit(input + int(yoffset)); } @@ -247,6 +250,7 @@ void GLWin::startWindow() { guiTextStyle = new Style(guiFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); menuStyle = new Style(menuFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); menuTextStyle = new Style(menuFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); + sharedTab = new Tab(this); tabs.add(new Tab(this)); current = 0; hasBeenInitialized = true; @@ -272,6 +276,7 @@ void GLWin::baseInit() { for (int i = 0; i < tabs.size(); ++i) { tabs[i]->init(); } + sharedTab->init(); } int GLWin::init(GLWin *g, uint32_t w, uint32_t h, uint32_t exitAfter) { @@ -300,6 +305,8 @@ void GLWin::cleanup() { delete tabs[i]; // TODO:cw[i]->cleanup(); } tabs.clear(); + delete sharedTab; + sharedTab = nullptr; delete defaultStyle; defaultStyle = nullptr; Shader::cleanAll(); @@ -349,6 +356,7 @@ void GLWin::mainLoop() { bgColor.a); // Clear the colorbuffer and depth glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); render(); + sharedTab->render(); renderTime += glfwGetTime() - startRender; glfwSwapBuffers(win); // Swap buffer so the scene shows on screen if (frameCount >= 150) { @@ -367,10 +375,12 @@ void GLWin::mainLoop() { } currentTab()->tick(); // update time in current tab for any models using // simulation time + sharedTab->tick(); needsUpdate = false; glfwPollEvents(); // Check and call events // note: any events needing a refresh should set dirty = true if (currentTab()->checkUpdate()) setUpdate(); + if (sharedTab->checkUpdate()) setUpdate(); if (needsUpdate) { update(); needsRender = true; @@ -480,7 +490,7 @@ void GLWin::prevTab() { Tab *GLWin::addTab() { Tab *newTab = new Tab(this); tabs.add(newTab); - current = tabs.size() - 1; + // current = tabs.size() - 1; return newTab; } diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index d9bdc860..4c874fe2 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -52,6 +52,7 @@ class GLWin { uint32_t frameNum; double lastRenderTime; // Stores last time of render char frameName[32]; + Tab* sharedTab; DynArray tabs; // list of web pages, ie tabs uint32_t current; // current (active) tab void checkUpdate(); @@ -124,6 +125,7 @@ class GLWin { MainCanvas* getMainCanvas(); Tab* currentTab() { return tabs[current]; } + Tab* getSharedTab() { return sharedTab; } void setSize(uint32_t w, uint32_t h) { width = w; diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index ce2ad3ba..d74c232a 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -27,55 +27,64 @@ NavigationBar::NavigationBar(MainCanvas* initialCanvas, canvases.insert(initialCanvas); this->isVertical = isVertical; + defaultButtonHeight = min(48_f32, height); defaultButtonWidth = min(90_f32, width); defaultEdgeWidth = min(16_f32, width / 3); - + /* addButton(defaultButtonWidth, defaultButtonHeight, axisPadding, "+", "add tab") .setAction(bind(&NavigationBar::addTab, this)); + */ } -NavigationBar::NavigationBar(Tab* initialTab, float x, float y, float width, +NavigationBar::NavigationBar(GLWin* w, float x, float y, float width, float height, float axisPadding, bool isVertical) - : NavigationBar{initialTab->getMainCanvas(), - initialTab->getMainCanvas()->getStyle(), - x, - y, - width, - height, - axisPadding, - isVertical} { - parentWin = initialTab->getParentWin(); + : NavigationBar(w->getSharedTab()->getMainCanvas(), + w->getSharedTab()->getMainCanvas()->getStyle(), x, y, width, + height, axisPadding, isVertical) { + parentWin = w; } -ButtonWidget& NavigationBar::addButton(float width, float height, +ButtonWidget* NavigationBar::addButton(float width, float height, float axisOffset, string label, const char action[]) { - buttons.emplace_back(currentCanvas, xPos, yPos, width, height, label, action); - buttons.back().setStyledMultiShape(&m); - buttons.back().setMultiText(&t); - buttons.back().redraw(); + if (isVertical) { + // TODO: emplace_back failing to copy m + // buttons.emplace_back(currentCanvas, xPos, yPos + axisOffset, width, + // height, label, action); + buttons.push_back(new ButtonWidget(currentCanvas, xPos, yPos + axisOffset, + width, height, label, action)); + } else { + // TODO: ditto + // buttons.emplace_back(currentCanvas, xPos + axisOffset, yPos, width, + // height, label, action); + buttons.push_back(new ButtonWidget(currentCanvas, xPos + axisOffset, yPos, + width, height, label, action)); + } + // buttons.back().setStyledMultiShape(&m); + // buttons.back().setMultiText(&t); + // buttons.back().redraw(); return buttons.back(); } -void NavigationBar::addTab() { +void NavigationBar::setButtonAction( + int buttonIndex, std::optional> func) { + buttons[buttonIndex]->setAction(func); +} + +void NavigationBar::addNewTab() { Tab* t = parentWin->addTab(); - t->addMember(this); - reparentButtons(t->getMainCanvas()); - t->setUpdate(); - t->setRender(); + addToTab(t); } -void NavigationBar::reparentButtons(MainCanvas* c) { - if (canvases.find(c) == canvases.end()) { - c->addLayer(&m); - c->addLayer(&t); - canvases.insert(c); - } - for (ButtonWidget& b : buttons) { - c->addClickableWidget(&b); - } +void NavigationBar::addToTab(Tab* tab) { + tab->addMember(this); + MainCanvas* newCanvas = tab->getMainCanvas(); + canvases.insert(newCanvas); + newCanvas->copy(*currentCanvas); + tab->setUpdate(); + tab->setRender(); } void NavigationBar::balanceButtons(int numButtons) {} \ No newline at end of file diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index ed8159dc..34965b18 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -1,12 +1,13 @@ #pragma once +#include #include #include "opengl/ButtonWidget.hh" class NavigationBar : public Member { private: - std::vector buttons; + std::vector buttons; std::unordered_set canvases; GLWin* parentWin; MainCanvas* currentCanvas; @@ -41,7 +42,7 @@ class NavigationBar : public Member { /** * @brief Create a new (horizontal or vertical) navigation bar * - * @param initialTab The initial tab to draw on + * @param w The initial window to draw on * @param x x-coordinate of top-left corner * @param y y-coordinate of top-left corner * @param width width of navigation bar @@ -49,7 +50,7 @@ class NavigationBar : public Member { * @param axisPadding distance between the edges of two buttons * @param isVertical allow vertical navigation bars (e.x. Ubuntu's task bar) */ - NavigationBar(Tab* initialTab, float x, float y, float width, float height, + NavigationBar(GLWin* w, float x, float y, float width, float height, float axisPadding, bool isVertical = false); /** @@ -62,35 +63,41 @@ class NavigationBar : public Member { * @param action a description of the button's action * @return ButtonWidget& a reference to the new button */ - ButtonWidget& addButton(float width, float height, float axisOffset, + ButtonWidget* addButton(float width, float height, float axisOffset, std::string label, const char action[]); /** - * @brief Balance n buttons on the nav bar - * - * This is particularly useful in scenarios where a screen can fit n tabs and - * there are m tabs that could be displayed (n < m). In this case, the - * NavigationBar will determine the ideal placement of each button such that - * at most numButtons will be displayed at a given time. + * @brief Set an action for a button in the nav bar * - * @param numButtons number of buttons to display + * @param buttonIndex index of button in buttons vector + * @param func function call for action */ - void balanceButtons(int numButtons); + void setButtonAction(int buttonIndex, + std::optional> func); /** - * @brief Allows the buttons to be reparented to a new MainCanvas + * @brief Balance n buttons on the nav bar * - * This function uses the fact that each InteractiveWidget2D, and therefore - * each Widget2D can use a custom StyledMultiShape2D and MultiText to swap - * over to a new MainCanvas and redraw each shape. + * This is particularly useful in scenarios where a screen can fit n tabs + * and there are m tabs that could be displayed (n < m). In this case, the + * NavigationBar will determine the ideal placement of each button such + * that at most numButtons will be displayed at a given time. * - * @param c + * @param numButtons number of buttons to display */ - void reparentButtons(MainCanvas* c); + void balanceButtons(int numButtons); /** * @brief Adds a new tab to the window and adds the navigation bar to the tab * */ - void addTab(); + void addNewTab(); + + void addToTab(Tab* tab); + + /* + void render() { + std::cout << "printing from NavigationBar::render()" << std::endl; + } + */ }; \ No newline at end of file diff --git a/src/opengl/Widget2D.hh b/src/opengl/Widget2D.hh index 4846cbee..8817a20d 100644 --- a/src/opengl/Widget2D.hh +++ b/src/opengl/Widget2D.hh @@ -1,25 +1,25 @@ -#pragma once -#include "opengl/GrailGUI.hh" - -/* - Represent a compound object to be drawn using StyledMultiShape2D and MultiText - -*/ - -class StyledMultiShape2D; -class MultiText; - -class Widget2D { - protected: - StyledMultiShape2D* m; - MultiText* t; - float x, y; // top left corner of the widget on the screen - float w, h; // width and height of the widget - public: - Widget2D(StyledMultiShape2D* m, MultiText* t, float x, float y, float w, - float h) - : m(m), t(t), x(x), y(y), w(w), h(h) {} - void setStyledMultiShape(StyledMultiShape2D* m) { this->m = m; } - void setMultiText(MultiText* t) { this->t = t; } - virtual void init() = 0; -}; +#pragma once +#include "opengl/GrailGUI.hh" + +/* + Represent a compound object to be drawn using StyledMultiShape2D and MultiText + +*/ + +class StyledMultiShape2D; +class MultiText; + +class Widget2D { + protected: + StyledMultiShape2D* m; + MultiText* t; + float x, y; // top left corner of the widget on the screen + float w, h; // width and height of the widget + public: + Widget2D(StyledMultiShape2D* m, MultiText* t, float x, float y, float w, + float h) + : m(m), t(t), x(x), y(y), w(w), h(h) {} + void setStyledMultiShape(StyledMultiShape2D* m) { this->m = m; } + void setMultiText(MultiText* t) { this->t = t; } + virtual void init() = 0; +}; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index de20284d..b7063d94 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,80 +1,81 @@ - -# add_grail_executable([BINNAME ] SRC LIBS ) - -# 2D Graphics -add_subdirectory(2d) - -# 3D Graphics -add_subdirectory(3d) - -# CAD -# add_grail_executable(SRC CAD/CurveTest.cc LIBS grail) -# add_grail_executable(SRC CAD/HelixTest.cc LIBS grail) -# add_grail_executable(SRC CAD/BezierTest.cc LIBS grail) -# add_grail_executable(SRC CAD/Vec3DTest.cc LIBS grail) -# add_grail_executable(SRC CAD/CircleTest.cc LIBS grail) -# add_grail_executable(SRC CAD/ExtrusionTest.cc LIBS grail) -# add_grail_executable(SRC CAD/FacetTest.cc LIBS grail) -# add_grail_executable(SRC CAD/LineTest.cc LIBS grail) -# add_grail_executable(SRC CAD/LinkedPathTest.cc LIBS grail) -# add_grail_executable(SRC CAD/CurveTest.cc LIBS grail) -# add_grail_executable(SRC CAD/testCylinder.cc LIBS grail) -# add_grail_executable(SRC CAD/testSphere.cc LIBS grail) -# add_grail_executable(SRC CAD/testRectangularPrism.cc LIBS grail) -# add_grail_executable(SRC CAD/testTriangle.cc LIBS grail) -# add_grail_executable(SRC CAD/testRectangle.cc LIBS grail) -# add_grail_executable(SRC CAD/testCircle.cc LIBS grail) -# add_grail_executable(SRC CAD/testGear.cc LIBS grail) -# add_grail_executable(SRC CAD/testTransform.cc LIBS grail) - -# Graphs -add_subdirectory(graph) - -# GUI -# add_grail_executable(SRC GUI/testWidgets.cc LIBS grail) - -# Maps -add_grail_executable(SRC maps/convertESRItoBlockLoader.cc LIBS grail) -# add_grail_executable(SRC maps/loadESRIShapefile.cc LIBS grail) -# add_grail_executable(SRC maps/testESRIPolygon.cc LIBS grail) -add_grail_executable(SRC maps/testDrawBlockMap.cc LIBS grail) -# add_grail_executable(SRC maps/ESRIMapDemo.cc LIBS grail) -add_grail_executable(SRC maps/testLoadFromESRI.cc LIBS grail) -add_grail_executable(SRC maps/testFastMapLoad.cc LIBS grail) - - - -# Media -if(${MPV_FOUND} AND ${PC_MPV_VERSION} VERSION_GREATER "1.26") - add_grail_executable(SRC media/testSingleAudio.cc LIBS grail) - add_grail_executable(SRC media/testAudio.cc LIBS grail) - add_grail_executable(SRC media/testVideo.cc LIBS grail) -endif() - -# Networking - -# Solar System -# add_grail_executable(BINNAME testSolar SRC solarsystem/DrawNASAEphemerisSolarSystem2d.cc LIBS grail) - - -# XDL -# add_grail_executable(SRC xdl/testStockServer.cc LIBS grail) -add_grail_executable(SRC xdl/testXDLButton.cc LIBS grail) - -# XP (Experimental) -add_grail_executable(SRC xp/testfmt.cc LIBS grail) -add_grail_executable(SRC xp/testMultiTab.cc LIBS grail) - -# Unsorted -# add_grail_executable(SRC ../src/xp/decompressBlockLoader.cc LIBS grail lzma) -add_grail_executable(SRC ../src/csp/GenericXDLClient.cc LIBS grail) -add_grail_executable(SRC ../src/csp/SimpleXDLServer.cc LIBS grail) -# add_grail_executable(SRC ../src/csp/GraphicalXDLClient.cc LIBS grailserver) -# add_grail_executable(SRC testPopupMenu.cc LIBS grail) -# add_grail_executable(SRC StockDemo.cc LIBS grail) - - - - - - + +# add_grail_executable([BINNAME ] SRC LIBS ) + +# 2D Graphics +add_subdirectory(2d) + +# 3D Graphics +add_subdirectory(3d) + +# CAD +# add_grail_executable(SRC CAD/CurveTest.cc LIBS grail) +# add_grail_executable(SRC CAD/HelixTest.cc LIBS grail) +# add_grail_executable(SRC CAD/BezierTest.cc LIBS grail) +# add_grail_executable(SRC CAD/Vec3DTest.cc LIBS grail) +# add_grail_executable(SRC CAD/CircleTest.cc LIBS grail) +# add_grail_executable(SRC CAD/ExtrusionTest.cc LIBS grail) +# add_grail_executable(SRC CAD/FacetTest.cc LIBS grail) +# add_grail_executable(SRC CAD/LineTest.cc LIBS grail) +# add_grail_executable(SRC CAD/LinkedPathTest.cc LIBS grail) +# add_grail_executable(SRC CAD/CurveTest.cc LIBS grail) +# add_grail_executable(SRC CAD/testCylinder.cc LIBS grail) +# add_grail_executable(SRC CAD/testSphere.cc LIBS grail) +# add_grail_executable(SRC CAD/testRectangularPrism.cc LIBS grail) +# add_grail_executable(SRC CAD/testTriangle.cc LIBS grail) +# add_grail_executable(SRC CAD/testRectangle.cc LIBS grail) +# add_grail_executable(SRC CAD/testCircle.cc LIBS grail) +# add_grail_executable(SRC CAD/testGear.cc LIBS grail) +# add_grail_executable(SRC CAD/testTransform.cc LIBS grail) + +# Graphs +add_subdirectory(graph) + +# GUI +# add_grail_executable(SRC GUI/testWidgets.cc LIBS grail) + +# Maps +add_grail_executable(SRC maps/convertESRItoBlockLoader.cc LIBS grail) +# add_grail_executable(SRC maps/loadESRIShapefile.cc LIBS grail) +# add_grail_executable(SRC maps/testESRIPolygon.cc LIBS grail) +add_grail_executable(SRC maps/testDrawBlockMap.cc LIBS grail) +# add_grail_executable(SRC maps/ESRIMapDemo.cc LIBS grail) +add_grail_executable(SRC maps/testLoadFromESRI.cc LIBS grail) +add_grail_executable(SRC maps/testFastMapLoad.cc LIBS grail) + + + +# Media +if(${MPV_FOUND} AND ${PC_MPV_VERSION} VERSION_GREATER "1.26") + add_grail_executable(SRC media/testSingleAudio.cc LIBS grail) + add_grail_executable(SRC media/testAudio.cc LIBS grail) + add_grail_executable(SRC media/testVideo.cc LIBS grail) +endif() + +# Networking + +# Solar System +# add_grail_executable(BINNAME testSolar SRC solarsystem/DrawNASAEphemerisSolarSystem2d.cc LIBS grail) + + +# XDL +# add_grail_executable(SRC xdl/testStockServer.cc LIBS grail) +add_grail_executable(SRC xdl/testXDLButton.cc LIBS grail) + +# XP (Experimental) +add_grail_executable(SRC xp/testfmt.cc LIBS grail) +add_grail_executable(SRC xp/testMultiTab.cc LIBS grail) +add_grail_executable(SRC xp/test2Tabs.cc LIBS grail) + +# Unsorted +# add_grail_executable(SRC ../src/xp/decompressBlockLoader.cc LIBS grail lzma) +add_grail_executable(SRC ../src/csp/GenericXDLClient.cc LIBS grail) +add_grail_executable(SRC ../src/csp/SimpleXDLServer.cc LIBS grail) +# add_grail_executable(SRC ../src/csp/GraphicalXDLClient.cc LIBS grailserver) +# add_grail_executable(SRC testPopupMenu.cc LIBS grail) +# add_grail_executable(SRC StockDemo.cc LIBS grail) + + + + + + diff --git a/test/xp/test2Tabs.cc b/test/xp/test2Tabs.cc new file mode 100644 index 00000000..0b8750e3 --- /dev/null +++ b/test/xp/test2Tabs.cc @@ -0,0 +1,53 @@ +#include + +#include "fmt/core.h" +#include "opengl/GrailGUI.hh" +#include "opengl/NavigationBar.hh" +#include "util/Ex.hh" + +using namespace std; +using namespace grail; + +class Member1 : public Member { + public: + Member1(Tab* tab) : Member(tab, 0, 0) { + MainCanvas* c = tab->getMainCanvas(); + StyledMultiShape2D* gui = c->getGui(); + + gui->fillRectangle(500, 600, 200, 200, red); + } +}; + +class Member2 : public Member { + public: + Member2(Tab* tab) : Member(tab, 0, 0) { + MainCanvas* c = tab->getMainCanvas(); + StyledMultiShape2D* gui = c->getGui(); + + gui->drawCircle(450, 50, 45, 5, purple); + } +}; + +class MultiTab : public NavigationBar { + public: + MultiTab(GLWin* w); +}; + +MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { + ButtonWidget* hi = addButton(200, 30, 0, "hi", "print hi"); + auto action = []() { fmt::print("hi\n"); }; + hi->setAction(action); + + ButtonWidget* next = addButton(200, 30, 50, "next", "next tab"); + auto action2 = [w]() { w->nextTab(); }; + next->setAction(action2); +} + +void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { + w->setTitle("Test Tabs"); + new Member1(defaultTab); + MultiTab* m = new MultiTab(w); + Tab* t2 = w->addTab(); + // m->addToTab(t2); + new Member2(t2); +} \ No newline at end of file diff --git a/test/xp/testMultiTab.cc b/test/xp/testMultiTab.cc index b6cfa402..3c8cb39b 100644 --- a/test/xp/testMultiTab.cc +++ b/test/xp/testMultiTab.cc @@ -1,40 +1,27 @@ #include -#include "opengl/ButtonWidget.hh" #include "opengl/GrailGUI.hh" #include "opengl/NavigationBar.hh" using namespace std; -class MultiTab : public Member { +class MultiTab : public NavigationBar { private: - ButtonWidget prev, next, add; - GLWin* parentWin; + GLWin* w; public: - void addTab(); - - MultiTab(Tab* tab); + MultiTab(GLWin* w); }; -void MultiTab::addTab() { - Tab* t = parentWin->addTab(); - t->addMember(this); - t->setUpdate(); -} - -MultiTab::MultiTab(Tab* tab) - : Member(tab), - prev(c, 0, 0, 200, 30, "previous", "previous tab"), - next(c, 0, 50, 200, 30, "next", "next tab"), - add(c, 0, 100, 200, 30, "+", "add tab") { - parentWin = tab->getParentWin(); - prev.setAction(bind(&GLWin::prevTab, parentWin)); - next.setAction(bind(&GLWin::nextTab, parentWin)); - add.setAction(bind(&MultiTab::addTab, this)); +MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { + ButtonWidget& prev = addButton(200, 30, 0, "previous", "previous tab"); + prev.setAction(bind(&GLWin::prevTab, w)); + ButtonWidget& next = addButton(200, 30, 50, "next", "next tab"); + next.setAction(bind(&GLWin::nextTab, w)); + ButtonWidget& add = addButton(200, 30, 100, "+", "add tab"); + add.setAction(bind(&MultiTab::addNewTab, this)); } void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { - new MultiTab(defaultTab); - new NavigationBar(defaultTab, 0, 500, 600, 50, 2); + new MultiTab(w); } From 8ffe91f2dc5cd2e95f15c39216ed4f7f5a90ec5c Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Thu, 26 May 2022 15:58:38 -0400 Subject: [PATCH 02/15] fix testMultiTab --- src/opengl/GLWin.cc | 1 - src/opengl/GLWin.hh | 1 + src/opengl/NavigationBar.cc | 4 +++- test/xp/test2Tabs.cc | 1 - test/xp/testMultiTab.cc | 15 ++++++--------- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/opengl/GLWin.cc b/src/opengl/GLWin.cc index b0c35c7c..3084b3c6 100644 --- a/src/opengl/GLWin.cc +++ b/src/opengl/GLWin.cc @@ -490,7 +490,6 @@ void GLWin::prevTab() { Tab *GLWin::addTab() { Tab *newTab = new Tab(this); tabs.add(newTab); - // current = tabs.size() - 1; return newTab; } diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index 4c874fe2..9a44e657 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -189,5 +189,6 @@ Shape* pick(int x, int y, Shape*); // click on (x,y), get Shape behind void prevTab(); Tab* addTab(); void removeTab(); + void toLastTab() { current = tabs.size() - 1; } void goToLink(const char ipaddr[], uint16_t port, uint32_t requestID); }; diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index d74c232a..dfb09e11 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -75,7 +75,9 @@ void NavigationBar::setButtonAction( void NavigationBar::addNewTab() { Tab* t = parentWin->addTab(); - addToTab(t); + canvases.insert(t->getMainCanvas()); + parentWin->toLastTab(); + // addToTab(t); } void NavigationBar::addToTab(Tab* tab) { diff --git a/test/xp/test2Tabs.cc b/test/xp/test2Tabs.cc index 0b8750e3..71c6636f 100644 --- a/test/xp/test2Tabs.cc +++ b/test/xp/test2Tabs.cc @@ -48,6 +48,5 @@ void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { new Member1(defaultTab); MultiTab* m = new MultiTab(w); Tab* t2 = w->addTab(); - // m->addToTab(t2); new Member2(t2); } \ No newline at end of file diff --git a/test/xp/testMultiTab.cc b/test/xp/testMultiTab.cc index 3c8cb39b..b6987699 100644 --- a/test/xp/testMultiTab.cc +++ b/test/xp/testMultiTab.cc @@ -6,20 +6,17 @@ using namespace std; class MultiTab : public NavigationBar { - private: - GLWin* w; - public: MultiTab(GLWin* w); }; MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { - ButtonWidget& prev = addButton(200, 30, 0, "previous", "previous tab"); - prev.setAction(bind(&GLWin::prevTab, w)); - ButtonWidget& next = addButton(200, 30, 50, "next", "next tab"); - next.setAction(bind(&GLWin::nextTab, w)); - ButtonWidget& add = addButton(200, 30, 100, "+", "add tab"); - add.setAction(bind(&MultiTab::addNewTab, this)); + ButtonWidget* prev = addButton(200, 30, 0, "previous", "previous tab"); + prev->setAction(bind(&GLWin::prevTab, w)); + ButtonWidget* next = addButton(200, 30, 50, "next", "next tab"); + next->setAction(bind(&GLWin::nextTab, w)); + ButtonWidget* add = addButton(200, 30, 100, "+", "add tab"); + add->setAction(bind(&MultiTab::addNewTab, this)); } void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { From cbd619397d17cfde9e880219163d3d3eff5ad4fd Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Fri, 27 May 2022 15:14:10 -0400 Subject: [PATCH 03/15] improve grailmain, NavigationBar --- src/opengl/ButtonWidget.hh | 5 +++++ src/opengl/GLWin.cc | 13 ++++++++---- src/opengl/GLWin.hh | 5 +++-- src/opengl/Main.cc | 5 ++--- src/opengl/Member.cc | 3 +++ src/opengl/Member.hh | 1 + src/opengl/NavigationBar.cc | 30 ++++++++++++++------------ src/opengl/NavigationBar.hh | 11 +++++++--- test/CMakeLists.txt | 2 +- test/xp/test2Tabs.cc | 42 ++++++++++++++++--------------------- test/xp/testMultiTab.cc | 9 ++++---- 11 files changed, 72 insertions(+), 54 deletions(-) diff --git a/src/opengl/ButtonWidget.hh b/src/opengl/ButtonWidget.hh index 6a35c4a7..393029c8 100644 --- a/src/opengl/ButtonWidget.hh +++ b/src/opengl/ButtonWidget.hh @@ -27,4 +27,9 @@ class ButtonWidget : public InteractiveWidget2D { } void updateCanvas(MainCanvas* canvas) { c = canvas; }; + + float getX() { return x; }; + float getY() { return y; }; + float getW() { return w; }; + float getH() { return h; }; }; \ No newline at end of file diff --git a/src/opengl/GLWin.cc b/src/opengl/GLWin.cc index 3084b3c6..ee522638 100644 --- a/src/opengl/GLWin.cc +++ b/src/opengl/GLWin.cc @@ -251,8 +251,8 @@ void GLWin::startWindow() { menuStyle = new Style(menuFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); menuTextStyle = new Style(menuFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); sharedTab = new Tab(this); - tabs.add(new Tab(this)); - current = 0; + // tabs.add(new Tab(this)); + current = -1; hasBeenInitialized = true; } void GLWin::baseInit() { @@ -313,9 +313,13 @@ void GLWin::cleanup() { } void GLWin::init() {} -void GLWin::render() { currentTab()->render(); } +void GLWin::render() { + if (current >= 0) currentTab()->render(); +} // default is no animation. Override if you want your class to animate -void GLWin::update() { currentTab()->update(); } +void GLWin::update() { + if (current >= 0) currentTab()->update(); +} // declare prototype access to static function in other file which calls // FaceFont::cleanup() @@ -490,6 +494,7 @@ void GLWin::prevTab() { Tab *GLWin::addTab() { Tab *newTab = new Tab(this); tabs.add(newTab); + current = tabs.size() - 1; return newTab; } diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index 9a44e657..5fbce49e 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -54,7 +54,7 @@ class GLWin { char frameName[32]; Tab* sharedTab; DynArray tabs; // list of web pages, ie tabs - uint32_t current; // current (active) tab + int32_t current; // current (active) tab void checkUpdate(); public: @@ -189,6 +189,7 @@ Shape* pick(int x, int y, Shape*); // click on (x,y), get Shape behind void prevTab(); Tab* addTab(); void removeTab(); - void toLastTab() { current = tabs.size() - 1; } + void switchTab(int tabIndex) { current = tabIndex; }; + void toLastTab() { current = tabs.size() - 1; }; void goToLink(const char ipaddr[], uint16_t port, uint32_t requestID); }; diff --git a/src/opengl/Main.cc b/src/opengl/Main.cc index 6afb5bbd..f87c12f3 100644 --- a/src/opengl/Main.cc +++ b/src/opengl/Main.cc @@ -4,13 +4,12 @@ using namespace std; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab); +void grailmain(int argc, char* argv[], GLWin* w); int main(int argc, char* argv[]) { try { GLWin w(1024, 800, 0xFFFFFFFF, 0x000000FF, "Grail Window"); - Tab* tab = w.currentTab(); - grailmain(argc, argv, &w, tab); + grailmain(argc, argv, &w); w.mainLoop(); // g->t = thread(crun, g); // TODO: move this to GLWin::cleanup or destructor? FontFace::emptyFaces(); diff --git a/src/opengl/Member.cc b/src/opengl/Member.cc index 0dd6b3ad..1dfa211d 100644 --- a/src/opengl/Member.cc +++ b/src/opengl/Member.cc @@ -13,6 +13,9 @@ Member::Member(Tab* tab, double frameRate, double dt) tab->addMember(this); } +Member::Member(GLWin* w, double frameRate, double dt) + : Member(w->addTab(), frameRate, dt) {} + void Member::setFrameRate(double frameRate) { tab->setFrameRate(frameRate); } void Member::setModelDt(double dt, double defaultDt) { diff --git a/src/opengl/Member.hh b/src/opengl/Member.hh index e5a14802..2d151ebe 100644 --- a/src/opengl/Member.hh +++ b/src/opengl/Member.hh @@ -14,6 +14,7 @@ class Member { public: Member(Tab* tab, double frameRate = -1, double dt = 0.0001); + Member(GLWin* w, double frameRate = -1, double dt = 0.0001); void setFrameRate(double frameRate); void setModelDt(double dt, double defaultDt); diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index dfb09e11..451076a6 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -46,28 +46,30 @@ NavigationBar::NavigationBar(GLWin* w, float x, float y, float width, parentWin = w; } -ButtonWidget* NavigationBar::addButton(float width, float height, - float axisOffset, string label, +ButtonWidget* NavigationBar::addButton(float width, float height, string label, const char action[]) { if (isVertical) { - // TODO: emplace_back failing to copy m - // buttons.emplace_back(currentCanvas, xPos, yPos + axisOffset, width, - // height, label, action); - buttons.push_back(new ButtonWidget(currentCanvas, xPos, yPos + axisOffset, + buttons.push_back(new ButtonWidget(currentCanvas, xPos, yPos + axisOffset(), width, height, label, action)); } else { - // TODO: ditto - // buttons.emplace_back(currentCanvas, xPos + axisOffset, yPos, width, - // height, label, action); - buttons.push_back(new ButtonWidget(currentCanvas, xPos + axisOffset, yPos, + buttons.push_back(new ButtonWidget(currentCanvas, xPos + axisOffset(), yPos, width, height, label, action)); } - // buttons.back().setStyledMultiShape(&m); - // buttons.back().setMultiText(&t); - // buttons.back().redraw(); return buttons.back(); } +float NavigationBar::axisOffset() { + if (buttons.empty()) { + return 0; + } else { + if (isVertical) { + return buttons.back()->getY() + buttons.back()->getH() + axisPadding; + } else { + return buttons.back()->getX() + buttons.back()->getW() + axisPadding; + } + } +} + void NavigationBar::setButtonAction( int buttonIndex, std::optional> func) { buttons[buttonIndex]->setAction(func); @@ -80,6 +82,7 @@ void NavigationBar::addNewTab() { // addToTab(t); } +/* void NavigationBar::addToTab(Tab* tab) { tab->addMember(this); MainCanvas* newCanvas = tab->getMainCanvas(); @@ -88,5 +91,6 @@ void NavigationBar::addToTab(Tab* tab) { tab->setUpdate(); tab->setRender(); } +*/ void NavigationBar::balanceButtons(int numButtons) {} \ No newline at end of file diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index 34965b18..f24892f2 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -58,13 +58,18 @@ class NavigationBar : public Member { * * @param width width of the new button * @param height height of the new button - * @param axisOffset offset relative to the previous button * @param label the text to be shown on the button * @param action a description of the button's action * @return ButtonWidget& a reference to the new button */ - ButtonWidget* addButton(float width, float height, float axisOffset, - std::string label, const char action[]); + ButtonWidget* addButton(float width, float height, std::string label, + const char action[]); + + /** + * @brief Automatically calculate axis offset for new button on nav bar + * + */ + float axisOffset(); /** * @brief Set an action for a button in the nav bar diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b7063d94..39e0f4a3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -63,7 +63,7 @@ add_grail_executable(SRC xdl/testXDLButton.cc LIBS grail) # XP (Experimental) add_grail_executable(SRC xp/testfmt.cc LIBS grail) -add_grail_executable(SRC xp/testMultiTab.cc LIBS grail) +#add_grail_executable(SRC xp/testMultiTab.cc LIBS grail) add_grail_executable(SRC xp/test2Tabs.cc LIBS grail) # Unsorted diff --git a/test/xp/test2Tabs.cc b/test/xp/test2Tabs.cc index 71c6636f..a215b2a6 100644 --- a/test/xp/test2Tabs.cc +++ b/test/xp/test2Tabs.cc @@ -1,5 +1,3 @@ -#include - #include "fmt/core.h" #include "opengl/GrailGUI.hh" #include "opengl/NavigationBar.hh" @@ -8,23 +6,19 @@ using namespace std; using namespace grail; -class Member1 : public Member { +class Square : public Member { public: - Member1(Tab* tab) : Member(tab, 0, 0) { - MainCanvas* c = tab->getMainCanvas(); - StyledMultiShape2D* gui = c->getGui(); - + Square(GLWin* w) : Member(w, 0, 0) { + StyledMultiShape2D* gui = tab->getMainCanvas()->getGui(); gui->fillRectangle(500, 600, 200, 200, red); } }; -class Member2 : public Member { +class Circle : public Member { public: - Member2(Tab* tab) : Member(tab, 0, 0) { - MainCanvas* c = tab->getMainCanvas(); - StyledMultiShape2D* gui = c->getGui(); - - gui->drawCircle(450, 50, 45, 5, purple); + Circle(GLWin* w) : Member(w, 0, 0) { + StyledMultiShape2D* gui = tab->getMainCanvas()->getGui(); + gui->fillCircle(600, 700, 100, 5, purple); } }; @@ -33,20 +27,20 @@ class MultiTab : public NavigationBar { MultiTab(GLWin* w); }; -MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { - ButtonWidget* hi = addButton(200, 30, 0, "hi", "print hi"); - auto action = []() { fmt::print("hi\n"); }; - hi->setAction(action); +MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 250, 200, 20, true) { + ButtonWidget* square = addButton(250, 50, "Square", "tab 1"); + square->setAction([w]() { w->switchTab(0); }); + + ButtonWidget* circle = addButton(250, 50, "Circle", "tab 2"); + circle->setAction([w]() { w->switchTab(1); }); - ButtonWidget* next = addButton(200, 30, 50, "next", "next tab"); - auto action2 = [w]() { w->nextTab(); }; - next->setAction(action2); + ButtonWidget* next = addButton(250, 50, "Next", "next tab"); + next->setAction([w]() { w->nextTab(); }); } -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test Tabs"); - new Member1(defaultTab); + new Square(w); MultiTab* m = new MultiTab(w); - Tab* t2 = w->addTab(); - new Member2(t2); + new Circle(w); } \ No newline at end of file diff --git a/test/xp/testMultiTab.cc b/test/xp/testMultiTab.cc index b6987699..8030b949 100644 --- a/test/xp/testMultiTab.cc +++ b/test/xp/testMultiTab.cc @@ -11,14 +11,15 @@ class MultiTab : public NavigationBar { }; MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { - ButtonWidget* prev = addButton(200, 30, 0, "previous", "previous tab"); + ButtonWidget* prev = addButton(200, 30, "previous", "previous tab"); prev->setAction(bind(&GLWin::prevTab, w)); - ButtonWidget* next = addButton(200, 30, 50, "next", "next tab"); + ButtonWidget* next = addButton(200, 30, "next", "next tab"); next->setAction(bind(&GLWin::nextTab, w)); - ButtonWidget* add = addButton(200, 30, 100, "+", "add tab"); + ButtonWidget* add = addButton(200, 30, "+", "add tab"); add->setAction(bind(&MultiTab::addNewTab, this)); } -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { + new Tab(w); new MultiTab(w); } From 4b2cb64b6a759e48cb353f2c74a56e588d759383 Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Fri, 27 May 2022 15:21:04 -0400 Subject: [PATCH 04/15] fix testMultiTab --- src/opengl/NavigationBar.cc | 1 - test/CMakeLists.txt | 2 +- test/xp/testMultiTab.cc | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index 451076a6..7dc5afd8 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -78,7 +78,6 @@ void NavigationBar::setButtonAction( void NavigationBar::addNewTab() { Tab* t = parentWin->addTab(); canvases.insert(t->getMainCanvas()); - parentWin->toLastTab(); // addToTab(t); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 39e0f4a3..b7063d94 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -63,7 +63,7 @@ add_grail_executable(SRC xdl/testXDLButton.cc LIBS grail) # XP (Experimental) add_grail_executable(SRC xp/testfmt.cc LIBS grail) -#add_grail_executable(SRC xp/testMultiTab.cc LIBS grail) +add_grail_executable(SRC xp/testMultiTab.cc LIBS grail) add_grail_executable(SRC xp/test2Tabs.cc LIBS grail) # Unsorted diff --git a/test/xp/testMultiTab.cc b/test/xp/testMultiTab.cc index 8030b949..04228a16 100644 --- a/test/xp/testMultiTab.cc +++ b/test/xp/testMultiTab.cc @@ -20,6 +20,6 @@ MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { } void grailmain(int argc, char* argv[], GLWin* w) { - new Tab(w); + w->addTab(); new MultiTab(w); } From eefd488adb48638216ff977c311287b808537cf1 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sat, 28 May 2022 22:18:31 -0400 Subject: [PATCH 05/15] Fix other tests, fix test/xp/CMakeLists.txt All currently compiling tests have been switched over to the new grailmain. Also, apparently test/xp/CMakeLists.txt was never added to the previous commit. Signed-off-by: ahuston-0 --- src/opengl/GraphStyle.hh | 30 ++++++++++++++++++++++++++++++ test/2d/testDisplayBook.cc | 10 +++++----- test/2d/testStyledMultishape.cc | 6 +++--- test/2d/testText3.cc | 6 +++--- test/2d/testTriangle.cc | 6 +++--- test/3d/Globe.cc | 6 +++--- test/3d/SolarSystem.cc | 7 +++---- test/graph/testBarChart.cc | 6 +++--- test/graph/testBoxChart.cc | 6 +++--- test/graph/testCandlestickChart.cc | 6 +++--- test/graph/testGapMinderWidget.cc | 6 +++--- test/graph/testLineGraph.cc | 6 ++---- test/maps/testDrawBlockMap.cc | 8 ++++---- test/media/testAudio.cc | 7 ++----- test/media/testSingleAudio.cc | 6 ++---- test/media/testVideo.cc | 6 ++---- test/xdl/testXDLButton.cc | 8 +++----- test/xp/CMakeLists.txt | 3 ++- 18 files changed, 79 insertions(+), 60 deletions(-) diff --git a/src/opengl/GraphStyle.hh b/src/opengl/GraphStyle.hh index e23b3754..20c39b8d 100644 --- a/src/opengl/GraphStyle.hh +++ b/src/opengl/GraphStyle.hh @@ -30,6 +30,17 @@ class GraphStyle : public Member { float pointSize; public: + /** + * @brief Construct a new Graph Style object + * + * A graph style provides a series of defaults for drawing graphs and their + * components + * + * @param tab A tab to add the graph style to + * @param faceName name of the font face + * @param titleSize size of the title font + * @param axisSize size of the axis font + */ GraphStyle(Tab* tab, const char faceName[], uint32_t titleSize, uint32_t axisSize) : Member(tab), @@ -64,6 +75,25 @@ class GraphStyle : public Member { barOutlineColors = {grail::gray, grail::black, grail::yellow}; } + /** + * @brief Construct a new Graph Style object, by creating a new tab + * + * A graph style provides a series of defaults for drawing graphs and their + * components + * + * TODO: See if this can use Member's GLWin constructor instead of manually + * adding a new tab. I had a feeling doing so would lead to double + * construction. + * + * @param w A window to draw on + * @param faceName name of the font face + * @param titleSize size of the title font + * @param axisSize size of the axis font + */ + GraphStyle(GLWin* w, const char faceName[], uint32_t titleSize, + uint32_t axisSize) + : GraphStyle(w->addTab(), faceName, titleSize, axisSize) {} + /** * @brief Summary * @details Description diff --git a/test/2d/testDisplayBook.cc b/test/2d/testDisplayBook.cc index b5e7c900..d02539f4 100644 --- a/test/2d/testDisplayBook.cc +++ b/test/2d/testDisplayBook.cc @@ -11,7 +11,7 @@ class BookViewer : public Member { const char *filename; public: - BookViewer(Tab *tab, const char filename[]); + BookViewer(GLWin *w, const char filename[]); void advance(); void back(); @@ -41,8 +41,8 @@ void BookViewer::bottom() { tab->setRender(); } -BookViewer::BookViewer(Tab *tab, const char filename[]) - : Member(tab), filename(filename) { +BookViewer::BookViewer(GLWin *w, const char filename[]) + : Member(w), filename(filename) { tab->bindEvent(264, &BookViewer::bottom, this); tab->bindEvent(265, &BookViewer::top, this); tab->bindEvent(262, &BookViewer::advance, this); @@ -68,7 +68,7 @@ BookViewer::BookViewer(Tab *tab, const char filename[]) // c->addLayer(new Image(400, 400, 400, 400, "res/trumpmelania.png", s)); } -void grailmain(int argc, char *argv[], GLWin *w, Tab *defaultTab) { +void grailmain(int argc, char *argv[], GLWin *w) { const char *filename = argc < 2 ? "res/Annatest.txt" : argv[1]; - new BookViewer(defaultTab, filename); + new BookViewer(w, filename); } diff --git a/test/2d/testStyledMultishape.cc b/test/2d/testStyledMultishape.cc index 26bd628f..efeb1b5b 100644 --- a/test/2d/testStyledMultishape.cc +++ b/test/2d/testStyledMultishape.cc @@ -5,7 +5,7 @@ using namespace std; using namespace grail; class TestStyledMultishape : public Member { public: - TestStyledMultishape(Tab* tab) : Member(tab, 0, 0) { + TestStyledMultishape(GLWin* w) : Member(w, 0, 0) { MainCanvas* c = tab->getMainCanvas(); StyledMultiShape2D* gui = c->getGui(); @@ -48,9 +48,9 @@ class TestStyledMultishape : public Member { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test StyledMultiShape"); - new TestStyledMultishape(defaultTab); + new TestStyledMultishape(w); } #if 0 diff --git a/test/2d/testText3.cc b/test/2d/testText3.cc index d19adc38..c4f48993 100644 --- a/test/2d/testText3.cc +++ b/test/2d/testText3.cc @@ -48,7 +48,7 @@ class TestText3 : public Member { return yStart + 50; } - TestText3(Tab* tab) : Member(tab, 0, 0.1) { + TestText3(GLWin* w) : Member(w, 0, 0.1) { Canvas* c = tab->getMainCanvas(); uint32_t width = c->getWidth(), height = c->getHeight(); @@ -72,7 +72,7 @@ class TestText3 : public Member { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test Text3"); - new TestText3(defaultTab); + new TestText3(w); } diff --git a/test/2d/testTriangle.cc b/test/2d/testTriangle.cc index f5a33a0a..e7237f5e 100644 --- a/test/2d/testTriangle.cc +++ b/test/2d/testTriangle.cc @@ -5,7 +5,7 @@ using namespace grail; class TestTriangle : public Member { public: - TestTriangle(Tab* tab) : Member(tab, 0, 0) {} + TestTriangle(GLWin* w) : Member(w, 0, 0) {} void init() { MainCanvas* c = tab->getMainCanvas(); @@ -15,7 +15,7 @@ class TestTriangle : public Member { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Solar System"); - new TestTriangle(defaultTab); + new TestTriangle(w); } diff --git a/test/3d/Globe.cc b/test/3d/Globe.cc index 666eca22..68d59bb3 100644 --- a/test/3d/Globe.cc +++ b/test/3d/Globe.cc @@ -10,7 +10,7 @@ class Globe : public Member { float earthRotationAngle; public: - Globe(Tab* tab) : Member(tab, 0, 0.1) { + Globe(GLWin* w) : Member(w, 0, 0.1) { earthRotationAngle = .01; Canvas* c = tab->getMainCanvas(); Camera* cam = c->setLookAtProjection(2, 3, 40, 0, 0, 0, 0, 0, 1); @@ -26,7 +26,7 @@ class Globe : public Member { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Globe"); - new Globe(defaultTab); + new Globe(w); } diff --git a/test/3d/SolarSystem.cc b/test/3d/SolarSystem.cc index 5e9244d3..23fde2df 100644 --- a/test/3d/SolarSystem.cc +++ b/test/3d/SolarSystem.cc @@ -86,9 +86,8 @@ class SolarSystem : public Member { constexpr static double SIDEREAL_DAY = 0.9972; // number of 24-hour "days" it takes earth to rotate once public: - SolarSystem(Tab* tab) : Member(tab, 0, .0125), bodies(10) { + SolarSystem(GLWin* w) : Member(w, 0, .0125), bodies(10) { cam = c->setLookAtProjection(2, 3, 40, 0, 0, 0, 0, 0, 1); - GLWin* w = tab->getParentWin(); const Style* s = w->getDefaultStyle(); const Font* font = w->getDefaultFont(); defineBindings(); @@ -153,7 +152,7 @@ void SolarSystem::defineBindings() { tab->bindEvent(Tab::Inputs::HOME, &Tab::gotoStartTime, tab); } -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Solar System"); - new SolarSystem(defaultTab); + new SolarSystem(w); } diff --git a/test/graph/testBarChart.cc b/test/graph/testBarChart.cc index 10bb30b2..f63896ba 100644 --- a/test/graph/testBarChart.cc +++ b/test/graph/testBarChart.cc @@ -7,7 +7,7 @@ using namespace grail; class TestBarChart : public GraphStyle { public: - TestBarChart(Tab* tab) : GraphStyle(tab, "TIMES", 20, 12) { + TestBarChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12) { MainCanvas* c = tab->getMainCanvas(); vector values = {4, 6, 8, 10, 12, 14}; vector logValues = {4, 8, 16, 32, 64, 128}; @@ -57,7 +57,7 @@ class TestBarChart : public GraphStyle { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* tab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test Bar Chart"); - tab->addMember(new TestBarChart(tab)); + new TestBarChart(w); } diff --git a/test/graph/testBoxChart.cc b/test/graph/testBoxChart.cc index d9a34dc8..994a6c85 100644 --- a/test/graph/testBoxChart.cc +++ b/test/graph/testBoxChart.cc @@ -7,7 +7,7 @@ using namespace grail; class TestBoxChart : public GraphStyle { public: - TestBoxChart(Tab* tab) : GraphStyle(tab, "TIMES", 20, 12) { + TestBoxChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12) { MainCanvas* c = tab->getMainCanvas(); vector data = {150, 350, 222, 100, 300, // @@ -54,7 +54,7 @@ class TestBoxChart : public GraphStyle { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* tab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test Bar Chart"); - tab->addMember(new TestBoxChart(tab)); + new TestBoxChart(w); } diff --git a/test/graph/testCandlestickChart.cc b/test/graph/testCandlestickChart.cc index 60471295..a5c588b0 100644 --- a/test/graph/testCandlestickChart.cc +++ b/test/graph/testCandlestickChart.cc @@ -7,7 +7,7 @@ using namespace grail; class TestCandlestickChart : public GraphStyle { public: - TestCandlestickChart(Tab* tab) : GraphStyle(tab, "TIMES", 20, 12) { + TestCandlestickChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12) { MainCanvas* c = tab->getMainCanvas(); vector data = { @@ -72,6 +72,6 @@ class TestCandlestickChart : public GraphStyle { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* tab) { - tab->addMember(new TestCandlestickChart(tab)); +void grailmain(int argc, char* argv[], GLWin* w) { + new TestCandlestickChart(w); } diff --git a/test/graph/testGapMinderWidget.cc b/test/graph/testGapMinderWidget.cc index d2a8b2c4..5d6a6651 100644 --- a/test/graph/testGapMinderWidget.cc +++ b/test/graph/testGapMinderWidget.cc @@ -15,7 +15,7 @@ class TestGapMinderWidget : public GraphStyle { GapMinderWidget* chart; public: - TestGapMinderWidget(Tab* tab) : GraphStyle(tab, "TIMES", 24, 12) { + TestGapMinderWidget(GLWin* w) : GraphStyle(w, "TIMES", 24, 12) { MainCanvas* c = tab->getMainCanvas(); const Style* s = new Style("TIMES", 24, 1, 0, 0, 0, // black background (unused) @@ -42,7 +42,7 @@ class TestGapMinderWidget : public GraphStyle { void update() { chart->animate(10000, 2); } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* tab) { +void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test Gap Minder Widget"); - tab->addMember(new TestGapMinderWidget(tab)); + new TestGapMinderWidget(w); } diff --git a/test/graph/testLineGraph.cc b/test/graph/testLineGraph.cc index 366d3274..ff0000ff 100644 --- a/test/graph/testLineGraph.cc +++ b/test/graph/testLineGraph.cc @@ -7,7 +7,7 @@ using namespace grail; class TestLineGraph : public GraphStyle { public: - TestLineGraph(Tab* tab) : GraphStyle(tab, "TIMES", 24, 12) { + TestLineGraph(GLWin* w) : GraphStyle(w, "TIMES", 24, 12) { MainCanvas* c = tab->getMainCanvas(); vector times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; @@ -65,6 +65,4 @@ class TestLineGraph : public GraphStyle { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* tab) { - tab->addMember(new TestLineGraph(tab)); -} +void grailmain(int argc, char* argv[], GLWin* w) { new TestLineGraph(w); } diff --git a/test/maps/testDrawBlockMap.cc b/test/maps/testDrawBlockMap.cc index 74912e64..6af17059 100644 --- a/test/maps/testDrawBlockMap.cc +++ b/test/maps/testDrawBlockMap.cc @@ -12,8 +12,8 @@ class TestDrawBlockMap : public Member { MapView2D* mv; public: - TestDrawBlockMap(Tab* tab, const char filename[]) - : Member(tab), // GLWin(0x000000, 0xCCCCCC, "Block Loader: Map Demo"), + TestDrawBlockMap(GLWin* w, const char filename[]) + : Member(w), // GLWin(0x000000, 0xCCCCCC, "Block Loader: Map Demo"), filename(filename), mv(nullptr) { MainCanvas* c = tab->getMainCanvas(); @@ -97,6 +97,6 @@ class TestDrawBlockMap : public Member { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { - new TestDrawBlockMap(defaultTab, "res/maps/uscounties.bml"); +void grailmain(int argc, char* argv[], GLWin* w) { + new TestDrawBlockMap(w, "res/maps/uscounties.bml"); } diff --git a/test/media/testAudio.cc b/test/media/testAudio.cc index 7374084f..df07b84c 100644 --- a/test/media/testAudio.cc +++ b/test/media/testAudio.cc @@ -22,8 +22,7 @@ class TestAudioPlayer : public Member { } public: - TestAudioPlayer(Tab *tab) - : Member(tab, 0), startTime(0), a(nullptr), step(0) {} + TestAudioPlayer(GLWin *w) : Member(w, 0), startTime(0), a(nullptr), step(0) {} // required to ensure that the memory of the audio player is freed ~TestAudioPlayer() { delete a; } @@ -136,6 +135,4 @@ class TestAudioPlayer : public Member { } }; -void grailmain(int argc, char *argv[], GLWin *w, Tab *defaultTab) { - new TestAudioPlayer(defaultTab); -} +void grailmain(int argc, char *argv[], GLWin *w) { new TestAudioPlayer(w); } diff --git a/test/media/testSingleAudio.cc b/test/media/testSingleAudio.cc index b7726f09..b5207f53 100644 --- a/test/media/testSingleAudio.cc +++ b/test/media/testSingleAudio.cc @@ -4,7 +4,7 @@ class TestSingleAudio : public Member { public: AudioPlayer *a; - TestSingleAudio(Tab *tab) : Member(tab) { + TestSingleAudio(GLWin *w) : Member(w) { a = new AudioPlayer(); a->setCurrentContext("default"); @@ -14,6 +14,4 @@ class TestSingleAudio : public Member { } }; -void grailmain(int argc, char *argv[], GLWin *w, Tab *defaultTab) { - defaultTab->addMember(new TestSingleAudio(defaultTab)); -} \ No newline at end of file +void grailmain(int argc, char *argv[], GLWin *w) { new TestSingleAudio(w); } \ No newline at end of file diff --git a/test/media/testVideo.cc b/test/media/testVideo.cc index 1bf79fc4..65d0c6bc 100644 --- a/test/media/testVideo.cc +++ b/test/media/testVideo.cc @@ -6,7 +6,7 @@ using namespace grail; class TestVideoPlayer : public Member { public: - TestVideoPlayer(Tab* tab) : Member(tab, 0) { + TestVideoPlayer(GLWin* w) : Member(w, 0) { VideoPlayer* v = c->addLayer(new VideoPlayer(c, 100, 100, 500, 500)); // playing a link from youtube (and maybe other places idk) requires you to @@ -21,6 +21,4 @@ class TestVideoPlayer : public Member { } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { - new TestVideoPlayer(defaultTab); -} +void grailmain(int argc, char* argv[], GLWin* w) { new TestVideoPlayer(w); } diff --git a/test/xdl/testXDLButton.cc b/test/xdl/testXDLButton.cc index 34451240..6259dec9 100644 --- a/test/xdl/testXDLButton.cc +++ b/test/xdl/testXDLButton.cc @@ -9,13 +9,11 @@ class NetworkedButton : public Member { ButtonWidget button; public: - NetworkedButton(Tab* tab) - : Member(tab), button(c, 0, 0, 100, 100, "", "click!") { + NetworkedButton(GLWin* w) + : Member(w), button(c, 0, 0, 100, 100, "", "click!") { button.setAction( bind(&GLWin::goToLink, tab->getParentWin(), "127.0.0.1", 8060, 0)); } }; -void grailmain(int argc, char* argv[], GLWin* w, Tab* defaultTab) { - defaultTab->addMember(new NetworkedButton(defaultTab)); -} \ No newline at end of file +void grailmain(int argc, char* argv[], GLWin* w) { new NetworkedButton(w); } \ No newline at end of file diff --git a/test/xp/CMakeLists.txt b/test/xp/CMakeLists.txt index 1d84e74a..bee37924 100644 --- a/test/xp/CMakeLists.txt +++ b/test/xp/CMakeLists.txt @@ -1,4 +1,5 @@ # add_grail_executable([BINNAME ] SRC LIBS ) add_grail_executable(SRC testfmt.cc LIBS grail) -add_grail_executable(SRC testMultiTab.cc LIBS grail) \ No newline at end of file +add_grail_executable(SRC testMultiTab.cc LIBS grail) +add_grail_executable(SRC test2Tabs.cc LIBS grail) \ No newline at end of file From f3f68f6b4ac91d1384105e3d92da1c0f1ae9c5d1 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sat, 28 May 2022 22:35:06 -0400 Subject: [PATCH 06/15] Add bounds checking to GLWin::currentTab() Currently this throws an exception if a tab doesn't exist. My hope is that the branch predictor will notice that the condition is true most of the time and just return most of the time. Signed-off-by: ahuston-0 --- src/opengl/GLWin.hh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index 5fbce49e..bcc417bb 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -12,6 +12,7 @@ #include "opengl/GLWinFonts.hh" #include "opengl/Shader.hh" #include "util/DynArray.hh" +#include "util/Ex.hh" #include "util/HashMap.hh" class GLFWwindow; // forward declaration, simplify: include file not needed // here @@ -124,10 +125,18 @@ class GLWin { } MainCanvas* getMainCanvas(); - Tab* currentTab() { return tabs[current]; } - Tab* getSharedTab() { return sharedTab; } + constexpr Tab* currentTab() { + if (current != -1) { + return tabs[current]; + } else { + throw Ex2( + Errcode::UNDEFINED, + "A tab must be created before trying to access the current tab"); + } + } + constexpr Tab* getSharedTab() { return sharedTab; } - void setSize(uint32_t w, uint32_t h) { + constexpr void setSize(uint32_t w, uint32_t h) { width = w; height = h; } From 6ed6e869bd0780c0f391bd6545aa4334bed3290e Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Tue, 31 May 2022 12:40:52 -0400 Subject: [PATCH 07/15] add test testGraphTabs --- src/opengl/NavigationBar.cc | 2 +- test/xp/CMakeLists.txt | 3 +- test/xp/testGraphTabs.cc | 169 ++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 test/xp/testGraphTabs.cc diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index 7dc5afd8..f727cdb3 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -14,7 +14,7 @@ NavigationBar::NavigationBar(MainCanvas* initialCanvas, const Style* initialStyle, float x, float y, float width, float height, float axisPadding, bool isVertical) - : Member(initialCanvas->getTab()), + : Member(initialCanvas->getTab(), 0), currentCanvas(initialCanvas), m(initialCanvas, initialStyle), t(initialCanvas, initialStyle), diff --git a/test/xp/CMakeLists.txt b/test/xp/CMakeLists.txt index bee37924..3e249e6f 100644 --- a/test/xp/CMakeLists.txt +++ b/test/xp/CMakeLists.txt @@ -2,4 +2,5 @@ add_grail_executable(SRC testfmt.cc LIBS grail) add_grail_executable(SRC testMultiTab.cc LIBS grail) -add_grail_executable(SRC test2Tabs.cc LIBS grail) \ No newline at end of file +add_grail_executable(SRC test2Tabs.cc LIBS grail) +add_grail_executable(SRC testGraphTabs.cc LIBS grail) \ No newline at end of file diff --git a/test/xp/testGraphTabs.cc b/test/xp/testGraphTabs.cc new file mode 100644 index 00000000..ac175254 --- /dev/null +++ b/test/xp/testGraphTabs.cc @@ -0,0 +1,169 @@ +#include "opengl/BarChartWidget.hh" +#include "opengl/BoxChartWidget.hh" +#include "opengl/GrailGUI.hh" +#include "opengl/GraphStyle.hh" +#include "opengl/LineGraphWidget.hh" +#include "opengl/NavigationBar.hh" + +using namespace std; +using namespace grail; + +class BarChart : public GraphStyle { + public: + BarChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + MainCanvas* c = tab->getMainCanvas(); + vector values = {4, 6, 8, 10, 12, 14}; + vector logValues = {4, 8, 16, 32, 64, 128}; + + vector names = {"red", "orange", "yellow", + "green", "blue", "purple"}; + + vector colors = {grail::red, grail::orange, grail::yellow, + grail::green, grail::blue, grail::purple}; + + vector outline{grail::green, grail::blue, grail::purple}; + + BarChartWidget bcw(c, 100, 100, 850, 400, GraphWidget::AxisType::TEXT, + GraphWidget::AxisType::LINEAR, this); + + // create x axis (categories) + bcw.setNames(names); + // bcw.createXAxis(GraphWidget::AxisType::TEXT); + bcw.xAxis->setTitle("Colors"); + + // y axis stuff + // bcw.createYAxis(GraphWidget::AxisType::LINEAR); + bcw.setValues(values); + + // setting general things for the graph + // the axis text styles must be set before + // creating the axes + bcw.setGraphTitle("Bar Chart"); + // bcw.setStyle(this); + + // bar chart widget specific bits + // bcw.setBarColors(colors); + // bcw.setBarOutlineColors(outline); + // linear + bcw.yAxis->setBounds(0, 60); + bcw.yAxis->setTickInterval(2); + bcw.yAxis->setTitle("y axis"); + + // logarithmic + // bcw.createYAxis(GraphWidget::AxisType::LOGARITHMIC); + // bcw.yAxis->setBounds(1, 256); + // bcw.yAxis->setTickInterval(2); + // bcw.yAxis->setTickFormat(4, 1); + // bcw.setValues(logValues); + + bcw.init(); + } +}; + +class BoxChart : public GraphStyle { + public: + BoxChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + MainCanvas* c = tab->getMainCanvas(); + + vector data = {150, 350, 222, 100, 300, // + 130, 300, 250, 190, 170, // + 100, 50, 20, 150, 200, // + 330, 200, 270, 180, 300, // + 49, 247, 325, 114, 89}; + + vector names = {"red", "orange", "yellow", "green", "blue"}; + + BoxChartWidget bcw(c, 100, 300, 850, 200, GraphWidget::AxisType::TEXT, + GraphWidget::AxisType::LINEAR, this); + + // setting general things for the graph + // the axis text styles must be set before + // creating the axes + bcw.setGraphTitle("Box Chart"); + + // create x axis (categories) + bcw.setNames(names); + + // set releavant x axis parameters + // if you try to set something not applicable to a text axis (as that's what + // the x axis always will be), the compiler will yell at you + bcw.xAxis->setTitle("Colors"); + + // y axis stuff + bcw.setData(data); + bcw.yAxis->setTitle("y axis"); + // linear + bcw.yAxis->setBounds(0, 500); + bcw.yAxis->setTickInterval(75); + + // set y axis parameters + // bar chart widget specific bits + bcw.setBoxWidth(45); + bcw.setPointsPerBox(5); + + bcw.init(); + } +}; + +class LineGraph : public GraphStyle { + public: + LineGraph(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 24, 12) { + MainCanvas* c = tab->getMainCanvas(); + + vector times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + vector values = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; + vector logValues = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; + + LineGraphWidget lgw(c, 250, 200, 500, 300, GraphWidget::AxisType::LINEAR, + GraphWidget::AxisType::LOGARITHMIC, this); + + // Graph Superclass settings + lgw.setGraphTitle("Line Graph"); + + // LineGraphWidget specific settings + lgw.setPointFormat('t', 5, grail::red); + + // x axis stuff + lgw.setXPoints(times); + + // set x axis parameters + lgw.xAxis->setBounds(times.front(), times.back()); + lgw.xAxis->setTickInterval(2); + lgw.xAxis->setTitle("x axis"); + lgw.xAxis->setTickFormat(3, 1); + + // y axis stuff + lgw.setYPoints(logValues); + + // set y axis parameters + lgw.yAxis->setBounds(logValues.front(), logValues.back()); + lgw.yAxis->setTickInterval(2); + lgw.yAxis->setTickFormat(4, 1); + lgw.yAxis->setTitle("y axis"); + + lgw.init(); + } +}; + +class Menu : public NavigationBar { + public: + Menu(GLWin* w); +}; + +Menu::Menu(GLWin* w) : NavigationBar(w, 150, 750, 300, 50, 40) { + ButtonWidget* bar = addButton(100, 50, "Bar", "tab 1"); + bar->setAction([w]() { w->switchTab(2); }); + + ButtonWidget* box = addButton(100, 50, "Box", "tab 2"); + box->setAction([w]() { w->switchTab(1); }); + + ButtonWidget* line = addButton(100, 50, "Line", "tab 3"); + line->setAction([w]() { w->switchTab(0); }); +} + +void grailmain(int argc, char* argv[], GLWin* w) { + new LineGraph(w); + new BoxChart(w); + new Menu(w); + new BarChart(w); +} \ No newline at end of file From 8bbb5e853fdc08e3028f1f48a3b22dcc330f024f Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Tue, 31 May 2022 13:37:22 -0400 Subject: [PATCH 08/15] add candlestick chart to testGraphTabs --- test/xp/testGraphTabs.cc | 88 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/test/xp/testGraphTabs.cc b/test/xp/testGraphTabs.cc index ac175254..d4ecb8db 100644 --- a/test/xp/testGraphTabs.cc +++ b/test/xp/testGraphTabs.cc @@ -1,5 +1,6 @@ #include "opengl/BarChartWidget.hh" #include "opengl/BoxChartWidget.hh" +#include "opengl/CandlestickChartWidget.hh" #include "opengl/GrailGUI.hh" #include "opengl/GraphStyle.hh" #include "opengl/LineGraphWidget.hh" @@ -145,25 +146,96 @@ class LineGraph : public GraphStyle { } }; +class CandlestickChart : public GraphStyle { + public: + CandlestickChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + MainCanvas* c = tab->getMainCanvas(); + + vector data = { + 153.25, 154.16, 152.99, 153.68, 153.34, 153.73, 152.15, 152.73, 152.66, + 153.58, 151.46, 153.57, 153.71, 153.9, 152.17, 153.26, 153.46, 154.53, + 153.36, 153.92, 153.08, 153.31, 151.91, 152.93, 153.63, 154.88, 153.5, + 154.83, 154.41, 154.93, 154.01, 154.74, 155.25, 156.17, 154.93, 155.28, + 155.5, 157.43, 154.54, 155.34, 155.41, 156.42, 155.19, 155.99, 155.79, + 156.81, 155.17, 155.44, 156.17, 156.72, 155.85, 156.43, 157.33, 159.43, + 157.09, 159.31, 159.21, 160.29, 158.66, 159.9, 159.85, 160.13, 159.03, + 159.19, 156.19, 156.52, 154.46, 155.42, 156.05, 157.18, 155.4, 155.69, + 156.33, 157.13, 154.94, 155.61, 155.73, 156.86, 155.64, 156.54, 156.35, + 156.99, 154.71, 155.85, 156.67, 157.26, 156.22, 156.85, 158.72, 163.01, + 158.13, 162.47, 163.3, 167.47, 163.13, 166.12, 167.3, 169.04, 166.34, + 168.43, 169.26, 169.33, 165.02, 166.29, 167.04, 167.9, 164.69, 167.51, + 173.38, 173.64, 170.51, 171.88, 171.75, 174.36, 171.1, 173.63, 173.29, + 174.51, 173.29, 174.18, 174.03, 175.61, 173.71, 175.61, 174.48, 175.46, + 172.52, 175.25, 175.11, 175.38, 174.27, 174.67}; + vector names = {"one", "two", "seven", "three"}; + CandlestickChartWidget ccw(c, 100, 100, 850, 400, + GraphWidget::AxisType::LINEAR, + GraphWidget::AxisType::LINEAR, this); + + // setting general things for the graph + // the axis text styles must be set before + // creating the axes + ccw.setGraphTitle("Candlestick Chart"); + + // bar chart widget specific bits + // ccw.setBoxWidth(5); + // ccw.setBoxColors(boxColors); + // ccw.setBoxOutlineColors(outlineColors); + + // create x axis (categories) + // ccw.setNames(names); + + // set relevant x axis parameters + // if you try to set something not applicable to a text axis (as that's what + // the x axis always will be), the compiler will yell at you + ccw.xAxis->setTitle("Date"); + // ccw.xAxis->setTickDrawSize(7); + // ccw.xAxis->setAxisColor(grail::green); + // ccw.xAxis->setTickColor(grail::purple); + + // y axis stuff + ccw.setData(data); + + // set y axis parameters + // ccw.yAxis->setIsVert(true); + + // linear + ccw.yAxis->setBounds(140, 180); + ccw.yAxis->setTickInterval(2); + + // ccw.yAxis->setTickDrawSize(10); + // ccw.yAxis->setShowTicks(true); + ccw.yAxis->setTitle("Price"); + // ccw.yAxis->setAxisColor(grail::yellow); + // ccw.yAxis->setTickColor(grail::red); + + ccw.init(); + } +}; + class Menu : public NavigationBar { public: Menu(GLWin* w); }; -Menu::Menu(GLWin* w) : NavigationBar(w, 150, 750, 300, 50, 40) { - ButtonWidget* bar = addButton(100, 50, "Bar", "tab 1"); - bar->setAction([w]() { w->switchTab(2); }); +Menu::Menu(GLWin* w) : NavigationBar(w, 40, 600, 300, 50, 40) { + ButtonWidget* bar = addButton(175, 50, "Bar", "tab 1"); + bar->setAction([w]() { w->switchTab(3); }); - ButtonWidget* box = addButton(100, 50, "Box", "tab 2"); - box->setAction([w]() { w->switchTab(1); }); + ButtonWidget* box = addButton(175, 50, "Box", "tab 2"); + box->setAction([w]() { w->switchTab(2); }); - ButtonWidget* line = addButton(100, 50, "Line", "tab 3"); - line->setAction([w]() { w->switchTab(0); }); + ButtonWidget* line = addButton(175, 50, "Line", "tab 3"); + line->setAction([w]() { w->switchTab(1); }); + + ButtonWidget* cstick = addButton(175, 50, "CStick", "tab 4"); + cstick->setAction([w]() { w->switchTab(0); }); } void grailmain(int argc, char* argv[], GLWin* w) { + new CandlestickChart(w); new LineGraph(w); new BoxChart(w); - new Menu(w); new BarChart(w); + new Menu(w); } \ No newline at end of file From 29403eefa209de89b95f182788e649cb8552211c Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Wed, 1 Jun 2022 14:53:05 -0400 Subject: [PATCH 09/15] improve button customization, break up testGraphTabs --- src/opengl/ButtonWidget.cc | 20 ++- src/opengl/ButtonWidget.hh | 9 +- src/opengl/GLWinFonts.cc | 4 + src/opengl/GLWinFonts.hh | 1 + src/opengl/InteractiveWidget2D.hh | 5 +- src/opengl/NavigationBar.cc | 37 ++++- src/opengl/NavigationBar.hh | 22 +++ test/xp/BarChart.hh | 58 ++++++++ test/xp/BoxChart.hh | 51 +++++++ test/xp/CandlestickChart.hh | 73 ++++++++++ test/xp/LineGraph.hh | 46 ++++++ test/xp/testGraphTabs.cc | 226 ++---------------------------- 12 files changed, 321 insertions(+), 231 deletions(-) create mode 100644 test/xp/BarChart.hh create mode 100644 test/xp/BoxChart.hh create mode 100644 test/xp/CandlestickChart.hh create mode 100644 test/xp/LineGraph.hh diff --git a/src/opengl/ButtonWidget.cc b/src/opengl/ButtonWidget.cc index 39b9f43a..eb1d185d 100644 --- a/src/opengl/ButtonWidget.cc +++ b/src/opengl/ButtonWidget.cc @@ -24,17 +24,25 @@ void ButtonWidget::click(float mouseX, float mouseY) { void ButtonWidget::init() {} -ButtonWidget::ButtonWidget(MainCanvas* c, float x, float y, float w, float h, +ButtonWidget::ButtonWidget(MainCanvas* c, const Style* s, float x, float y, + float w, float h, const std::string& text, + const char action[]) + : InteractiveWidget2D(c, s, x, y, w, h), text(text) { + redraw(); +} + +ButtonWidget::ButtonWidget(MainCanvas* c, const Style* s, float x, float y, const std::string& text, const char action[]) - : InteractiveWidget2D(c, x, y, w, h), text(text) { + : InteractiveWidget2D(c, s, x, y, s->f->getWidth(text), s->f->getHeight()), + text(text) { redraw(); } void ButtonWidget::redraw() { - int borderSize = 2; + float borderSize = s->lineWidth; m->fillRectangle(x - borderSize, y - borderSize, w + (borderSize * 2), - h + (borderSize * 2), grail::black); - m->fillRectangle(x, y, w, h, grail::red); - t->addCentered(x, y, w, h, c->getStyle()->f, text); + h + (borderSize * 2), s->bg); + m->fillRectangle(x, y, w, h, s->fg); + t->addCentered(x, y, w, h, s->f, text); } \ No newline at end of file diff --git a/src/opengl/ButtonWidget.hh b/src/opengl/ButtonWidget.hh index 393029c8..76b264a0 100644 --- a/src/opengl/ButtonWidget.hh +++ b/src/opengl/ButtonWidget.hh @@ -12,10 +12,13 @@ class ButtonWidget : public InteractiveWidget2D { std::optional> func; public: - ButtonWidget(MainCanvas* c, float x, float y, float w, float h, - const std::string& text, const char action[]); - ButtonWidget(StyledMultiShape2D* m, MultiText* t, float x, float y, float w, + ButtonWidget(MainCanvas* c, const Style* s, float x, float y, float w, float h, const std::string& text, const char action[]); + ButtonWidget(StyledMultiShape2D* m, MultiText* t, const Style* s, float x, + float y, float w, float h, const std::string& text, + const char action[]); + ButtonWidget(MainCanvas* c, const Style* s, float x, float y, + const std::string& text, const char action[]); void click(float mouseX, float mouseY) override; void init() override; diff --git a/src/opengl/GLWinFonts.cc b/src/opengl/GLWinFonts.cc index 032beb8f..394aea57 100644 --- a/src/opengl/GLWinFonts.cc +++ b/src/opengl/GLWinFonts.cc @@ -197,6 +197,10 @@ float Font::getWidth(const char text[], uint32_t len) const { return w; } +float Font::getWidth(const string& text) const { + return getWidth(text.c_str(), text.length()); +} + FontFace::FontFace(FT_Library ft, const string& faceName, const string& facePath, uint32_t minFontSize, uint32_t inc, uint32_t maxFontSize, uint8_t bitmap[], uint32_t& sizeX, diff --git a/src/opengl/GLWinFonts.hh b/src/opengl/GLWinFonts.hh index f44024de..f9701781 100644 --- a/src/opengl/GLWinFonts.hh +++ b/src/opengl/GLWinFonts.hh @@ -140,6 +140,7 @@ class Font { return textureId; } // get the texture shared by all Fonts within the FontFace float getWidth(const char text[], const uint32_t len) const; + float getWidth(const std::string& text) const; friend std::ostream& operator<<(std::ostream& s, const Font& f) { return s << "Font height=" << f.height << " numGlyphs=" << f.glyphs.size(); // return s << "Font " << f.parentFace->faceName << " height=" << f.height diff --git a/src/opengl/InteractiveWidget2D.hh b/src/opengl/InteractiveWidget2D.hh index 32cefc0c..65b51643 100644 --- a/src/opengl/InteractiveWidget2D.hh +++ b/src/opengl/InteractiveWidget2D.hh @@ -10,12 +10,15 @@ class InteractiveWidget2D : public Widget2D { protected: MainCanvas* c; + const Style* s; bool isPressed; public: - InteractiveWidget2D(MainCanvas* c, float x, float y, float w, float h) + InteractiveWidget2D(MainCanvas* c, const Style* s, float x, float y, float w, + float h) : Widget2D(c->getGui(), c->getGuiText(), x, y, w, h), c(c), + s(s), isPressed(false) { c->addClickableWidget(this); } diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index f727cdb3..cd89a09b 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -27,10 +27,13 @@ NavigationBar::NavigationBar(MainCanvas* initialCanvas, canvases.insert(initialCanvas); this->isVertical = isVertical; + parentWin = initialCanvas->getWin(); defaultButtonHeight = min(48_f32, height); defaultButtonWidth = min(90_f32, width); defaultEdgeWidth = min(16_f32, width / 3); + buttonStyle = + new Style(parentWin->getMenuFont(), grail::black, grail::red, 1); /* addButton(defaultButtonWidth, defaultButtonHeight, axisPadding, "+", "add tab") @@ -42,18 +45,29 @@ NavigationBar::NavigationBar(GLWin* w, float x, float y, float width, float height, float axisPadding, bool isVertical) : NavigationBar(w->getSharedTab()->getMainCanvas(), w->getSharedTab()->getMainCanvas()->getStyle(), x, y, width, - height, axisPadding, isVertical) { - parentWin = w; -} + height, axisPadding, isVertical) {} ButtonWidget* NavigationBar::addButton(float width, float height, string label, const char action[]) { if (isVertical) { - buttons.push_back(new ButtonWidget(currentCanvas, xPos, yPos + axisOffset(), - width, height, label, action)); + buttons.push_back(new ButtonWidget(currentCanvas, buttonStyle, xPos, + yPos + axisOffset(), width, height, + label, action)); } else { - buttons.push_back(new ButtonWidget(currentCanvas, xPos + axisOffset(), yPos, - width, height, label, action)); + buttons.push_back(new ButtonWidget(currentCanvas, buttonStyle, + xPos + axisOffset(), yPos, width, height, + label, action)); + } + return buttons.back(); +} + +ButtonWidget* NavigationBar::addButton(string label, const char action[]) { + if (isVertical) { + buttons.push_back(new ButtonWidget(currentCanvas, buttonStyle, xPos, + yPos + axisOffset(), label, action)); + } else { + buttons.push_back(new ButtonWidget( + currentCanvas, buttonStyle, xPos + axisOffset(), yPos, label, action)); } return buttons.back(); } @@ -75,6 +89,15 @@ void NavigationBar::setButtonAction( buttons[buttonIndex]->setAction(func); } +void NavigationBar::setButtonStyle(const Font* f, glm::vec4 borderColor, + glm::vec4 buttonColor, + float borderThickness) { + buttonStyle->f = f; + buttonStyle->bg = borderColor; + buttonStyle->fg = buttonColor; + buttonStyle->lineWidth = borderThickness; +} + void NavigationBar::addNewTab() { Tab* t = parentWin->addTab(); canvases.insert(t->getMainCanvas()); diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index f24892f2..da91014d 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -65,6 +65,17 @@ class NavigationBar : public Member { ButtonWidget* addButton(float width, float height, std::string label, const char action[]); + /** + * @brief Create a new button and return a reference to it. Button + * width/height are automatically determined based on the text and buttonStyle + * font + * + * @param label the text to be shown on the button + * @param action a description of the button's action + * @return ButtonWidget& a reference to the new button + */ + ButtonWidget* addButton(std::string label, const char action[]); + /** * @brief Automatically calculate axis offset for new button on nav bar * @@ -80,6 +91,17 @@ class NavigationBar : public Member { void setButtonAction(int buttonIndex, std::optional> func); + /** + * @brief Redefine the style of all buttons in the nav bar + * + * @param f font of button text + * @param borderColor color of button border + * @param buttonColor main color of button + * @param borderThickness thickness of button border + */ + void setButtonStyle(const Font* f, glm::vec4 borderColor, + glm::vec4 buttonColor, float borderThickness); + /** * @brief Balance n buttons on the nav bar * diff --git a/test/xp/BarChart.hh b/test/xp/BarChart.hh new file mode 100644 index 00000000..512f8b6b --- /dev/null +++ b/test/xp/BarChart.hh @@ -0,0 +1,58 @@ +#pragma once +#include "opengl/BarChartWidget.hh" +#include "opengl/GrailGUI.hh" +#include "opengl/GraphStyle.hh" + +using namespace std; + +class BarChart : public GraphStyle { + public: + BarChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + MainCanvas* c = tab->getMainCanvas(); + vector values = {4, 6, 8, 10, 12, 14}; + vector logValues = {4, 8, 16, 32, 64, 128}; + + vector names = {"red", "orange", "yellow", + "green", "blue", "purple"}; + + vector colors = {grail::red, grail::orange, grail::yellow, + grail::green, grail::blue, grail::purple}; + + vector outline{grail::green, grail::blue, grail::purple}; + + BarChartWidget bcw(c, 100, 300, 850, 400, GraphWidget::AxisType::TEXT, + GraphWidget::AxisType::LINEAR, this); + + // create x axis (categories) + bcw.setNames(names); + // bcw.createXAxis(GraphWidget::AxisType::TEXT); + bcw.xAxis->setTitle("Colors"); + + // y axis stuff + // bcw.createYAxis(GraphWidget::AxisType::LINEAR); + bcw.setValues(values); + + // setting general things for the graph + // the axis text styles must be set before + // creating the axes + bcw.setGraphTitle("Bar Chart"); + // bcw.setStyle(this); + + // bar chart widget specific bits + // bcw.setBarColors(colors); + // bcw.setBarOutlineColors(outline); + // linear + bcw.yAxis->setBounds(0, 60); + bcw.yAxis->setTickInterval(2); + bcw.yAxis->setTitle("y axis"); + + // logarithmic + // bcw.createYAxis(GraphWidget::AxisType::LOGARITHMIC); + // bcw.yAxis->setBounds(1, 256); + // bcw.yAxis->setTickInterval(2); + // bcw.yAxis->setTickFormat(4, 1); + // bcw.setValues(logValues); + + bcw.init(); + } +}; \ No newline at end of file diff --git a/test/xp/BoxChart.hh b/test/xp/BoxChart.hh new file mode 100644 index 00000000..e82668a3 --- /dev/null +++ b/test/xp/BoxChart.hh @@ -0,0 +1,51 @@ +#pragma once +#include "opengl/BoxChartWidget.hh" +#include "opengl/GrailGUI.hh" +#include "opengl/GraphStyle.hh" + +using namespace std; + +class BoxChart : public GraphStyle { + public: + BoxChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + MainCanvas* c = tab->getMainCanvas(); + + vector data = {150, 350, 222, 100, 300, // + 130, 300, 250, 190, 170, // + 100, 50, 20, 150, 200, // + 330, 200, 270, 180, 300, // + 49, 247, 325, 114, 89}; + + vector names = {"red", "orange", "yellow", "green", "blue"}; + + BoxChartWidget bcw(c, 100, 300, 850, 200, GraphWidget::AxisType::TEXT, + GraphWidget::AxisType::LINEAR, this); + + // setting general things for the graph + // the axis text styles must be set before + // creating the axes + bcw.setGraphTitle("Box Chart"); + + // create x axis (categories) + bcw.setNames(names); + + // set releavant x axis parameters + // if you try to set something not applicable to a text axis (as that's what + // the x axis always will be), the compiler will yell at you + bcw.xAxis->setTitle("Colors"); + + // y axis stuff + bcw.setData(data); + bcw.yAxis->setTitle("y axis"); + // linear + bcw.yAxis->setBounds(0, 500); + bcw.yAxis->setTickInterval(75); + + // set y axis parameters + // bar chart widget specific bits + bcw.setBoxWidth(45); + bcw.setPointsPerBox(5); + + bcw.init(); + } +}; \ No newline at end of file diff --git a/test/xp/CandlestickChart.hh b/test/xp/CandlestickChart.hh new file mode 100644 index 00000000..80f3c861 --- /dev/null +++ b/test/xp/CandlestickChart.hh @@ -0,0 +1,73 @@ +#pragma once +#include "opengl/CandlestickChartWidget.hh" +#include "opengl/GrailGUI.hh" +#include "opengl/GraphStyle.hh" + +using namespace std; + +class CandlestickChart : public GraphStyle { + public: + CandlestickChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + MainCanvas* c = tab->getMainCanvas(); + + vector data = { + 153.25, 154.16, 152.99, 153.68, 153.34, 153.73, 152.15, 152.73, 152.66, + 153.58, 151.46, 153.57, 153.71, 153.9, 152.17, 153.26, 153.46, 154.53, + 153.36, 153.92, 153.08, 153.31, 151.91, 152.93, 153.63, 154.88, 153.5, + 154.83, 154.41, 154.93, 154.01, 154.74, 155.25, 156.17, 154.93, 155.28, + 155.5, 157.43, 154.54, 155.34, 155.41, 156.42, 155.19, 155.99, 155.79, + 156.81, 155.17, 155.44, 156.17, 156.72, 155.85, 156.43, 157.33, 159.43, + 157.09, 159.31, 159.21, 160.29, 158.66, 159.9, 159.85, 160.13, 159.03, + 159.19, 156.19, 156.52, 154.46, 155.42, 156.05, 157.18, 155.4, 155.69, + 156.33, 157.13, 154.94, 155.61, 155.73, 156.86, 155.64, 156.54, 156.35, + 156.99, 154.71, 155.85, 156.67, 157.26, 156.22, 156.85, 158.72, 163.01, + 158.13, 162.47, 163.3, 167.47, 163.13, 166.12, 167.3, 169.04, 166.34, + 168.43, 169.26, 169.33, 165.02, 166.29, 167.04, 167.9, 164.69, 167.51, + 173.38, 173.64, 170.51, 171.88, 171.75, 174.36, 171.1, 173.63, 173.29, + 174.51, 173.29, 174.18, 174.03, 175.61, 173.71, 175.61, 174.48, 175.46, + 172.52, 175.25, 175.11, 175.38, 174.27, 174.67}; + vector names = {"one", "two", "seven", "three"}; + CandlestickChartWidget ccw(c, 100, 300, 850, 400, + GraphWidget::AxisType::LINEAR, + GraphWidget::AxisType::LINEAR, this); + + // setting general things for the graph + // the axis text styles must be set before + // creating the axes + ccw.setGraphTitle("Candlestick Chart"); + + // bar chart widget specific bits + // ccw.setBoxWidth(5); + // ccw.setBoxColors(boxColors); + // ccw.setBoxOutlineColors(outlineColors); + + // create x axis (categories) + // ccw.setNames(names); + + // set relevant x axis parameters + // if you try to set something not applicable to a text axis (as that's what + // the x axis always will be), the compiler will yell at you + ccw.xAxis->setTitle("Date"); + // ccw.xAxis->setTickDrawSize(7); + // ccw.xAxis->setAxisColor(grail::green); + // ccw.xAxis->setTickColor(grail::purple); + + // y axis stuff + ccw.setData(data); + + // set y axis parameters + // ccw.yAxis->setIsVert(true); + + // linear + ccw.yAxis->setBounds(140, 180); + ccw.yAxis->setTickInterval(2); + + // ccw.yAxis->setTickDrawSize(10); + // ccw.yAxis->setShowTicks(true); + ccw.yAxis->setTitle("Price"); + // ccw.yAxis->setAxisColor(grail::yellow); + // ccw.yAxis->setTickColor(grail::red); + + ccw.init(); + } +}; \ No newline at end of file diff --git a/test/xp/LineGraph.hh b/test/xp/LineGraph.hh new file mode 100644 index 00000000..ca9db013 --- /dev/null +++ b/test/xp/LineGraph.hh @@ -0,0 +1,46 @@ +#pragma once +#include "opengl/GrailGUI.hh" +#include "opengl/GraphStyle.hh" +#include "opengl/LineGraphWidget.hh" + +using namespace std; + +class LineGraph : public GraphStyle { + public: + LineGraph(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 24, 12) { + MainCanvas* c = tab->getMainCanvas(); + + vector times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + vector values = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; + vector logValues = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; + + LineGraphWidget lgw(c, 250, 300, 500, 300, GraphWidget::AxisType::LINEAR, + GraphWidget::AxisType::LOGARITHMIC, this); + + // Graph Superclass settings + lgw.setGraphTitle("Line Graph"); + + // LineGraphWidget specific settings + lgw.setPointFormat('t', 5, grail::red); + + // x axis stuff + lgw.setXPoints(times); + + // set x axis parameters + lgw.xAxis->setBounds(times.front(), times.back()); + lgw.xAxis->setTickInterval(2); + lgw.xAxis->setTitle("x axis"); + lgw.xAxis->setTickFormat(3, 1); + + // y axis stuff + lgw.setYPoints(logValues); + + // set y axis parameters + lgw.yAxis->setBounds(logValues.front(), logValues.back()); + lgw.yAxis->setTickInterval(2); + lgw.yAxis->setTickFormat(4, 1); + lgw.yAxis->setTitle("y axis"); + + lgw.init(); + } +}; \ No newline at end of file diff --git a/test/xp/testGraphTabs.cc b/test/xp/testGraphTabs.cc index d4ecb8db..705dd8ff 100644 --- a/test/xp/testGraphTabs.cc +++ b/test/xp/testGraphTabs.cc @@ -1,234 +1,32 @@ -#include "opengl/BarChartWidget.hh" -#include "opengl/BoxChartWidget.hh" -#include "opengl/CandlestickChartWidget.hh" +#include "BarChart.hh" +#include "BoxChart.hh" +#include "CandlestickChart.hh" +#include "LineGraph.hh" #include "opengl/GrailGUI.hh" -#include "opengl/GraphStyle.hh" -#include "opengl/LineGraphWidget.hh" #include "opengl/NavigationBar.hh" using namespace std; using namespace grail; -class BarChart : public GraphStyle { - public: - BarChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { - MainCanvas* c = tab->getMainCanvas(); - vector values = {4, 6, 8, 10, 12, 14}; - vector logValues = {4, 8, 16, 32, 64, 128}; - - vector names = {"red", "orange", "yellow", - "green", "blue", "purple"}; - - vector colors = {grail::red, grail::orange, grail::yellow, - grail::green, grail::blue, grail::purple}; - - vector outline{grail::green, grail::blue, grail::purple}; - - BarChartWidget bcw(c, 100, 100, 850, 400, GraphWidget::AxisType::TEXT, - GraphWidget::AxisType::LINEAR, this); - - // create x axis (categories) - bcw.setNames(names); - // bcw.createXAxis(GraphWidget::AxisType::TEXT); - bcw.xAxis->setTitle("Colors"); - - // y axis stuff - // bcw.createYAxis(GraphWidget::AxisType::LINEAR); - bcw.setValues(values); - - // setting general things for the graph - // the axis text styles must be set before - // creating the axes - bcw.setGraphTitle("Bar Chart"); - // bcw.setStyle(this); - - // bar chart widget specific bits - // bcw.setBarColors(colors); - // bcw.setBarOutlineColors(outline); - // linear - bcw.yAxis->setBounds(0, 60); - bcw.yAxis->setTickInterval(2); - bcw.yAxis->setTitle("y axis"); - - // logarithmic - // bcw.createYAxis(GraphWidget::AxisType::LOGARITHMIC); - // bcw.yAxis->setBounds(1, 256); - // bcw.yAxis->setTickInterval(2); - // bcw.yAxis->setTickFormat(4, 1); - // bcw.setValues(logValues); - - bcw.init(); - } -}; - -class BoxChart : public GraphStyle { - public: - BoxChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { - MainCanvas* c = tab->getMainCanvas(); - - vector data = {150, 350, 222, 100, 300, // - 130, 300, 250, 190, 170, // - 100, 50, 20, 150, 200, // - 330, 200, 270, 180, 300, // - 49, 247, 325, 114, 89}; - - vector names = {"red", "orange", "yellow", "green", "blue"}; - - BoxChartWidget bcw(c, 100, 300, 850, 200, GraphWidget::AxisType::TEXT, - GraphWidget::AxisType::LINEAR, this); - - // setting general things for the graph - // the axis text styles must be set before - // creating the axes - bcw.setGraphTitle("Box Chart"); - - // create x axis (categories) - bcw.setNames(names); - - // set releavant x axis parameters - // if you try to set something not applicable to a text axis (as that's what - // the x axis always will be), the compiler will yell at you - bcw.xAxis->setTitle("Colors"); - - // y axis stuff - bcw.setData(data); - bcw.yAxis->setTitle("y axis"); - // linear - bcw.yAxis->setBounds(0, 500); - bcw.yAxis->setTickInterval(75); - - // set y axis parameters - // bar chart widget specific bits - bcw.setBoxWidth(45); - bcw.setPointsPerBox(5); - - bcw.init(); - } -}; - -class LineGraph : public GraphStyle { - public: - LineGraph(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 24, 12) { - MainCanvas* c = tab->getMainCanvas(); - - vector times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - vector values = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; - vector logValues = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; - - LineGraphWidget lgw(c, 250, 200, 500, 300, GraphWidget::AxisType::LINEAR, - GraphWidget::AxisType::LOGARITHMIC, this); - - // Graph Superclass settings - lgw.setGraphTitle("Line Graph"); - - // LineGraphWidget specific settings - lgw.setPointFormat('t', 5, grail::red); - - // x axis stuff - lgw.setXPoints(times); - - // set x axis parameters - lgw.xAxis->setBounds(times.front(), times.back()); - lgw.xAxis->setTickInterval(2); - lgw.xAxis->setTitle("x axis"); - lgw.xAxis->setTickFormat(3, 1); - - // y axis stuff - lgw.setYPoints(logValues); - - // set y axis parameters - lgw.yAxis->setBounds(logValues.front(), logValues.back()); - lgw.yAxis->setTickInterval(2); - lgw.yAxis->setTickFormat(4, 1); - lgw.yAxis->setTitle("y axis"); - - lgw.init(); - } -}; - -class CandlestickChart : public GraphStyle { - public: - CandlestickChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { - MainCanvas* c = tab->getMainCanvas(); - - vector data = { - 153.25, 154.16, 152.99, 153.68, 153.34, 153.73, 152.15, 152.73, 152.66, - 153.58, 151.46, 153.57, 153.71, 153.9, 152.17, 153.26, 153.46, 154.53, - 153.36, 153.92, 153.08, 153.31, 151.91, 152.93, 153.63, 154.88, 153.5, - 154.83, 154.41, 154.93, 154.01, 154.74, 155.25, 156.17, 154.93, 155.28, - 155.5, 157.43, 154.54, 155.34, 155.41, 156.42, 155.19, 155.99, 155.79, - 156.81, 155.17, 155.44, 156.17, 156.72, 155.85, 156.43, 157.33, 159.43, - 157.09, 159.31, 159.21, 160.29, 158.66, 159.9, 159.85, 160.13, 159.03, - 159.19, 156.19, 156.52, 154.46, 155.42, 156.05, 157.18, 155.4, 155.69, - 156.33, 157.13, 154.94, 155.61, 155.73, 156.86, 155.64, 156.54, 156.35, - 156.99, 154.71, 155.85, 156.67, 157.26, 156.22, 156.85, 158.72, 163.01, - 158.13, 162.47, 163.3, 167.47, 163.13, 166.12, 167.3, 169.04, 166.34, - 168.43, 169.26, 169.33, 165.02, 166.29, 167.04, 167.9, 164.69, 167.51, - 173.38, 173.64, 170.51, 171.88, 171.75, 174.36, 171.1, 173.63, 173.29, - 174.51, 173.29, 174.18, 174.03, 175.61, 173.71, 175.61, 174.48, 175.46, - 172.52, 175.25, 175.11, 175.38, 174.27, 174.67}; - vector names = {"one", "two", "seven", "three"}; - CandlestickChartWidget ccw(c, 100, 100, 850, 400, - GraphWidget::AxisType::LINEAR, - GraphWidget::AxisType::LINEAR, this); - - // setting general things for the graph - // the axis text styles must be set before - // creating the axes - ccw.setGraphTitle("Candlestick Chart"); - - // bar chart widget specific bits - // ccw.setBoxWidth(5); - // ccw.setBoxColors(boxColors); - // ccw.setBoxOutlineColors(outlineColors); - - // create x axis (categories) - // ccw.setNames(names); - - // set relevant x axis parameters - // if you try to set something not applicable to a text axis (as that's what - // the x axis always will be), the compiler will yell at you - ccw.xAxis->setTitle("Date"); - // ccw.xAxis->setTickDrawSize(7); - // ccw.xAxis->setAxisColor(grail::green); - // ccw.xAxis->setTickColor(grail::purple); - - // y axis stuff - ccw.setData(data); - - // set y axis parameters - // ccw.yAxis->setIsVert(true); - - // linear - ccw.yAxis->setBounds(140, 180); - ccw.yAxis->setTickInterval(2); - - // ccw.yAxis->setTickDrawSize(10); - // ccw.yAxis->setShowTicks(true); - ccw.yAxis->setTitle("Price"); - // ccw.yAxis->setAxisColor(grail::yellow); - // ccw.yAxis->setTickColor(grail::red); - - ccw.init(); - } -}; - class Menu : public NavigationBar { public: Menu(GLWin* w); }; -Menu::Menu(GLWin* w) : NavigationBar(w, 40, 600, 300, 50, 40) { - ButtonWidget* bar = addButton(175, 50, "Bar", "tab 1"); +Menu::Menu(GLWin* w) : NavigationBar(w, 2, 2, 300, 50, 10) { + setButtonStyle((Font*)FontFace::get("TIMES", 28, FontFace::BOLD), + grail::black, grail::yellow, 2); + + ButtonWidget* bar = addButton("Bar", "tab 1"); bar->setAction([w]() { w->switchTab(3); }); - ButtonWidget* box = addButton(175, 50, "Box", "tab 2"); + ButtonWidget* box = addButton("Box", "tab 2"); box->setAction([w]() { w->switchTab(2); }); - ButtonWidget* line = addButton(175, 50, "Line", "tab 3"); + ButtonWidget* line = addButton("Line", "tab 3"); line->setAction([w]() { w->switchTab(1); }); - ButtonWidget* cstick = addButton(175, 50, "CStick", "tab 4"); + ButtonWidget* cstick = addButton("CStick", "tab 4"); cstick->setAction([w]() { w->switchTab(0); }); } From 42f74e5aeda93ecbcfe4b01edfe60c1961e340ac Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Thu, 2 Jun 2022 15:33:53 -0400 Subject: [PATCH 10/15] Add bar box drawing, code cleanup --- src/opengl/NavigationBar.cc | 87 +++++++++++++++++++++++++------------ src/opengl/NavigationBar.hh | 31 ++++++++++--- test/xp/BarChart.hh | 2 - test/xp/BoxChart.hh | 2 - test/xp/CandlestickChart.hh | 2 - test/xp/LineGraph.hh | 2 - test/xp/testGraphTabs.cc | 11 +++-- test/xp/testMultiTab.cc | 2 +- 8 files changed, 91 insertions(+), 48 deletions(-) diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index cd89a09b..fce80e2f 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -15,30 +15,26 @@ NavigationBar::NavigationBar(MainCanvas* initialCanvas, float width, float height, float axisPadding, bool isVertical) : Member(initialCanvas->getTab(), 0), - currentCanvas(initialCanvas), - m(initialCanvas, initialStyle), - t(initialCanvas, initialStyle), + c(initialCanvas), + parentWin(initialCanvas->getWin()), xPos(x), yPos(y), barWidth(width), barHeight(height), axisPadding(axisPadding), isVertical(isVertical) { - canvases.insert(initialCanvas); - - this->isVertical = isVertical; - parentWin = initialCanvas->getWin(); + buttonStyle = + new Style(parentWin->getMenuFont(), grail::black, grail::red, 1); + /* defaultButtonHeight = min(48_f32, height); defaultButtonWidth = min(90_f32, width); defaultEdgeWidth = min(16_f32, width / 3); - buttonStyle = - new Style(parentWin->getMenuFont(), grail::black, grail::red, 1); - /* + addButton(defaultButtonWidth, defaultButtonHeight, axisPadding, "+", - "add tab") - .setAction(bind(&NavigationBar::addTab, this)); - */ + "add tab") + .setAction(bind(&NavigationBar::addTab, this)); + */ } NavigationBar::NavigationBar(GLWin* w, float x, float y, float width, @@ -50,24 +46,23 @@ NavigationBar::NavigationBar(GLWin* w, float x, float y, float width, ButtonWidget* NavigationBar::addButton(float width, float height, string label, const char action[]) { if (isVertical) { - buttons.push_back(new ButtonWidget(currentCanvas, buttonStyle, xPos, + buttons.push_back(new ButtonWidget(c, buttonStyle, xPos, yPos + axisOffset(), width, height, label, action)); } else { - buttons.push_back(new ButtonWidget(currentCanvas, buttonStyle, - xPos + axisOffset(), yPos, width, height, - label, action)); + buttons.push_back(new ButtonWidget(c, buttonStyle, xPos + axisOffset(), + yPos, width, height, label, action)); } return buttons.back(); } ButtonWidget* NavigationBar::addButton(string label, const char action[]) { if (isVertical) { - buttons.push_back(new ButtonWidget(currentCanvas, buttonStyle, xPos, + buttons.push_back(new ButtonWidget(c, buttonStyle, xPos, yPos + axisOffset(), label, action)); } else { - buttons.push_back(new ButtonWidget( - currentCanvas, buttonStyle, xPos + axisOffset(), yPos, label, action)); + buttons.push_back(new ButtonWidget(c, buttonStyle, xPos + axisOffset(), + yPos, label, action)); } return buttons.back(); } @@ -75,12 +70,12 @@ ButtonWidget* NavigationBar::addButton(string label, const char action[]) { float NavigationBar::axisOffset() { if (buttons.empty()) { return 0; + } + + if (isVertical) { + return buttons.back()->getY() + buttons.back()->getH() + axisPadding; } else { - if (isVertical) { - return buttons.back()->getY() + buttons.back()->getH() + axisPadding; - } else { - return buttons.back()->getX() + buttons.back()->getW() + axisPadding; - } + return buttons.back()->getX() + buttons.back()->getW() + axisPadding; } } @@ -98,13 +93,49 @@ void NavigationBar::setButtonStyle(const Font* f, glm::vec4 borderColor, buttonStyle->lineWidth = borderThickness; } +void NavigationBar::drawBarBox(glm::vec4 borderColor, glm::vec4 boxColor, + float borderSize) { + StyledMultiShape2D* m = c->getGui(); + m->fillRectangle(xPos - borderSize, yPos - borderSize, + barWidth + (borderSize * 2), barHeight + (borderSize * 2), + borderColor); + m->fillRectangle(xPos, yPos, barWidth, barHeight, boxColor); + + for (ButtonWidget* b : buttons) { + b->redraw(); + } +} + +void NavigationBar::fitBarDimensions(float widthPadding, float heightPadding) { + if (isVertical) { + barWidth = buttons[0]->getW(); + for (ButtonWidget* b : buttons) { + barWidth = max(b->getW(), barWidth); + } + + barHeight = buttons.back()->getY() + buttons.back()->getH() - + buttons.front()->getY(); + } else { + barWidth = buttons.back()->getX() + buttons.back()->getW() - + buttons.front()->getX(); + + barHeight = buttons[0]->getH(); + for (ButtonWidget* b : buttons) { + barHeight = max(b->getH(), barHeight); + } + } + + barWidth += widthPadding; + barHeight += heightPadding; +} + +/* void NavigationBar::addNewTab() { Tab* t = parentWin->addTab(); - canvases.insert(t->getMainCanvas()); - // addToTab(t); + // canvases.insert(t->getMainCanvas()); + // addToTab(t); } -/* void NavigationBar::addToTab(Tab* tab) { tab->addMember(this); MainCanvas* newCanvas = tab->getMainCanvas(); diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index da91014d..90f93e81 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -8,11 +8,8 @@ class NavigationBar : public Member { private: std::vector buttons; - std::unordered_set canvases; GLWin* parentWin; - MainCanvas* currentCanvas; - StyledMultiShape2D m; - MultiText t; + MainCanvas* c; float defaultButtonWidth; float defaultButtonHeight; @@ -102,6 +99,27 @@ class NavigationBar : public Member { void setButtonStyle(const Font* f, glm::vec4 borderColor, glm::vec4 buttonColor, float borderThickness); + /** + * @brief Draw a box around the dimension of the nav bar + * + * @param borderColor color of box border + * @param buttonColor main color of box + * @param borderThickness thickness of box border + */ + void drawBarBox(glm::vec4 borderColor, glm::vec4 boxColor, + float borderThickness); + + /** + * @brief Updates the dimensions of the nav bar to fit around the buttons. + * Option to add padding between the buttons and nav bar edges + * + * @param widthPadding horizontal distance between nav bar edge and closest + * button + * @param heightPadding vertical distance between nav bar edge and closest + * button + */ + void fitBarDimensions(float widthPadding = 0, float heightPadding = 0); + /** * @brief Balance n buttons on the nav bar * @@ -117,12 +135,11 @@ class NavigationBar : public Member { /** * @brief Adds a new tab to the window and adds the navigation bar to the tab * - */ + * + /* void addNewTab(); void addToTab(Tab* tab); - - /* void render() { std::cout << "printing from NavigationBar::render()" << std::endl; } diff --git a/test/xp/BarChart.hh b/test/xp/BarChart.hh index 512f8b6b..6938d89e 100644 --- a/test/xp/BarChart.hh +++ b/test/xp/BarChart.hh @@ -1,7 +1,5 @@ #pragma once #include "opengl/BarChartWidget.hh" -#include "opengl/GrailGUI.hh" -#include "opengl/GraphStyle.hh" using namespace std; diff --git a/test/xp/BoxChart.hh b/test/xp/BoxChart.hh index e82668a3..6a378105 100644 --- a/test/xp/BoxChart.hh +++ b/test/xp/BoxChart.hh @@ -1,7 +1,5 @@ #pragma once #include "opengl/BoxChartWidget.hh" -#include "opengl/GrailGUI.hh" -#include "opengl/GraphStyle.hh" using namespace std; diff --git a/test/xp/CandlestickChart.hh b/test/xp/CandlestickChart.hh index 80f3c861..0e655aca 100644 --- a/test/xp/CandlestickChart.hh +++ b/test/xp/CandlestickChart.hh @@ -1,7 +1,5 @@ #pragma once #include "opengl/CandlestickChartWidget.hh" -#include "opengl/GrailGUI.hh" -#include "opengl/GraphStyle.hh" using namespace std; diff --git a/test/xp/LineGraph.hh b/test/xp/LineGraph.hh index ca9db013..de466a56 100644 --- a/test/xp/LineGraph.hh +++ b/test/xp/LineGraph.hh @@ -1,6 +1,4 @@ #pragma once -#include "opengl/GrailGUI.hh" -#include "opengl/GraphStyle.hh" #include "opengl/LineGraphWidget.hh" using namespace std; diff --git a/test/xp/testGraphTabs.cc b/test/xp/testGraphTabs.cc index 705dd8ff..96c2c30e 100644 --- a/test/xp/testGraphTabs.cc +++ b/test/xp/testGraphTabs.cc @@ -8,12 +8,12 @@ using namespace std; using namespace grail; -class Menu : public NavigationBar { +class ChartNavBar : public NavigationBar { public: - Menu(GLWin* w); + ChartNavBar(GLWin* w); }; -Menu::Menu(GLWin* w) : NavigationBar(w, 2, 2, 300, 50, 10) { +ChartNavBar::ChartNavBar(GLWin* w) : NavigationBar(w, 0, 0, 400, 50, 10) { setButtonStyle((Font*)FontFace::get("TIMES", 28, FontFace::BOLD), grail::black, grail::yellow, 2); @@ -28,12 +28,15 @@ Menu::Menu(GLWin* w) : NavigationBar(w, 2, 2, 300, 50, 10) { ButtonWidget* cstick = addButton("CStick", "tab 4"); cstick->setAction([w]() { w->switchTab(0); }); + + fitBarDimensions(5, 5); + drawBarBox(grail::black, grail::gray, 2); } void grailmain(int argc, char* argv[], GLWin* w) { + new ChartNavBar(w); new CandlestickChart(w); new LineGraph(w); new BoxChart(w); new BarChart(w); - new Menu(w); } \ No newline at end of file diff --git a/test/xp/testMultiTab.cc b/test/xp/testMultiTab.cc index 04228a16..d40807f7 100644 --- a/test/xp/testMultiTab.cc +++ b/test/xp/testMultiTab.cc @@ -16,7 +16,7 @@ MultiTab::MultiTab(GLWin* w) : NavigationBar(w, 0, 0, 200, 130, 20, true) { ButtonWidget* next = addButton(200, 30, "next", "next tab"); next->setAction(bind(&GLWin::nextTab, w)); ButtonWidget* add = addButton(200, 30, "+", "add tab"); - add->setAction(bind(&MultiTab::addNewTab, this)); + add->setAction(bind(&GLWin::addTab, w)); } void grailmain(int argc, char* argv[], GLWin* w) { From 6959f0fc122ffcdf514a849e286ebc75dea18756 Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Fri, 3 Jun 2022 15:37:34 -0400 Subject: [PATCH 11/15] add AutoNavBar --- src/opengl/AutoNavBar.cc | 75 ++++++++++++++++++++++++++++++++++++ src/opengl/AutoNavBar.hh | 24 ++++++++++++ src/opengl/CMakeLists.txt | 1 + src/opengl/GLWin.cc | 3 +- src/opengl/GLWin.hh | 2 + src/opengl/GraphStyle.hh | 8 ++-- src/opengl/Member.cc | 17 ++++++-- src/opengl/Member.hh | 10 ++++- src/opengl/NavigationBar.cc | 26 ++++++++----- src/opengl/NavigationBar.hh | 22 +++++++---- test/xp/BarChart.hh | 2 +- test/xp/BoxChart.hh | 2 +- test/xp/CMakeLists.txt | 3 +- test/xp/CandlestickChart.hh | 2 +- test/xp/LineGraph.hh | 2 +- test/xp/testAutoGraphTabs.cc | 19 +++++++++ test/xp/testGraphTabs.cc | 2 +- 17 files changed, 185 insertions(+), 35 deletions(-) create mode 100644 src/opengl/AutoNavBar.cc create mode 100644 src/opengl/AutoNavBar.hh create mode 100644 test/xp/testAutoGraphTabs.cc diff --git a/src/opengl/AutoNavBar.cc b/src/opengl/AutoNavBar.cc new file mode 100644 index 00000000..d2fe4221 --- /dev/null +++ b/src/opengl/AutoNavBar.cc @@ -0,0 +1,75 @@ +#include "opengl/AutoNavBar.hh" + +using namespace std; + +AutoNavBar::AutoNavBar(GLWin* w, float x, float y, float axisPadding, + float horizontalPadding, float verticalPadding, + bool isVertical, bool isReverseOrder) + : NavigationBar(w, x, y, 0, 0, axisPadding, isVertical), + currentX(x), + currentY(y), + horizontalPadding(horizontalPadding), + verticalPadding(verticalPadding), + isReverseOrder(isReverseOrder) { + w->autoNavBar = this; +} + +/* + 1. how to add left-to-right, right-to-left automatically + + + 2. how to set button actions properly + +*/ +void AutoNavBar::addButton(Member* m) { + int index = buttons.size(); + ButtonWidget* bw; + if (isVertical) { + bw = new ButtonWidget(c, buttonStyle, xPos, yPos + axisOffset(), + m->getName(), "action"); + } else { + bw = new ButtonWidget(c, buttonStyle, xPos + axisOffset(), yPos, + m->getName(), "action"); + } + buttons.push_back(bw); + bw->setAction(bind(&GLWin::switchTab, parentWin, index)); + +#if 0 + + if (isReverseOrder) { + if (isVertical) { + // TODO: New positioning algorithm for when isLeftToRight is true + // axisOffset() will not work + buttons.insert(buttons.begin(), + bw = new ButtonWidget(c, buttonStyle, xPos, yPos + axisOffset(), + m->getName(), "action")); + } else { + buttons.insert(buttons.begin(), + bw = new ButtonWidget(c, buttonStyle, xPos + axisOffset(), yPos, + m->getName(), "action")); + } + updateButtonPositions(); + } else { + if (isVertical) { + buttons.push_back(bw = new ButtonWidget( + c, buttonStyle, xPos, yPos + axisOffset(), m->getName(), "action")); + } else { + buttons.push_back(bw = new ButtonWidget(c, buttonStyle, xPos + axisOffset(), + yPos, m->getName(), "action")); + } + } + + int index = buttons.size() - 1; // get the index of the current button so we can activate the corresponding tab + bw->setAction(bind(GLWin::switchTab(index), parentWin)); +#endif + fitBarDimensions(horizontalPadding, verticalPadding); + drawBarBox(); +} + +void AutoNavBar::advancePosition() { + if (isVertical) { + currentY += axisOffset(); + } else { + currentX += axisOffset(); + } +} \ No newline at end of file diff --git a/src/opengl/AutoNavBar.hh b/src/opengl/AutoNavBar.hh new file mode 100644 index 00000000..0916cd76 --- /dev/null +++ b/src/opengl/AutoNavBar.hh @@ -0,0 +1,24 @@ +#pragma once + +#include "opengl/NavigationBar.hh" + +/** + * @brief Version of NavigationBar in which new buttons are automatically added + * when a new member is added. The dimensions of the buttons and the navigation + * bar are also automatically determined and updated. + * + */ +class AutoNavBar : public NavigationBar { + private: + bool isReverseOrder; + float horizontalPadding, verticalPadding; + float currentX, currentY; + + public: + AutoNavBar(GLWin* w, float x, float y, float axisPadding, + float horizontalPadding, float verticalPadding, + bool isVertical = false, bool isReverseOrder = false); + + void addButton(Member* m); + void advancePosition(); +}; \ No newline at end of file diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt index 47b3361c..87871fbc 100644 --- a/src/opengl/CMakeLists.txt +++ b/src/opengl/CMakeLists.txt @@ -1,4 +1,5 @@ set(grail-opengl + AutoNavBar.cc AxisWidget.cc BarChartWidget.cc BoxChartWidget.cc diff --git a/src/opengl/GLWin.cc b/src/opengl/GLWin.cc index ee522638..9047ee07 100644 --- a/src/opengl/GLWin.cc +++ b/src/opengl/GLWin.cc @@ -168,7 +168,8 @@ GLWin::GLWin(uint32_t bgColor, uint32_t fgColor, const string &title, faces(16), dragMode(false), mousePressX(0), - mousePressY(0) { + mousePressY(0), + autoNavBar(nullptr) { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index bcc417bb..99c501d0 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -23,6 +23,7 @@ class Style; class Font; class XDLIterator; class MainCanvas; +class AutoNavBar; class GLWin { protected: @@ -67,6 +68,7 @@ class GLWin { uint32_t width, height; // width and height of the window in pixels bool needsUpdate, needsRender; bool focused; + AutoNavBar* autoNavBar; uint32_t exitAfter; // if not zero, will terminate private: diff --git a/src/opengl/GraphStyle.hh b/src/opengl/GraphStyle.hh index 20c39b8d..75200465 100644 --- a/src/opengl/GraphStyle.hh +++ b/src/opengl/GraphStyle.hh @@ -42,8 +42,8 @@ class GraphStyle : public Member { * @param axisSize size of the axis font */ GraphStyle(Tab* tab, const char faceName[], uint32_t titleSize, - uint32_t axisSize) - : Member(tab), + uint32_t axisSize, const char name[]) + : Member(tab, name), // two lines and the overall title baseStyle(faceName, axisSize, 1, 0, 0, 0, 0.3, 0.3, 0.3, 5), titleStyle(faceName, titleSize, 1, 0, 0, 0, 0, 0, 0, 5), @@ -91,8 +91,8 @@ class GraphStyle : public Member { * @param axisSize size of the axis font */ GraphStyle(GLWin* w, const char faceName[], uint32_t titleSize, - uint32_t axisSize) - : GraphStyle(w->addTab(), faceName, titleSize, axisSize) {} + uint32_t axisSize, const char name[]) + : GraphStyle(w->addTab(), faceName, titleSize, axisSize, name) {} /** * @brief Summary diff --git a/src/opengl/Member.cc b/src/opengl/Member.cc index 1dfa211d..fc391b3a 100644 --- a/src/opengl/Member.cc +++ b/src/opengl/Member.cc @@ -1,20 +1,26 @@ +#include "opengl/AutoNavBar.hh" #include "opengl/GrailGUI.hh" using namespace std; // BUG: If Frame Rate exceeds refresh rate (noticed at 120fps where // default is 60fps), animation breaks at the Tab level -Member::Member(Tab* tab, double frameRate, double dt) - : tab(tab), c(tab->getMainCanvas()) { +Member::Member(Tab* tab, string name, double frameRate, double dt) + : tab(tab), c(tab->getMainCanvas()), name(name) { tab->setFrameRate(frameRate); tab->setDt(dt); tab->setDefaultDt(0.0001); tab->addMember(this); + + GLWin* w = tab->getParentWin(); + if (w->autoNavBar != nullptr) { + w->autoNavBar->addButton(this); + } } -Member::Member(GLWin* w, double frameRate, double dt) - : Member(w->addTab(), frameRate, dt) {} +Member::Member(GLWin* w, string name, double frameRate, double dt) + : Member(w->addTab(), name, frameRate, dt) {} void Member::setFrameRate(double frameRate) { tab->setFrameRate(frameRate); } @@ -23,6 +29,9 @@ void Member::setModelDt(double dt, double defaultDt) { tab->setDefaultDt(defaultDt); } +string Member::getName() { return name; }; +void Member::setName(string newName) { name = newName; }; + void Member::init() {} void Member::render() {} void Member::update() {} diff --git a/src/opengl/Member.hh b/src/opengl/Member.hh index 2d151ebe..83749b33 100644 --- a/src/opengl/Member.hh +++ b/src/opengl/Member.hh @@ -11,14 +11,20 @@ class Member { protected: Tab* tab; MainCanvas* c; + std::string name; public: - Member(Tab* tab, double frameRate = -1, double dt = 0.0001); - Member(GLWin* w, double frameRate = -1, double dt = 0.0001); + Member(Tab* tab, std::string name = "Member", double frameRate = -1, + double dt = 0.0001); + Member(GLWin* w, std::string name = "Member", double frameRate = -1, + double dt = 0.0001); void setFrameRate(double frameRate); void setModelDt(double dt, double defaultDt); + std::string getName(); + void setName(std::string newName); + // Allow members to override init, render, and update // Tabs iterate through each of these manually diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index fce80e2f..9a63fd45 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -10,11 +10,10 @@ using namespace std; // TODO: make this confirm to some design guide, maybe use material's design // guide on tabs? -NavigationBar::NavigationBar(MainCanvas* initialCanvas, - const Style* initialStyle, float x, float y, +NavigationBar::NavigationBar(MainCanvas* initialCanvas, float x, float y, float width, float height, float axisPadding, bool isVertical) - : Member(initialCanvas->getTab(), 0), + : Member(initialCanvas->getTab(), "NavBar", 0), c(initialCanvas), parentWin(initialCanvas->getWin()), xPos(x), @@ -25,6 +24,7 @@ NavigationBar::NavigationBar(MainCanvas* initialCanvas, isVertical(isVertical) { buttonStyle = new Style(parentWin->getMenuFont(), grail::black, grail::red, 1); + barStyle = new Style(parentWin->getMenuFont(), grail::black, grail::gray, 1); /* defaultButtonHeight = min(48_f32, height); @@ -39,9 +39,8 @@ NavigationBar::NavigationBar(MainCanvas* initialCanvas, NavigationBar::NavigationBar(GLWin* w, float x, float y, float width, float height, float axisPadding, bool isVertical) - : NavigationBar(w->getSharedTab()->getMainCanvas(), - w->getSharedTab()->getMainCanvas()->getStyle(), x, y, width, - height, axisPadding, isVertical) {} + : NavigationBar(w->getSharedTab()->getMainCanvas(), x, y, width, height, + axisPadding, isVertical) {} ButtonWidget* NavigationBar::addButton(float width, float height, string label, const char action[]) { @@ -93,13 +92,20 @@ void NavigationBar::setButtonStyle(const Font* f, glm::vec4 borderColor, buttonStyle->lineWidth = borderThickness; } -void NavigationBar::drawBarBox(glm::vec4 borderColor, glm::vec4 boxColor, - float borderSize) { +void NavigationBar::setBarStyle(glm::vec4 borderColor, glm::vec4 barColor, + float borderThickness) { + barStyle->bg = borderColor; + barStyle->fg = barColor; + barStyle->lineWidth = borderThickness; +} + +void NavigationBar::drawBarBox() { StyledMultiShape2D* m = c->getGui(); + float borderSize = barStyle->lineWidth; m->fillRectangle(xPos - borderSize, yPos - borderSize, barWidth + (borderSize * 2), barHeight + (borderSize * 2), - borderColor); - m->fillRectangle(xPos, yPos, barWidth, barHeight, boxColor); + barStyle->bg); + m->fillRectangle(xPos, yPos, barWidth, barHeight, barStyle->fg); for (ButtonWidget* b : buttons) { b->redraw(); diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index 90f93e81..2bbd43ab 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -6,7 +6,7 @@ #include "opengl/ButtonWidget.hh" class NavigationBar : public Member { - private: + protected: std::vector buttons; GLWin* parentWin; MainCanvas* c; @@ -16,6 +16,7 @@ class NavigationBar : public Member { float defaultEdgeWidth; Style* buttonStyle; + Style* barStyle; float xPos, yPos, barWidth, barHeight, axisPadding; bool isVertical; @@ -31,9 +32,8 @@ class NavigationBar : public Member { * @param axisPadding distance between the edges of two buttons * @param isVertical allow vertical navigation bars (e.x. Ubuntu's task bar) */ - NavigationBar(MainCanvas* initialCanvas, const Style* initialStyle, float x, - float y, float width, float height, float axisPadding, - bool isVertical); + NavigationBar(MainCanvas* initialCanvas, float x, float y, float width, + float height, float axisPadding, bool isVertical); public: /** @@ -100,14 +100,20 @@ class NavigationBar : public Member { glm::vec4 buttonColor, float borderThickness); /** - * @brief Draw a box around the dimension of the nav bar + * @brief Redefine the style for the nav bar box * * @param borderColor color of box border - * @param buttonColor main color of box + * @param barColor main color of box * @param borderThickness thickness of box border */ - void drawBarBox(glm::vec4 borderColor, glm::vec4 boxColor, - float borderThickness); + void setBarStyle(glm::vec4 borderColor, glm::vec4 barColor, + float borderThickness); + + /** + * @brief Draw a box around the dimension of the nav bar + * + */ + void drawBarBox(); /** * @brief Updates the dimensions of the nav bar to fit around the buttons. diff --git a/test/xp/BarChart.hh b/test/xp/BarChart.hh index 6938d89e..ebdf8ac4 100644 --- a/test/xp/BarChart.hh +++ b/test/xp/BarChart.hh @@ -5,7 +5,7 @@ using namespace std; class BarChart : public GraphStyle { public: - BarChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + BarChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12, "Bar") { MainCanvas* c = tab->getMainCanvas(); vector values = {4, 6, 8, 10, 12, 14}; vector logValues = {4, 8, 16, 32, 64, 128}; diff --git a/test/xp/BoxChart.hh b/test/xp/BoxChart.hh index 6a378105..7f179910 100644 --- a/test/xp/BoxChart.hh +++ b/test/xp/BoxChart.hh @@ -5,7 +5,7 @@ using namespace std; class BoxChart : public GraphStyle { public: - BoxChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + BoxChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12, "Box") { MainCanvas* c = tab->getMainCanvas(); vector data = {150, 350, 222, 100, 300, // diff --git a/test/xp/CMakeLists.txt b/test/xp/CMakeLists.txt index 3e249e6f..8de0e823 100644 --- a/test/xp/CMakeLists.txt +++ b/test/xp/CMakeLists.txt @@ -3,4 +3,5 @@ add_grail_executable(SRC testfmt.cc LIBS grail) add_grail_executable(SRC testMultiTab.cc LIBS grail) add_grail_executable(SRC test2Tabs.cc LIBS grail) -add_grail_executable(SRC testGraphTabs.cc LIBS grail) \ No newline at end of file +add_grail_executable(SRC testGraphTabs.cc LIBS grail) +add_grail_executable(SRC testAutoGraphTabs.cc LIBS grail) \ No newline at end of file diff --git a/test/xp/CandlestickChart.hh b/test/xp/CandlestickChart.hh index 0e655aca..66d60b0a 100644 --- a/test/xp/CandlestickChart.hh +++ b/test/xp/CandlestickChart.hh @@ -5,7 +5,7 @@ using namespace std; class CandlestickChart : public GraphStyle { public: - CandlestickChart(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 20, 12) { + CandlestickChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12, "CStick") { MainCanvas* c = tab->getMainCanvas(); vector data = { diff --git a/test/xp/LineGraph.hh b/test/xp/LineGraph.hh index de466a56..b9eb3485 100644 --- a/test/xp/LineGraph.hh +++ b/test/xp/LineGraph.hh @@ -5,7 +5,7 @@ using namespace std; class LineGraph : public GraphStyle { public: - LineGraph(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 24, 12) { + LineGraph(GLWin* w) : GraphStyle(w->addTab(), "TIMES", 24, 12, "Line") { MainCanvas* c = tab->getMainCanvas(); vector times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; diff --git a/test/xp/testAutoGraphTabs.cc b/test/xp/testAutoGraphTabs.cc new file mode 100644 index 00000000..29bd4bb2 --- /dev/null +++ b/test/xp/testAutoGraphTabs.cc @@ -0,0 +1,19 @@ +#include "BarChart.hh" +#include "BoxChart.hh" +#include "CandlestickChart.hh" +#include "LineGraph.hh" +#include "opengl/AutoNavBar.hh" +#include "opengl/GrailGUI.hh" + +using namespace std; +using namespace grail; + +void grailmain(int argc, char* argv[], GLWin* w) { + AutoNavBar* bar = new AutoNavBar(w, 0, 0, 10, 5, 5); + bar->setButtonStyle(FontFace::get("TIMES", 28, FontFace::BOLD), grail::black, + grail::yellow, 2); + new CandlestickChart(w); + new LineGraph(w); + new BoxChart(w); + new BarChart(w); +} \ No newline at end of file diff --git a/test/xp/testGraphTabs.cc b/test/xp/testGraphTabs.cc index 96c2c30e..682cac47 100644 --- a/test/xp/testGraphTabs.cc +++ b/test/xp/testGraphTabs.cc @@ -30,7 +30,7 @@ ChartNavBar::ChartNavBar(GLWin* w) : NavigationBar(w, 0, 0, 400, 50, 10) { cstick->setAction([w]() { w->switchTab(0); }); fitBarDimensions(5, 5); - drawBarBox(grail::black, grail::gray, 2); + drawBarBox(); } void grailmain(int argc, char* argv[], GLWin* w) { From 0a8766b7c7580f20651d6672d4504469dd605560 Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Mon, 6 Jun 2022 16:58:06 -0400 Subject: [PATCH 12/15] Add reverse order functionality to AutoNavBar --- src/opengl/AutoNavBar.cc | 147 +++++++++++++++++------------------ src/opengl/AutoNavBar.hh | 84 ++++++++++++++------ src/opengl/ButtonWidget.hh | 2 + src/opengl/NavigationBar.hh | 11 +-- test/xp/testAutoGraphTabs.cc | 36 ++++----- 5 files changed, 160 insertions(+), 120 deletions(-) diff --git a/src/opengl/AutoNavBar.cc b/src/opengl/AutoNavBar.cc index d2fe4221..0aaee62c 100644 --- a/src/opengl/AutoNavBar.cc +++ b/src/opengl/AutoNavBar.cc @@ -1,75 +1,74 @@ -#include "opengl/AutoNavBar.hh" - -using namespace std; - -AutoNavBar::AutoNavBar(GLWin* w, float x, float y, float axisPadding, - float horizontalPadding, float verticalPadding, - bool isVertical, bool isReverseOrder) - : NavigationBar(w, x, y, 0, 0, axisPadding, isVertical), - currentX(x), - currentY(y), - horizontalPadding(horizontalPadding), - verticalPadding(verticalPadding), - isReverseOrder(isReverseOrder) { - w->autoNavBar = this; -} - -/* - 1. how to add left-to-right, right-to-left automatically - - - 2. how to set button actions properly - -*/ -void AutoNavBar::addButton(Member* m) { - int index = buttons.size(); - ButtonWidget* bw; - if (isVertical) { - bw = new ButtonWidget(c, buttonStyle, xPos, yPos + axisOffset(), - m->getName(), "action"); - } else { - bw = new ButtonWidget(c, buttonStyle, xPos + axisOffset(), yPos, - m->getName(), "action"); - } - buttons.push_back(bw); - bw->setAction(bind(&GLWin::switchTab, parentWin, index)); - -#if 0 - - if (isReverseOrder) { - if (isVertical) { - // TODO: New positioning algorithm for when isLeftToRight is true - // axisOffset() will not work - buttons.insert(buttons.begin(), - bw = new ButtonWidget(c, buttonStyle, xPos, yPos + axisOffset(), - m->getName(), "action")); - } else { - buttons.insert(buttons.begin(), - bw = new ButtonWidget(c, buttonStyle, xPos + axisOffset(), yPos, - m->getName(), "action")); - } - updateButtonPositions(); - } else { - if (isVertical) { - buttons.push_back(bw = new ButtonWidget( - c, buttonStyle, xPos, yPos + axisOffset(), m->getName(), "action")); - } else { - buttons.push_back(bw = new ButtonWidget(c, buttonStyle, xPos + axisOffset(), - yPos, m->getName(), "action")); - } - } - - int index = buttons.size() - 1; // get the index of the current button so we can activate the corresponding tab - bw->setAction(bind(GLWin::switchTab(index), parentWin)); -#endif - fitBarDimensions(horizontalPadding, verticalPadding); - drawBarBox(); -} - -void AutoNavBar::advancePosition() { - if (isVertical) { - currentY += axisOffset(); - } else { - currentX += axisOffset(); - } +#include "opengl/AutoNavBar.hh" + +using namespace std; + +AutoNavBar::AutoNavBar(GLWin* w, float x, float y, float axisPadding, + float horizontalPadding, float verticalPadding, + bool isVertical, bool isReverseOrder) + : NavigationBar(w, x, y, 0, 0, axisPadding, isVertical), + horizontalPadding(horizontalPadding), + verticalPadding(verticalPadding), + isReverseOrder(isReverseOrder) { + w->autoNavBar = this; +} + +void AutoNavBar::addButton(Member* m) { + int index = buttons.size(); + ButtonWidget* bw = NavigationBar::addButton(m->getName(), "action"); + bw->setAction(bind(&GLWin::switchTab, parentWin, index)); + + if (isReverseOrder) { + reverseButtonOrder(); + c->getGuiText()->clear(); + } + + fitBarDimensions(horizontalPadding, verticalPadding); + drawBarBox(); +} + +void AutoNavBar::reverseButtonOrder() { + float currentX = xPos; + float currentY = yPos; + for (int i = buttons.size() - 1; i >= 0; i--) { + if (isVertical) { + buttons[i]->setY(currentY); + currentY += buttons[i]->getH() + axisPadding; + } else { + buttons[i]->setX(currentX); + currentX += buttons[i]->getW() + axisPadding; + } + } +} + +void AutoNavBar::fitBarDimensions(float widthPadding, float heightPadding) { + if (isVertical) { + barWidth = buttons[0]->getW(); + for (ButtonWidget* b : buttons) { + barWidth = max(b->getW(), barWidth); + } + + if (isReverseOrder) { + barHeight = buttons.front()->getY() + buttons.front()->getH() - + buttons.back()->getY(); + } else { + barHeight = buttons.back()->getY() + buttons.back()->getH() - + buttons.front()->getY(); + } + } else { + if (isReverseOrder) { + barWidth = buttons.front()->getX() + buttons.front()->getW() - + buttons.back()->getX(); + } else { + barWidth = buttons.back()->getX() + buttons.back()->getW() - + buttons.front()->getX(); + } + + barHeight = buttons[0]->getH(); + for (ButtonWidget* b : buttons) { + barHeight = max(b->getH(), barHeight); + } + } + + barWidth += widthPadding; + barHeight += heightPadding; } \ No newline at end of file diff --git a/src/opengl/AutoNavBar.hh b/src/opengl/AutoNavBar.hh index 0916cd76..f61e3bd4 100644 --- a/src/opengl/AutoNavBar.hh +++ b/src/opengl/AutoNavBar.hh @@ -1,24 +1,62 @@ -#pragma once - -#include "opengl/NavigationBar.hh" - -/** - * @brief Version of NavigationBar in which new buttons are automatically added - * when a new member is added. The dimensions of the buttons and the navigation - * bar are also automatically determined and updated. - * - */ -class AutoNavBar : public NavigationBar { - private: - bool isReverseOrder; - float horizontalPadding, verticalPadding; - float currentX, currentY; - - public: - AutoNavBar(GLWin* w, float x, float y, float axisPadding, - float horizontalPadding, float verticalPadding, - bool isVertical = false, bool isReverseOrder = false); - - void addButton(Member* m); - void advancePosition(); +#pragma once + +#include "opengl/NavigationBar.hh" + +/** + * @brief Version of NavigationBar in which new buttons are automatically added + * when a new member is added. The dimensions of the buttons and the navigation + * bar are also automatically determined and updated. An AutoNavBar should be + * added to a window BEFORE any other members. + * + */ +class AutoNavBar : public NavigationBar { + private: + bool isReverseOrder; + float horizontalPadding, verticalPadding; + + public: + /** + * @brief Create a new automated navigation bar + * + * @param w The initial window to draw on + * @param x x-coordinate of top-left corner + * @param y y-coordinate of top-left corner + * @param axisPadding distance between the edges of two buttons + * @param horizontalPadding horizontal distance between buttons and bar edge + * @param verticalPadding vertical distance between buttons and bar edge + * @param isVertical allow vertical navigation bars (e.x. Ubuntu's task bar) + * @param isReverseOrder display buttons in the reverse order the members are + * added (leftmost/topmost button corresponds to first member displayed) + */ + AutoNavBar(GLWin* w, float x, float y, float axisPadding, + float horizontalPadding, float verticalPadding, + bool isVertical = false, bool isReverseOrder = false); + + /** + * @brief Add a button to the nav bar for a new member + * + * @param m pointer to member + */ + void addButton(Member* m); + + /** + * @brief Update the positions of all buttons in the nav bar such that their + * displayed left-to-right/top-to-bottom order is opposite that of their index + * order + * + */ + void reverseButtonOrder(); + + /** + * @brief Updates the dimensions of the nav bar to fit around the buttons. + * Option to add padding between the buttons and nav bar edges. Override of + * fitBarDimensions function from NavigationBar that accounts for + * isReverseOrder + * + * @param widthPadding horizontal distance between nav bar edge and closest + * button + * @param heightPadding vertical distance between nav bar edge and closest + * button + */ + void fitBarDimensions(float widthPadding = 0, float heightPadding = 0); }; \ No newline at end of file diff --git a/src/opengl/ButtonWidget.hh b/src/opengl/ButtonWidget.hh index 76b264a0..b9842fa6 100644 --- a/src/opengl/ButtonWidget.hh +++ b/src/opengl/ButtonWidget.hh @@ -32,7 +32,9 @@ class ButtonWidget : public InteractiveWidget2D { void updateCanvas(MainCanvas* canvas) { c = canvas; }; float getX() { return x; }; + void setX(float newX) { x = newX; }; float getY() { return y; }; + void setY(float newY) { y = newY; }; float getW() { return w; }; float getH() { return h; }; }; \ No newline at end of file diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index 2bbd43ab..c02e961c 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -51,30 +51,31 @@ class NavigationBar : public Member { float axisPadding, bool isVertical = false); /** - * @brief Create a new button and return a reference to it + * @brief Create a new button and return a pointer to it * * @param width width of the new button * @param height height of the new button * @param label the text to be shown on the button * @param action a description of the button's action - * @return ButtonWidget& a reference to the new button + * @return ButtonWidget* a pointer to the new button */ ButtonWidget* addButton(float width, float height, std::string label, const char action[]); /** - * @brief Create a new button and return a reference to it. Button + * @brief Create a new button and return a pointer to it. Button * width/height are automatically determined based on the text and buttonStyle * font * * @param label the text to be shown on the button * @param action a description of the button's action - * @return ButtonWidget& a reference to the new button + * @return ButtonWidget* a pointer to the new button */ ButtonWidget* addButton(std::string label, const char action[]); /** - * @brief Automatically calculate axis offset for new button on nav bar + * @brief Automatically calculate and return the axis offset for new button on + * nav bar * */ float axisOffset(); diff --git a/test/xp/testAutoGraphTabs.cc b/test/xp/testAutoGraphTabs.cc index 29bd4bb2..3fbea410 100644 --- a/test/xp/testAutoGraphTabs.cc +++ b/test/xp/testAutoGraphTabs.cc @@ -1,19 +1,19 @@ -#include "BarChart.hh" -#include "BoxChart.hh" -#include "CandlestickChart.hh" -#include "LineGraph.hh" -#include "opengl/AutoNavBar.hh" -#include "opengl/GrailGUI.hh" - -using namespace std; -using namespace grail; - -void grailmain(int argc, char* argv[], GLWin* w) { - AutoNavBar* bar = new AutoNavBar(w, 0, 0, 10, 5, 5); - bar->setButtonStyle(FontFace::get("TIMES", 28, FontFace::BOLD), grail::black, - grail::yellow, 2); - new CandlestickChart(w); - new LineGraph(w); - new BoxChart(w); - new BarChart(w); +#include "BarChart.hh" +#include "BoxChart.hh" +#include "CandlestickChart.hh" +#include "LineGraph.hh" +#include "opengl/AutoNavBar.hh" +#include "opengl/GrailGUI.hh" + +using namespace std; +using namespace grail; + +void grailmain(int argc, char* argv[], GLWin* w) { + AutoNavBar* bar = new AutoNavBar(w, 0, 0, 10, 5, 5, false, true); + bar->setButtonStyle(FontFace::get("TIMES", 28, FontFace::BOLD), grail::black, + grail::yellow, 2); + new CandlestickChart(w); + new LineGraph(w); + new BoxChart(w); + new BarChart(w); } \ No newline at end of file From 4cab90e719a4ead59808a31840ec32a297d93a40 Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Fri, 10 Jun 2022 13:38:43 -0400 Subject: [PATCH 13/15] add DropDownMenu (WIP) --- src/opengl/AutoNavBar.cc | 37 ++++++++-------- src/opengl/AutoNavBar.hh | 7 +++ src/opengl/CMakeLists.txt | 1 + src/opengl/DropDownMenu.cc | 87 +++++++++++++++++++++++++++++++++++++ src/opengl/DropDownMenu.hh | 40 +++++++++++++++++ src/opengl/GLWin.cc | 12 ++++- src/opengl/GLWin.hh | 4 +- src/opengl/NavigationBar.cc | 38 +++++++++++----- src/opengl/NavigationBar.hh | 14 ++++++ test/xp/CMakeLists.txt | 3 +- test/xp/testMenu.cc | 30 +++++++++++++ 11 files changed, 238 insertions(+), 35 deletions(-) create mode 100644 src/opengl/DropDownMenu.cc create mode 100644 src/opengl/DropDownMenu.hh create mode 100644 test/xp/testMenu.cc diff --git a/src/opengl/AutoNavBar.cc b/src/opengl/AutoNavBar.cc index 0aaee62c..12424504 100644 --- a/src/opengl/AutoNavBar.cc +++ b/src/opengl/AutoNavBar.cc @@ -42,33 +42,30 @@ void AutoNavBar::reverseButtonOrder() { void AutoNavBar::fitBarDimensions(float widthPadding, float heightPadding) { if (isVertical) { - barWidth = buttons[0]->getW(); - for (ButtonWidget* b : buttons) { - barWidth = max(b->getW(), barWidth); - } + barWidth = buttonsWidth() + widthPadding; + barHeight = buttonsLength() + heightPadding; + } else { + barWidth = buttonsLength() + widthPadding; + barHeight = buttonsWidth() + heightPadding; + } +} +float AutoNavBar::buttonsLength() { + if (isVertical) { if (isReverseOrder) { - barHeight = buttons.front()->getY() + buttons.front()->getH() - - buttons.back()->getY(); + return buttons.front()->getY() + buttons.front()->getH() - + buttons.back()->getY(); } else { - barHeight = buttons.back()->getY() + buttons.back()->getH() - - buttons.front()->getY(); + return buttons.back()->getY() + buttons.back()->getH() - + buttons.front()->getY(); } } else { if (isReverseOrder) { - barWidth = buttons.front()->getX() + buttons.front()->getW() - - buttons.back()->getX(); + return buttons.front()->getX() + buttons.front()->getW() - + buttons.back()->getX(); } else { - barWidth = buttons.back()->getX() + buttons.back()->getW() - - buttons.front()->getX(); - } - - barHeight = buttons[0]->getH(); - for (ButtonWidget* b : buttons) { - barHeight = max(b->getH(), barHeight); + return buttons.back()->getX() + buttons.back()->getW() - + buttons.front()->getX(); } } - - barWidth += widthPadding; - barHeight += heightPadding; } \ No newline at end of file diff --git a/src/opengl/AutoNavBar.hh b/src/opengl/AutoNavBar.hh index f61e3bd4..7ed23a12 100644 --- a/src/opengl/AutoNavBar.hh +++ b/src/opengl/AutoNavBar.hh @@ -59,4 +59,11 @@ class AutoNavBar : public NavigationBar { * button */ void fitBarDimensions(float widthPadding = 0, float heightPadding = 0); + + /** + * @brief Calculates and returns the lengthwise distance of the list of + * buttons in the nav bar. Override of buttonsLength function from + * NavigationBar that accounts for isReverseOrder + */ + float buttonsLength(); }; \ No newline at end of file diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt index 87871fbc..ca3bc092 100644 --- a/src/opengl/CMakeLists.txt +++ b/src/opengl/CMakeLists.txt @@ -9,6 +9,7 @@ set(grail-opengl Colors.cc Document.cc DocView.cc + DropDownMenu.cc ErrNames.cc ESRIPolygon.cc ESRIShape.cc diff --git a/src/opengl/DropDownMenu.cc b/src/opengl/DropDownMenu.cc new file mode 100644 index 00000000..4b0125f9 --- /dev/null +++ b/src/opengl/DropDownMenu.cc @@ -0,0 +1,87 @@ +#include "opengl/DropDownMenu.hh" + +#include + +DropDownMenu::DropDownMenu(GLWin* w, float x, float y, float menuWidth, + float menuHeight, const char label[], + float axisPadding, Style* buttonStyle, + bool isVertical) + : Member(w->getSharedMenuTab(), "DDMenu", 0), + w(w), + buttonStyle(buttonStyle), + isVertical(isVertical) { + menuButton = new ButtonWidget(tab->getMainCanvas(), buttonStyle, x, y, label, + "open menu"); + menuButton->setAction([this]() { this->openClose(); }); + + if (isVertical) { + nav = new NavigationBar(w, x, y + menuButton->getH(), menuWidth, menuHeight, + axisPadding, isVertical); + } else { + nav = new NavigationBar(w, x + menuButton->getW(), y, menuWidth, menuHeight, + axisPadding, isVertical); + } + nav->setButtonStyle(buttonStyle->f, buttonStyle->bg, buttonStyle->fg, + buttonStyle->lineWidth); + + // closeMenu(); + isOpen = true; +} + +// TODO: fix menu breaking when isReverseOrder is true +DropDownMenu::DropDownMenu(GLWin* w, float x, float y, const char label[], + float axisPadding, float menuHorizontalPadding, + float menuVerticalPadding, Style* buttonStyle, + bool isVertical, bool isReverseOrder) + : Member(w->getSharedMenuTab(), "DDMenu", 0), + w(w), + buttonStyle(buttonStyle), + isVertical(isVertical) { + menuButton = new ButtonWidget(tab->getMainCanvas(), buttonStyle, x, y, label, + "open menu"); + menuButton->setAction([this]() { this->openClose(); }); + + if (isVertical) { + nav = new AutoNavBar(w, x, y + menuButton->getH(), axisPadding, + menuHorizontalPadding, menuVerticalPadding, isVertical, + isReverseOrder); + } else { + nav = new AutoNavBar(w, x + menuButton->getW(), y, axisPadding, + menuHorizontalPadding, menuVerticalPadding, isVertical, + isReverseOrder); + } + nav->setButtonStyle(buttonStyle->f, buttonStyle->bg, buttonStyle->fg, + buttonStyle->lineWidth); + + // closeMenu(); + isOpen = true; +} + +void DropDownMenu::openMenu() { + std::cout << "Opening menu!" << std::endl; + isOpen = true; +} +void DropDownMenu::closeMenu() { + std::cout << "Closing menu!" << std::endl; + isOpen = false; + /* + MainCanvas* c = w->getSharedTab()->getMainCanvas(); + c->getGui()->clear(); + c->getGuiText()->clear(); + */ +} + +/* +void DropDownMenu::setButtonStyle(const Font* f, glm::vec4 borderColor, + glm::vec4 buttonColor, + float borderThickness) { + buttonStyle->f = f; + buttonStyle->bg = borderColor; + buttonStyle->fg = buttonColor; + buttonStyle->lineWidth = borderThickness; + + c->getGuiText()->clear(); + menuButton->redraw(); + nav->setButtonStyle(f, borderColor, buttonColor, borderThickness); +} +*/ \ No newline at end of file diff --git a/src/opengl/DropDownMenu.hh b/src/opengl/DropDownMenu.hh new file mode 100644 index 00000000..e94f34e9 --- /dev/null +++ b/src/opengl/DropDownMenu.hh @@ -0,0 +1,40 @@ +#pragma once + +#include "opengl/AutoNavBar.hh" + +class DropDownMenu : public Member { + private: + NavigationBar* nav; + ButtonWidget* menuButton; + GLWin* w; + bool isVertical, isOpen; + Style* buttonStyle; + + public: + DropDownMenu(GLWin* w, float x, float y, float menuWidth, float menuHeight, + const char label[], float axisPadding, + Style* buttonStyle = new Style(FontFace::get("TIMES", 20, + FontFace::BOLD), + grail::black, grail::red, 1), + bool isVertical = true); + DropDownMenu(GLWin* w, float x, float y, const char label[], + float axisPadding, float menuHorizontalPadding, + float menuVerticalPadding, + Style* buttonStyle = new Style(FontFace::get("TIMES", 20, + FontFace::BOLD), + grail::black, grail::red, 1), + bool isVertical = true, bool isReverseOrder = false); + void openMenu(); + void closeMenu(); + void openClose() { + if (isOpen) { + closeMenu(); + } else { + openMenu(); + } + }; + /* + void setButtonStyle(const Font* f, glm::vec4 borderColor, + glm::vec4 buttonColor, float borderThickness); + */ +}; \ No newline at end of file diff --git a/src/opengl/GLWin.cc b/src/opengl/GLWin.cc index 9047ee07..83df5e17 100644 --- a/src/opengl/GLWin.cc +++ b/src/opengl/GLWin.cc @@ -95,6 +95,7 @@ void GLWin::keyCallback(GLFWwindow *win, int key, int scancode, int action, uint32_t input = (mods << 11) | (action << 9) | key; cerr << "key: " << key << " mods: " << mods << " input=" << input << '\n'; winMap[win]->sharedTab->doit(input); + winMap[win]->sharedMenuTab->doit(input); winMap[win]->currentTab()->doit(input); } @@ -109,6 +110,7 @@ void GLWin::mouseButtonCallback(GLFWwindow *win, int button, int action, fmt::print("mouse!{}, action={}, location=({}, {}), input={}\n", button, action, w->mouseX, w->mouseY, input); winMap[win]->sharedTab->doit(input); + winMap[win]->sharedMenuTab->doit(input); winMap[win]->currentTab()->doit(input); } @@ -117,6 +119,7 @@ void GLWin::scrollCallback(GLFWwindow *win, double xoffset, double yoffset) { // todo: we would have to copy offsets into the object given the way this is uint32_t input = 400; winMap[win]->sharedTab->doit(input + int(yoffset)); + winMap[win]->sharedMenuTab->doit(input + int(yoffset)); winMap[win]->currentTab()->doit(input + int(yoffset)); } @@ -252,7 +255,8 @@ void GLWin::startWindow() { menuStyle = new Style(menuFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); menuTextStyle = new Style(menuFont, 0.5, 0.5, 0.5, 0, 0, 0, 1, COMMON_SHADER); sharedTab = new Tab(this); - // tabs.add(new Tab(this)); + sharedMenuTab = new Tab(this); + // tabs.add(new Tab(this)); current = -1; hasBeenInitialized = true; } @@ -277,6 +281,7 @@ void GLWin::baseInit() { for (int i = 0; i < tabs.size(); ++i) { tabs[i]->init(); } + sharedMenuTab->init(); sharedTab->init(); } @@ -308,6 +313,8 @@ void GLWin::cleanup() { tabs.clear(); delete sharedTab; sharedTab = nullptr; + delete sharedMenuTab; + sharedMenuTab = nullptr; delete defaultStyle; defaultStyle = nullptr; Shader::cleanAll(); @@ -362,6 +369,7 @@ void GLWin::mainLoop() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); render(); sharedTab->render(); + sharedMenuTab->render(); renderTime += glfwGetTime() - startRender; glfwSwapBuffers(win); // Swap buffer so the scene shows on screen if (frameCount >= 150) { @@ -381,11 +389,13 @@ void GLWin::mainLoop() { currentTab()->tick(); // update time in current tab for any models using // simulation time sharedTab->tick(); + sharedMenuTab->tick(); needsUpdate = false; glfwPollEvents(); // Check and call events // note: any events needing a refresh should set dirty = true if (currentTab()->checkUpdate()) setUpdate(); if (sharedTab->checkUpdate()) setUpdate(); + if (sharedMenuTab->checkUpdate()) setUpdate(); if (needsUpdate) { update(); needsRender = true; diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index 99c501d0..6be71017 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -54,7 +54,8 @@ class GLWin { uint32_t frameNum; double lastRenderTime; // Stores last time of render char frameName[32]; - Tab* sharedTab; + Tab* sharedTab; // For nav bars + Tab* sharedMenuTab; // For buttons that open/close menus DynArray tabs; // list of web pages, ie tabs int32_t current; // current (active) tab void checkUpdate(); @@ -137,6 +138,7 @@ class GLWin { } } constexpr Tab* getSharedTab() { return sharedTab; } + constexpr Tab* getSharedMenuTab() { return sharedMenuTab; } constexpr void setSize(uint32_t w, uint32_t h) { width = w; diff --git a/src/opengl/NavigationBar.cc b/src/opengl/NavigationBar.cc index 9a63fd45..0e204eb9 100644 --- a/src/opengl/NavigationBar.cc +++ b/src/opengl/NavigationBar.cc @@ -114,25 +114,39 @@ void NavigationBar::drawBarBox() { void NavigationBar::fitBarDimensions(float widthPadding, float heightPadding) { if (isVertical) { - barWidth = buttons[0]->getW(); + barWidth = buttonsWidth() + widthPadding; + barHeight = buttonsLength() + heightPadding; + } else { + barWidth = buttonsLength() + widthPadding; + barHeight = buttonsWidth() + heightPadding; + } +} + +float NavigationBar::buttonsLength() { + if (isVertical) { + return buttons.back()->getY() + buttons.back()->getH() - + buttons.front()->getY(); + } else { + return buttons.back()->getX() + buttons.back()->getW() - + buttons.front()->getX(); + } +} + +float NavigationBar::buttonsWidth() { + float width; + if (isVertical) { + width = buttons[0]->getW(); for (ButtonWidget* b : buttons) { - barWidth = max(b->getW(), barWidth); + width = max(b->getW(), width); } - barHeight = buttons.back()->getY() + buttons.back()->getH() - - buttons.front()->getY(); } else { - barWidth = buttons.back()->getX() + buttons.back()->getW() - - buttons.front()->getX(); - - barHeight = buttons[0]->getH(); + width = buttons[0]->getH(); for (ButtonWidget* b : buttons) { - barHeight = max(b->getH(), barHeight); + width = max(b->getH(), width); } } - - barWidth += widthPadding; - barHeight += heightPadding; + return width; } /* diff --git a/src/opengl/NavigationBar.hh b/src/opengl/NavigationBar.hh index c02e961c..b0e05222 100644 --- a/src/opengl/NavigationBar.hh +++ b/src/opengl/NavigationBar.hh @@ -127,6 +127,18 @@ class NavigationBar : public Member { */ void fitBarDimensions(float widthPadding = 0, float heightPadding = 0); + /** + * @brief Calculates and returns the lengthwise distance of the list of + * buttons in the nav bar + */ + float buttonsLength(); + + /** + * @brief Calculates and returns the crosswise distance of the list of + * buttons in the nav bar + */ + float buttonsWidth(); + /** * @brief Balance n buttons on the nav bar * @@ -139,6 +151,8 @@ class NavigationBar : public Member { */ void balanceButtons(int numButtons); + MainCanvas* getCanvas() { return c; }; + /** * @brief Adds a new tab to the window and adds the navigation bar to the tab * diff --git a/test/xp/CMakeLists.txt b/test/xp/CMakeLists.txt index 8de0e823..65a54386 100644 --- a/test/xp/CMakeLists.txt +++ b/test/xp/CMakeLists.txt @@ -4,4 +4,5 @@ add_grail_executable(SRC testfmt.cc LIBS grail) add_grail_executable(SRC testMultiTab.cc LIBS grail) add_grail_executable(SRC test2Tabs.cc LIBS grail) add_grail_executable(SRC testGraphTabs.cc LIBS grail) -add_grail_executable(SRC testAutoGraphTabs.cc LIBS grail) \ No newline at end of file +add_grail_executable(SRC testAutoGraphTabs.cc LIBS grail) +add_grail_executable(SRC testMenu.cc LIBS grail) \ No newline at end of file diff --git a/test/xp/testMenu.cc b/test/xp/testMenu.cc new file mode 100644 index 00000000..20d2a729 --- /dev/null +++ b/test/xp/testMenu.cc @@ -0,0 +1,30 @@ +#include "opengl/DropDownMenu.hh" +#include "opengl/GrailGUI.hh" + +using namespace std; +using namespace grail; + +class Square : public Member { + public: + Square(GLWin* w) : Member(w, "Square", 0, 0) { + StyledMultiShape2D* gui = tab->getMainCanvas()->getGui(); + gui->fillRectangle(500, 600, 200, 200, red); + } +}; + +class Circle : public Member { + public: + Circle(GLWin* w) : Member(w, "Circle", 0, 0) { + StyledMultiShape2D* gui = tab->getMainCanvas()->getGui(); + gui->fillCircle(600, 700, 100, 5, purple); + } +}; + +void grailmain(int argc, char* argv[], GLWin* w) { + w->setTitle("Test Tabs"); + Style* s = new Style(FontFace::get("TIMES", 28, FontFace::BOLD), grail::black, + grail::lightblue, 2); + new DropDownMenu(w, 0, 0, "Tabs", 5, 0, 0, s); + new Square(w); + new Circle(w); +} \ No newline at end of file From 1ea8f2c54ed2212b1d2e0c082558f48c3a72ceff Mon Sep 17 00:00:00 2001 From: Trent Reichenbach Date: Fri, 10 Jun 2022 16:42:10 -0400 Subject: [PATCH 14/15] fix CallbackHandler for multiple tabs on one display --- src/opengl/DropDownMenu.cc | 15 +++++---------- src/util/Callbacks.cc | 6 ++---- src/util/Callbacks.hh | 6 +++--- test/xp/testMenu.cc | 3 ++- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/opengl/DropDownMenu.cc b/src/opengl/DropDownMenu.cc index 4b0125f9..3323d757 100644 --- a/src/opengl/DropDownMenu.cc +++ b/src/opengl/DropDownMenu.cc @@ -9,7 +9,8 @@ DropDownMenu::DropDownMenu(GLWin* w, float x, float y, float menuWidth, : Member(w->getSharedMenuTab(), "DDMenu", 0), w(w), buttonStyle(buttonStyle), - isVertical(isVertical) { + isVertical(isVertical), + isOpen(false) { menuButton = new ButtonWidget(tab->getMainCanvas(), buttonStyle, x, y, label, "open menu"); menuButton->setAction([this]() { this->openClose(); }); @@ -23,9 +24,6 @@ DropDownMenu::DropDownMenu(GLWin* w, float x, float y, float menuWidth, } nav->setButtonStyle(buttonStyle->f, buttonStyle->bg, buttonStyle->fg, buttonStyle->lineWidth); - - // closeMenu(); - isOpen = true; } // TODO: fix menu breaking when isReverseOrder is true @@ -36,7 +34,8 @@ DropDownMenu::DropDownMenu(GLWin* w, float x, float y, const char label[], : Member(w->getSharedMenuTab(), "DDMenu", 0), w(w), buttonStyle(buttonStyle), - isVertical(isVertical) { + isVertical(isVertical), + isOpen(false) { menuButton = new ButtonWidget(tab->getMainCanvas(), buttonStyle, x, y, label, "open menu"); menuButton->setAction([this]() { this->openClose(); }); @@ -52,9 +51,6 @@ DropDownMenu::DropDownMenu(GLWin* w, float x, float y, const char label[], } nav->setButtonStyle(buttonStyle->f, buttonStyle->bg, buttonStyle->fg, buttonStyle->lineWidth); - - // closeMenu(); - isOpen = true; } void DropDownMenu::openMenu() { @@ -64,11 +60,10 @@ void DropDownMenu::openMenu() { void DropDownMenu::closeMenu() { std::cout << "Closing menu!" << std::endl; isOpen = false; - /* + MainCanvas* c = w->getSharedTab()->getMainCanvas(); c->getGui()->clear(); c->getGuiText()->clear(); - */ } /* diff --git a/src/util/Callbacks.cc b/src/util/Callbacks.cc index 77f0e213..860eafdd 100644 --- a/src/util/Callbacks.cc +++ b/src/util/Callbacks.cc @@ -4,13 +4,11 @@ using namespace std; -CallbackHandler::CallbackHandler() { +CallbackHandler::CallbackHandler() : actionNameMap(64, 4096) { + inputMap.fill(0); for (int i = 0; i < 3; i++) numActions[i] = 1; } -HashMap CallbackHandler::actionNameMap(64, 4096); -std::array inputMap(); - uint32_t CallbackHandler::internalRegisterAction(const char name[], Security s, function action) { uint32_t securityIndex = uint32_t(s); diff --git a/src/util/Callbacks.hh b/src/util/Callbacks.hh index c237cf8e..b31e869a 100644 --- a/src/util/Callbacks.hh +++ b/src/util/Callbacks.hh @@ -22,13 +22,13 @@ class CallbackHandler { template using CallbackFunc = void (T::*)(void); - inline static std::array inputMap; + std::array inputMap; /* map an integer code to a function to execute the actions are all the publicly available performance the code can DO */ - inline static std::array, 4096> actionMap; - static HashMap actionNameMap; + std::array, 4096> actionMap; + HashMap actionNameMap; uint32_t lookupAction(const char actionName[]); // static GLWin* w; void setEvent(uint32_t e, uint32_t a) { inputMap[e] = a; } diff --git a/test/xp/testMenu.cc b/test/xp/testMenu.cc index 20d2a729..b4a52593 100644 --- a/test/xp/testMenu.cc +++ b/test/xp/testMenu.cc @@ -24,7 +24,8 @@ void grailmain(int argc, char* argv[], GLWin* w) { w->setTitle("Test Tabs"); Style* s = new Style(FontFace::get("TIMES", 28, FontFace::BOLD), grail::black, grail::lightblue, 2); - new DropDownMenu(w, 0, 0, "Tabs", 5, 0, 0, s); + DropDownMenu* menu = new DropDownMenu(w, 0, 0, "Tabs", 5, 0, 0, s); new Square(w); new Circle(w); + menu->closeMenu(); } \ No newline at end of file From 908fb04ee2fd5e3ba39159c0182c08fd30203d56 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Thu, 16 Jun 2022 21:09:31 -0400 Subject: [PATCH 15/15] Fix GraphWidget tests for CI Copies over .gitattributes from main repo to ensure that files are handled properly. Fixes several tests dependent on GraphWidget and ButtonWidget to ensure that the demos are kept in working condition (and the CI is not spitting out errors every time a push is made) Signed-off-by: ahuston-0 --- .gitattributes | 13 +++++++++++++ test/graph/testBarChart.cc | 2 +- test/graph/testBoxChart.cc | 2 +- test/graph/testCandlestickChart.cc | 2 +- test/graph/testGapMinderWidget.cc | 2 +- test/graph/testLineGraph.cc | 2 +- test/xdl/testXDLButton.cc | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c2dbd15e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# Allow custom line endings during checkout, but enforce LF on checkin +*.cc text +*.c text +*.hh text +*.h text + +*.py text +*.md text + +*.txt text + +*.bml binary + diff --git a/test/graph/testBarChart.cc b/test/graph/testBarChart.cc index f63896ba..6a15b960 100644 --- a/test/graph/testBarChart.cc +++ b/test/graph/testBarChart.cc @@ -7,7 +7,7 @@ using namespace grail; class TestBarChart : public GraphStyle { public: - TestBarChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12) { + TestBarChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12, "Bar Chart") { MainCanvas* c = tab->getMainCanvas(); vector values = {4, 6, 8, 10, 12, 14}; vector logValues = {4, 8, 16, 32, 64, 128}; diff --git a/test/graph/testBoxChart.cc b/test/graph/testBoxChart.cc index 994a6c85..8fc517aa 100644 --- a/test/graph/testBoxChart.cc +++ b/test/graph/testBoxChart.cc @@ -7,7 +7,7 @@ using namespace grail; class TestBoxChart : public GraphStyle { public: - TestBoxChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12) { + TestBoxChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12, "Box Chart") { MainCanvas* c = tab->getMainCanvas(); vector data = {150, 350, 222, 100, 300, // diff --git a/test/graph/testCandlestickChart.cc b/test/graph/testCandlestickChart.cc index a5c588b0..7309bdbd 100644 --- a/test/graph/testCandlestickChart.cc +++ b/test/graph/testCandlestickChart.cc @@ -7,7 +7,7 @@ using namespace grail; class TestCandlestickChart : public GraphStyle { public: - TestCandlestickChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12) { + TestCandlestickChart(GLWin* w) : GraphStyle(w, "TIMES", 20, 12, "Candlestick Chart") { MainCanvas* c = tab->getMainCanvas(); vector data = { diff --git a/test/graph/testGapMinderWidget.cc b/test/graph/testGapMinderWidget.cc index 5d6a6651..4054e7fa 100644 --- a/test/graph/testGapMinderWidget.cc +++ b/test/graph/testGapMinderWidget.cc @@ -15,7 +15,7 @@ class TestGapMinderWidget : public GraphStyle { GapMinderWidget* chart; public: - TestGapMinderWidget(GLWin* w) : GraphStyle(w, "TIMES", 24, 12) { + TestGapMinderWidget(GLWin* w) : GraphStyle(w, "TIMES", 24, 12, "Gapninder graph") { MainCanvas* c = tab->getMainCanvas(); const Style* s = new Style("TIMES", 24, 1, 0, 0, 0, // black background (unused) diff --git a/test/graph/testLineGraph.cc b/test/graph/testLineGraph.cc index ff0000ff..91ed960f 100644 --- a/test/graph/testLineGraph.cc +++ b/test/graph/testLineGraph.cc @@ -7,7 +7,7 @@ using namespace grail; class TestLineGraph : public GraphStyle { public: - TestLineGraph(GLWin* w) : GraphStyle(w, "TIMES", 24, 12) { + TestLineGraph(GLWin* w) : GraphStyle(w, "TIMES", 24, 12,"Line Graph") { MainCanvas* c = tab->getMainCanvas(); vector times = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; diff --git a/test/xdl/testXDLButton.cc b/test/xdl/testXDLButton.cc index 6259dec9..c596aa85 100644 --- a/test/xdl/testXDLButton.cc +++ b/test/xdl/testXDLButton.cc @@ -10,7 +10,7 @@ class NetworkedButton : public Member { public: NetworkedButton(GLWin* w) - : Member(w), button(c, 0, 0, 100, 100, "", "click!") { + : Member(w), button(c, w->getDefaultStyle(),0, 0, 100, 100, "", "click!") { button.setAction( bind(&GLWin::goToLink, tab->getParentWin(), "127.0.0.1", 8060, 0)); }