Recent Posts

Pages: 1 2 [3] 4 5 ... 10
21
Feature requests / Re: SpinCtrl
« Last post by texus on 19 July 2020, 14:38:14 »
I've implemented saving and loading. Some fixes unrelated to SpinControl were needed to make it work.
The mouse cursor change has also been added by now.
22
Help requests / Re: Change mouse pointer when resizing childwindow
« Last post by texus on 19 July 2020, 11:44:56 »
TGUI 0.9-dev will now change the mouse cursor when hovering over the borders of a child window (if setResizable(true) was called).
The code was a lot more complicated that I originally thought so there is no chance at all that this would be backported to 0.8.

More information about the final design can be found in the announcement I made in Discord:
Quote
TGUI 0.9-dev now supports changing the mouse cursor.
There are 3 ways the mouse cursors are used:

1) Resize cursors will automatically be shown when hovering over the borders of a resizable child window. The default invisible border width has also been increased from 5 to 10 pixels. Those changes make resizing a child window a lot easier.

2) A setMouseCursor function has been added to the Widget class. The requested mouse cursor will be shown when the mouse hovers over the widget. The following line would cause the I-beam cursor to be visible when hovering over an edit box:
editBox->setMouseCursor(tgui::Cursor::Type::Text);

3) You can set a mouse cursor that will be used anywhere on the window and which overrides the cursor from the previous two methods. To do this, call the setOverrideMouseCursor on the Gui object. Call the restoreOverrideMouseCursor() function later to let the gui change the cursor automatically again based on the widget below the mouse.

Styling the cursors:
System cursors are used by default. Bitmaps are also supported by using the static tgui::Cursor::setStyle(Type type, const std::uint8_t* pixels, Vector2u size, Vector2u hotspot) method.

Changes to building TGUI:
- Minimum SFML version was increased from 2.3.2 to 2.5.0
- TGUI will now links to X11 on Linux to work around a limitation in SFML
23
Feature requests / Re: SpinCtrl
« Last post by Kvaz1r on 17 July 2020, 23:54:56 »
Wow, mouse cursors will be really cool addition.

Yeah, I'm sure that I missed something (except code style of course). I only now found that widgets based on SubwidgetContainer don't have load/save support out-of-the-box. And I don't see how it should be implemented (I haven't big experience with any DSL-based GUI therefore not use it at all so it's not a problem for me).
24
Feature requests / Re: SpinCtrl
« Last post by texus on 15 July 2020, 19:57:23 »
The code has been merged. Thanks again for contributing this.

I noticed that there is still a warning left, but I will fix this myself. Once I'm done with what I'm working on (ability to change mouse cursors plus some code reorganization), I'm going to have a detailed look at the code you added and make some nitpick changes anyway.
25
Feature requests / Re: SpinCtrl
« Last post by Kvaz1r on 15 July 2020, 09:54:07 »
Does it really matter that if the user typed "123text", we keep the "123" instead of resetting the value? I don't think anyone is even going to notice the behavior (because you typically do type actual digits in it). And I would kind of consider it a feature that it keeps the value I typed if I accidentally hit another button together with the enter key :).
Maybe the edit box should have Validator::Float set, that way you can't even type text or have multiple commas.
Yeah, I didn't think about that. Updated with validator. 
26
Feature requests / Re: SpinCtrl
« Last post by texus on 14 July 2020, 19:31:51 »
Does it really matter that if the user typed "123text", we keep the "123" instead of resetting the value? I don't think anyone is even going to notice the behavior (because you typically do type actual digits in it). And I would kind of consider it a feature that it keeps the value I typed if I accidentally hit another button together with the enter key :).
Maybe the edit box should have Validator::Float set, that way you can't even type text or have multiple commas.

The compile error is coming from line 45 because you have a generic lambda. GCC 5 doesn't seem to like it that you call a member function from inside a generic lambda. You should change "auto" to "float" there. I personally never use auto for simple integers and floats, usually it doesn't matter but in this particular case you can't use auto (at least not when keeping the older compilers supported).
There are also a few warnings about you reusing the "value" variable name multiple times in the same function (line 45 and 69 reuse the name declared at line 33).
27
Feature requests / Re: SpinCtrl
« Last post by Kvaz1r on 14 July 2020, 15:12:13 »
Maybe instead of choosing Int vs Float, there should be an amount of digits behind the comma? If set to 0, only ints get accepted, if set to 2 then "x", "x.a" or "x.ab" would be accepted but "x.abc" would be rounded. The default could be -1 which allows any float input.
That's indeed better.

