Some docstrings for Document types
Getty Ritter
7 years ago
| 6 | 6 | |
| 7 | 7 | /// This value represents both the current document in-memory as well |
| 8 | 8 | /// as the entirety of the values that we will want to both save and |
| 9 |
/// restore |
|
| 9 | /// restore. | |
| 10 | 10 | pub struct Document { |
| 11 | 11 | pub tilesheet: image::DynamicImage, |
| 12 | 12 | pub metadata: Metadata, |
| 13 | 13 | pub rules: (), |
| 14 | 14 | } |
| 15 | 15 | |
| 16 |
/// This should be renamed |
|
| 16 | /// This should be renamed probably, but it's the configuration-level | |
| 17 | /// info about a document (e.g. the tile size) | |
| 17 | 18 | #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] |
| 18 | 19 | pub struct Metadata { |
| 19 | 20 | pub tile_width: u16, |
| 22 | 23 | } |
| 23 | 24 | |
| 24 | 25 | impl Document { |
| 26 | /// Attempt to read a `Document` from anything which implements | |
| 27 | /// `Read` and `Seek`. The file format for Palladio files is | |
| 28 | /// documented externally. | |
| 25 | 29 | pub fn open_from_file<R: Read + Seek>(r: &mut R) -> Result<Document, Error> { |
| 26 | 30 | let mut archive = ZipArchive::new(r)?; |
| 27 | 31 | let tilesheet = { |
| 40 | 44 | Ok(Document{ tilesheet, metadata, rules }) |
| 41 | 45 | } |
| 42 | 46 | |
| 47 | /// Attempt to write a `Document` from anything which implements | |
| 48 | /// `Write` and `Seek`. The file format for Palladio files is | |
| 49 | /// documented externally. | |
| 43 | 50 | pub fn save_to_file<W: Write + Seek>(&self, w: &mut W) -> Result<(), Error> { |
| 44 | 51 | use zip::write::FileOptions; |
| 45 | 52 | |
| 65 | 72 | Ok(()) |
| 66 | 73 | } |
| 67 | 74 | |
| 75 | /// Create a new fresh document with an empty 32x32 image, a | |
| 76 | /// configured tile size of 16x16, and no rules | |
| 68 | 77 | pub fn dummy() -> Document { |
| 69 | 78 | Document { |
| 70 | 79 | tilesheet: image::DynamicImage::new_rgb8(32, 32), |
| 85 | 94 | |
| 86 | 95 | #[test] |
| 87 | 96 | fn round_trip() { |
| 97 | // First, save our dummy `Document` to an in-memory buffer | |
| 88 | 98 | let mut buf = Cursor::new(Vec::new()); |
| 89 | 99 | let doc1 = Document::dummy(); |
| 90 | 100 | doc1.save_to_file(&mut buf).unwrap(); |
| 101 | ||
| 102 | // then take that buffer back, and reparse it | |
| 91 | 103 | let buf = buf.into_inner(); |
| 92 | 104 | let doc2 = Document::open_from_file(&mut BufReader::new(Cursor::new(buf))).unwrap(); |
| 105 | // we can't assert equality over the image itself, so let's | |
| 106 | // just assert that the other parts are equal | |
| 93 | 107 | assert!(doc1.metadata == doc2.metadata); |
| 108 | assert!(doc1.rules == doc2.rules); | |
| 94 | 109 | } |
| 95 | 110 | } |
| 1 | use gdk; | |
| 2 | use gtk::{ | |
| 3 | self, | |
| 4 | BoxExt, | |
| 5 | EntryExt, | |
| 6 | ContainerExt, | |
| 7 | HeaderBarExt, | |
| 8 | PanedExt, | |
| 9 | WindowExt, | |
| 10 | WidgetExt, | |
| 11 | DialogExt, | |
| 12 | FileChooserExt, | |
| 13 | ButtonExt, | |
| 14 | }; | |
| 15 | use std::cell::RefCell; | |
| 16 | use std::process; | |
| 17 | use std::rc::Rc; | |
| 18 | ||
| 19 | pub struct GridCanvas { | |
| 20 | pub canvas: gtk::DrawingArea, | |
| 21 | pub mouse_loc: Rc<RefCell<Option<(i32, i32)>>>, | |
| 22 | } | |
| 23 | ||
| 24 | impl GridCanvas { | |
| 25 | fn new() -> GridCanvas { | |
| 26 | let canvas = gtk::DrawingArea::new(); | |
| 27 | let mouse_loc = Rc::new(RefCell::new(Some((2, 2)))); | |
| 28 | let reader_mouse = mouse_loc.clone(); | |
| 29 | let writer_mouse = mouse_loc.clone(); | |
| 30 | ||
| 31 | canvas.connect_draw(move |cv, ctx| { | |
| 32 | let w = cv.get_allocated_width(); | |
| 33 | let h = cv.get_allocated_height(); | |
| 34 | ctx.set_source_rgb(1.0, 1.0, 1.0); | |
| 35 | ctx.rectangle(0.0, 0.0, w as f64, h as f64); | |
| 36 | ctx.fill(); | |
| 37 | ||
| 38 | ctx.set_source_rgb(0.9, 0.9, 0.9); | |
| 39 | reader_mouse.borrow().map(|(x, y)| { | |
| 40 | ctx.rectangle(x as f64 * 32.0, y as f64 * 32.0, 32.0, 32.0); | |
| 41 | ctx.fill(); | |
| 42 | }); | |
| 43 | ||
| 44 | ctx.set_source_rgb(0.8, 0.8, 0.8); | |
| 45 | for x in 0..((w / 32) + 1) { | |
| 46 | ctx.move_to(x as f64 * 32.0, 0.0); | |
| 47 | ctx.line_to(x as f64 * 32.0, h as f64); | |
| 48 | ctx.stroke(); | |
| 49 | } | |
| 50 | for y in 0..((h / 32) + 1) { | |
| 51 | ctx.move_to(0.0, y as f64 * 32.0); | |
| 52 | ctx.line_to(w as f64, y as f64 * 32.0); | |
| 53 | ctx.stroke(); | |
| 54 | } | |
| 55 | gtk::Inhibit(false) | |
| 56 | }); | |
| 57 | ||
| 58 | canvas.connect_motion_notify_event(move |cv, motion| { | |
| 59 | let (x, y) = motion.get_position(); | |
| 60 | *writer_mouse.borrow_mut() = Some((x as i32 / 32, y as i32 / 32)); | |
| 61 | cv.queue_draw(); | |
| 62 | gtk::Inhibit(false) | |
| 63 | }); | |
| 64 | ||
| 65 | canvas.add_events(gdk::POINTER_MOTION_MASK.bits() as i32); | |
| 66 | ||
| 67 | GridCanvas { | |
| 68 | canvas, | |
| 69 | mouse_loc, | |
| 70 | } | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 74 | pub struct App { | |
| 75 | pub window: gtk::Window, | |
| 76 | pub canvas: GridCanvas, | |
| 77 | pub container: gtk::Paned, | |
| 78 | pub toolbar: Toolbar, | |
| 79 | pub header: Header, | |
| 80 | } | |
| 81 | ||
| 82 | impl App { | |
| 83 | fn new() -> App { | |
| 84 | let window = gtk::Window::new(gtk::WindowType::Toplevel); | |
| 85 | let container = gtk::Paned::new(gtk::Orientation::Horizontal); | |
| 86 | let header = Header::new(); | |
| 87 | let canvas = GridCanvas::new(); | |
| 88 | ||
| 89 | window.add_events(gdk::POINTER_MOTION_MASK.bits() as i32); | |
| 90 | window.set_titlebar(&header.container); | |
| 91 | window.set_title("Palladio"); | |
| 92 | window.set_wmclass("palladio", "Palladio"); | |
| 93 | ||
| 94 | gtk::Window::set_default_icon_name("iconname"); | |
| 95 | ||
| 96 | window.connect_delete_event(move |_, _| { | |
| 97 | gtk::main_quit(); | |
| 98 | gtk::Inhibit(false) | |
| 99 | }); | |
| 100 | ||
| 101 | let toolbar = Toolbar::new(); | |
| 102 | container.pack1(&canvas.canvas, true, true); | |
| 103 | container.pack2(&toolbar.toolbar, false, true); | |
| 104 | window.add(&container); | |
| 105 | ||
| 106 | App { window, header, canvas, toolbar, container } | |
| 107 | } | |
| 108 | ||
| 109 | pub fn run() { | |
| 110 | if gtk::init().is_err() { | |
| 111 | eprintln!("Failed to initialize GTK application"); | |
| 112 | process::exit(1); | |
| 113 | } | |
| 114 | ||
| 115 | let app = App::new(); | |
| 116 | app.window.show_all(); | |
| 117 | gtk::main(); | |
| 118 | } | |
| 119 | } | |
| 120 | ||
| 121 | // HEADER | |
| 122 | ||
| 123 | pub struct Header { | |
| 124 | pub container: gtk::HeaderBar, | |
| 125 | pub open_btn: gtk::Button, | |
| 126 | pub save_btn: gtk::Button, | |
| 127 | pub save_as_btn: gtk::Button, | |
| 128 | } | |
| 129 | ||
| 130 | impl Header { | |
| 131 | fn new() -> Header { | |
| 132 | let container = gtk::HeaderBar::new(); | |
| 133 | container.set_title("Palladio"); | |
| 134 | container.set_show_close_button(true); | |
| 135 | ||
| 136 | let open_btn = gtk::Button::new_with_label("Open"); | |
| 137 | let save_btn = gtk::Button::new_with_label("Save"); | |
| 138 | let save_as_btn = gtk::Button::new_with_label("Save As"); | |
| 139 | ||
| 140 | container.pack_start(&open_btn); | |
| 141 | container.pack_end(&save_btn); | |
| 142 | container.pack_end(&save_as_btn); | |
| 143 | ||
| 144 | open_btn.connect_clicked(Header::do_open); | |
| 145 | open_btn.connect_clicked(Header::do_save); | |
| 146 | open_btn.connect_clicked(Header::do_save); | |
| 147 | ||
| 148 | Header { container, open_btn, save_btn, save_as_btn } | |
| 149 | } | |
| 150 | ||
| 151 | fn do_open(_: >k::Button) { | |
| 152 | let open_dialog = gtk::FileChooserDialog::new( | |
| 153 | Some("Open"), | |
| 154 | Some(>k::Window::new(gtk::WindowType::Popup)), | |
| 155 | gtk::FileChooserAction::Open, | |
| 156 | ); | |
| 157 | ||
| 158 | open_dialog.add_button("Cancel", gtk::ResponseType::Cancel.into()); | |
| 159 | open_dialog.add_button("Open", gtk::ResponseType::Ok.into()); | |
| 160 | ||
| 161 | // if open_dialog.run() == gtk::ResponseType::Ok.into() { | |
| 162 | // println!("got {:?}", open_dialog.get_filename()); | |
| 163 | // } | |
| 164 | ||
| 165 | open_dialog.destroy(); | |
| 166 | } | |
| 167 | ||
| 168 | fn do_save(_: >k::Button) { | |
| 169 | let save_dialog = gtk::FileChooserDialog::new( | |
| 170 | Some("Open"), | |
| 171 | Some(>k::Window::new(gtk::WindowType::Popup)), | |
| 172 | gtk::FileChooserAction::Open, | |
| 173 | ); | |
| 174 | ||
| 175 | save_dialog.add_button("Cancel", gtk::ResponseType::Cancel.into()); | |
| 176 | save_dialog.add_button("Open", gtk::ResponseType::Ok.into()); | |
| 177 | ||
| 178 | // if save_dialog.run() == gtk::ResponseType::Ok.into() { | |
| 179 | // println!("got {:?}", save_dialog.get_filename()); | |
| 180 | // } | |
| 181 | ||
| 182 | save_dialog.destroy(); | |
| 183 | } | |
| 184 | } | |
| 185 | ||
| 186 | ||
| 187 | pub struct Toolbar { | |
| 188 | toolbar: gtk::Box, | |
| 189 | tile_width: gtk::Entry, | |
| 190 | tile_height: gtk::Entry, | |
| 191 | load_tileset_btn: gtk::Button, | |
| 192 | } | |
| 193 | ||
| 194 | impl Toolbar { | |
| 195 | fn new() -> Toolbar { | |
| 196 | let container = gtk::Box::new(gtk::Orientation::Vertical, 5); | |
| 197 | ||
| 198 | let tile_label = gtk::Label::new("Tileset"); | |
| 199 | ||
| 200 | let tile_width = gtk::Entry::new(); | |
| 201 | tile_width.set_text("16"); | |
| 202 | let tile_height = gtk::Entry::new(); | |
| 203 | tile_height.set_text("16"); | |
| 204 | ||
| 205 | let load_tileset_btn = gtk::Button::new_with_label("Load Tileset Image"); | |
| 206 | ||
| 207 | container.pack_start(&tile_label, false, true, 0); | |
| 208 | container.pack_start(&tile_width, false, true, 0); | |
| 209 | container.pack_start(&tile_height, false, true, 0); | |
| 210 | container.pack_start(&load_tileset_btn, false, true, 0); | |
| 211 | ||
| 212 | Toolbar { | |
| 213 | toolbar: container, | |
| 214 | tile_width, | |
| 215 | tile_height, | |
| 216 | load_tileset_btn, | |
| 217 | } | |
| 218 | } | |
| 219 | } |
| 1 | use gdk; | |
| 2 | use gtk::{ | |
| 3 | self, | |
| 4 | BoxExt, | |
| 5 | EntryExt, | |
| 6 | ContainerExt, | |
| 7 | HeaderBarExt, | |
| 8 | PanedExt, | |
| 9 | WindowExt, | |
| 10 | WidgetExt, | |
| 11 | DialogExt, | |
| 12 | FileChooserExt, | |
| 13 | ButtonExt, | |
| 14 | }; | |
| 15 | use std::cell::RefCell; | |
| 16 | use std::process; | |
| 17 | use std::rc::Rc; | |
| 18 | ||
| 19 | pub struct GridCanvas { | |
| 20 | pub canvas: gtk::DrawingArea, | |
| 21 | pub mouse_loc: Rc<RefCell<Option<(i32, i32)>>>, | |
| 22 | } | |
| 23 | ||
| 24 | impl GridCanvas { | |
| 25 | fn new() -> GridCanvas { | |
| 26 | let canvas = gtk::DrawingArea::new(); | |
| 27 | let mouse_loc = Rc::new(RefCell::new(Some((2, 2)))); | |
| 28 | let reader_mouse = mouse_loc.clone(); | |
| 29 | let writer_mouse = mouse_loc.clone(); | |
| 30 | ||
| 31 | canvas.connect_draw(move |cv, ctx| { | |
| 32 | let w = cv.get_allocated_width(); | |
| 33 | let h = cv.get_allocated_height(); | |
| 34 | ctx.set_source_rgb(1.0, 1.0, 1.0); | |
| 35 | ctx.rectangle(0.0, 0.0, w as f64, h as f64); | |
| 36 | ctx.fill(); | |
| 37 | ||
| 38 | ctx.set_source_rgb(0.9, 0.9, 0.9); | |
| 39 | reader_mouse.borrow().map(|(x, y)| { | |
| 40 | ctx.rectangle(x as f64 * 32.0, y as f64 * 32.0, 32.0, 32.0); | |
| 41 | ctx.fill(); | |
| 42 | }); | |
| 43 | ||
| 44 | ctx.set_source_rgb(0.8, 0.8, 0.8); | |
| 45 | for x in 0..((w / 32) + 1) { | |
| 46 | ctx.move_to(x as f64 * 32.0, 0.0); | |
| 47 | ctx.line_to(x as f64 * 32.0, h as f64); | |
| 48 | ctx.stroke(); | |
| 49 | } | |
| 50 | for y in 0..((h / 32) + 1) { | |
| 51 | ctx.move_to(0.0, y as f64 * 32.0); | |
| 52 | ctx.line_to(w as f64, y as f64 * 32.0); | |
| 53 | ctx.stroke(); | |
| 54 | } | |
| 55 | gtk::Inhibit(false) | |
| 56 | }); | |
| 57 | ||
| 58 | canvas.connect_motion_notify_event(move |cv, motion| { | |
| 59 | let (x, y) = motion.get_position(); | |
| 60 | *writer_mouse.borrow_mut() = Some((x as i32 / 32, y as i32 / 32)); | |
| 61 | cv.queue_draw(); | |
| 62 | gtk::Inhibit(false) | |
| 63 | }); | |
| 64 | ||
| 65 | canvas.add_events(gdk::POINTER_MOTION_MASK.bits() as i32); | |
| 66 | ||
| 67 | GridCanvas { | |
| 68 | canvas, | |
| 69 | mouse_loc, | |
| 70 | } | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 74 | pub struct App { | |
| 75 | pub window: gtk::Window, | |
| 76 | pub canvas: GridCanvas, | |
| 77 | pub container: gtk::Paned, | |
| 78 | pub toolbar: Toolbar, | |
| 79 | pub header: Header, | |
| 80 | } | |
| 81 | ||
| 82 | impl App { | |
| 83 | fn new() -> App { | |
| 84 | let window = gtk::Window::new(gtk::WindowType::Toplevel); | |
| 85 | let container = gtk::Paned::new(gtk::Orientation::Horizontal); | |
| 86 | let header = Header::new(); | |
| 87 | let canvas = GridCanvas::new(); | |
| 88 | ||
| 89 | window.add_events(gdk::POINTER_MOTION_MASK.bits() as i32); | |
| 90 | window.set_titlebar(&header.container); | |
| 91 | window.set_title("Palladio"); | |
| 92 | window.set_wmclass("palladio", "Palladio"); | |
| 93 | ||
| 94 | gtk::Window::set_default_icon_name("iconname"); | |
| 95 | ||
| 96 | window.connect_delete_event(move |_, _| { | |
| 97 | gtk::main_quit(); | |
| 98 | gtk::Inhibit(false) | |
| 99 | }); | |
| 100 | ||
| 101 | let toolbar = Toolbar::new(); | |
| 102 | container.pack1(&canvas.canvas, true, true); | |
| 103 | container.pack2(&toolbar.toolbar, false, true); | |
| 104 | window.add(&container); | |
| 105 | ||
| 106 | App { window, header, canvas, toolbar, container } | |
| 107 | } | |
| 108 | ||
| 109 | pub fn run() { | |
| 110 | if gtk::init().is_err() { | |
| 111 | eprintln!("Failed to initialize GTK application"); | |
| 112 | process::exit(1); | |
| 113 | } | |
| 114 | ||
| 115 | let app = App::new(); | |
| 116 | app.window.show_all(); | |
| 117 | gtk::main(); | |
| 118 | } | |
| 119 | } | |
| 120 | ||
| 121 | // HEADER | |
| 122 | ||
| 123 | pub struct Header { | |
| 124 | pub container: gtk::HeaderBar, | |
| 125 | pub open_btn: gtk::Button, | |
| 126 | pub save_btn: gtk::Button, | |
| 127 | pub save_as_btn: gtk::Button, | |
| 128 | } | |
| 129 | ||
| 130 | impl Header { | |
| 131 | fn new() -> Header { | |
| 132 | let container = gtk::HeaderBar::new(); | |
| 133 | container.set_title("Palladio"); | |
| 134 | container.set_show_close_button(true); | |
| 135 | ||
| 136 | let open_btn = gtk::Button::new_with_label("Open"); | |
| 137 | let save_btn = gtk::Button::new_with_label("Save"); | |
| 138 | let save_as_btn = gtk::Button::new_with_label("Save As"); | |
| 139 | ||
| 140 | container.pack_start(&open_btn); | |
| 141 | container.pack_end(&save_btn); | |
| 142 | container.pack_end(&save_as_btn); | |
| 143 | ||
| 144 | open_btn.connect_clicked(Header::do_open); | |
| 145 | open_btn.connect_clicked(Header::do_save); | |
| 146 | open_btn.connect_clicked(Header::do_save); | |
| 147 | ||
| 148 | Header { container, open_btn, save_btn, save_as_btn } | |
| 149 | } | |
| 150 | ||
| 151 | fn do_open(_: >k::Button) { | |
| 152 | let open_dialog = gtk::FileChooserDialog::new( | |
| 153 | Some("Open"), | |
| 154 | Some(>k::Window::new(gtk::WindowType::Popup)), | |
| 155 | gtk::FileChooserAction::Open, | |
| 156 | ); | |
| 157 | ||
| 158 | open_dialog.add_button("Cancel", gtk::ResponseType::Cancel.into()); | |
| 159 | open_dialog.add_button("Open", gtk::ResponseType::Ok.into()); | |
| 160 | ||
| 161 | // if open_dialog.run() == gtk::ResponseType::Ok.into() { | |
| 162 | // println!("got {:?}", open_dialog.get_filename()); | |
| 163 | // } | |
| 164 | ||
| 165 | open_dialog.destroy(); | |
| 166 | } | |
| 167 | ||
| 168 | fn do_save(_: >k::Button) { | |
| 169 | let save_dialog = gtk::FileChooserDialog::new( | |
| 170 | Some("Open"), | |
| 171 | Some(>k::Window::new(gtk::WindowType::Popup)), | |
| 172 | gtk::FileChooserAction::Open, | |
| 173 | ); | |
| 174 | ||
| 175 | save_dialog.add_button("Cancel", gtk::ResponseType::Cancel.into()); | |
| 176 | save_dialog.add_button("Open", gtk::ResponseType::Ok.into()); | |
| 177 | ||
| 178 | // if save_dialog.run() == gtk::ResponseType::Ok.into() { | |
| 179 | // println!("got {:?}", save_dialog.get_filename()); | |
| 180 | // } | |
| 181 | ||
| 182 | save_dialog.destroy(); | |
| 183 | } | |
| 184 | } | |
| 185 | ||
| 186 | ||
| 187 | pub struct Toolbar { | |
| 188 | toolbar: gtk::Box, | |
| 189 | tile_width: gtk::Entry, | |
| 190 | tile_height: gtk::Entry, | |
| 191 | load_tileset_btn: gtk::Button, | |
| 192 | } | |
| 193 | ||
| 194 | impl Toolbar { | |
| 195 | fn new() -> Toolbar { | |
| 196 | let container = gtk::Box::new(gtk::Orientation::Vertical, 5); | |
| 197 | ||
| 198 | let tile_label = gtk::Label::new("Tileset"); | |
| 199 | ||
| 200 | let tile_width = gtk::Entry::new(); | |
| 201 | tile_width.set_text("16"); | |
| 202 | let tile_height = gtk::Entry::new(); | |
| 203 | tile_height.set_text("16"); | |
| 204 | ||
| 205 | let load_tileset_btn = gtk::Button::new_with_label("Load Tileset Image"); | |
| 206 | ||
| 207 | container.pack_start(&tile_label, false, true, 0); | |
| 208 | container.pack_start(&tile_width, false, true, 0); | |
| 209 | container.pack_start(&tile_height, false, true, 0); | |
| 210 | container.pack_start(&load_tileset_btn, false, true, 0); | |
| 211 | ||
| 212 | Toolbar { | |
| 213 | toolbar: container, | |
| 214 | tile_width, | |
| 215 | tile_height, | |
| 216 | load_tileset_btn, | |
| 217 | } | |
| 218 | } | |
| 219 | } |