diff --git a/.vscode/settings.json b/.vscode/settings.json index 3ca748198cece50e56ba3045077895a9bb52d950..970fe196c03e8b3ef674f1e6e840c593b0b67def 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -74,6 +74,15 @@ "xmemory": "cpp", "xtr1common": "cpp", "xtree": "cpp", - "xutility": "cpp" + "xutility": "cpp", + "bitset": "cpp", + "codecvt": "cpp", + "condition_variable": "cpp", + "deque": "cpp", + "future": "cpp", + "queue": "cpp", + "random": "cpp", + "set": "cpp", + "stack": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a001a6bfb2a6ef5a69c435d87e2fc358fea1a4ba..e578234beccfe2c7489b67bfa2bff0e314a6884c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,8 +63,8 @@ find_package(OpenGL REQUIRED) # Add subdirectory for the GLApp library add_subdirectory(src) -# Build the example, off by default -option(BUILD_EXAMPLE "Build the hello world example" OFF) +# Build the example, on by default +option(BUILD_EXAMPLE "Build the hello world example" ON) if(BUILD_EXAMPLE) add_subdirectory(Example) endif() diff --git a/Example/GLAppHelloWorld.cpp b/Example/GLAppHelloWorld.cpp index ef3b1a6d8a37bed9920941624e5bac808d67b968..31b63955b097b715ad5e22f366ee4fce19169167 100644 --- a/Example/GLAppHelloWorld.cpp +++ b/Example/GLAppHelloWorld.cpp @@ -32,6 +32,8 @@ #include "GLApp/GLTitledPanel.h" #include "GLApp/GLSpinner.h" #include "GLApp/GLInputBox.h" +#include "GLApp/GLRadioButton.h" +#include "GLApp/GLRadioGroup.h" #include "GradientWindow.h" #include "TabWindow.h" @@ -83,6 +85,12 @@ GLAppHelloWorld::~GLAppHelloWorld() { //SAFE_DELETE(formulaXCloseablePanel); SAFE_DELETE(functionPanel); + SAFE_DELETE(radio1); + SAFE_DELETE(radio2); + SAFE_DELETE(radio3); + SAFE_DELETE(radio4); + SAFE_DELETE(showSelectedRadioButton); + SAFE_DELETE(gradientWindow); SAFE_DELETE(colorPickerTabWindow); } @@ -136,6 +144,12 @@ void GLAppHelloWorld::ProcessMessage(GLComponent* src, int message) { } return; } + if (src == showSelectedRadioButton) { + int selectedRadioInd = parentRadioGroup->GetSelectedIndex(); // Replace with GetSelected() to get the selected GLRadioButton object + GLMessageBox::Display( + fmt::format("Selected radio button index: {}", selectedRadioInd).c_str(), + "Radio button", GLDLG_OK, GLDLG_ICONINFO); + } break; case MSG_TOGGLE: if (src == textToggle) { @@ -198,6 +212,16 @@ void GLAppHelloWorld::ProcessMessage(GLComponent* src, int message) { formulaXCloseablePanel->SetBounds(x, y, w, h + heightInc); } break; + case MSG_RADIO: + if (src == radio1) + GLMessageBox::Display("Radio button 1 clicked", "Radio button", GLDLG_OK, GLDLG_ICONINFO); + else if (src == radio2) + GLMessageBox::Display("Radio button 2 clicked", "Radio button", GLDLG_OK, GLDLG_ICONINFO); + else if (src == radio3) + GLMessageBox::Display("Radio button 3 clicked", "Radio button", GLDLG_OK, GLDLG_ICONINFO); + else if (src == radio4) + GLMessageBox::Display("Radio button 4 clicked", "Radio button", GLDLG_OK, GLDLG_ICONINFO); + break; default: return; } @@ -228,7 +252,7 @@ void GLAppHelloWorld::PlaceComponents() { iconLabel->SetBounds(cursorX, cursorY, controlWidth + 10, controlHeight); cursorX += controlWidth + 10 + xSpacing; - iconInfoToggle->SetBounds(cursorX, cursorY, 60, controlHeight); + iconInfoToggle->SetBounds(cursorX, cursorY, 90, controlHeight + 50); cursorX += 60; iconWarningToggle->SetBounds(cursorX, cursorY, controlWidth, controlHeight); @@ -282,7 +306,17 @@ void GLAppHelloWorld::PlaceComponents() { panelCursorY = 30; functionPanel->SetCompBounds(formulaYLabel, panelCursorX, panelCursorY, controlWidth, controlHeight); - cursorY += controlWidth + ySpacing; + cursorY += controlHeight + 70 + ySpacing; + + radio1->SetBounds(cursorX, cursorY, 90, 15); + cursorX += 90; + radio2->SetBounds(cursorX, cursorY, 90, 15); + cursorX += 90; + radio3->SetBounds(cursorX, cursorY, 90, 15); + cursorX += 90; + radio4->SetBounds(cursorX, cursorY, 90, 15); + cursorX += 120; + showSelectedRadioButton->SetBounds(cursorX, cursorY, controlWidth, controlHeight); } int GLAppHelloWorld::FrameMove() { @@ -402,6 +436,20 @@ int GLAppHelloWorld::OneTimeSceneInit() { formulaSetXButton = new GLButton(0, "Set x"); formulaXCloseablePanel->Add(formulaSetXButton); + parentRadioGroup = std::make_shared<GLRadioGroup>(); + radio1 = new GLRadioButton(0, "Test button 1", parentRadioGroup); + parentRadioGroup->Select(radio1); + Add(radio1); + radio2 = new GLRadioButton(1, "Test button 2", parentRadioGroup); + Add(radio2); + radio3 = new GLRadioButton(2, "Test button 3", parentRadioGroup); + Add(radio3); + radio4 = new GLRadioButton(3, "Test button 4", parentRadioGroup); + Add(radio4); + + showSelectedRadioButton = new GLButton(0, "Show selected radio message"); + Add(showSelectedRadioButton); + gradientWindow = new GradientWindow(); colorPickerTabWindow = new ColorPicker(); diff --git a/Example/GLAppHelloWorld.h b/Example/GLAppHelloWorld.h index 6b4a54b0855a829880b4712115d8eab7b5f8d286..8731204274699b3452c7f7198ecb6f2ba9680e31 100644 --- a/Example/GLAppHelloWorld.h +++ b/Example/GLAppHelloWorld.h @@ -3,6 +3,7 @@ #include <list> // for recents #include <string> #include <vector> +#include <memory> #include <GLApp/GLApp.h> #include "GLApp/GLChart/GLChartConst.h" @@ -21,6 +22,8 @@ class GLChart; class GLDataView; class GLTitledPanel; class GLSpinner; +class GLRadioButton; +class GLRadioGroup; class GradientWindow; class ColorPicker; @@ -64,6 +67,12 @@ private: GLButton* formulaSetXButton; GLTitledPanel* formulaXCloseablePanel; GLTitledPanel* functionPanel; + std::shared_ptr<GLRadioGroup> parentRadioGroup; + GLRadioButton* radio1; + GLRadioButton* radio2; + GLRadioButton* radio3; + GLRadioButton* radio4; + GLButton* showSelectedRadioButton; GradientWindow* gradientWindow; ColorPicker* colorPickerTabWindow; diff --git a/copy_to_build/images/fnt_sansserif_8.png b/copy_to_build/images/fnt_sansserif_8.png index 152e96186c3ca30dd09493f0e55bf181f64d16ec..30b0c5adae8ba92bbd41d125d9d3390d62a3e090 100644 Binary files a/copy_to_build/images/fnt_sansserif_8.png and b/copy_to_build/images/fnt_sansserif_8.png differ diff --git a/copy_to_build/images/gui_background.png b/copy_to_build/images/gui_background.png index d85456723d4990ec743d5fc3bd2578727c2a0a08..44f70f62caee38ba18338f3163507304096cd59c 100644 Binary files a/copy_to_build/images/gui_background.png and b/copy_to_build/images/gui_background.png differ diff --git a/copy_to_build/images/gui_backgrounda.png b/copy_to_build/images/gui_backgrounda.png index f584893947e81b00c900d071f835dade10cc41bc..b4f8f69d4db80fb326a3c027253b0aa0431a9f81 100644 Binary files a/copy_to_build/images/gui_backgrounda.png and b/copy_to_build/images/gui_backgrounda.png differ diff --git a/include/GLApp/GLRadioButton.h b/include/GLApp/GLRadioButton.h new file mode 100644 index 0000000000000000000000000000000000000000..697c5cd5259c82fc1c46d234b4df4d174f8dcf04 --- /dev/null +++ b/include/GLApp/GLRadioButton.h @@ -0,0 +1,36 @@ + +#ifndef _GLRADIOBUTTONH_ +#define _GLRADIOBUTTONH_ + +#include "GLComponent.h" +#include <string> +#include <memory> +#include <iostream> +//#include "GLSprite.h" +class Sprite2D; +class GLFont2D; +class GLRadioGroup; + +class GLRadioButton : public GLComponent { +public: + GLRadioButton(int compId, const std::string& text, std::shared_ptr<GLRadioGroup> parentRadioGroup); + + void SetText(const std::string& text); + bool GetSelected(); + void SetSelected(bool setSelected); + void SelectInParent(); + std::shared_ptr<GLRadioGroup> GetParentRadioGroup(); + + void Paint(); + void ManageEvent(SDL_Event* evt); + void SetFontColor(float red, float green, float blue); + void SetFontColor(int red, int green, int blue); +private: + + std::string text; + bool selected; + float r, g, b; + std::shared_ptr<GLRadioGroup> parentRadioGroup; +}; + +#endif /* _GLRADIOBUTTONH_ */ \ No newline at end of file diff --git a/include/GLApp/GLRadioGroup.h b/include/GLApp/GLRadioGroup.h new file mode 100644 index 0000000000000000000000000000000000000000..4d5d8c5c745a7c2d2b343b3e7124e56a00767068 --- /dev/null +++ b/include/GLApp/GLRadioGroup.h @@ -0,0 +1,22 @@ +#ifndef _GLRADIOGROUP_ +#define _GLRADIOGROUP_ + +#include <vector> +#include <iostream> + +class GLRadioButton; + +class GLRadioGroup { +public: + void Select(GLRadioButton* button); + void Register(GLRadioButton* button); + void Unregister(GLRadioButton* button); + int GetSelectedIndex(); + GLRadioButton* GetSelected(); + +private: + std::vector<GLRadioButton*> buttons; + GLRadioButton* selectedButton = nullptr; +}; + +#endif /* _GLRADIOGROUP_ */ \ No newline at end of file diff --git a/include/GLApp/GLToolkit.h b/include/GLApp/GLToolkit.h index 5be53a5a81b8e204bf62198f7d52f2ab55061013..a8bea8c4b9e71300d1354454dcbb9fc045b431c8 100644 --- a/include/GLApp/GLToolkit.h +++ b/include/GLApp/GLToolkit.h @@ -90,6 +90,7 @@ public: const int height,const int state); static void DrawSmallButton(int x,int y,int state); static void DrawTinyButton(int x,int y,int state); + static void DrawRoundButton(const int x, const int y); static void DrawToggle(int x,int y); static void DrawBar(int x,int y,int width,int height); static void DrawTextBack(const int x,const int y,const int width, diff --git a/include/GLApp/GLTypes.h b/include/GLApp/GLTypes.h index 7b786f76843b162219d6404a82e0619b45958e2a..de348df9763b9fa9549b99025c7553bd4b3ab1be 100644 --- a/include/GLApp/GLTypes.h +++ b/include/GLApp/GLTypes.h @@ -24,6 +24,7 @@ #define MSG_TAB 14 // Tab window change #define MSG_SPINNER 15 // Spinner change #define MSG_PANELR 16 // Panel open/close +#define MSG_RADIO 17 // Radio select #define MSG_USER 256 diff --git a/src/GLApp/GLRadioButton.cpp b/src/GLApp/GLRadioButton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63dc6112b26f74a25712699a17591eebd823caa0 --- /dev/null +++ b/src/GLApp/GLRadioButton.cpp @@ -0,0 +1,90 @@ + +#include "GLApp/GLWindow.h" +#include "GLApp/GLRadioButton.h" +#include "GLApp/GLRadioGroup.h" +#include "GLApp/GLToolkit.h" +#include "GLApp/GLSprite.h" +#include "GLApp/GLFont.h" +#include "GLHelper/MathTools.h" +#include <cstring> //strcpy, etc. +#include <vector> + +/** + * Create a new radio button, set its parent radio group and register it inside it. + * @param compId The id of this radio button. + * @param text The text on the button. + * @param parentRadioGroup The parent radio group to register the radio button under. + */ +GLRadioButton::GLRadioButton(int compId, const std::string& text, std::shared_ptr<GLRadioGroup> parentRadioGroup) : GLComponent(compId) { + this->text = text; + selected = false; + r = g = b = 0.0f; //default color: black + this->parentRadioGroup = parentRadioGroup; + this->parentRadioGroup->Register(this); +} + +bool GLRadioButton::GetSelected() { + return selected; +} + +void GLRadioButton::SetSelected(bool setSelected) { + selected = setSelected; +} + +/** + * Set the state of this radio button to `selected` and select it in its radio group. + */ +void GLRadioButton::SelectInParent() { + if (parentRadioGroup) + parentRadioGroup->Select(this); +} + +std::shared_ptr<GLRadioGroup> GLRadioButton::GetParentRadioGroup() { + return parentRadioGroup; +} + +void GLRadioButton::SetText(const std::string& text) { + this->text = text; +} + +void GLRadioButton::SetFontColor(int red, int green, int blue) { + SetFontColor((float)red / 255.0f, (float)green / 255.0f, (float)blue / 255.0f); +} + +void GLRadioButton::SetFontColor(float red, float green, float blue) { + r = red; + g = green; + b = blue; +} + +void GLRadioButton::Paint() { + if (!parent) return; + GLFont2D* font = GLToolkit::GetDialogFont(); + + GLComponent::Paint(); + + font->SetTextColor(r, g, b); + font->GLDrawText(posX + 16, posY + 2, text.c_str(), false); + + GLToolkit::DrawRoundButton(posX + 2, posY + 3); + if (selected) { + font->SetTextColor(0.0f, 0.0f, 0.0f); + font->GLDrawText(posX + 4, posY + 1, "\216", false); + } + GLToolkit::CheckGLErrors("GLRadioButton::Paint()"); +} + +void GLRadioButton::ManageEvent(SDL_Event* evt) { + + if (!parent) return; + + if (evt->type == SDL_MOUSEBUTTONDOWN) { + if (evt->button.button == SDL_BUTTON_LEFT) { + selected = true; + if (parentRadioGroup) { + parentRadioGroup->Select(this); + } + parent->ProcessMessage(this, MSG_RADIO); + } + } +} diff --git a/src/GLApp/GLRadioGroup.cpp b/src/GLApp/GLRadioGroup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0c25666214ad13064d6e9a581354573a914763f --- /dev/null +++ b/src/GLApp/GLRadioGroup.cpp @@ -0,0 +1,58 @@ +#include "GLApp/GLRadioGroup.h" +#include "GLApp/GLRadioButton.h" +#include "GLApp/GLTypes.h" +#include <algorithm> + +/** + * Select a radio button in this group, deselecting the current one. + * @param button The radio button to select. + */ +void GLRadioGroup::Select(GLRadioButton* button) { + if (selectedButton) { + for (GLRadioButton* button : buttons) + button->SetSelected(false); + } + selectedButton = button; + selectedButton->SetSelected(true); +} + +/** + * Register a radio button in this group. + * A radio button can only be registered if this group + * is set as its parent radio group during construction. + * @param button The radio button to register. + */ +void GLRadioGroup::Register(GLRadioButton *button) { + // Group can accept a button only if it is already the button's parent. + // Prevents buttons from belonging to multiple groups. + if (button->GetParentRadioGroup().get() == this) { + std::vector<GLRadioButton*>::iterator it = std::find(buttons.begin(), buttons.end(), button); + if (it == buttons.end()) { // Register the button only if it's not yet registered + buttons.push_back(button); + } + } +} + +void GLRadioGroup::Unregister(GLRadioButton *button) { + std::vector<GLRadioButton*>::iterator it = std::find(buttons.begin(), buttons.end(), button); + if (it != buttons.end()) + buttons.erase(it); +} + +/** + * Get the index of the sleceted radio button. + * @return The index of the selected button, -1 if no button is selected. + */ +int GLRadioGroup::GetSelectedIndex() { + std::vector<GLRadioButton*>::iterator it = std::find(buttons.begin(), buttons.end(), selectedButton); + if (it != buttons.end()) + return it - buttons.begin(); + return -1; +} + +/** + * Get the selected radio button. + */ +GLRadioButton* GLRadioGroup::GetSelected() { + return selectedButton; +} diff --git a/src/GLApp/GLToolkit.cpp b/src/GLApp/GLToolkit.cpp index 8f46c7962e5ba6f0e54f96a2520647787e8a1bbb..bfbb41fbfb4be01068d35220845a179bed4dd85d 100644 --- a/src/GLApp/GLToolkit.cpp +++ b/src/GLApp/GLToolkit.cpp @@ -450,6 +450,13 @@ void GLToolkit::DrawSmallButton(int x,int y,int state) { } +void GLToolkit::DrawRoundButton(const int x, const int y) { + compTex->SetColor(1.0f, 1.0f, 1.0f); + compTex->UpdateSprite(x, y, x + 12, y + 12); + compTex->SetSpriteMapping(17.0f / TW, 95.0f / TW, 29.0f / TW, 107.0f / TW); + compTex->Render(false); +} + void GLToolkit::DrawToggle(int x,int y) { compTex->SetColor(1.0f,1.0f,1.0f);