From 33e7b23ab252ad01c2c54c8ca569c43064f2ab2f Mon Sep 17 00:00:00 2001 From: Jaby Date: Sat, 8 Mar 2025 17:04:26 +0100 Subject: [PATCH 1/5] Various improvements; Logic is now being reported about added and removed elements to be in sync with GUI --- src/Tools/tim_tool/src/gui/file_tab.rs | 2 +- src/Tools/tim_tool/src/gui/main_tab.rs | 72 +++++++++++++------ src/Tools/tim_tool/src/logic/mod.rs | 42 ++++++++--- .../tim_tool/src/logic/{tim.rs => tim/mod.rs} | 29 ++------ src/Tools/tim_tool/src/logic/tim/types.rs | 20 ++++++ src/Tools/tim_tool/src/main.rs | 23 +++--- 6 files changed, 127 insertions(+), 61 deletions(-) rename src/Tools/tim_tool/src/logic/{tim.rs => tim/mod.rs} (89%) create mode 100644 src/Tools/tim_tool/src/logic/tim/types.rs diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index d076e654..df361c1a 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -2,7 +2,7 @@ use crate::MainWindow; use super::{GUIElements, GUIElementsRef, MainWindowRef, display_error}; use slint::{Image, SharedString}; use std::rc::Rc; -use tim_tool::logic::tim::Encoding; +use tim_tool::logic::tim::types::Encoding; use tool_helper::Error; pub struct FileTab { diff --git a/src/Tools/tim_tool/src/gui/main_tab.rs b/src/Tools/tim_tool/src/gui/main_tab.rs index 4e2b5c32..ddc68fa6 100644 --- a/src/Tools/tim_tool/src/gui/main_tab.rs +++ b/src/Tools/tim_tool/src/gui/main_tab.rs @@ -2,12 +2,31 @@ use crate::{gui::{VRAM_HEIGHT, VRAM_WIDTH}, MainWindow, VRAMImage}; use super::{GUIElementsRef, MainWindowRef}; use slint::{Model, SharedString}; -use tim_tool::logic::tim::Encoding; -use std::{rc::Rc, sync::{Arc, Mutex}}; +use tim_tool::logic::tim::types::Encoding; +use std::{ops::RangeInclusive, rc::Rc, sync::{Arc, Mutex}}; struct VRAM { - pub file_list: Rc>, - pub image_list: Rc> + count: usize, + file_list: Rc>, + image_list: Rc> +} + +impl VRAM { + pub fn push(&mut self, name: slint::StandardListViewItem, image: VRAMImage) { + self.file_list.push(name); + self.image_list.push(image); + self.count += 1; + } + + pub fn remove(&mut self, idx: usize) { + self.count -= 1; + self.file_list.remove(idx); + self.image_list.remove(idx); + } + + pub fn pop(&mut self) { + self.remove(self.count - 1); + } } pub struct MainTab { @@ -24,12 +43,12 @@ impl MainTab { main_window.borrow().set_main_tab_vram_file_list(vram_file_list.clone().into()); main_window.borrow().set_main_tab_vram_images(vram_image_list.clone().into()); - MainTab{main_window, vram: Arc::new(Mutex::new(VRAM{file_list: vram_file_list, image_list: vram_image_list}))} + MainTab{main_window, vram: Arc::new(Mutex::new(VRAM{count: 0, file_list: vram_file_list, image_list: vram_image_list}))} } - pub fn add_new_vram_file(&mut self, file_name: &String, image: slint::Image, encoding: Encoding, image_palette: Option) { - let vram_data = self.vram.lock().expect("VRAM already locked"); - let add_new_image = |file_name: &String, image: slint::Image, encoding: Encoding, palette_count: i32, is_palette: bool| { + pub fn add_new_vram_file(&mut self, file_name: &String, image: slint::Image, encoding: Encoding, image_palette: Option) -> usize { + let mut vram_data = self.vram.lock().expect("VRAM already locked"); + let mut add_new_image = |file_name: &String, image: slint::Image, encoding: Encoding, palette_count: i32, is_palette: bool| { let encoding_str = if is_palette {""} else {encoding.to_str()}; let vram_image = VRAMImage{ img: image, @@ -40,28 +59,27 @@ impl MainTab { is_palette, }; - vram_data.file_list.push(slint::StandardListViewItem::from(file_name.as_str())); - vram_data.image_list.push(vram_image); + vram_data.push(slint::StandardListViewItem::from(file_name.as_str()), vram_image); }; + let mut images_added = 1; add_new_image(file_name, image, encoding, if image_palette.is_some() {1} else {0}, false); if let Some(image_palette) = image_palette { let file_name = " => ".to_owned() + file_name.as_str() + " (Palette)"; + + images_added += 1; add_new_image(&file_name, image_palette, encoding, 0, true); } + + images_added } - pub fn remove_vram_file(&mut self, idx: usize) -> bool { - let vram_data = self.vram.lock().expect("VRAM already locked"); - let remove_image = |idx: usize| { - vram_data.file_list.remove(idx); - vram_data.image_list.remove(idx); - }; - - let extras = { + pub fn remove_vram_file(&mut self, idx: usize) -> Result, &'static str> { + let mut vram_data = self.vram.lock().expect("VRAM already locked"); + let extras = { if let Some(element) = vram_data.image_list.iter().skip(idx).next() { if element.is_palette { - return false; + return Err("Can not remove palette. Delete image instead"); } else { @@ -74,10 +92,22 @@ impl MainTab { } }; - for _ in idx..=idx+extras { + let range = idx..=idx+extras; + let mut remove_image = |idx: usize| { + vram_data.remove(idx); + }; + + for _ in range.clone() { remove_image(idx); } - return true; + return Ok(range); + } + + pub fn pop_vram_files(&mut self, count: usize) { + let mut vram_data = self.vram.lock().expect("VRAM already locked"); + for _ in 0..count { + vram_data.pop(); + } } pub fn move_vram_image(&mut self, idx: usize, dx: i32, dy: i32) { diff --git a/src/Tools/tim_tool/src/logic/mod.rs b/src/Tools/tim_tool/src/logic/mod.rs index 71fbe9fc..9c7791cf 100644 --- a/src/Tools/tim_tool/src/logic/mod.rs +++ b/src/Tools/tim_tool/src/logic/mod.rs @@ -1,20 +1,27 @@ pub mod tim; - -use std::path::PathBuf; +use std::{ops::RangeInclusive, path::PathBuf}; use slint::Image; -use tim::{Encoding, TIMInfo}; +use tim::{types::Encoding, TIMInfo}; use tool_helper::Error; pub struct Logic { + added_tims: Vec>, unadded_tim: Option, } impl Logic { pub fn new() -> Logic { - Logic{unadded_tim: None} + Logic{added_tims: Default::default(), unadded_tim: None} } - pub fn set_unadded_tim(&mut self, path: &PathBuf) -> Result<(Image, Option), Error> { + pub fn remove_added_tim(&mut self, range: RangeInclusive) { + let idx = *range.start(); + for _ in range { + self.added_tims.remove(idx); + } + } + + pub fn load_unadded_tim(&mut self, path: &PathBuf) -> Result<(Image, Option), Error> { let tim_info = TIMInfo::from_image(path)?; let image = tim_info.get_slint_images(Encoding::FullColor); @@ -22,14 +29,33 @@ impl Logic { Ok(image) } - pub fn add_unadded_tim_as(&mut self, _name: &String, encoding: Encoding) -> Result<(Image, Option), Error> { + pub fn get_converted_unadded_tim_image(&self, encoding: Encoding) -> Result<(Image, Option), Error> { if let Some(unadded_tim) = &self.unadded_tim { let (image, palette) = unadded_tim.get_slint_images(encoding); - - self.unadded_tim = None; Ok((image, palette)) } + else { + Err(Error::from_str("No data found for loaded image")) + } + } + + pub fn add_unadded_tim(&mut self, images_added: usize) -> Result<(), Error> { + if let Some(_) = &self.unadded_tim { + if images_added >= 1 { + self.added_tims.push(std::mem::replace(&mut self.unadded_tim, None)); + + for _ in 0..(images_added - 1) { + self.added_tims.push(None); + } + Ok(()) + } + + else { + Err(Error::from_str("Can not add 0 images")) + } + } + else { Err(Error::from_str("No data found for loaded image")) } diff --git a/src/Tools/tim_tool/src/logic/tim.rs b/src/Tools/tim_tool/src/logic/tim/mod.rs similarity index 89% rename from src/Tools/tim_tool/src/logic/tim.rs rename to src/Tools/tim_tool/src/logic/tim/mod.rs index 6f176afc..ab0f8c5b 100644 --- a/src/Tools/tim_tool/src/logic/tim.rs +++ b/src/Tools/tim_tool/src/logic/tim/mod.rs @@ -1,29 +1,12 @@ +pub mod types; + use std::{fs::File, path::PathBuf}; use slint::{Rgba8Pixel, SharedPixelBuffer}; use tool_helper::Error; - -#[derive(Clone, Copy)] -pub enum Encoding { - FourBit, - EightBit, - FullColor, -} - -impl Encoding { - const FOUR_BIT_NAME:&str = "4 bit"; - const EIGHT_BIT_NAME:&str = "8 bit"; - const FULL_COLOR_NAME:&str = "Full color"; - - pub const fn to_str(&self) -> &str { - match self { - Encoding::FourBit => Self::FOUR_BIT_NAME, - Encoding::EightBit => Self::EIGHT_BIT_NAME, - Encoding::FullColor => Self::FULL_COLOR_NAME, - } - } -} +use types::Encoding; pub struct TIMInfo { + _path: PathBuf, image_data: SharedPixelBuffer, palette: Option, } @@ -69,7 +52,7 @@ impl TIMInfo { _ => {return Err(Error::from_str("Only 4 and 8bit color depth are supported for indexed color images"));} } } - Ok(TIMInfo{image_data, palette: Some(PaletteInfo::new(palette_colors))}) + Ok(TIMInfo{_path: path.clone(), image_data, palette: Some(PaletteInfo::new(palette_colors))}) } else { @@ -87,7 +70,7 @@ impl TIMInfo { _ => {return Err(Error::from_str("Only 8bit color depth are supported for direct color images"));} } } - Ok(TIMInfo{image_data, palette: None}) + Ok(TIMInfo{_path: path.clone(), image_data, palette: None}) } } diff --git a/src/Tools/tim_tool/src/logic/tim/types.rs b/src/Tools/tim_tool/src/logic/tim/types.rs new file mode 100644 index 00000000..01ef2f10 --- /dev/null +++ b/src/Tools/tim_tool/src/logic/tim/types.rs @@ -0,0 +1,20 @@ +#[derive(Clone, Copy)] +pub enum Encoding { + FourBit, + EightBit, + FullColor, +} + +impl Encoding { + const FOUR_BIT_NAME:&str = "4 bit"; + const EIGHT_BIT_NAME:&str = "8 bit"; + const FULL_COLOR_NAME:&str = "Full color"; + + pub const fn to_str(&self) -> &str { + match self { + Encoding::FourBit => Self::FOUR_BIT_NAME, + Encoding::EightBit => Self::EIGHT_BIT_NAME, + Encoding::FullColor => Self::FULL_COLOR_NAME, + } + } +} \ No newline at end of file diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index 496e4767..ffae5ca9 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -17,24 +17,26 @@ fn main() -> Result<(), slint::PlatformError> { let main_window_ref = Rc::new(RefCell::new(MainWindow::new()?)); let gui_elements_ref = Rc::new(RefCell::new(GUIElements::new(main_window_ref.clone())?)); - setup_main_tab(gui_elements_ref.clone()); - setup_file_tab(gui_elements_ref.clone(), logic_ref); + setup_main_tab(gui_elements_ref.clone(), logic_ref.clone()); + setup_file_tab(gui_elements_ref.clone(), logic_ref.clone()); let main_window = main_window_ref.borrow(); main_window.run() } -fn setup_main_tab(gui_elements_ref: Rc>) { +fn setup_main_tab(gui_elements_ref: Rc>, logic_ref: Rc>) { let gui_elements = gui_elements_ref.borrow(); gui_elements.main_tab.on_move_vram_image(gui_elements_ref.clone(), move |main_tab, _main_window, idx, dx, dy| { main_tab.move_vram_image(idx as usize, dx, dy); }); + let logic = logic_ref.clone(); gui_elements.main_tab.on_remove_file(gui_elements_ref.clone(), move |main_tab, _main_window, idx| { if idx >= 0 { - if !main_tab.remove_vram_file(idx as usize) { - display_information("Removing VRAM file", "Can not remove palette. Delete image instead"); + match main_tab.remove_vram_file(idx as usize) { + Ok(range) => logic.borrow_mut().remove_added_tim(range), + Err(error) => display_information("Removing VRAM file", error) } } }); @@ -66,7 +68,7 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc VRAM_WIDTH as u32 || img_size.height > VRAM_HEIGHT as u32 { @@ -85,9 +87,14 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc Date: Sat, 8 Mar 2025 17:11:00 +0100 Subject: [PATCH 2/5] Display full image in main window preview --- src/Tools/tim_tool/src/gui/main_tab.rs | 9 +++++---- src/Tools/tim_tool/src/main.rs | 5 +++-- src/Tools/tim_tool/ui/tab/main-tab.slint | 5 +++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Tools/tim_tool/src/gui/main_tab.rs b/src/Tools/tim_tool/src/gui/main_tab.rs index ddc68fa6..4bb58145 100644 --- a/src/Tools/tim_tool/src/gui/main_tab.rs +++ b/src/Tools/tim_tool/src/gui/main_tab.rs @@ -46,11 +46,12 @@ impl MainTab { MainTab{main_window, vram: Arc::new(Mutex::new(VRAM{count: 0, file_list: vram_file_list, image_list: vram_image_list}))} } - pub fn add_new_vram_file(&mut self, file_name: &String, image: slint::Image, encoding: Encoding, image_palette: Option) -> usize { + pub fn add_new_vram_file(&mut self, file_name: &String, full_image: slint::Image, image: slint::Image, encoding: Encoding, image_palette: Option) -> usize { let mut vram_data = self.vram.lock().expect("VRAM already locked"); - let mut add_new_image = |file_name: &String, image: slint::Image, encoding: Encoding, palette_count: i32, is_palette: bool| { + let mut add_new_image = |file_name: &String, full_image: slint::Image, image: slint::Image, encoding: Encoding, palette_count: i32, is_palette: bool| { let encoding_str = if is_palette {""} else {encoding.to_str()}; let vram_image = VRAMImage{ + full_img: full_image, img: image, x: 0, y: 0, @@ -63,12 +64,12 @@ impl MainTab { }; let mut images_added = 1; - add_new_image(file_name, image, encoding, if image_palette.is_some() {1} else {0}, false); + add_new_image(file_name, full_image, image, encoding, if image_palette.is_some() {1} else {0}, false); if let Some(image_palette) = image_palette { let file_name = " => ".to_owned() + file_name.as_str() + " (Palette)"; images_added += 1; - add_new_image(&file_name, image_palette, encoding, 0, true); + add_new_image(&file_name, image_palette.clone(), image_palette, encoding, 0, true); } images_added diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index ffae5ca9..e5e672a7 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -6,7 +6,7 @@ use gui::{GUIElements, VRAM_WIDTH, VRAM_HEIGHT, display_information}; use rfd::FileDialog; use std::{cell::RefCell, rc::Rc}; use slint::SharedString; -use tim_tool::logic::Logic; +use tim_tool::logic::{tim::types::Encoding, Logic}; use tool_helper::Error; slint::include_modules!(); @@ -88,8 +88,9 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc { cur_sel_x.text = root.vram_images[current-item].x; cur_sel_y.text = root.vram_images[current-item].y; - cur_sel_img.source = root.vram_images[current-item].img; + cur_sel_img.source = root.vram_images[current-item].full_img; encoding_text.encoding_str = root.vram_images[current-item].encoding_str; cur_sel_img.visible = true; } From a0368c1e517b0348cef00075e8d8fdddb510038e Mon Sep 17 00:00:00 2001 From: Jaby Date: Tue, 11 Mar 2025 20:35:11 +0100 Subject: [PATCH 3/5] Improve scrolling slightly --- src/Tools/tim_tool/ui/tab/main-tab.slint | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tools/tim_tool/ui/tab/main-tab.slint b/src/Tools/tim_tool/ui/tab/main-tab.slint index e28282cc..fdd28332 100644 --- a/src/Tools/tim_tool/ui/tab/main-tab.slint +++ b/src/Tools/tim_tool/ui/tab/main-tab.slint @@ -112,11 +112,11 @@ export component MainTab inherits Rectangle { function update_viewport() { if abs(self.viewport-x) + self.width > self.viewport-width { - self.viewport-x = 0; + self.viewport-x += (self.width + abs(self.viewport-x)) - self.viewport-width; } if abs(self.viewport-y) + self.height > self.viewport-height { - self.viewport-y = 0; + self.viewport-y += (self.height + abs(self.viewport-y)) - self.viewport-height; } } } From 2317bd9b29cd0502829cc08f96c46df258bd096e Mon Sep 17 00:00:00 2001 From: Jaby Date: Tue, 11 Mar 2025 20:46:37 +0100 Subject: [PATCH 4/5] Set program version depending on own version --- src/Tools/tim_tool/src/main.rs | 8 ++++++++ src/Tools/tim_tool/ui/app-window.slint | 6 +++++- src/Tools/tim_tool/ui/tab/about-tab.slint | 7 ++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index e5e672a7..44cf7809 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -19,6 +19,7 @@ fn main() -> Result<(), slint::PlatformError> { setup_main_tab(gui_elements_ref.clone(), logic_ref.clone()); setup_file_tab(gui_elements_ref.clone(), logic_ref.clone()); + setup_about_tab(main_window_ref.clone()); let main_window = main_window_ref.borrow(); main_window.run() @@ -100,4 +101,11 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc>) { + const VERSION: &str = env!("CARGO_PKG_VERSION"); + + let main_window = main_window_ref.borrow(); + main_window.invoke_set_version(SharedString::from(VERSION)); } \ No newline at end of file diff --git a/src/Tools/tim_tool/ui/app-window.slint b/src/Tools/tim_tool/ui/app-window.slint index e933f4dd..6d58590e 100644 --- a/src/Tools/tim_tool/ui/app-window.slint +++ b/src/Tools/tim_tool/ui/app-window.slint @@ -57,10 +57,14 @@ export component MainWindow inherits Window { } Tab { title: "About"; - AboutTab {} + about_tab := AboutTab {} } } + public function set_version(version: string) { + about_tab.version = version; + } + public function change_to_load_file() { file_tab.state = State.ConvertImage; tab_widget.current-index = 0; diff --git a/src/Tools/tim_tool/ui/tab/about-tab.slint b/src/Tools/tim_tool/ui/tab/about-tab.slint index 6f470cf6..54e0770f 100644 --- a/src/Tools/tim_tool/ui/tab/about-tab.slint +++ b/src/Tools/tim_tool/ui/tab/about-tab.slint @@ -1,14 +1,19 @@ import { AboutSlint } from "std-widgets.slint"; export component AboutTab { + in property version; y: 0px; VerticalLayout { padding: 8px; alignment: start; Text { font-size: 24pt; - text: "TIM_Tool Version 0.1.0"; + text: "TIM_Tool Version " + root.version; horizontal-alignment: center; } + Image { + source: @image-url("../assets/TimTool64x64.png"); + image-rendering: pixelated; + } Text { font-size: 20pt; text: "Part of JabyEngine"; From c5386eccd5496dc81329f052230f9d0434a536f0 Mon Sep 17 00:00:00 2001 From: Jaby Date: Tue, 11 Mar 2025 20:49:37 +0100 Subject: [PATCH 5/5] Proper handling of non existing project page --- src/Tools/tim_tool/ui/tab/file-tab.slint | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Tools/tim_tool/ui/tab/file-tab.slint b/src/Tools/tim_tool/ui/tab/file-tab.slint index a9a9e078..bb0a78ba 100644 --- a/src/Tools/tim_tool/ui/tab/file-tab.slint +++ b/src/Tools/tim_tool/ui/tab/file-tab.slint @@ -7,7 +7,10 @@ export enum State { component ProjectWidget inherits Rectangle { Text { - text: "!!Planschbecken!!"; + text: "Projects not supported yet"; + color: #FF0000; + font-size: 30pt; + font-weight: 800; } }