How to write custom Container in gtk-rs?

145 Views Asked by At

How can I write a custom Container in gtk-rs for GTK-3? I use gtk-rs 0.15.0 (to be compatible with the last GTK-3 compatible version of webkit2gtk). I couldn't find any reasonable documentation.

Reason behind this: I use a horizontally aligned Box layout, where I want a left component take roughly 2/3 window-width and the remainder component 1/3. "Roughly" meaning: In detail it's more complicated, but setting the sizes manually, also with hexpand set to false, leads to "wobbling" sizes, conflicting with the constantly changing contents sizes, all in all shaky behavior. Writing a custom container seems to be the cleanest way.

Is there any example code / project (e.g. GitHub ?) where a custom Container was written in gtk-rs for GTK-3?

1

There are 1 best solutions below

5
Sylvester Kruin - try Codidact On

There's no need to write a custom container; to do what you described, you can simply use Grid.

Using Grid

As you probably know, the Grid container is made up of rows and columns. A single widget can take up multiple rows and columns. Thus, if you want one widget to span 2/3 of the window and the other to span 1/3 of it, you can use three columns of a Grid, and make the first widget cover two columns while the second widget covers just one.

In order to do this, you use the width and height arguments of Grid.attach(). For example, this widget will span two columns:

grid.attach(
    &widget,
    0, // X position (column)
    0, // Y position (row)
    2, // width (in columns)
    1  // height (in rows)
);

Now in order for the column proportions to be correct, you also need to set the columns homogeneous:

grid.set_column_homogeneous(true);

The same principles can be applied to rows too.

Example

All that being said, here is a simple working example with a Button and an Entry. The Button (on the left) takes up 2/3 of the width of the window, while the Entry (on the right) takes up only 1/3.

use gtk::prelude::*;
use gtk;

/// Create the window and all its widgets
fn create_window(app: &gtk::Application) {

    // The main window
    let window = gtk::ApplicationWindow::builder()
        .application(app)
        .title("Example")
        .build();
    window.set_position(gtk::WindowPosition::Center);

    // A Grid
    let grid = gtk::Grid::new();
    grid.set_column_homogeneous(true); // Makes sure the columns are proportional
    window.add(&grid);

    // A button that's 2 columns wide
    let button = gtk::Button::with_label("2/3 of the window");
    grid.attach(&button, 0, 0, 2, 1);

    // An entry that's only 1 column wide
    let entry = gtk::Entry::builder()
        .placeholder_text("1/3 of the window")
        .build();
    grid.attach(&entry, 2, 0, 1, 1);

    // Show all the widgets after creation
    window.show_all();
}

fn main() {

    // Create the application
    let app = gtk::Application::builder()
        .application_id("rust.example.app")
        .build();
    app.connect_activate(create_window);
    app.run();
}