use anyhow::{anyhow, bail, Result}; use gio::prelude::{ApplicationExt, ApplicationExtManual}; use gtk::{BoxExt, ButtonExt, ContainerExt, GtkWindowExt, WidgetExt}; use std::cell::RefCell; use std::rc::Rc; struct AppData { symbol: char, color: (f64, f64, f64), } impl AppData { fn draw_to_file(&self) -> Result<()> { let f = std::fs::File::create("samp.svg")?; let surf = cairo::SvgSurface::for_stream(100.0, 100.0, f)?; self.render(&cairo::Context::new(&surf))?; if let Err(err) = surf.finish_output_stream() { bail!(err.error); }; Ok(()) } fn render(&self, ctx: &cairo::Context) -> Result<()> { ctx.set_source_rgb(self.color.0, self.color.1, self.color.2); ctx.paint(); ctx.set_source_rgb(0., 0., 0.); ctx.move_to(0.0, -23.0); let layout = pangocairo::functions::create_layout(&ctx) .ok_or_else(|| anyhow!("Could not create layout"))?; layout.set_width(100 * 1024); layout.set_alignment(pango::Alignment::Center); let font = pango::FontDescription::from_string("Fira Sans 92"); layout.set_font_description(Some(&font)); layout.set_text(&self.symbol.to_string()); pangocairo::functions::show_layout(&ctx, &layout); Ok(()) } } #[derive(Clone)] struct App { data: Rc>, } impl App { fn new() -> App { let app_data = AppData { symbol: 'X', color: (0.5, 0.5, 0.5), }; let data = Rc::new(RefCell::new(app_data)); App { data } } } fn mk_app(gtk_app: >k::Application) { let app = App::new(); let window = gtk::ApplicationWindow::new(gtk_app); window.set_title("I Am Legend"); window.set_default_size(300, 100); window.set_resizable(false); let container = gtk::Box::new(gtk::Orientation::Vertical, 4); container.pack_start(&mk_icon_choice('A', app.clone()), false, true, 0); container.pack_start(&mk_icon_choice('B', app.clone()), false, true, 0); container.pack_start(&mk_icon_choice('C', app.clone()), false, true, 0); container.pack_start(&mk_icon_choice('D', app.clone()), false, true, 0); let flow = gtk::Box::new(gtk::Orientation::Horizontal, 2); flow.pack_start(&container, false, true, 0); let button = gtk::Button::with_label("Click me!"); flow.pack_start(&button, false, true, 0); let canvas = gtk::DrawingArea::new(); let copy = app.clone(); canvas.connect_draw(move |_cv, ctx| { if let Err(err) = copy.data.borrow_mut().render(ctx) { eprintln!("Error in rendering: {}", err); } gtk::Inhibit(false) }); flow.pack_start(&canvas, true, true, 0); button.connect_clicked(move |_| { if let Err(err) = app.data.borrow_mut().draw_to_file() { eprintln!("Error in rendering: {}", err); } }); window.add(&flow); window.show_all(); } fn mk_icon_choice(choice: char, cell: App) -> gtk::Button { let button = gtk::Button::with_label(&choice.to_string()); button.connect_clicked(move |_| { cell.data.borrow_mut().symbol = choice; println!("Choosing '{}'", choice); }); button } fn main() { let application = gtk::Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default()) .expect("failed to initialize GTK application"); application.connect_activate(|app| { mk_app(app); }); application.run(&[]); }