Skip to content

Commit 215a452

Browse files
committed
add: Now the pdfs are fit to image size, but still needs a custom size option, and the gui can convert and save the output pdf file.
1 parent 40efda9 commit 215a452

File tree

4 files changed

+146
-27
lines changed

4 files changed

+146
-27
lines changed

convert/src/lib.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ extern crate printpdf;
22
use printpdf::*;
33
use image_crate::codecs::{jpeg::JpegDecoder, png::PngDecoder};
44
use std::{path::Path, fs::File, io::BufWriter};
5+
//use std::cmp::max;
6+
7+
const PPI_BY_DPI: f64 = 0.084666667;
58

69
#[allow(dead_code)]
710
pub mod conf;
@@ -11,11 +14,23 @@ pub struct Convert {
1114
config: conf::Conf,
1215
}
1316

17+
// TODO: Convert page size by setting a pdf size
18+
//#[derive(Clone, Copy)]
19+
//enum PdfSizes {
20+
// A2,
21+
// A3,
22+
// A4,
23+
// A5,
24+
// ImgSize,
25+
//}
26+
1427
enum ImgExtension {
1528
Png,
1629
Jpg,
1730
}
1831

32+
33+
1934
impl Convert {
2035
pub fn new(config: conf::Conf) -> Self {
2136
Convert { config }
@@ -32,9 +47,30 @@ impl Convert {
3247
let img_extension = get_img_extension(p.to_string());
3348
match img_extension {
3449
Some(ft) => {
35-
let (page, layer) = doc.add_page(Mm(210.0), Mm(297.0), "Layer");
50+
let (img, px) = load_img(p.to_string(), ft);
51+
let mm = px2mm(px.0, px.1);
52+
let mut page_mm = (Mm(0.0), Mm(0.0));
53+
let s_ratio = 1.0;
54+
55+
// TODO: Create a flag option to pdf size and center image on page
56+
//s_ratio = max(1, max((210.0 / mm.0) as i32, (297.0 / mm.1) as i32)) as f64;
57+
58+
59+
60+
// set to img size
61+
page_mm.0 = Mm(mm.0);
62+
page_mm.1 = Mm(mm.1);
63+
64+
let (page, layer) = doc.add_page(page_mm.0 * s_ratio, page_mm.1 * s_ratio, "Layer");
3665
let current_layer = doc.get_page(page).get_layer(layer);
37-
load_and_write_img(p.to_string(), current_layer.clone(), ft)
66+
67+
let img_transform = ImageTransform {
68+
scale_x: Some(s_ratio),
69+
scale_y: Some(s_ratio),
70+
.. Default::default()
71+
};
72+
img.add_to_layer(current_layer.clone(), img_transform);
73+
3874
},
3975
None => {}
4076
}
@@ -68,19 +104,24 @@ fn get_img_extension(path: String) -> Option<ImgExtension> {
68104
}
69105
}
70106

71-
fn load_and_write_img(path: String, current_layer: PdfLayerReference, ft: ImgExtension) {
107+
fn px2mm(x: f64, y: f64) -> (f64, f64) {
108+
(x * PPI_BY_DPI, y * PPI_BY_DPI)
109+
}
110+
111+
fn load_img(path: String, ft: ImgExtension) -> (Image, (f64, f64)) {
72112
match ft {
73113
ImgExtension::Jpg => {
74114
let mut image_file = File::open(Path::new(&path)).unwrap();
75115
let img = Image::try_from(JpegDecoder::new(&mut image_file).unwrap()).unwrap();
76-
img.add_to_layer(current_layer.clone(), ImageTransform::default());
77-
116+
let px = (img.image.width.0 as f64, img.image.height.0 as f64);
117+
(img, px)
78118
},
79119
ImgExtension::Png => {
80120
let mut image_file = File::open(Path::new(&path)).unwrap();
81121
let mut img = Image::try_from(PngDecoder::new(&mut image_file).unwrap()).unwrap();
122+
let px = (img.image.width.0 as f64, img.image.height.0 as f64);
82123
img.image = remove_alpha_channel_from_image_x_object(img.image);
83-
img.add_to_layer(current_layer.clone(), ImageTransform::default());
124+
(img, px)
84125
},
85126
}
86127
}

gui/src/rpdfapp/components/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ impl InputButton {
9595
pub fn add_path(&mut self, path: String) {
9696
self.image_paths.push(path);
9797
}
98+
99+
pub fn clean_images(&mut self) -> bool {
100+
if self.image_paths.is_empty() {
101+
return false;
102+
}
103+
self.image_paths.clear();
104+
true
105+
}
106+
107+
pub fn send(&mut self) {
108+
self.btn.do_callback();
109+
}
98110
}
99111

100112
pub struct ButtonSection {
@@ -134,6 +146,10 @@ impl ButtonSection {
134146
pub fn create_input_button(&mut self, label: String, w: i32) -> InputButton {
135147
InputButton::new(&mut self.flex, label, w)
136148
}
149+
150+
pub fn flex(&mut self) -> &mut Flex {
151+
&mut self.flex
152+
}
137153
}
138154

139155
pub struct PreviewSection {
@@ -179,6 +195,7 @@ impl PreviewSection {
179195
pub fn add_image(&mut self, path: String, w: i32, h: i32, pad: i32, margin: i32) -> ImageItem {
180196
ImageItem::new(&mut self.flex, path, w, h, pad, margin)
181197
}
198+
182199
}
183200

184201
type ImageWrapp = Option<SharedImage>;

gui/src/rpdfapp/mod.rs

Lines changed: 80 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use convert::{Convert, conf::Conf};
12
use fltk::{
23
prelude::*,
34
frame::{self, Frame},
@@ -39,6 +40,12 @@ fn main_menu(sys_menu: &mut MyMenu, s: &Sender<Message>) {
3940
// );
4041
//}
4142

43+
pub fn center() -> (i32, i32) {
44+
(
45+
(app::screen_size().0 / 2.0) as i32,
46+
(app::screen_size().1 / 2.0) as i32,
47+
)
48+
}
4249

4350

4451
pub struct RpdfApp {
@@ -54,7 +61,7 @@ pub struct RpdfApp {
5461

5562
impl RpdfApp {
5663
pub fn new() -> Self {
57-
let app = app::App::default().with_scheme(Scheme::Base);
64+
let app = app::App::default().with_scheme(Scheme::Gtk);
5865
let (s, r) = app::channel::<Message>();
5966
let mut main_win = Window::default()
6067
.with_size(W_WIDTH, W_HEIGHT)
@@ -74,8 +81,9 @@ impl RpdfApp {
7481
let mut b_section = ButtonSection::new(&mut app_flex, 50, 10, 10);
7582
let mut input_button = b_section.create_input_button("@fileopen Open image".to_string(), 140);
7683
input_button.emit(s, Message::FileOperation(FileOperations::Upload));
77-
let mut convert_button = b_section.create_button("Convert images".to_string(), 140);
78-
convert_button.emit(s, Message::FileOperation(FileOperations::Convert));
84+
let mut convert_button = b_section.create_button("@filenew Convert and save images".to_string(), 200);
85+
convert_button.emit(s, Message::FileOperation(FileOperations::ConvertAndSave));
86+
convert_button.deactivate();
7987

8088
b_section.end();
8189

@@ -105,20 +113,63 @@ impl RpdfApp {
105113
}
106114
}
107115

108-
fn open_files_dialog(&mut self) {
116+
fn open_files_dialog(&mut self) -> Result<bool, String> {
109117
let mut dialog = NativeFileChooser::new(NativeFileChooserType::BrowseMultiFile);
110118
dialog.set_filter("*.{png,jpg}");
111119
dialog.show();
112-
for p in dialog.filenames().iter() {
113-
let path = p.to_string_lossy().to_string();
114-
if ! self.input_button.get_paths().contains(&path) {
120+
let file_names: Vec<String> = dialog.filenames().iter().map(|p| p.to_string_lossy().to_string()).collect();
121+
if file_names.is_empty() {
122+
dialog::message_title("Choose file");
123+
dialog::alert(center().0 - 200, center().1 - 100, "Please choose a file!");
124+
return Ok(false);
125+
}
126+
127+
for path in file_names.iter() {
128+
if ! self.input_button.get_paths().contains(&path.clone()) {
115129
self.input_button.add_path(path.clone());
116130
self.p_section.begin();
117-
self.p_section.add_image(path, IMAGE_WIDTH, IMAGE_HEIGTH, IMAGE_PAD, IMAGE_MARGIN);
131+
self.p_section.add_image(path.to_string(), IMAGE_WIDTH, IMAGE_HEIGTH, IMAGE_PAD, IMAGE_MARGIN);
118132
self.p_section.end();
119133
self.p_section.redraw();
120134
}
121135
}
136+
137+
Ok(true)
138+
}
139+
140+
fn convert_and_save(&mut self) -> Result<bool, String> {
141+
let mut dlg = dialog::FileDialog::new(dialog::FileDialogType::BrowseSaveFile);
142+
dlg.set_option(dialog::FileDialogOptions::SaveAsConfirm);
143+
dlg.show();
144+
let out = dlg.filename().to_string_lossy().to_string();
145+
if out.is_empty() {
146+
dialog::message_title("Choose save file");
147+
dialog::alert(center().0 - 200, center().1 - 100, "Please specify a file!");
148+
return Ok(false);
149+
}
150+
151+
self.p_section.flex().deactivate();
152+
self.b_section.flex().deactivate();
153+
let images = self.input_button.get_paths().clone();
154+
let config = Conf::from_images(images, out);
155+
let cvrt = Convert::new(config);
156+
self.clean_preview_section()?;
157+
cvrt.save_to_pdf()?;
158+
159+
self.p_section.flex().activate();
160+
self.b_section.flex().activate();
161+
self.b_section.flex().child(1).unwrap().deactivate();
162+
Ok(true)
163+
}
164+
165+
fn clean_preview_section(&mut self) -> Result<bool, String> {
166+
if ! self.input_button.clean_images() {
167+
dialog::alert(center().0 - 200, center().1 - 100, "No image in preview section!");
168+
return Ok(false);
169+
}
170+
self.p_section.flex().clear();
171+
172+
Ok(true)
122173
}
123174

124175
pub fn launch(&mut self) {
@@ -141,13 +192,12 @@ impl RpdfApp {
141192
},
142193
Message::FileOperation(fopt) => match fopt {
143194
FileOperations::Upload => {
144-
self.open_files_dialog();
195+
if self.open_files_dialog().unwrap() {
196+
self.b_section.flex().child(1).unwrap().activate();
197+
}
145198
},
146-
FileOperations::Convert => {
147-
todo!("pass image paths to convert lib then create a handler to save on output name")
148-
},
149-
FileOperations::Save => {
150-
todo!()
199+
FileOperations::ConvertAndSave => {
200+
self.convert_and_save();
151201
},
152202
},
153203
Message::PdfSize(ps) => match ps {
@@ -168,13 +218,26 @@ impl RpdfApp {
168218
}
169219
},
170220
Message::About => {
171-
todo!()
221+
dialog::message_title("About");
222+
dialog::message(center().0 - 200, center().1 - 100, "About dialog");
172223
},
173224
Message::Help => {
174-
todo!()
225+
dialog::message_title("Help");
226+
dialog::message(center().0 - 200, center().1 - 100, "About dialog");
175227
},
176228
Message::Quit => {
177-
self.app.quit();
229+
if self.input_button.get_paths().is_empty() {
230+
self.app.quit();
231+
} else {
232+
match dialog::choice2_default("Would you like to convert and save", "No", "Yes", "Cancel") {
233+
Some(1) => self.b_section.flex().child(1).unwrap().do_callback(),
234+
Some(0) => self.app.quit(),
235+
Some(2) => {},
236+
None => {},
237+
_ => {}
238+
}
239+
240+
}
178241
},
179242
Message::None => todo!()
180243
}

gui/src/utils.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ pub enum Message {
2121
#[derive(Clone, Copy)]
2222
pub enum FileOperations {
2323
Upload,
24-
Convert,
25-
Save,
24+
ConvertAndSave,
2625
}
2726

2827
impl FileOperations {
2928
pub fn get_variant(e_v: String) -> Message {
3029
match e_v.as_str() {
3130
"Upload" => Message::FileOperation(FileOperations::Upload),
32-
"Convert" => Message::FileOperation(FileOperations::Convert),
33-
"Save" => Message::FileOperation(FileOperations::Save),
31+
"Convert" => Message::FileOperation(FileOperations::ConvertAndSave),
3432
_ => Message::None,
3533
}
3634
}

0 commit comments

Comments
 (0)