Some docstrings for Document types
Getty Ritter
6 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 | } |