main.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. use anyhow::{anyhow, bail, Result};
  2. use gio::prelude::{ApplicationExt, ApplicationExtManual};
  3. use gtk::{BoxExt, ButtonExt, ContainerExt, GtkWindowExt, WidgetExt};
  4. use std::cell::RefCell;
  5. use std::rc::Rc;
  6. struct AppData {
  7. symbol: char,
  8. color: (f64, f64, f64),
  9. }
  10. impl AppData {
  11. fn draw_to_file(&self) -> Result<()> {
  12. let f = std::fs::File::create("samp.svg")?;
  13. let surf = cairo::SvgSurface::for_stream(100.0, 100.0, f)?;
  14. self.render(&cairo::Context::new(&surf))?;
  15. if let Err(err) = surf.finish_output_stream() {
  16. bail!(err.error);
  17. };
  18. Ok(())
  19. }
  20. fn render(&self, ctx: &cairo::Context) -> Result<()> {
  21. ctx.set_source_rgb(self.color.0, self.color.1, self.color.2);
  22. ctx.paint();
  23. ctx.set_source_rgb(0., 0., 0.);
  24. ctx.move_to(0.0, -23.0);
  25. let layout = pangocairo::functions::create_layout(&ctx)
  26. .ok_or_else(|| anyhow!("Could not create layout"))?;
  27. layout.set_width(100 * 1024);
  28. layout.set_alignment(pango::Alignment::Center);
  29. let font = pango::FontDescription::from_string("Fira Sans 92");
  30. layout.set_font_description(Some(&font));
  31. layout.set_text(&self.symbol.to_string());
  32. pangocairo::functions::show_layout(&ctx, &layout);
  33. Ok(())
  34. }
  35. }
  36. #[derive(Clone)]
  37. struct App {
  38. data: Rc<RefCell<AppData>>,
  39. }
  40. impl App {
  41. fn new() -> App {
  42. let app_data = AppData {
  43. symbol: 'X',
  44. color: (0.5, 0.5, 0.5),
  45. };
  46. let data = Rc::new(RefCell::new(app_data));
  47. App { data }
  48. }
  49. }
  50. fn mk_app(gtk_app: &gtk::Application) {
  51. let app = App::new();
  52. let window = gtk::ApplicationWindow::new(gtk_app);
  53. window.set_title("I Am Legend");
  54. window.set_default_size(300, 100);
  55. window.set_resizable(false);
  56. let container = gtk::Box::new(gtk::Orientation::Vertical, 4);
  57. container.pack_start(&mk_icon_choice('A', app.clone()), false, true, 0);
  58. container.pack_start(&mk_icon_choice('B', app.clone()), false, true, 0);
  59. container.pack_start(&mk_icon_choice('C', app.clone()), false, true, 0);
  60. container.pack_start(&mk_icon_choice('D', app.clone()), false, true, 0);
  61. let flow = gtk::Box::new(gtk::Orientation::Horizontal, 2);
  62. flow.pack_start(&container, false, true, 0);
  63. let button = gtk::Button::with_label("Click me!");
  64. flow.pack_start(&button, false, true, 0);
  65. let canvas = gtk::DrawingArea::new();
  66. let copy = app.clone();
  67. canvas.connect_draw(move |_cv, ctx| {
  68. if let Err(err) = copy.data.borrow_mut().render(ctx) {
  69. eprintln!("Error in rendering: {}", err);
  70. }
  71. gtk::Inhibit(false)
  72. });
  73. flow.pack_start(&canvas, true, true, 0);
  74. button.connect_clicked(move |_| {
  75. if let Err(err) = app.data.borrow_mut().draw_to_file() {
  76. eprintln!("Error in rendering: {}", err);
  77. }
  78. });
  79. window.add(&flow);
  80. window.show_all();
  81. }
  82. fn mk_icon_choice(choice: char, cell: App) -> gtk::Button {
  83. let button = gtk::Button::with_label(&choice.to_string());
  84. button.connect_clicked(move |_| {
  85. cell.data.borrow_mut().symbol = choice;
  86. println!("Choosing '{}'", choice);
  87. });
  88. button
  89. }
  90. fn main() {
  91. let application =
  92. gtk::Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default())
  93. .expect("failed to initialize GTK application");
  94. application.connect_activate(|app| {
  95. mk_app(app);
  96. });
  97. application.run(&[]);
  98. }