Issue with scroll

31 views
Skip to first unread message

Владислав

unread,
Jun 10, 2024, 5:35:00 AMJun 10
to fltk.general
Hi guys. I have a problem with Fl_scroll. I have custom elements in the scroll list, and they work pretty fine, but when im scrolling elements drawn not so good, align broken, when i scroll so fast text just doesnt shown, only back color

i tried to redraw every element when it resizes and redraw fl_scroll it self, but nothing really changed. Thanks


main.cpp

Greg Ercolano

unread,
Jun 10, 2024, 4:20:57 PMJun 10
to fltkg...@googlegroups.com
On 6/10/24 02:11, Владислав wrote:
Hi guys. I have a problem with Fl_scroll. I have custom elements in the scroll list, and they work pretty fine, but when im scrolling elements drawn not so good, align broken, when i scroll so fast text just doesnt shown, only back color

    Make sure your child widgets draw their backgrounds
    to ensure they erase properly, and make sure Fl_Scroll's own
    box() type remains default, so its background draws over children
    after they're moved correctly.

    Read the docs carefully for Fl_Scroll, and look at some examples of
    how it's used.

    Keep in mind that some children might draw their labels outside
    their xywh area, and in Fl_Scroll that might be a problem.

wea...@gmail.com

unread,
Jun 11, 2024, 2:42:00 AMJun 11
to fltk.general
Hi.

I have looked into the code. I couldn't solve your problem, but I found some things that might cause some trouble.
ChatElement is a subclass of Fl_Group. You forgot to call end(). The same is true for ChatList. You don't need to call add() in the loop to add elements to your group (Fl_Scroll). Widgets are added automatically until end() is called.

Greg Ercolano

unread,
Jun 11, 2024, 3:16:40 AMJun 11
to fltkg...@googlegroups.com

On 6/10/24 23:42, wea...@gmail.com wrote:

I have looked into the code.

    Oh, I didn't notice the OP had included code as an attachment.

    Another thing: if children in an Fl_Group are resized, it should call
    init_sizes() when done with the resizes to let the group know the
    children have been modified.

    Also keep in mind Fl_Group::resize() will resize the children,
    based on its own behavior, then you go in after that to make
    changes to the children the way you want, then call init_sizes();
    before returning from your custom resize() override.

    Here's a reduced version of the code so that it builds, and some
    fixes applied. (I didn't look into any of the begin()/end() stuff,
    just changing the resize() calls around and adding init_sizes()
    seemed to help)

___________________________________________________________________

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Scroll.H>
#include <algorithm>

constexpr int window_w = 600;
constexpr int window_h = 400;

namespace savin::views
{

    class ResizableBox : public Fl_Box
    {
    public:
        ResizableBox(int x, int y, int w, int h, const char *l = 0)
            : Fl_Box(x, y, w, h, l)
        {
            box(FL_BORDER_BOX);
            color(FL_BLUE);
        }

        auto resize(int x, int y, int w, int h) -> void override
        {
            int size = w < h ? w : h;
            Fl_Box::resize(x, y, size, size);
        }
    };

    class ChatList : public Fl_Scroll
    {
    public:
        ChatList(int x, int y, int w, int h, const char *l = 0)
            : Fl_Scroll(x, y, w, h, l)
        {
            box(FL_BORDER_BOX);
            color(FL_RED);
            type(Fl_Scroll::VERTICAL_ALWAYS);
        }

        auto handle(int event) -> int override{
            return Fl_Scroll::handle(event);
        }

        auto resize(int x, int y, int w, int h) -> void override
        {
            auto chatlist_max_width = Fl::w() * 0.15;
            auto chatlist_width = std::min(float(parent()->w() * 0.2), float(chatlist_max_width));

            Fl_Scroll::resize(x, y, chatlist_width, h);  // MOVED

            for (int i = 0; i < children(); i++)
            {
                auto ch = child(i);
                if(ch->type()!=6) continue;
                ch->resize(1, ch->y(), chatlist_width - 30, ch->h());
            }

            init_sizes();                               // ADDED
            redraw();
        }

    };

    class ChatElement : public Fl_Group
    {
    public:
        ChatElement(int x, int y, int w, int h, const char *l = 0)
            : Fl_Group(x, y, w, h, l)
        {
            box(FL_BORDER_BOX);
            color(FL_GREEN);

            name = new Fl_Output(0, 0, 0, 0);
            name->value("Savin");
            name->box(FL_NO_BOX);
            online_status = new Fl_Output(0, 0, 0, 0);
            online_status->value("Online");
            online_status->box(FL_NO_BOX);
            avatar = new ResizableBox(0, 0, 0, 0);
            last_message = new Fl_Text_Display(0, 0, 0, 0);
        }

        auto resize(int x, int y, int w, int h) -> void override
        {
            float top_height = h * 0.25;
            float avatar_max_height = h - top_height;
            float avatar_size = std::min(float(avatar_max_height), float(w * 0.3));

            Fl_Group::resize(x, y, w, h);       // MOVED
            name->resize(x, y, w / 2, top_height);
            online_status->resize(x + w / 2, y, y + w / 2, top_height);
            avatar->resize(x, y + top_height, avatar_size, avatar_size);
            last_message->resize(x + avatar_size, y + top_height, w - avatar_size, h * 0.75);
            init_sizes();                       // ADDED
        }

        Fl_Output *name;
        Fl_Output *online_status;
        ResizableBox *avatar;
        Fl_Text_Display *last_message;
    };
}

auto main(int argc, char **argv) -> int
{
    Fl_Window *window = new Fl_Double_Window(window_w, window_h, "App");

    auto temp = new savin::views::ChatList(0, 0, window_w / 7, window_h);
    int start = 0;
    for (int i = 0; i < 10; i++)
    {
        auto element = new savin::views::ChatElement(0, start, 150, 70);
        element->type(6);
        temp->add(element);
        start += 71;
    }
    temp->resizable(0);

    window->size_range(600, 400);
    window->resizable(temp);
    window->end();
    window->show(argc, argv);
    window->resize(window->x(), window->y(), window_w+1, window_h);

    return Fl::run();
}

wea...@gmail.com

unread,
Jun 11, 2024, 3:20:35 AMJun 11
to fltk.general
I've been experimenting with it a little bit and it seems that the problem is the way you position and recalculate positions of your widgets in ChatElement. I disabled all widgets in ChatElement, but "name" (Fl_Output). I initialized it with
name = new Fl_Output(x, y, w/2, h*0.25);

I used the default resize() in ChatElement instead of the reimplemented one and the "name" (Fl_Output) was displayed correctly.
You need to rethink this positioning code.

Владислав

unread,
Jun 11, 2024, 4:37:52 AMJun 11
to fltk.general
Thank you very much for your help, everything works perfectly. The solution provided by seriss.com is simply wonderful, I couldn't have thought that I should use such a function. But thanks to everyone else for the advice as well, I will definitely follow it. I apologize for not uploading a video with the problem and not describing it well enough, this is my first question on the forum :) Thank you again so much!!! init_sizes() solved the problem  

вторник, 11 июня 2024 г. в 09:20:35 UTC+2, wea...@gmail.com:
Reply all
Reply to author
Forward
0 new messages