Backward compatibility
This commit is contained in:
parent
5e602d1540
commit
0f7d9f060e
|
|
@ -107,7 +107,7 @@ impl CropWindow {
|
|||
crop_pos: Option<(f64, f64)>,
|
||||
) -> Option<(f64, f64)> {
|
||||
let mut container =
|
||||
ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::new())));
|
||||
ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::default())));
|
||||
{
|
||||
let prop = &mut container.properties.write().unwrap();
|
||||
prop.dimension = prop.original_dimension;
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
//! Thread to manage drawing in background
|
||||
|
||||
use crate::{
|
||||
globals,
|
||||
main_window::{MainWindow, Page},
|
||||
utils, AppMessage,
|
||||
utils::{self, ImagePropertiesFile},
|
||||
AppMessage,
|
||||
};
|
||||
use fltk::{
|
||||
app,
|
||||
|
|
@ -119,7 +119,7 @@ pub(crate) fn spawn_image_thread(
|
|||
&mut count,
|
||||
&mut dimension,
|
||||
&app_sender,
|
||||
&properties,
|
||||
Arc::clone(&properties),
|
||||
&mut _container,
|
||||
);
|
||||
status.set_label("");
|
||||
|
|
@ -152,7 +152,7 @@ pub(crate) fn spawn_image_thread(
|
|||
&mut count,
|
||||
&mut dimension,
|
||||
&app_sender,
|
||||
&properties,
|
||||
Arc::clone(&properties),
|
||||
&mut _container,
|
||||
);
|
||||
status.set_label("");
|
||||
|
|
@ -242,7 +242,7 @@ fn load_image(
|
|||
count: &mut Frame,
|
||||
dimension: &mut Frame,
|
||||
app_sender: &app::Sender<crate::AppMessage>,
|
||||
properties: &Arc<RwLock<ImageProperties>>,
|
||||
properties: Arc<RwLock<ImageProperties>>,
|
||||
container: &mut Option<ImageContainer>,
|
||||
) {
|
||||
let imgs = images_path.read().unwrap();
|
||||
|
|
@ -254,136 +254,85 @@ fn load_image(
|
|||
count.set_label(&format!("[{}/{}]", file_choice.value() + 1, imgs.len()));
|
||||
let file = imgs.get(file_choice.value() as usize).unwrap();
|
||||
|
||||
*container = Some(ImageContainer::new(&file, Arc::clone(properties)));
|
||||
*container = Some(ImageContainer::new(&file, Arc::clone(&properties)));
|
||||
|
||||
if let Some(cont) = container {
|
||||
let file = Path::new(&file);
|
||||
let conf = file.with_extension("conf");
|
||||
|
||||
let properties = Arc::clone(&cont.properties);
|
||||
let mut use_defaults = true;
|
||||
if conf.exists() {
|
||||
let mut prop = properties.write().unwrap();
|
||||
match fs::read_to_string(&conf) {
|
||||
Ok(read) => {
|
||||
if let Ok(saved_prop) = serde_json::from_str::<ImageProperties>(&read) {
|
||||
utils::set_color_btn_rgba(saved_prop.rgba, layer_rgb);
|
||||
layer_alpha.set_value(saved_prop.rgba[3] as f64);
|
||||
quote.set_value(&saved_prop.quote);
|
||||
subquote.set_value(&saved_prop.subquote);
|
||||
subquote2.set_value(&saved_prop.subquote2);
|
||||
tag.set_value(&saved_prop.tag);
|
||||
tag2.set_value(&saved_prop.tag2);
|
||||
quote_position.set_range(0.0, prop.original_dimension.1);
|
||||
quote_position.set_value(saved_prop.quote_position);
|
||||
subquote_position.set_range(0.0, prop.original_dimension.1);
|
||||
subquote_position.set_value(saved_prop.subquote_position);
|
||||
subquote2_position.set_range(0.0, prop.original_dimension.1);
|
||||
subquote2_position.set_value(saved_prop.subquote2_position);
|
||||
tag_position.set_range(0.0, prop.original_dimension.1);
|
||||
tag_position.set_value(saved_prop.tag_position);
|
||||
tag2_position.set_range(0.0, prop.original_dimension.1);
|
||||
tag2_position.set_value(saved_prop.tag2_position);
|
||||
quote_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
subquote_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
subquote2_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
quote_position_slider.set_value(saved_prop.quote_position);
|
||||
subquote_position_slider.set_value(saved_prop.subquote_position);
|
||||
subquote2_position_slider.set_value(saved_prop.subquote2_position);
|
||||
tag_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
tag_position_slider.set_value(saved_prop.tag_position);
|
||||
tag2_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
tag2_position_slider.set_value(saved_prop.tag2_position);
|
||||
let read = fs::read_to_string(&conf).unwrap_or("{}".to_owned());
|
||||
let read = match serde_json::from_str::<ImagePropertiesFile>(&read) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
warn!("Config is corrupt\n{:?}", e);
|
||||
match dialog::choice_default("Config is corrupt, fix??", "yes", "no", "") {
|
||||
1 => {
|
||||
if let Err(e) = fs::remove_file(&conf) {
|
||||
dialog::alert_default("Failed to delete image properties file!");
|
||||
warn!("Failed to delete image properties file!\n{:?}", e);
|
||||
}
|
||||
ImagePropertiesFile::default()
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut properties = cont.properties.write().unwrap();
|
||||
properties.merge(read, &tag.value(), &tag2.value());
|
||||
properties.is_saved = true;
|
||||
|
||||
quote.set_value(&properties.quote);
|
||||
subquote.set_value(&properties.subquote);
|
||||
subquote2.set_value(&properties.subquote2);
|
||||
tag.set_value(&properties.tag);
|
||||
tag2.set_value(&properties.tag2);
|
||||
|
||||
quote_position.set_range(0.0, properties.original_dimension.1);
|
||||
quote_position.set_value(properties.quote_position);
|
||||
quote_position_slider.set_range(0.0, properties.original_dimension.1);
|
||||
quote_position_slider.set_value(properties.quote_position);
|
||||
|
||||
subquote_position.set_range(0.0, properties.original_dimension.1);
|
||||
subquote_position.set_value(properties.subquote_position);
|
||||
subquote_position_slider.set_range(0.0, properties.original_dimension.1);
|
||||
subquote_position_slider.set_value(properties.subquote_position);
|
||||
|
||||
subquote2_position.set_range(0.0, properties.original_dimension.1);
|
||||
subquote2_position.set_value(properties.subquote2_position);
|
||||
subquote2_position_slider.set_range(0.0, properties.original_dimension.1);
|
||||
subquote2_position_slider.set_value(properties.subquote2_position);
|
||||
|
||||
tag_position.set_range(0.0, properties.original_dimension.1);
|
||||
tag_position.set_value(properties.tag_position);
|
||||
tag_position_slider.set_range(0.0, properties.original_dimension.1);
|
||||
tag_position_slider.set_value(properties.tag_position);
|
||||
|
||||
tag2_position.set_range(0.0, properties.original_dimension.1);
|
||||
tag2_position.set_value(properties.tag2_position);
|
||||
tag2_position_slider.set_range(0.0, properties.original_dimension.1);
|
||||
tag2_position_slider.set_value(properties.tag2_position);
|
||||
|
||||
utils::set_color_btn_rgba(properties.color_layer, layer_rgb);
|
||||
layer_alpha.set_value(properties.color_layer[3] as f64);
|
||||
|
||||
dimension.set_label(&format!(
|
||||
"[{}x{}]",
|
||||
prop.original_dimension.0, prop.original_dimension.1
|
||||
properties.original_dimension.0, properties.original_dimension.1
|
||||
));
|
||||
|
||||
prop.quote = saved_prop.quote;
|
||||
prop.subquote = saved_prop.subquote;
|
||||
prop.subquote2 = saved_prop.subquote2;
|
||||
prop.tag = saved_prop.tag;
|
||||
prop.tag2 = saved_prop.tag2;
|
||||
prop.quote_position = saved_prop.quote_position;
|
||||
prop.subquote_position = saved_prop.subquote_position;
|
||||
prop.subquote2_position = saved_prop.subquote2_position;
|
||||
prop.tag_position = saved_prop.tag_position;
|
||||
prop.tag2_position = saved_prop.tag2_position;
|
||||
prop.rgba = saved_prop.rgba;
|
||||
prop.is_saved = true;
|
||||
use_defaults = false;
|
||||
drop(prop);
|
||||
|
||||
let crop_position = properties.crop_position;
|
||||
drop(properties);
|
||||
match crop {
|
||||
Some((x, y)) => cont.apply_crop_position(x, y),
|
||||
None => match saved_prop.crop_position {
|
||||
None => match crop_position {
|
||||
Some((x, y)) => cont.apply_crop_position(x, y),
|
||||
None => cont.apply_crop(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
dialog::alert_default("Failed to open config file!");
|
||||
warn!("Failed to open config file!\n{:?}", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if use_defaults {
|
||||
let mut prop = properties.write().unwrap();
|
||||
if crop.is_none() {
|
||||
quote.set_value("");
|
||||
prop.quote = "".to_owned();
|
||||
subquote.set_value("");
|
||||
prop.subquote = "".to_owned();
|
||||
subquote2.set_value("");
|
||||
prop.subquote2 = "".to_owned();
|
||||
}
|
||||
quote_position.set_range(0.0, prop.original_dimension.1);
|
||||
quote_position.set_value(prop.quote_position);
|
||||
subquote_position.set_range(0.0, prop.original_dimension.1);
|
||||
subquote_position.set_value(prop.subquote_position);
|
||||
subquote2_position.set_range(0.0, prop.original_dimension.1);
|
||||
subquote2_position.set_value(prop.subquote2_position);
|
||||
tag_position.set_range(0.0, prop.original_dimension.1);
|
||||
tag_position.set_value(prop.tag_position);
|
||||
tag2_position.set_range(0.0, prop.original_dimension.1);
|
||||
tag2_position.set_value(prop.tag2_position);
|
||||
quote_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
quote_position_slider.set_value(prop.quote_position);
|
||||
subquote_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
subquote_position_slider.set_value(prop.subquote_position);
|
||||
subquote2_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
subquote2_position_slider.set_value(prop.subquote2_position);
|
||||
tag_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
tag_position_slider.set_value(prop.tag_position);
|
||||
tag2_position_slider.set_range(0.0, prop.original_dimension.1);
|
||||
tag2_position_slider.set_value(prop.tag2_position);
|
||||
|
||||
let glob = &globals::CONFIG.read().unwrap();
|
||||
utils::set_color_btn_rgba(glob.color_layer, layer_rgb);
|
||||
layer_alpha.set_value(glob.color_layer[3] as f64);
|
||||
prop.rgba = glob.color_layer;
|
||||
drop(glob);
|
||||
|
||||
match crop {
|
||||
Some((x, y)) => {
|
||||
prop.is_saved = false;
|
||||
drop(prop);
|
||||
cont.apply_crop_position(x, y);
|
||||
}
|
||||
None => {
|
||||
prop.is_saved = true;
|
||||
drop(prop);
|
||||
cont.apply_crop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cont.apply_scale();
|
||||
let prop = properties.read().unwrap();
|
||||
let (width, height) = prop.dimension;
|
||||
let (width, height) = cont.properties.read().unwrap().dimension;
|
||||
page.col_flex.set_size(&page.image, height as i32);
|
||||
page.row_flex.set_size(&page.col_flex, width as i32);
|
||||
page.col_flex.recalc();
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ impl MainWindow {
|
|||
win.make_resizable(true);
|
||||
win.show();
|
||||
|
||||
let properties = Arc::new(RwLock::new(ImageProperties::new()));
|
||||
let properties = Arc::new(RwLock::new(ImageProperties::default()));
|
||||
let (rx, tx) = std::sync::mpsc::channel();
|
||||
let mut main_win = Self {
|
||||
win,
|
||||
|
|
@ -500,7 +500,7 @@ impl MainWindow {
|
|||
self.reset_darklayer_btn.set_callback(move |_| {
|
||||
let mut prop = properties.write().unwrap();
|
||||
let color = globals::CONFIG.read().unwrap().color_layer;
|
||||
prop.rgba = color;
|
||||
prop.color_layer = color;
|
||||
prop.is_saved = false;
|
||||
utils::set_color_btn_rgba(color, &mut layer_rgb);
|
||||
layer_alpha.set_value(color[3] as f64);
|
||||
|
|
@ -932,10 +932,14 @@ impl MainWindow {
|
|||
let (r, g, b) = dialog::color_chooser_with_default(
|
||||
"Pick a colour",
|
||||
dialog::ColorMode::Byte,
|
||||
(prop.rgba[0], prop.rgba[1], prop.rgba[2]),
|
||||
(
|
||||
prop.color_layer[0],
|
||||
prop.color_layer[1],
|
||||
prop.color_layer[2],
|
||||
),
|
||||
);
|
||||
prop.rgba = [r, g, b, prop.rgba[3]];
|
||||
utils::set_color_btn_rgba(prop.rgba, &mut f);
|
||||
prop.color_layer = [r, g, b, prop.color_layer[3]];
|
||||
utils::set_color_btn_rgba(prop.color_layer, &mut f);
|
||||
f.redraw();
|
||||
prop.is_saved = false;
|
||||
sender.send(DrawMessage::RedrawToBuffer).unwrap();
|
||||
|
|
@ -948,7 +952,7 @@ impl MainWindow {
|
|||
let sender = self.sender.clone();
|
||||
self.layer_alpha.set_callback(move |f| {
|
||||
let mut prop = properties.write().unwrap();
|
||||
prop.rgba[3] = f.value() as u8;
|
||||
prop.color_layer[3] = f.value() as u8;
|
||||
prop.is_saved = false;
|
||||
sender.send(DrawMessage::RedrawToBuffer).unwrap();
|
||||
sender.send(DrawMessage::Flush).unwrap();
|
||||
|
|
|
|||
115
src/utils.rs
115
src/utils.rs
|
|
@ -84,7 +84,6 @@ impl ImageContainer {
|
|||
|
||||
let img = DynamicImage::ImageRgb8(img.into_rgb8());
|
||||
let (width, height): (f64, f64) = Coord::from(img.dimensions()).into();
|
||||
let (width, height) = (width, height);
|
||||
|
||||
let config = globals::CONFIG.read().unwrap();
|
||||
let mut prop = properties.write().unwrap();
|
||||
|
|
@ -162,7 +161,7 @@ impl ImageContainer {
|
|||
|
||||
draw_layer_and_text(
|
||||
&mut tmp,
|
||||
&prop.rgba,
|
||||
&prop.color_layer,
|
||||
&prop.quote,
|
||||
&prop.subquote,
|
||||
&prop.subquote2,
|
||||
|
|
@ -198,7 +197,10 @@ impl ImageContainer {
|
|||
|
||||
let mut prop = prop.clone();
|
||||
prop.path = None;
|
||||
if let Err(e) = fs::write(&path_conf, serde_json::to_string(&prop).unwrap()) {
|
||||
if let Err(e) = fs::write(
|
||||
&path_conf,
|
||||
serde_json::to_string(&ImagePropertiesFile::from(&prop)).unwrap(),
|
||||
) {
|
||||
dialog::alert_default("Failed to save conf!");
|
||||
warn!("Failed to save conf!\n{:?}", e);
|
||||
}
|
||||
|
|
@ -216,7 +218,7 @@ impl ImageContainer {
|
|||
|
||||
draw_layer_and_text(
|
||||
&mut img,
|
||||
&prop.rgba,
|
||||
&prop.color_layer,
|
||||
&prop.quote,
|
||||
&prop.subquote,
|
||||
&prop.subquote2,
|
||||
|
|
@ -281,7 +283,7 @@ impl ImageContainer {
|
|||
Some(p) => Path::new(p),
|
||||
None => return,
|
||||
};
|
||||
let path_conf = path_original.with_extension("conf");
|
||||
let path_properties = path_original.with_extension("conf");
|
||||
let export = path_original.parent().unwrap().join("export").join(
|
||||
path_original
|
||||
.with_extension("png")
|
||||
|
|
@ -298,10 +300,10 @@ impl ImageContainer {
|
|||
}
|
||||
}
|
||||
|
||||
if path_conf.exists() {
|
||||
if let Err(e) = fs::remove_file(path_conf) {
|
||||
dialog::alert_default("Failed to delete image conf!");
|
||||
warn!("Failed to delete image conf!\n{:?}", e);
|
||||
if path_properties.exists() {
|
||||
if let Err(e) = fs::remove_file(path_properties) {
|
||||
dialog::alert_default("Failed to delete image properties file!");
|
||||
warn!("Failed to delete image properties file!\n{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +316,66 @@ impl ImageContainer {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub(crate) struct ImagePropertiesFile {
|
||||
// pub(crate) dimension: Option<(f64, f64)>,
|
||||
// pub(crate) original_dimension: Option<(f64, f64)>,
|
||||
pub(crate) crop_position: Option<(f64, f64)>,
|
||||
pub(crate) quote: Option<String>,
|
||||
pub(crate) subquote: Option<String>,
|
||||
pub(crate) subquote2: Option<String>,
|
||||
pub(crate) tag: Option<String>,
|
||||
pub(crate) tag2: Option<String>,
|
||||
pub(crate) quote_position: Option<f64>, // as per original
|
||||
pub(crate) subquote_position: Option<f64>, // as per original
|
||||
pub(crate) subquote2_position: Option<f64>, // as per original
|
||||
pub(crate) tag_position: Option<f64>, // as per original
|
||||
pub(crate) tag2_position: Option<f64>, // as per original
|
||||
pub(crate) color_layer: Option<[u8; 4]>,
|
||||
}
|
||||
|
||||
impl Default for ImagePropertiesFile {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
// dimension: None,
|
||||
// original_dimension: None,
|
||||
crop_position: None,
|
||||
quote: None,
|
||||
subquote: None,
|
||||
subquote2: None,
|
||||
tag: None,
|
||||
tag2: None,
|
||||
quote_position: None,
|
||||
subquote_position: None,
|
||||
subquote2_position: None,
|
||||
tag_position: None,
|
||||
tag2_position: None,
|
||||
color_layer: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ImageProperties> for ImagePropertiesFile {
|
||||
fn from(props: &ImageProperties) -> Self {
|
||||
Self {
|
||||
// dimension: Some(props.dimension),
|
||||
// original_dimension: Some(props.original_dimension),
|
||||
crop_position: props.crop_position,
|
||||
quote: Some(props.quote.clone()),
|
||||
subquote: Some(props.subquote.clone()),
|
||||
subquote2: Some(props.subquote2.clone()),
|
||||
tag: Some(props.tag.clone()),
|
||||
tag2: Some(props.tag2.clone()),
|
||||
quote_position: Some(props.quote_position),
|
||||
subquote_position: Some(props.subquote_position),
|
||||
subquote2_position: Some(props.subquote2_position),
|
||||
tag_position: Some(props.tag_position),
|
||||
tag2_position: Some(props.tag2_position),
|
||||
color_layer: Some(props.color_layer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub(crate) struct ImageProperties {
|
||||
pub(crate) path: Option<PathBuf>,
|
||||
|
|
@ -330,12 +392,12 @@ pub(crate) struct ImageProperties {
|
|||
pub(crate) subquote2_position: f64, // as per original
|
||||
pub(crate) tag_position: f64, // as per original
|
||||
pub(crate) tag2_position: f64, // as per original
|
||||
pub(crate) rgba: [u8; 4],
|
||||
pub(crate) color_layer: [u8; 4],
|
||||
pub(crate) is_saved: bool,
|
||||
}
|
||||
|
||||
impl ImageProperties {
|
||||
pub(crate) fn new() -> Self {
|
||||
impl Default for ImageProperties {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
path: None,
|
||||
dimension: (0.0, 0.0),
|
||||
|
|
@ -351,12 +413,39 @@ impl ImageProperties {
|
|||
subquote2_position: 0.0,
|
||||
tag_position: 0.0,
|
||||
tag2_position: 0.0,
|
||||
rgba: [0; 4],
|
||||
color_layer: [0; 4],
|
||||
is_saved: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageProperties {
|
||||
pub(crate) fn merge(
|
||||
&mut self,
|
||||
props: ImagePropertiesFile,
|
||||
tag_default: &str,
|
||||
tag2_default: &str,
|
||||
) {
|
||||
if let Some(v) = props.crop_position {
|
||||
self.crop_position = Some(v);
|
||||
}
|
||||
|
||||
self.quote = props.quote.unwrap_or("".to_owned());
|
||||
self.subquote = props.subquote.unwrap_or("".to_owned());
|
||||
self.subquote2 = props.subquote2.unwrap_or("".to_owned());
|
||||
self.tag = props.tag.unwrap_or(tag_default.to_owned());
|
||||
self.tag2 = props.tag2.unwrap_or(tag2_default.to_owned());
|
||||
self.quote_position = props.quote_position.unwrap_or(self.quote_position);
|
||||
self.subquote_position = props.subquote_position.unwrap_or(self.subquote_position);
|
||||
self.subquote2_position = props.subquote2_position.unwrap_or(self.subquote2_position);
|
||||
self.tag_position = props.tag_position.unwrap_or(self.tag_position);
|
||||
self.tag2_position = props.tag2_position.unwrap_or(self.tag2_position);
|
||||
self.color_layer = props
|
||||
.color_layer
|
||||
.unwrap_or(globals::CONFIG.read().unwrap().color_layer);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_layer_and_text(
|
||||
tmp: &mut DynamicImage,
|
||||
rgba: &[u8; 4],
|
||||
|
|
|
|||
Loading…
Reference in New Issue