gdritter repos palladio / a6cf060
Some docstrings for Document types Getty Ritter 6 years ago
3 changed file(s) with 236 addition(s) and 221 deletion(s). Collapse all Expand all
66
77 /// This value represents both the current document in-memory as well
88 /// as the entirety of the values that we will want to both save and
9 /// restore
9 /// restore.
1010 pub struct Document {
1111 pub tilesheet: image::DynamicImage,
1212 pub metadata: Metadata,
1313 pub rules: (),
1414 }
1515
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)
1718 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1819 pub struct Metadata {
1920 pub tile_width: u16,
2223 }
2324
2425 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.
2529 pub fn open_from_file<R: Read + Seek>(r: &mut R) -> Result<Document, Error> {
2630 let mut archive = ZipArchive::new(r)?;
2731 let tilesheet = {
4044 Ok(Document{ tilesheet, metadata, rules })
4145 }
4246
47 /// Attempt to write a `Document` from anything which implements
48 /// `Write` and `Seek`. The file format for Palladio files is
49 /// documented externally.
4350 pub fn save_to_file<W: Write + Seek>(&self, w: &mut W) -> Result<(), Error> {
4451 use zip::write::FileOptions;
4552
6572 Ok(())
6673 }
6774
75 /// Create a new fresh document with an empty 32x32 image, a
76 /// configured tile size of 16x16, and no rules
6877 pub fn dummy() -> Document {
6978 Document {
7079 tilesheet: image::DynamicImage::new_rgb8(32, 32),
8594
8695 #[test]
8796 fn round_trip() {
97 // First, save our dummy `Document` to an in-memory buffer
8898 let mut buf = Cursor::new(Vec::new());
8999 let doc1 = Document::dummy();
90100 doc1.save_to_file(&mut buf).unwrap();
101
102 // then take that buffer back, and reparse it
91103 let buf = buf.into_inner();
92104 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
93107 assert!(doc1.metadata == doc2.metadata);
108 assert!(doc1.rules == doc2.rules);
94109 }
95110 }
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(_: &gtk::Button) {
152 let open_dialog = gtk::FileChooserDialog::new(
153 Some("Open"),
154 Some(&gtk::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(_: &gtk::Button) {
169 let save_dialog = gtk::FileChooserDialog::new(
170 Some("Open"),
171 Some(&gtk::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 }
+0
-219
src/view.rs less more
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(_: &gtk::Button) {
152 let open_dialog = gtk::FileChooserDialog::new(
153 Some("Open"),
154 Some(&gtk::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(_: &gtk::Button) {
169 let save_dialog = gtk::FileChooserDialog::new(
170 Some("Open"),
171 Some(&gtk::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 }