gdritter repos palladio / fc3e0a0
Added some file type malarkey Getty Ritter 6 years ago
5 changed file(s) with 154 addition(s) and 1 deletion(s). Collapse all Expand all
66 [dependencies]
77 gtk = { version = "0.2", features = ["v3_22"] }
88 rand = "0.4.2"
9 failure = "0.1.1"
10 serde = "1.0.43"
11 serde_json = "*"
12 serde_derive = "*"
13 zip = "0.3"
14 image = "*"
1 pub const PROGRAM_NAME: &'static str = "Palladio";
2 pub const PROGRAM_VERSION: &'static str = "0.0";
11 extern crate gtk;
22 extern crate rand;
3 extern crate failure;
4 extern crate image;
5 extern crate zip;
6 extern crate serde;
7 #[macro_use] extern crate serde_derive;
8 extern crate serde_json;
39
10 pub mod constants;
411 pub mod grammar;
512 pub mod model;
613 pub mod view;
1 use failure::Error;
2 use image;
3 use serde_json;
4 use std::io::{Read, Write, Seek};
5 use zip::{ZipArchive, ZipWriter};
6
17 pub struct State {
2 pub document: Option<Document>,
8 pub document: Document,
9 pub save_state: SaveState,
10 }
11
12 #[derive(Debug)]
13 pub enum SaveState {
14 Unsaved,
15 Modified,
16 Saved,
317 }
418
519 pub struct Document {
20 pub tilesheet: image::DynamicImage,
21 pub metadata: Metadata,
22 pub rules: (),
623 }
24
25 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
26 pub struct Metadata {
27 pub tile_width: u16,
28 pub tile_height: u16,
29 pub config_loop_forever: bool,
30 }
31
32 impl Document {
33 pub fn open_from_file<R: Read + Seek>(r: &mut R) -> Result<Document, Error> {
34 let mut archive = ZipArchive::new(r)?;
35 let tilesheet = {
36 let mut buf = Vec::new();
37 archive.by_name("tilesheet.png")?.read_to_end(&mut buf)?;
38 image::load_from_memory(&buf)?
39 };
40 let metadata = {
41 let file = archive.by_name("metadata.json")?;
42 serde_json::from_reader(file)?
43 };
44 let rules = {
45 let file = archive.by_name("rules.json")?;
46 serde_json::from_reader(file)?
47 };
48 Ok(Document{ tilesheet, metadata, rules })
49 }
50
51 pub fn save_to_file<W: Write + Seek>(&self, w: &mut W) -> Result<(), Error> {
52 use zip::write::FileOptions;
53
54 let mut zip = ZipWriter::new(w);
55 zip.start_file("tilesheet.png", FileOptions::default())?;
56 self.tilesheet.write_to(&mut zip, image::ImageOutputFormat::PNG)?;
57
58 zip.start_file("metadata.json", FileOptions::default())?;
59 serde_json::to_writer(&mut zip, &self.metadata)?;
60
61 zip.start_file("rules.json", FileOptions::default())?;
62 serde_json::to_writer(&mut zip, &self.rules)?;
63
64 zip.start_file("info.txt", FileOptions::default())?;
65 writeln!(
66 &mut zip,
67 "Created by {} v{}",
68 ::constants::PROGRAM_NAME,
69 ::constants::PROGRAM_VERSION,
70 )?;
71
72 zip.finish()?;
73 Ok(())
74 }
75
76 pub fn dummy() -> Document {
77 Document {
78 tilesheet: image::DynamicImage::new_rgb8(32, 32),
79 metadata: Metadata {
80 tile_width: 16,
81 tile_height: 16,
82 config_loop_forever: false,
83 },
84 rules: (),
85 }
86 }
87 }
88
89 #[cfg(test)]
90 mod tests {
91 use super::Document;
92 use std::io::{BufReader, Cursor};
93
94 #[test]
95 fn round_trip() {
96 let mut buf = Cursor::new(Vec::new());
97 let doc1 = Document::dummy();
98 doc1.save_to_file(&mut buf).unwrap();
99 let buf = buf.into_inner();
100 let doc2 = Document::open_from_file(&mut BufReader::new(Cursor::new(buf))).unwrap();
101 assert!(doc1.metadata == doc2.metadata);
102 }
103 }
44 HeaderBarExt,
55 WindowExt,
66 WidgetExt,
7 DialogExt,
8 FileChooserExt,
9 ButtonExt,
710 };
811 use std::process;
912
8790 container.pack_end(&save_btn);
8891 container.pack_end(&save_as_btn);
8992
93 open_btn.connect_clicked(Header::do_open);
94 open_btn.connect_clicked(Header::do_save);
95 open_btn.connect_clicked(Header::do_save);
96
9097 Header { container, open_btn, save_btn, save_as_btn }
9198 }
99
100 fn do_open(_: &gtk::Button) {
101 let open_dialog = gtk::FileChooserDialog::new(
102 Some("Open"),
103 Some(&gtk::Window::new(gtk::WindowType::Popup)),
104 gtk::FileChooserAction::Open,
105 );
106
107 open_dialog.add_button("Cancel", gtk::ResponseType::Cancel.into());
108 open_dialog.add_button("Open", gtk::ResponseType::Ok.into());
109
110 // if open_dialog.run() == gtk::ResponseType::Ok.into() {
111 // println!("got {:?}", open_dialog.get_filename());
112 // }
113
114 open_dialog.destroy();
115 }
116
117 fn do_save(_: &gtk::Button) {
118 let save_dialog = gtk::FileChooserDialog::new(
119 Some("Open"),
120 Some(&gtk::Window::new(gtk::WindowType::Popup)),
121 gtk::FileChooserAction::Open,
122 );
123
124 save_dialog.add_button("Cancel", gtk::ResponseType::Cancel.into());
125 save_dialog.add_button("Open", gtk::ResponseType::Ok.into());
126
127 // if save_dialog.run() == gtk::ResponseType::Ok.into() {
128 // println!("got {:?}", save_dialog.get_filename());
129 // }
130
131 save_dialog.destroy();
132 }
92133 }