Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to remove focus from an element when hovering with the mouse pointer? #838

Open
DanuulKa03 opened this issue Apr 5, 2024 · 2 comments

Comments

@DanuulKa03
Copy link

Have a good day to you.
Please help me. I'm using MyToggleImpl from one of your projects, but I can't figure out how to keep inverted and remove focus when hovering over the element with the mouse pointer. Focus and inverted should remain when working with the keyboard.

    class MyToggleImpl : public ComponentBase {
    public:
        MyToggleImpl(const char* label_on, const char* label_off, bool* state)
                : label_on_(label_on), label_off_(label_off), state_(state) {}

    private:
        // Component implementation.
        Element Render() override {
            bool is_focused = Focused();
            bool is_active = Active();
            auto style = (is_focused || hovered_) ? inverted
                                                  : is_active              ? bold
                                                                           : nothing;
            auto focus_management = is_focused  ? focus
                                                : is_active ? ftxui::select
                                                            : nothing;

            Element my_text = *state_ ? text(label_on_) : text(label_off_);
            return my_text | style | focus_management | reflect(box_);
        }

        bool OnEvent(Event event) override {
            if (!CaptureMouse(event))
                return false;

            if (event.is_mouse())
                return OnMouseEvent(event);

            hovered_ = false;
            if (event == Event::Character(' ') || event == Event::Return) {
                *state_ = !*state_;
                TakeFocus();
                return true;
            }
            return false;
        }

        bool OnMouseEvent(Event event) {
            hovered_ = box_.Contain(event.mouse().x, event.mouse().y);

            if (!CaptureMouse(event))
                return false;

            if (!hovered_)
                return false;

            if (event.mouse().button == Mouse::Left &&
                event.mouse().motion == Mouse::Pressed) {
                *state_ = !*state_;
                return true;
            }

            return false;
        }

        bool Focusable() const final { return true; }

        const char* label_on_;
        const char* label_off_;
        bool* const state_;
        bool hovered_ = false;
        Box box_;
    };

I managed to completely remove all mouse actions :) But I don't need such a result.

Perhaps I'm digging in the wrong place and need to do something here.

Component MyButton(const char* prefix,
                   const char* title,
                   std::function<void()> on_click) {
    class Impl : public ComponentBase {
    public:
        Impl(const char* prefix, const char* title, std::function<void()> on_click)
                : on_click_(std::move(on_click)), prefix_(prefix), title_(title) {}

        // Component implementation:
        Element Render() override {
            auto style = Focused() ? (Decorator(inverted) | focus) : nothing;
            return hbox({
                                text(prefix_),
                                text(title_) | style | color(Color::GrayDark) | reflect(box_),
                        });
        }

        bool OnEvent(Event event) override {
            if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
                if (!CaptureMouse(event))
                    return false;

                TakeFocus();

                if (event.mouse().button == Mouse::Left &&
                    event.mouse().motion == Mouse::Pressed) {
                    on_click_();
                    return true;
                }

                return false;
            }

            if (event == Event::Return) {
                on_click_();
                return true;
            }
            return false;
        }

        bool Focusable() const final { return true; }

    private:
        std::function<void()> on_click_;
        const char* prefix_;
        const char* title_;
        Box box_;
    };

    return Make<Impl>(prefix, title, std::move(on_click));
}

@DanuulKa03
Copy link
Author

@ArthurSonzogni it may not be clear what I meant, I'm talking about this effect

05.04.2024.13.16.37.webm

@ArthurSonzogni
Copy link
Owner

I consider this to be a limitation of FTXUI with the mouse. It can't easily be fixed at the moment. Sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants