c++gtkmm4

How to use Gtk::Viewport in GTKMM4?


I have a large widget that I would like to fit into a small place and make it scrollable. For this, I have an example code as follows.

Unfortunately, the viewport size grows to 100x200.

How can I make the viewport stay 100x100 to allow the scrolling?

#include <gtkmm.h>

class LargeWidget : public Gtk::DrawingArea {
public:
    LargeWidget(int width, int height) {
        set_content_width(width);
        set_content_height(height);
    }
};


class Window : public Gtk::Window {
    Gtk::Box box;
    Gtk::Scrollbar scrollbar;
    Glib::RefPtr<Gtk::Adjustment> h, v;
    Gtk::Viewport viewport;
    LargeWidget large_widget;

public:
    Window() : h(Gtk::Adjustment::create(0, 0, 100)),
               v(Gtk::Adjustment::create(0, 0, 200)),
               viewport(h, v),
               large_widget(100, 200) {
        scrollbar.set_orientation(Gtk::Orientation::VERTICAL);
        scrollbar.set_adjustment(viewport.get_vadjustment());

        viewport.set_child(large_widget);

        box.set_orientation(Gtk::Orientation::HORIZONTAL);
        box.append(viewport);
        box.append(scrollbar);

        set_default_size(100, 100);
        set_child(box);
    }
};


int main(int argc, char **argv) {
    auto app = Gtk::Application::create("hu.aszn.playground");
    return app->make_window_and_run<Window>(argc, argv);
}

I tried:

viewport.size_allocate(Gtk::Allocation(0, 0, 100, 100), 0);

and

viewport.set_size_request(100, 100);

Thank you for your help.


Solution

  • set_size_request only sets the minimum size, not the maximum.

    You need to override Gtk::Widget::get_request_mode_vfunc and return Gtk::SizeRequestMode::CONSTANT_SIZE and override Gtk::Widget::measure_vfunc and set the size to 100 in either direction, or your widget will stretch to its child size, just subclass the viewport to do this, see Height For Width Geometry management and gtkmm Custom Widgets for more information.

    class MyViewport : public Gtk::Viewport {
    protected:
        Gtk::SizeRequestMode get_request_mode_vfunc() const override
        {
            return Gtk::SizeRequestMode::CONSTANT_SIZE;
        }
    
        void measure_vfunc(Gtk::Orientation orientation, int for_size,
            int& minimum, int& natural, int& minimum_baseline, int& natural_baseline) const override
        {
            // Don't use baseline alignment.
            minimum_baseline = -1;
            natural_baseline = -1;
    
            minimum = 100;
            natural = 100;
        }
    };