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: >k::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();
}