rustgtkgtk3gtk-rs

How can I remove the duplication in this Rust code?


This working Rust code repeats itself somewhat:

fn append_column(tree: &TreeView, attribute: &str, id: i32) {
    let column = TreeViewColumn::new();
    match attribute {
        "text" => {
            let cell = CellRendererText::new();    
            TreeViewColumnExt::pack_start(&column, &cell, true);
            TreeViewColumnExt::add_attribute(&column, &cell, attribute, id);
        }
        "pixbuf" => {
            let cell = CellRendererPixbuf::new();
            TreeViewColumnExt::pack_start(&column, &cell, true);
            TreeViewColumnExt::add_attribute(&column, &cell, attribute, id);
        }
        _ => { panic!("Unexpected attribute") }
    }
    tree.append_column(&column);
}

I've tried to simplify it using downcast() as follows:

fn append_column(tree: &TreeView, attribute: &str, id: i32) {
    let column = TreeViewColumn::new();
    let cell : CellRenderer;
    match attribute {
        "text" => { cell = CellRendererText::new().downcast::<CellRenderer>().unwrap() }
        "pixbuf" => { cell = CellRendererPixbuf::new().downcast::<CellRenderer>().unwrap() }
        _ => { panic!("Unexpected attribute") }
    }
    TreeViewColumnExt::pack_start(&column, &cell, true);
    TreeViewColumnExt::add_attribute(&column, &cell, attribute, id);
    tree.append_column(&column);
}

but I get the follow errors:

error[E0277]: the trait bound `CellRenderer: IsA<CellRendererText>` is not satisfied
   --> src/main.rs:23:52
    |
23  |         "text" => { cell = CellRendererText::new().downcast::<CellRenderer>().unwrap() }
    |                                                    ^^^^^^^^ the trait `IsA<CellRendererText>` is not implemented for `CellRenderer`

Can I remove the duplication?


Solution

  • As Jmb noted you want to use upcast instead of downcast after which your code can be written as:

    use gtk::{
        prelude::*, CellRenderer, CellRendererPixbuf, CellRendererText, TreeView, TreeViewColumn,
    };
    
    fn append_column(tree: &TreeView, attribute: &str, id: i32) {
        let column = TreeViewColumn::new();
        let cell: CellRenderer = match attribute {
            "text" => CellRendererText::new().upcast(),
            "pixbuf" => CellRendererPixbuf::new().upcast(),
            _ => panic!("Unexpected attribute"),
    
        };
        TreeViewColumnExt::pack_start(&column, &cell, true);
        TreeViewColumnExt::add_attribute(&column, &cell, attribute, id);
        tree.append_column(&column);
    }