main.rs 3.5 KB

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