3

enter image description here

I have been recently learning making simple GUIs with gtk-rs but have run into an issue where numeric data is left justified in the list store / tree view and I want to have it right justified.

The code below is a modification from here: https://github.com/gtk-rs/examples/blob/master/src/bin/list_store.rs

I have been able to get the column headers to justify to center (for date) and right (for population & area) by using ".set_alignment" but have been unable to change the alignment of the data itself.

String data is easy enough to manipulate (I embedded a tab in the date items and it lines up nicely. However, if I change the population & area data to be formatted strings, they will sort as such when their column header is clicked rather than as a numeric.

Any & all help is greatly appreciated!

extern crate gio;
extern crate gtk;

use gtk::prelude::*;
use std::rc::Rc;
use std::env::args;
use gio::prelude::*;

#[repr(i32)]
enum Columns {
    State,
    Population,
    Area,
    Date,
}

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);

    window.set_title("List Store");
    window.set_border_width(10);
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(300, 500);

    let vbox = gtk::Box::new(gtk::Orientation::Vertical, 8);
    window.add(&vbox);

    let label = gtk::Label::new(Some("US State Facts"));
    vbox.add(&label);

    let sw = gtk::ScrolledWindow::new(None::<&gtk::Adjustment>, None:: <&gtk::Adjustment>);
    sw.set_shadow_type(gtk::ShadowType::EtchedIn);
    sw.set_policy(gtk::PolicyType::Never, gtk::PolicyType::Automatic);
    vbox.add(&sw);

    let model = Rc::new(create_model());
    let treeview = gtk::TreeView::new_with_model(&*model);
    treeview.set_vexpand(true);

    sw.add(&treeview);

    add_columns(&treeview);

    window.show_all();
}

struct Data {
    state: String,
    population: u32,
    area: u32,
    date: String,
}

fn create_model() -> gtk::ListStore {

    let col_types: [gtk::Type; 4] = [
        gtk::Type::String,
        gtk::Type::U32,
        gtk::Type::U32,
        gtk::Type::String,
    ];

    let data: [Data; 14] = [
        Data {
            state: "Alabama".to_string(),
            population: 4887871,
            area: 125767,
            date: "\t1819.12.14".to_string(),
        },
        Data {
            state: "Alaska".to_string(),
            population: 737438,
            area: 1723337,
            date: "\t1959.01.03".to_string(),
        },
        Data {
            state: "Arkansas".to_string(),
            population: 3013825,
            area: 137732,
            date: "\t1836.06.15".to_string(),
        },
        Data {
            state: "Arizona".to_string(),
            population: 7171646,
            area: 295234,
            date: "\t1912.02.14".to_string(),
        },
        Data {
            state: "California".to_string(),
            population: 39557045,
            area: 423972,
            date: "\t1850.09.09".to_string(),
        },
        Data {
            state: "Colorado".to_string(),
            population: 5695564,
            area: 269601,
            date: "\t1876.08.01".to_string(),
        },
        Data {
            state: "Connecticut".to_string(),
            population: 3572665,
            area: 14357,
            date: "\t1788.01.09".to_string(),
        },
        Data {
            state: "Delaware".to_string(),
            population: 967171,
            area: 6446,
            date: "\t1787.12.07".to_string(),
        },
        Data {
            state: "Maine".to_string(),
            population: 1338404,
            area: 91633,
            date: "\t1820.03.15".to_string(),
        },
        Data {
            state: "Maryland".to_string(),
            population: 6042718,
            area: 32131,
            date: "\t1788.04.28".to_string(),
        },
        Data {
            state: "Massachusetts".to_string(),
            population: 6902149,
            area: 27336,
            date: "\t1788.02.06".to_string(),
        },
        Data {
            state: "Michigan".to_string(),
            population: 9998915,
            area: 250487,
            date: "\t1837.01.26".to_string(),
        },
        Data {
            state: "Missouri".to_string(),
            population: 6126452,
            area: 180540,
            date: "\t1821.08.10".to_string(),
        },
        Data {
            state: "Nebraska".to_string(),
            population: 1929268,
            area: 200330,
            date: "\t1867.03.01".to_string(),
        },
    ];

    let store = gtk::ListStore::new(&col_types);

    let col_indices: [u32; 4] = [0, 1, 2, 3];

    for (_, d) in data.iter().enumerate() {
        let values: [&dyn ToValue; 4] = [
            &d.state,
            &d.population,
            &d.area,
            &d.date,
        ];
        store.set(&store.append(), &col_indices, &values);
    }

    store
}

