GTK4: Drawing a rubberband

I am trying to push Shotwell to GTK4 currently, which surprisingly works smoother than I anticipated.

I have stumbled over one thing, though. With GTK3 I am using gtk_render_background/gtk_render_frame on a style context with the class “rubberband” to draw a selection rubberband on a DrawingArea. I think I stole that from libgd:

        get_style_context().save();
        get_style_context().add_class("rubberband");
        // pixelate selection rectangle interior
        if (visible_band.width > 1 && visible_band.height > 1) {
            get_style_context().render_background(ctx, visible_band.x, visible_band.y, visible_band.width, visible_band.height);
        }

        // border
        get_style_context().render_frame(ctx, visible_band.x, visible_band.y, visible_band.width, visible_band.height);
        get_style_context().restore();

In principle that still works fine, but instead of a rubberband I get an opaque rectangle in background color. What am I missing here?

Ok, at least I know understand why it does not work. It looks like the default theme only comes with a CSS type rubberband, not not a CSS class rubberband anymore.

Solved with a small proxy widget just to steal the style from…

    class RubberbandProxy : Gtk.Widget {
        public RubberbandProxy(Gtk.Widget parent) {
            Object();
            set_parent(parent);
        }

        ~RubberbandProxy() {
            unparent();
        }

        static construct {
            set_css_name("rubberband");
        }
    }

    private void draw_selection_band(Cairo.Context ctx) {
        // no selection band, nothing to draw
        if (selection_band.width <= 1 || selection_band.height <= 1)
            return;
        
        // This requires adjustments
        if (hadjustment == null || vadjustment == null)
            return;
        
        // find the visible intersection of the viewport and the selection band
        Gdk.Rectangle visible_page = get_adjustment_page(hadjustment, vadjustment);
        Gdk.Rectangle visible_band = Gdk.Rectangle();
        visible_page.intersect(selection_band, out visible_band);
        
        var style = new RubberbandProxy(this).get_style_context();

        style.save();
        // pixelate selection rectangle interior
        if (visible_band.width > 1 && visible_band.height > 1) {
            style.render_background(ctx, visible_band.x, visible_band.y, visible_band.width, visible_band.height);
        }
        
        // border
        style.render_frame(ctx, visible_band.x, visible_band.y, visible_band.width, visible_band.height);
        style.restore();
    }
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.