main.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. use anyhow::{anyhow, bail, Result};
  2. use gio::prelude::{ApplicationExt, ApplicationExtManual};
  3. use gtk::{
  4. BoxExt, ButtonExt, ContainerExt, EditableSignals, EntryExt, GtkWindowExt, LabelExt, WidgetExt,
  5. };
  6. use std::cell::RefCell;
  7. use std::rc::Rc;
  8. mod dmc;
  9. struct AppData {
  10. symbol: char,
  11. dmc: Option<dmc::DMC>,
  12. }
  13. impl AppData {
  14. fn draw_to_file(&self) -> Result<()> {
  15. let f = std::fs::File::create("samp.svg")?;
  16. let surf = cairo::SvgSurface::for_stream(100.0, 100.0, f)?;
  17. self.render(&cairo::Context::new(&surf))?;
  18. if let Err(err) = surf.finish_output_stream() {
  19. bail!(err.error);
  20. };
  21. Ok(())
  22. }
  23. fn render(&self, ctx: &cairo::Context) -> Result<()> {
  24. let color = self.color();
  25. ctx.set_source_rgb(color.0, color.1, color.2);
  26. ctx.paint();
  27. ctx.set_source_rgb(0., 0., 0.);
  28. ctx.move_to(0.0, -23.0);
  29. let layout = pangocairo::functions::create_layout(&ctx)
  30. .ok_or_else(|| anyhow!("Could not create layout"))?;
  31. layout.set_width(100 * 1024);
  32. layout.set_alignment(pango::Alignment::Center);
  33. let font = pango::FontDescription::from_string("Fira Sans 92");
  34. layout.set_font_description(Some(&font));
  35. layout.set_text(&self.symbol.to_string());
  36. pangocairo::functions::show_layout(&ctx, &layout);
  37. Ok(())
  38. }
  39. fn color(&self) -> (f64, f64, f64) {
  40. self.dmc
  41. .map(|dmc| dmc.color)
  42. .unwrap_or_else(|| (0.5, 0.5, 0.5))
  43. }
  44. }
  45. #[derive(Clone)]
  46. struct App {
  47. data: Rc<RefCell<AppData>>,
  48. }
  49. impl App {
  50. fn new() -> App {
  51. let app_data = AppData {
  52. symbol: 'X',
  53. dmc: None,
  54. };
  55. let data = Rc::new(RefCell::new(app_data));
  56. App { data }
  57. }
  58. }
  59. fn mk_app() {
  60. let app = App::new();
  61. let window = gtk::Window::new(gtk::WindowType::Toplevel);
  62. window.connect_delete_event(move |_, _| {
  63. gtk::main_quit();
  64. gtk::Inhibit(false)
  65. });
  66. window.set_title("I Am Legend");
  67. window.set_default_size(500, 100);
  68. window.set_resizable(false);
  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 container = gtk::Box::new(gtk::Orientation::Vertical, 2);
  77. let label = gtk::Label::new(None);
  78. {
  79. let color = gtk::Entry::new();
  80. let app = app.clone();
  81. let window = window.clone();
  82. let label = label.clone();
  83. color.connect_changed(move |s| {
  84. let str = s.get_text();
  85. if let Some(color) = dmc::LOOKUP.get(str.as_str()) {
  86. app.data.borrow_mut().dmc = Some(*color.clone());
  87. label.set_text(color.name);
  88. } else {
  89. app.data.borrow_mut().dmc = None;
  90. label.set_text("");
  91. }
  92. window.queue_draw_area(0, 0, 500, 100);
  93. });
  94. container.pack_start(&color, false, true, 0);
  95. }
  96. {
  97. let button = gtk::Button::with_label("EXPORT IT");
  98. let app = app.clone();
  99. button.connect_clicked(move |_| {
  100. if let Err(err) = app.data.borrow_mut().draw_to_file() {
  101. eprintln!("Error in rendering: {}", err);
  102. }
  103. });
  104. container.pack_start(&button, false, true, 0);
  105. }
  106. container.pack_start(&label, false, true, 0);
  107. flow.pack_start(&container, false, true, 0);
  108. {
  109. let canvas = gtk::DrawingArea::new();
  110. canvas.connect_draw(move |_cv, ctx| {
  111. if let Err(err) = app.data.borrow_mut().render(ctx) {
  112. eprintln!("Error in rendering: {}", err);
  113. }
  114. gtk::Inhibit(false)
  115. });
  116. flow.pack_start(&canvas, true, true, 0);
  117. }
  118. window.add(&flow);
  119. window.show_all();
  120. }
  121. fn mk_icon_choice(choice: char, cell: App) -> gtk::Button {
  122. let button = gtk::Button::with_label(&choice.to_string());
  123. button.connect_clicked(move |_| {
  124. cell.data.borrow_mut().symbol = choice;
  125. println!("Choosing '{}'", choice);
  126. });
  127. button
  128. }
  129. fn main() {
  130. if gtk::init().is_err() {
  131. eprintln!("Failed to initialize GTK application");
  132. } else {
  133. mk_app();
  134. gtk::main();
  135. }
  136. }