//fn add_columns(treeview: &gtk::TreeView) 
fn add_columns(treeview: &gtk::TreeView) {

    // Column for state name
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("State");
        column.add_attribute(&renderer, "text", Columns::State as i32);
        column.set_sort_column_id(Columns::State as i32);
        column.set_fixed_width(150);
        column.set_alignment(0.0);
        treeview.append_column(&column);
    }

    // Column for population
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Population");
        column.add_attribute(&renderer, "text", Columns::Population as i32);
        column.set_sort_column_id(Columns::Population as i32);
        column.set_fixed_width(150);
        column.set_alignment(1.0);
        treeview.append_column(&column);
    } 

    // Column for area
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Area");
        column.add_attribute(&renderer, "text", Columns::Area as i32);
        column.set_sort_column_id(Columns::Area as i32);
        column.set_fixed_width(150);
        column.set_alignment(1.0);
        treeview.append_column(&column);
    }

    // Column for date
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Date");
        column.add_attribute(&renderer, "text", Columns::Date as i32);
        column.set_sort_column_id(Columns::Date as i32);
        column.set_fixed_width(150);
        column.set_alignment(0.5);
        treeview.append_column(&column);
    }
}


fn main() {
    let application = gtk::Application::new(
        Some("com.github.gtk-rs.examples.list-store"),
        Default::default(),
    )
    .expect("Initialization failed...");

    application.connect_startup(|app| {
         build_ui(app);
    });

    application.connect_activate(|_| {});

    application.run(&args().collect::<Vec<_>>());
}

Cargo.toml:

[package]
name = "testit"
version = "0.1.0"
authors = ["jerry"]
edition = "2018"

[dependencies]
gio = "0.7.0"
gtk = "0.7.0"   

The Fix: renderer.set_alignment(1.0, 1.0);

// Column for population
{
    let renderer = gtk::CellRendererText::new();
    renderer.set_alignment(1.0, 1.0);
    let column = gtk::TreeViewColumn::new();
    column.pack_start(&renderer, true);
    column.set_title("Population");
    column.add_attribute(&renderer, "text", Columns::Population as i32);
    column.set_sort_column_id(Columns::Population as i32);
    column.set_fixed_width(150);
    column.set_alignment(1.0);
    treeview.append_column(&column);
} 

Good result: enter image description here

Compiler Error: enter image description here

Jman
  • 187
  • 1
  • 3
  • 12
  • 1
    Would you mind posting how to compile this example? I usually use Python. I know the answer to this question, but I am not fluent in Rust. – theGtknerd Jul 22 '19 at 01:02
  • To compile this may be more than you want to waste your time on, although I do appreciate the offer. If do want to compile & run you will need the Rust Setup (https://www.rust-lang.org/learn/get-started). – Jman Jul 22 '19 at 14:52
  • Once Rust is installed, run command "cargo new testit" from the terminal then navigate to that folder. Inside you will see a single file "Cargo.toml" - for this paste the gio & gtk lines from the Cargo,toml above into that file and save it. Next, open the '"src" folder and open the file "main.rs" and delete all the text in it. Copy & paste the main code listing from this bug into "main.rs" and save it. On the terminal type "cargo run" and you should see the crates updating and when it finishes, the gui window will appear. – Jman Jul 22 '19 at 15:00
  • I get yada-yada errors, ending in **Could not compile `fragile`**. So I will wait until you get to test my suggestions. – theGtknerd Jul 22 '19 at 15:05

1 Answers1

6

You are looking for the xalign property. As far as I can tell, this would result in:

renderer.set_property("xalign", 1.00)
theGtknerd
  • 3,647
  • 1
  • 13
  • 34
  • Thanks very much for your input!. The Rust compiler is very fussy and would not let me compile the line of code you recommend. I suspect it is due to the single quotes as Rust uses a single quote for lifetimes (which is another whole can of worms). Nevertheless, you have given me a good direction to investigate further which I appreciate greatly. I won't have much time to spend on this again until this weekend (I am just a hobbyist not a real programmer). If I am able to get your code tweaked to work in my little project I will definitely return and log this a fix. – Jman Jul 22 '19 at 14:44
  • Double quotes, then? `renderer.set_property("xalign", 1.00)` – theGtknerd Jul 22 '19 at 14:54
  • Played around a bit more and it turns out on Rust what I need is this: renderer.set_property(1.0, 1.0) – Jman Jul 22 '19 at 15:08
  • I never would have found this without your help - thank you very much! – Jman Jul 22 '19 at 15:09
  • That seems wierd according to the Gtk semantics. Are you sure the "xalign" property doesn't work? – theGtknerd Jul 22 '19 at 15:10
  • Rust, in my limited experience, is very weird to me at times. The last image shows the compiler error where it wants a float instead of a string. Changing this to a float fixed everything. I never would have gotten this working without your help and I cannot thank you enough! – Jman Jul 22 '19 at 15:23
  • 1
    Aha, you are using `renderer.set_alignment(1.0, 1.0)`! While this works, I actually stated `renderer.set_property("xalign", 1.0)`. With `set_alignment` you are actually setting the x and y alignment properties. Due to some other things that may bite you later on, I would only use the xalign property. – theGtknerd Jul 22 '19 at 15:29