|
@@ -1,198 +1,13 @@
|
|
|
-use anyhow::{anyhow, bail, Result};
|
|
|
-use gtk::prelude::WidgetExtManual;
|
|
|
-use gtk::{
|
|
|
- BoxExt, ButtonExt, ContainerExt, DialogExt, EditableSignals, EntryExt, FileChooserExt,
|
|
|
- GtkWindowExt, LabelExt, WidgetExt,
|
|
|
-};
|
|
|
-use std::cell::RefCell;
|
|
|
-use std::rc::Rc;
|
|
|
-
|
|
|
+mod app;
|
|
|
mod dmc;
|
|
|
-
|
|
|
-struct AppData {
|
|
|
- symbol: char,
|
|
|
- dmc: Option<dmc::DMC>,
|
|
|
-}
|
|
|
-
|
|
|
-impl AppData {
|
|
|
- fn draw_to_file<P: AsRef<std::path::Path>>(&self, path: P) -> Result<()> {
|
|
|
- let f = std::fs::File::create(path)?;
|
|
|
- let surf = cairo::SvgSurface::for_stream(100.0, 100.0, f)?;
|
|
|
- self.render(&cairo::Context::new(&surf), 100.0, 100.0)?;
|
|
|
- if let Err(err) = surf.finish_output_stream() {
|
|
|
- bail!(err.error);
|
|
|
- };
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- fn render(&self, ctx: &cairo::Context, w: f64, h: f64) -> Result<()> {
|
|
|
- let off_x = (w - 100.) / 2.0;
|
|
|
- let off_y = (h - 100.) / 2.0;
|
|
|
-
|
|
|
- let color = self.color();
|
|
|
- ctx.set_source_rgb(color.0, color.1, color.2);
|
|
|
- ctx.paint();
|
|
|
-
|
|
|
- ctx.set_source_rgb(0., 0., 0.);
|
|
|
- ctx.rectangle(off_x, off_y, 100., 100.);
|
|
|
- ctx.stroke();
|
|
|
-
|
|
|
- ctx.move_to(off_x, off_y - 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(())
|
|
|
- }
|
|
|
-
|
|
|
- fn color(&self) -> (f64, f64, f64) {
|
|
|
- self.dmc
|
|
|
- .map(|dmc| dmc.color)
|
|
|
- .unwrap_or_else(|| (0.5, 0.5, 0.5))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Clone)]
|
|
|
-struct App {
|
|
|
- data: Rc<RefCell<AppData>>,
|
|
|
- window: gtk::Window,
|
|
|
-}
|
|
|
-
|
|
|
-impl App {
|
|
|
- fn new(window: gtk::Window) -> App {
|
|
|
- let app_data = AppData {
|
|
|
- symbol: 'X',
|
|
|
- dmc: None,
|
|
|
- };
|
|
|
- let data = Rc::new(RefCell::new(app_data));
|
|
|
- App { data, window }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-fn mk_app() {
|
|
|
- let window = gtk::Window::new(gtk::WindowType::Toplevel);
|
|
|
- let app = App::new(window.clone());
|
|
|
- window.connect_delete_event(move |_, _| {
|
|
|
- gtk::main_quit();
|
|
|
- gtk::Inhibit(false)
|
|
|
- });
|
|
|
-
|
|
|
- window.set_title("I Am Legend");
|
|
|
- window.set_default_size(500, 200);
|
|
|
- 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 container = gtk::Box::new(gtk::Orientation::Vertical, 2);
|
|
|
- let label = gtk::Label::new(None);
|
|
|
- let button = gtk::Button::with_label("EXPORT IT");
|
|
|
-
|
|
|
- {
|
|
|
- let color = gtk::Entry::new();
|
|
|
- let app = app.clone();
|
|
|
- let window = window.clone();
|
|
|
- let label = label.clone();
|
|
|
- let button = button.clone();
|
|
|
- color.connect_changed(move |s| {
|
|
|
- let str = s.get_text();
|
|
|
- if let Some(color) = dmc::LOOKUP.get(str.as_str()) {
|
|
|
- app.data.borrow_mut().dmc = Some(*color.clone());
|
|
|
- label.set_text(color.name);
|
|
|
- button.set_sensitive(true);
|
|
|
- } else {
|
|
|
- app.data.borrow_mut().dmc = None;
|
|
|
- label.set_text("");
|
|
|
- button.set_sensitive(false);
|
|
|
- }
|
|
|
- window.queue_draw_area(0, 0, 500, 200);
|
|
|
- });
|
|
|
- container.pack_start(&color, false, true, 0);
|
|
|
- }
|
|
|
-
|
|
|
- {
|
|
|
- button.set_sensitive(false);
|
|
|
- let app = app.clone();
|
|
|
- let window = window.clone();
|
|
|
- button.connect_clicked(move |_| {
|
|
|
- let dialog = gtk::FileChooserDialog::with_buttons(
|
|
|
- Some("Select filename"),
|
|
|
- Some(&window),
|
|
|
- gtk::FileChooserAction::Save,
|
|
|
- &[
|
|
|
- ("_Cancel", gtk::ResponseType::Cancel),
|
|
|
- ("_Open", gtk::ResponseType::Ok),
|
|
|
- ],
|
|
|
- );
|
|
|
- let filter = gtk::FileFilter::new();
|
|
|
- filter.add_mime_type("image/svg+xml");
|
|
|
- filter.add_pattern("*.svg");
|
|
|
- filter.set_name(Some("SVG image"));
|
|
|
- dialog.add_filter(&filter);
|
|
|
- if dialog.run() == gtk::ResponseType::Ok {
|
|
|
- if let Some(tgt) = dialog.get_filename() {
|
|
|
- let mut tgt = tgt.to_owned();
|
|
|
- if !tgt.ends_with(".svg") {
|
|
|
- tgt.set_extension("svg");
|
|
|
- }
|
|
|
- println!("saving to {:?}", tgt);
|
|
|
- if let Err(err) = app.data.borrow_mut().draw_to_file(tgt) {
|
|
|
- eprintln!("Error in rendering: {}", err);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- unsafe {
|
|
|
- dialog.destroy();
|
|
|
- }
|
|
|
- });
|
|
|
- container.pack_start(&button, false, true, 0);
|
|
|
- }
|
|
|
-
|
|
|
- container.pack_start(&label, false, true, 0);
|
|
|
- flow.pack_start(&container, false, true, 0);
|
|
|
-
|
|
|
- {
|
|
|
- let canvas = gtk::DrawingArea::new();
|
|
|
- canvas.connect_draw(move |cv, ctx| {
|
|
|
- let w = cv.get_allocated_width();
|
|
|
- let h = cv.get_allocated_height();
|
|
|
- if let Err(err) = app.data.borrow_mut().render(ctx, w as f64, h as f64) {
|
|
|
- eprintln!("Error in rendering: {}", err);
|
|
|
- }
|
|
|
- gtk::Inhibit(false)
|
|
|
- });
|
|
|
- flow.pack_start(&canvas, true, true, 0);
|
|
|
- }
|
|
|
-
|
|
|
- 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;
|
|
|
- cell.window.queue_draw_area(0, 0, 500, 200);
|
|
|
- });
|
|
|
- button
|
|
|
-}
|
|
|
+mod view;
|
|
|
|
|
|
fn main() {
|
|
|
if gtk::init().is_err() {
|
|
|
eprintln!("Failed to initialize GTK application");
|
|
|
} else {
|
|
|
- mk_app();
|
|
|
+ view::View::create().setup().show();
|
|
|
+ // view::mk_app();
|
|
|
gtk::main();
|
|
|
}
|
|
|
}
|