From 706a61dad756355ad4c0645a18f281398e9f5583 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Fri, 20 Sep 2024 09:15:46 +0200 Subject: [PATCH 01/19] Fix typo of Color constructor --- src/color.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color.cpp b/src/color.cpp index cb39bf8..3c294cc 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -66,7 +66,7 @@ namespace gcn Color::Color(int color) : r((color >> 16) & 0xFF), g((color >> 8) & 0xFF), - b((color >> 8) & 0xFF) + b((color >> 0) & 0xFF) {} Color::Color(int r, int g, int b, int a) : r(r), g(g), b(b), a(a) From 7f214e2ac09aeaf82bdc06fb36ca7a591b49c08c Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Sat, 21 Sep 2024 22:50:47 +0200 Subject: [PATCH 02/19] Add inputbox in Widget example Fix message display of `InputBox` Remove some duplicated virtual methods of `InputBox`. --- examples/widgets_example.hpp | 32 ++++- include/guisan/widgets/inputbox.hpp | 14 +- src/widget.cpp | 12 +- src/widgets/inputbox.cpp | 206 +++++----------------------- 4 files changed, 76 insertions(+), 188 deletions(-) diff --git a/examples/widgets_example.hpp b/examples/widgets_example.hpp index 674b1a1..3ecbb33 100644 --- a/examples/widgets_example.hpp +++ b/examples/widgets_example.hpp @@ -28,7 +28,7 @@ namespace WidgetsExample } }; - class MainContainer + class MainContainer : public gcn::ActionListener { public: MainContainer(gcn::Gui& gui, int width, int height) @@ -54,6 +54,15 @@ namespace WidgetsExample button = std::make_unique("Button"); + button->addActionListener(this); + + inputBox = std::make_unique("Change name", " Set name of label "); + + inputBox->setVisible(false); + inputBox->setMovable(true); + inputBox->setFrameSize(1); + inputBox->addActionListener(this); + textField = std::make_unique("Text field"); textBox = std::make_unique("Lorem ipsum dolor sit amet consectetur\n" @@ -116,6 +125,7 @@ namespace WidgetsExample top->add(button.get(), 325, 10); top->add(textField.get(), 375, 10); top->add(textBoxScrollArea.get(), 290, 50); + top->add(inputBox.get(), 270, 180); top->add(listBox.get(), 290, 200); top->add(dropDown.get(), 580, 10); top->add(checkBox1.get(), 580, 50); @@ -132,6 +142,25 @@ namespace WidgetsExample ~MainContainer() = default; + // Implement the action function in ActionListener to receive actions + // The eventId tells us which widget called the action function. + void action(const gcn::ActionEvent& actionEvent) override { + if (actionEvent.getSource() == button.get()) + { + inputBox->setVisible(true); + top->moveToTop(inputBox.get()); + } + else if (actionEvent.getSource() == inputBox.get()) + { + inputBox->setVisible(false); + if (inputBox->getClickedButton() == 0) + { + label->setCaption(inputBox->getText()); + label->adjustSize(); + } + } + } + private: std::unique_ptr font; // A font @@ -143,6 +172,7 @@ namespace WidgetsExample std::unique_ptr label; // A label std::unique_ptr icon; // An icon (image) std::unique_ptr button; // A button + std::unique_ptr inputBox; // An input box std::unique_ptr textField; // One-line text field std::unique_ptr textBox; // Multi-line text box std::unique_ptr textBoxScrollArea; // Scroll area for the text box diff --git a/include/guisan/widgets/inputbox.hpp b/include/guisan/widgets/inputbox.hpp index 99332b8..50e5e06 100644 --- a/include/guisan/widgets/inputbox.hpp +++ b/include/guisan/widgets/inputbox.hpp @@ -85,7 +85,10 @@ namespace gcn * @param ok the string corresponding to the "OK" button * @param cancel the string corresponding to the "Cancel" button */ - InputBox(const std::string& caption, const std::string& message, const std::string &ok = "OK", const std::string &cancel = "Cancel"); + InputBox(const std::string& caption, + const std::string& message, + const std::string& ok = "OK", + const std::string& cancel = "Cancel"); /** * Destructor. @@ -103,7 +106,7 @@ namespace gcn /** * Get the text that was input by the user * Use in conjunction with getClickedButton() to tell an empty string from a cancel operation. - * + * * @return the text which was typed by the user */ std::string getText() const; @@ -114,18 +117,11 @@ namespace gcn */ int getClickedButton() const; - // Inherited from Widget - - void draw(Graphics* graphics) override; - // Inherited from MouseListener - void mousePressed(MouseEvent& mouseEvent) override; - void mouseDragged(MouseEvent& mouseEvent) override; void mouseReleased(MouseEvent& mouseEvent) override; protected: - std::string mMessage; int mClickedButton = -1; Button *mButtonOK = nullptr; diff --git a/src/widget.cpp b/src/widget.cpp index 81c4bb8..5d89d85 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1049,15 +1049,15 @@ namespace gcn graphics->pushClipArea(mDimension); draw(graphics); - const Rectangle& childrenArea = getChildrenArea(); + Rectangle childrenArea = getChildrenArea(); graphics->pushClipArea(childrenArea); + childrenArea.x = 0; + childrenArea.y = 0; - std::list::const_iterator iter; - for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + for (auto* widget : mChildren) { - Widget* widget = (*iter); - // Only draw a widget if it's visible and if it visible - // inside the children area. + // Only draw a widget if it's visible + // and if it visible inside the children area. if (widget->isVisible() && childrenArea.isIntersecting(widget->getDimension())) { widget->_draw(graphics); diff --git a/src/widgets/inputbox.cpp b/src/widgets/inputbox.cpp index 13a651d..117c399 100644 --- a/src/widgets/inputbox.cpp +++ b/src/widgets/inputbox.cpp @@ -72,8 +72,7 @@ namespace gcn const std::string& message, const std::string& ok, const std::string& cancel) : - Window(caption), - mMessage(message) + Window(caption) { addMouseListener(this); setMovable(false); @@ -93,9 +92,9 @@ namespace gcn mButtonCancel->setAlignment(Graphics::Center); mButtonCancel->addMouseListener(this); mButtonCancel->adjustSize(); - + // Look-and-feel: make both buttons the same width - if(mButtonCancel->getWidth() > mButtonOK->getWidth()) + if (mButtonCancel->getWidth() > mButtonOK->getWidth()) { mButtonOK->setWidth(mButtonCancel->getWidth()); } @@ -103,26 +102,30 @@ namespace gcn { mButtonCancel->setWidth(mButtonOK->getWidth()); } - - setHeight((int)getTitleBarHeight() + mLabel->getHeight() + mText->getHeight() + 6 * mPadding + mButtonOK->getHeight() + 2 * getFrameSize()); + + setHeight((int) getTitleBarHeight() + mLabel->getHeight() + mText->getHeight() + + 6 * mPadding + mButtonOK->getHeight() + 2 * getFrameSize()); setWidth(mLabel->getWidth() + 2 * mPadding + 2 * getFrameSize()); - if(2 * mButtonOK->getWidth() + 4 * mPadding + 2 * getFrameSize() > getWidth()) + if (2 * mButtonOK->getWidth() + 4 * mPadding + 2 * getFrameSize() > getWidth()) { - setWidth(2 * mButtonOK->getWidth() + 4*mPadding + 2 * getFrameSize()); + setWidth(2 * mButtonOK->getWidth() + 4 * mPadding + 2 * getFrameSize()); } mText->setWidth(getWidth() - 2 * getFrameSize() - 5 * mPadding); - - this->add(mLabel, (getWidth() - mLabel->getWidth())/2 - mPadding, mPadding); - this->add(mText, 2*mPadding, 2 * mPadding + mLabel->getHeight()); - int yButtons = getHeight() - (int)getTitleBarHeight() - getFrameSize() - 2*mPadding - mButtonOK->getHeight(); - this->add(mButtonOK, (getWidth() - 2 * mButtonOK->getWidth())/4, yButtons); - this->add(mButtonCancel, getWidth() - 2*getFrameSize() - mButtonOK->getWidth() - mPadding, yButtons); - + + this->add(mLabel, (getWidth() - mLabel->getWidth()) / 2 - mPadding, mPadding); + this->add(mText, 2 * mPadding, 2 * mPadding + mLabel->getHeight()); + int yButtons = getHeight() - (int) getTitleBarHeight() - getFrameSize() - 2 * mPadding + - mButtonOK->getHeight(); + this->add(mButtonOK, (getWidth() - 2 * mButtonOK->getWidth()) / 4, yButtons); + this->add(mButtonCancel, + getWidth() - 2 * getFrameSize() - mButtonOK->getWidth() - mPadding, + yButtons); + try { requestModalFocus(); - } - catch (Exception e) + } + catch (Exception e) { // Not having modal focus is not critical } @@ -131,184 +134,43 @@ namespace gcn InputBox::~InputBox() { releaseModalFocus(); - + delete mLabel; delete mButtonOK; delete mButtonCancel; delete mText; } - void InputBox::draw(Graphics* graphics) - { - Color faceColor = getBaseColor(); - Color highlightColor, shadowColor; - int alpha = getBaseColor().a; - //int width = getWidth() + getFrameSize() * 2 - 1; - //int height = getHeight() + getFrameSize() * 2 - 1; - highlightColor = faceColor + 0x303030; - highlightColor.a = alpha; - shadowColor = faceColor - 0x303030; - shadowColor.a = alpha; - - Rectangle d = getChildrenArea(); - - // Fill the background around the content - graphics->setColor(faceColor); - // Fill top - graphics->fillRectangle(Rectangle(0,0,getWidth(),d.y - 1)); - // Fill left - graphics->fillRectangle(Rectangle(0,d.y - 1, d.x - 1, getHeight() - d.y + 1)); - // Fill right - graphics->fillRectangle(Rectangle(d.x + d.width + 1, - d.y - 1, - getWidth() - d.x - d.width - 1, - getHeight() - d.y + 1)); - // Fill bottom - graphics->fillRectangle(Rectangle(d.x - 1, - d.y + d.height + 1, - d.width + 2, - getHeight() - d.height - d.y - 1)); - - if (isOpaque()) - { - graphics->fillRectangle(d); - } - - // Construct a rectangle one pixel bigger than the content - d.x -= 1; - d.y -= 1; - d.width += 2; - d.height += 2; - - // Draw a border around the content - graphics->setColor(shadowColor); - // Top line - graphics->drawLine(d.x, - d.y, - d.x + d.width - 2, - d.y); - - // Left line - graphics->drawLine(d.x, - d.y + 1, - d.x, - d.y + d.height - 1); - - graphics->setColor(highlightColor); - // Right line - graphics->drawLine(d.x + d.width - 1, - d.y, - d.x + d.width - 1, - d.y + d.height - 2); - // Bottom line - graphics->drawLine(d.x + 1, - d.y + d.height - 1, - d.x + d.width - 1, - d.y + d.height - 1); - - //drawChildren(graphics); - - int textX; - int textY; - - textY = ((int)getTitleBarHeight() - getFont()->getHeight()) / 2; - - switch (getAlignment()) - { - case Graphics::Left: - textX = 4; - break; - case Graphics::Center: - textX = getWidth() / 2; - break; - case Graphics::Right: - textX = getWidth() - 4; - break; - default: - throw GCN_EXCEPTION("Unknown alignment."); - } - - if (isEnabled()) - graphics->setColor(getForegroundColor()); - else - graphics->setColor(Color(128, 128, 128)); - graphics->setFont(getFont()); - graphics->pushClipArea(Rectangle(0, 0, getWidth(), getTitleBarHeight() - 1)); - graphics->drawText(getCaption(), textX, textY, getAlignment(), isEnabled()); - graphics->popClipArea(); - } - - void InputBox::mousePressed(MouseEvent& mouseEvent) - { - if (mouseEvent.getSource() != this) - { - return; - } - - if (getParent() != NULL) - { - getParent()->moveToTop(this); - } - - mDragOffsetX = mouseEvent.getX(); - mDragOffsetY = mouseEvent.getY(); - - mMoved = mouseEvent.getY() <= (int)mTitleBarHeight; - } - void InputBox::mouseReleased(MouseEvent& mouseEvent) { - if (mouseEvent.getSource() != this) - { - if(mouseEvent.getSource() == mButtonOK) - { - mClickedButton = 0; - distributeActionEvent(); - } - if(mouseEvent.getSource() == mButtonCancel) - { - mClickedButton = 1; - setVisible(false); - distributeActionEvent(); - } - - } - else + if (mouseEvent.getSource() == mButtonOK) { - mMoved = false; + mClickedButton = 0; + distributeActionEvent(); } - } - - void InputBox::mouseDragged(MouseEvent& mouseEvent) - { - if (mouseEvent.isConsumed() || mouseEvent.getSource() != this) + else if (mouseEvent.getSource() == mButtonCancel) { - return; + mClickedButton = 1; + setVisible(false); + distributeActionEvent(); } - - if (isMovable() && mMoved) - { - setPosition(mouseEvent.getX() - mDragOffsetX + getX(), - mouseEvent.getY() - mDragOffsetY + getY()); - } - - mouseEvent.consume(); + Window::mouseReleased(mouseEvent); } - + int InputBox::getClickedButton() const { return mClickedButton; } - + std::string InputBox::getText() const { return mText->getText(); } - + void InputBox::addToContainer(Container* container) { int x = container->getWidth() - getWidth(); int y = container->getHeight() - getHeight(); - container->add(this, x/2, y/2); + container->add(this, x / 2, y / 2); } -} +} // namespace gcn From 220c871e9201d94e978d4d493f8ec16242ac3079 Mon Sep 17 00:00:00 2001 From: Jarod42 Date: Sat, 21 Sep 2024 22:57:21 +0200 Subject: [PATCH 03/19] [cleanup] Use `std::unique_ptr` in `InputBox` --- include/guisan/widgets/inputbox.hpp | 9 +++++---- src/widgets/inputbox.cpp | 25 ++++++++++--------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/include/guisan/widgets/inputbox.hpp b/include/guisan/widgets/inputbox.hpp index 50e5e06..0fb7c32 100644 --- a/include/guisan/widgets/inputbox.hpp +++ b/include/guisan/widgets/inputbox.hpp @@ -57,6 +57,7 @@ #ifndef GCN_INPUTBOX_HPP #define GCN_INPUTBOX_HPP +#include #include #include "guisan/mouselistener.hpp" @@ -124,10 +125,10 @@ namespace gcn protected: int mClickedButton = -1; - Button *mButtonOK = nullptr; - Button *mButtonCancel = nullptr; - Label *mLabel = nullptr; - TextField *mText = nullptr; + std::unique_ptr