Instead of using std::stof and exceptions, I think String::toFloat should be used. Whether we should depend on the locale to parse numbers is arguable, but for now it would probably be best to rely on the code always behaving the same on every pc.
Yeah, I though about that, but String::toFloat doesn't have any way to know was full string converted or only some first part. E.g. "123text" give 123  so one need or make extra conversion back to string or something else. For now I copied simplified version of toFloat as a private function, but guess String::toFloat should contains overloading for such cases. Maybe like std::stof with parameter for storing the number of characters processed or something else.
28
Help requests / Re: Change mouse pointer when resizing childwindow
« Last post by texus on 11 July 2020, 18:16:21 »
It's probably not going to be finished this weekend. The implementation is a bit more complicated than expected (e.g. the mouse cursor is tied to a window and therefore to a specific Gui object). Because of this I decided to add the cursor code together with a larger change, so it will take a bit longer.
29
Feature requests / Re: SpinCtrl
« Last post by texus on 10 July 2020, 23:25:12 »
Thanks a lot. I'm sure several people will find this class useful.

The only think that I miss in the class is the setSize function. If setSize is called on the SpinCtrl, the spin button should probably keep its ratio (so if height is doubled then width is doubled too) and the edit box would take up all the remaining width.

I'm not a big fan of having a createIntegerSpinCtrl function, I would prefer that all widgets would be created via the 'create' function, but I don't see many alternatives either. Maybe instead of choosing Int vs Float, there should be an amount of digits behind the comma? If set to 0, only ints get accepted, if set to 2 then "x", "x.a" or "x.ab" would be accepted but "x.abc" would be rounded. The default could be -1 which allows any float input.
Maybe the TextChanged event could also be replaced by ReturnOrUnfocused, so that you can still e.g. copy "x.abc" into the edit field and it would only be rounded and accepted when pressing enter or unfocusing the edit box?
Ultimately I'll leave this decision up to you, it's just some idea to think about. I would merge the class no matter how the int vs float is solved.

Instead of using std::stof and exceptions, I think String::toFloat should be used. Whether we should depend on the locale to parse numbers is arguable, but for now it would probably be best to rely on the code always behaving the same on every pc. I recently discovered that std::stof does depend on the locale and may turn "1.5" into "1" for some people, which is why I stopped using std::stof in the String class.

Finally some nitpicks. Maybe you would have already made some of these changes when cleaning up the code, but here are a couple of minor things that don't correspond to the rest of TGUI code:
- You can use SignalFloat instead of SignalTyped<float>
- SetValue shouldn't have capital S
- Lowercase 'f' instead of 'F' is used in TGUI behind floating point numbers
- If a value isn't going to be changed, it can be a 'const' variable (e.g. curValue)
30
Feature requests / Re: SpinCtrl
« Last post by Kvaz1r on 10 July 2020, 14:51:40 »
I've finally finished SpinCtrl, here is code and example:

Code: [Select]
#include <TGUI/TGUI.hpp>
#include <iostream>

class SpinCtrl : public tgui::SubwidgetContainer
{
public:
    typedef std::shared_ptr<SpinCtrl> Ptr; //!< Shared widget pointer
    typedef std::shared_ptr<const SpinCtrl> ConstPtr; //!< Shared constant widget pointer

