238 lines
7.8 KiB
Rust
238 lines
7.8 KiB
Rust
use crate::utils::{self, Coord, ImageContainer, ImageProperties};
|
|
use fltk::{
|
|
app, button::Button, draw, enums::Event, frame::Frame, group::Flex, prelude::*, window::Window,
|
|
};
|
|
use image::GenericImageView;
|
|
use std::{
|
|
cell::RefCell,
|
|
rc::Rc,
|
|
sync::{Arc, RwLock},
|
|
};
|
|
|
|
static mut PATH: String = String::new();
|
|
|
|
/// Window to crop the existing image
|
|
pub(crate) struct CropWindow {
|
|
pub win: Window,
|
|
apply_btn: Button,
|
|
container: Rc<RefCell<Option<ImageContainer>>>,
|
|
page: Page,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub(crate) struct Page {
|
|
pub(crate) image_view: Frame,
|
|
pub(crate) row_flex: Flex,
|
|
pub(crate) col_flex: Flex,
|
|
}
|
|
|
|
impl CropWindow {
|
|
pub(crate) fn new() -> Self {
|
|
let mut win = Window::new(0, 0, 500, 600, "Crop").center_screen();
|
|
|
|
let mut main_flex = Flex::default().size_of_parent().column();
|
|
|
|
// Work area
|
|
let center_row_flex = Flex::default().row();
|
|
Frame::default();
|
|
|
|
let center_col_flex = Flex::default().column();
|
|
Frame::default();
|
|
let img_view = Frame::default();
|
|
Frame::default();
|
|
center_col_flex.end();
|
|
|
|
Frame::default();
|
|
center_row_flex.end();
|
|
|
|
// Panel
|
|
let top_padding_btn = Frame::default();
|
|
let mut panel_flex = Flex::default().row();
|
|
Frame::default();
|
|
let apply_btn = Button::default().with_label("apply");
|
|
Frame::default();
|
|
panel_flex.set_size(&apply_btn, 100);
|
|
panel_flex.end();
|
|
let bottom_padding_btn = Frame::default();
|
|
|
|
main_flex.set_size(&top_padding_btn, 5);
|
|
main_flex.set_size(&panel_flex, 30);
|
|
main_flex.set_size(&bottom_padding_btn, 5);
|
|
main_flex.end();
|
|
|
|
win.end();
|
|
win.make_modal(true);
|
|
win.make_resizable(true);
|
|
|
|
let mut crop_win = Self {
|
|
win,
|
|
apply_btn,
|
|
container: Rc::new(RefCell::new(None)),
|
|
page: Page {
|
|
image_view: img_view,
|
|
row_flex: center_row_flex,
|
|
col_flex: center_col_flex,
|
|
},
|
|
};
|
|
|
|
crop_win.draw();
|
|
crop_win.event();
|
|
crop_win
|
|
}
|
|
|
|
/// Call it to show window to crop image
|
|
pub(crate) fn load_to_crop(
|
|
&mut self,
|
|
path: &str,
|
|
crop_pos: Option<(f64, f64)>,
|
|
) -> Option<(f64, f64)> {
|
|
unsafe {
|
|
PATH = path.to_owned();
|
|
}
|
|
|
|
let mut container =
|
|
ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::new())));
|
|
{
|
|
let prop = &mut container.properties.write().unwrap();
|
|
prop.dimension = prop.original_dimension;
|
|
prop.crop_position = match crop_pos {
|
|
Some(a) => Some(a),
|
|
None => Some((0.0, 0.0)),
|
|
};
|
|
}
|
|
|
|
container.apply_scale();
|
|
let (image_width, image_height): (f64, f64) =
|
|
Coord::from(container.image.dimensions()).into();
|
|
self.win.set_size(image_width as i32, 600);
|
|
|
|
self.page
|
|
.row_flex
|
|
.set_size(&self.page.col_flex, image_width as i32);
|
|
self.page.row_flex.recalc();
|
|
|
|
self.page
|
|
.col_flex
|
|
.set_size(&self.page.image_view, image_height as i32);
|
|
self.page.col_flex.recalc();
|
|
|
|
*self.container.borrow_mut() = Some(container);
|
|
|
|
self.page.image_view.redraw();
|
|
self.win.show();
|
|
while self.win.shown() {
|
|
app::wait();
|
|
}
|
|
|
|
if let Some(cont) = &*self.container.borrow() {
|
|
cont.properties.read().unwrap().crop_position
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn draw(&mut self) {
|
|
let container = Rc::clone(&self.container);
|
|
self.page.image_view.draw(move |f| {
|
|
if let Some(cont) = &*container.borrow() {
|
|
let image = &cont.buffer;
|
|
|
|
draw::draw_image(
|
|
image.as_rgb8().unwrap().as_raw(),
|
|
f.x(),
|
|
f.y(),
|
|
image.width() as i32,
|
|
image.height() as i32,
|
|
fltk::enums::ColorDepth::Rgb8,
|
|
)
|
|
.unwrap();
|
|
|
|
let prop = cont.properties.read().unwrap();
|
|
let (original_width, original_height) = prop.original_dimension;
|
|
let (original_x, original_y) = prop.crop_position.unwrap();
|
|
let (resized_width, resized_height) = (image.width() as f64, image.height() as f64);
|
|
let (bound_width, bound_height) = utils::get_4_5(resized_width, resized_height);
|
|
|
|
let (bound_x, bound_y) = (
|
|
(original_x * resized_width as f64) / original_width,
|
|
(original_y * resized_height as f64) / original_height,
|
|
);
|
|
|
|
draw::set_color_rgb(255, 0, 0);
|
|
draw::draw_rect(
|
|
f.x() + bound_x as i32,
|
|
f.y() + bound_y as i32,
|
|
bound_width as i32,
|
|
bound_height as i32,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
fn event(&mut self) {
|
|
let mut last: Option<(f64, f64)> = None;
|
|
let container = Rc::clone(&self.container);
|
|
self.page.image_view.handle(move |f, ev| {
|
|
if let Some(cont) = &*container.borrow_mut() {
|
|
let image = &cont.buffer;
|
|
|
|
let mut prop = cont.properties.write().unwrap();
|
|
|
|
let (original_x, original_y) = prop.crop_position.unwrap();
|
|
let (original_width, original_heigth) = prop.original_dimension;
|
|
let (original_bound_width, original_bound_height) =
|
|
utils::get_4_5(original_width, original_heigth);
|
|
let point = original_width / image.width() as f64;
|
|
let (event_x, event_y) = (
|
|
(app::event_x() - f.x()) as f64 * point,
|
|
(app::event_y() - f.y()) as f64 * point,
|
|
);
|
|
if ev == Event::Push {
|
|
last = Some((event_x, event_y));
|
|
} else if ev == Event::Drag {
|
|
if let Some((lx, ly)) = last {
|
|
let dx = event_x - lx;
|
|
if (dx > 0.0 && original_x + original_bound_width < original_width)
|
|
|| (dx < 0.0 && original_x > 0.0)
|
|
{
|
|
let mut new_x = original_x + dx;
|
|
if new_x + original_bound_width > original_width {
|
|
new_x = original_width - original_bound_width;
|
|
} else if new_x < 0.0 {
|
|
new_x = 0.0;
|
|
}
|
|
|
|
prop.crop_position = prop.crop_position.map(|(_, y)| (new_x, y));
|
|
}
|
|
|
|
let dy = event_y - ly;
|
|
if (dy > 0.0 && original_y + original_bound_height < original_heigth)
|
|
|| (dy < 0.0 && original_y > 0.0)
|
|
{
|
|
let mut new_y = original_y + dy;
|
|
if new_y + original_bound_height > original_heigth {
|
|
new_y = original_heigth - original_bound_height;
|
|
} else if new_y < 0.0 {
|
|
new_y = 0.0;
|
|
}
|
|
|
|
prop.crop_position = prop.crop_position.map(|(x, _)| (x, new_y));
|
|
}
|
|
|
|
f.redraw();
|
|
last = Some((event_x, event_y));
|
|
}
|
|
} else if ev == Event::Released {
|
|
last = None;
|
|
}
|
|
}
|
|
true
|
|
});
|
|
|
|
let mut wind = self.win.clone();
|
|
self.apply_btn.set_callback(move |_| {
|
|
wind.do_callback();
|
|
});
|
|
}
|
|
}
|