    SpinCtrl(float min = 0.0F, float max = 10.0F, float step = 1.0F, float value = 0.0F)
    {
        m_type = "SpinCtrl";

        m_spinButton = tgui::SpinButton::create();
        m_spinText = tgui::EditBox::create();
        m_spinText->setText(tgui::String(m_spinButton->getValue()));

        m_spinButton->setPosition(tgui::bindRight(m_spinText), tgui::bindTop(m_spinText));
        m_spinButton->onValueChange([this](const float value)
            {
                m_spinText->setText(tgui::String(value));
                onValueChange.emit(this, value);
            });

        m_spinButton->setMinimum(min);
        m_spinButton->setMaximum(max);
        m_spinButton->setValue(value);
        m_spinButton->setStep(step);

        m_spinText->setSize(m_spinText->getSize().x, m_spinButton->getSize().y);
        m_spinText->onTextChange([this](const tgui::String& text)
            {
                auto curValue = m_spinButton->getValue();
                try
                {
                    std::size_t pos = 0;
                    float value = std::stof(text.toAnsiString(), &pos);
                    if (pos != text.size() || !inRange(value))
                    {
                        m_spinText->setText(tgui::String(curValue));
                    }
                    else if (curValue != value)
                    {
                        m_spinButton->setValue(value);
                    }
                }
                catch (...)
                {
                    m_spinText->setText(tgui::String(curValue));
                }
            });
        m_container->add(m_spinText);
        m_container->add(m_spinButton);
        auto butSize = m_spinButton->getSize();
        auto txtSize = m_spinText->getSize();
        setSize({ butSize.x + txtSize.x, butSize.y });
    }
    static SpinCtrl::Ptr create(float min = 0.0F, float max = 10.0F, float step = 1.0F, float value = 0.0F)
    {
        return std::make_shared<SpinCtrl>(min, max, step, value);
    }
    static SpinCtrl::Ptr copy(SpinCtrl::ConstPtr spinctrl)
    {
        if (spinctrl)
            return std::static_pointer_cast<SpinCtrl>(spinctrl->clone());
        else
            return nullptr;
    }
    Widget::Ptr clone() const override
    {
        return std::make_shared<SpinCtrl>(*this);
    }
    bool SetValue(const float value)
    {
        if (inRange(value) && m_spinButton->getValue() != value)
        {
            m_spinButton->setValue(value);
            m_spinText->setText(tgui::String(value));
            return true;
        }
        return false;
    }
    void setMinimum(const float min)
    {
        m_spinButton->setMinimum(min);
    }
    void setMaximum(const float max)
    {
        m_spinButton->setMaximum(max);
    }
    void setStep(const float inc)
    {
        m_spinButton->setStep(inc);
    }
    float getValue() const
    {
        return m_spinButton->getValue();
    }
    float getMinimum() const
    {
        return m_spinButton->getMinimum();
    }
    float getMaximum() const
    {
        return m_spinButton->getMaximum();
    }
    float getStep() const
    {
        return m_spinButton->getStep();
    }
    tgui::SpinButtonRenderer* getSpinButtonRenderer()
    {
        return m_spinButton->getRenderer();
    }
    tgui::SpinButtonRenderer* getSpinButtonSharedRenderer()
    {
        return m_spinButton->getSharedRenderer();
    }
    tgui::EditBoxRenderer* getSpinTextRenderer()
    {
        return m_spinText->getRenderer();
    }
    tgui::EditBoxRenderer* getSpinTextSharedRenderer()
    {
        return m_spinText->getSharedRenderer();
    }

    tgui::SignalTyped<float> onValueChange = { "ValueChanged" };

private:
    bool inRange(const float value) const
    {
        return m_spinButton->getMinimum() <= value && value <= m_spinButton->getMaximum();
    }

    tgui::SpinButton::Ptr m_spinButton;
    tgui::EditBox::Ptr m_spinText;
};

class MyFrame
{
public:
    MyFrame()
    {
        window.create(sf::VideoMode(800, 600), "SpinCtrl");
        gui.setTarget(window);
        auto spin = SpinCtrl::create(0, 10, 0.2F, 5);
        spin->getSpinTextRenderer()->setBackgroundColor(tgui::Color(205, 14, 98));
        spin->getSpinTextRenderer()->setBackgroundColorHover(tgui::Color(205, 14, 98));
        spin->getSpinButtonRenderer()->setBackgroundColor(tgui::Color(138, 250, 134));
        spin->getSpinButtonRenderer()->setBackgroundColorHover(tgui::Color(138, 250, 134));
        gui.add(spin);

        spin->onValueChange([](float value) { std::cout << "New value is " << value << '\n'; });
    }

    void main()
    {
        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                gui.handleEvent(event);
            }
            gui.draw();
            window.display();
        }
    }
    sf::RenderWindow window;
    tgui::Gui gui;
};

int main()
{
    MyFrame().main();
}

If such implementation is ok, I am going to open PR (will split onto .h/.cpp and add tests).

As an option maybe it make sense to add method createIntegerSpinCtrl and set in that method Integer Validator.
Pages: 1 2 [3] 4 5 ... 10