feat: image copy and paste
This commit is contained in:
parent
1f909904c2
commit
cb5e1d837a
5 changed files with 155 additions and 2 deletions
78
Cargo.lock
generated
78
Cargo.lock
generated
|
|
@ -136,6 +136,27 @@ version = "1.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||
|
||||
[[package]]
|
||||
name = "arboard"
|
||||
version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
|
||||
dependencies = [
|
||||
"clipboard-win",
|
||||
"image",
|
||||
"log",
|
||||
"objc2 0.6.4",
|
||||
"objc2-app-kit 0.3.2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-foundation 0.3.2",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"windows-sys 0.59.0",
|
||||
"wl-clipboard-rs",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arg_enum_proc_macro"
|
||||
version = "0.3.4"
|
||||
|
|
@ -1226,6 +1247,12 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.9"
|
||||
|
|
@ -1900,6 +1927,7 @@ dependencies = [
|
|||
name = "imagey"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"dirs",
|
||||
"iced",
|
||||
"image",
|
||||
|
|
@ -3065,6 +3093,16 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.25.1"
|
||||
|
|
@ -3131,6 +3169,17 @@ version = "2.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.13"
|
||||
|
|
@ -4253,6 +4302,17 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree_magic_mini"
|
||||
version = "3.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"nom",
|
||||
"petgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.25.1"
|
||||
|
|
@ -5116,6 +5176,24 @@ version = "0.57.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||
|
||||
[[package]]
|
||||
name = "wl-clipboard-rs"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9651471a32e87d96ef3a127715382b2d11cc7c8bb9822ded8a7cc94072eb0a3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"os_pipe",
|
||||
"rustix 1.1.4",
|
||||
"thiserror 2.0.18",
|
||||
"tree_magic_mini",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wayland-protocols-wlr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-dl"
|
||||
version = "2.21.0"
|
||||
|
|
|
|||
|
|
@ -22,3 +22,7 @@ features = [ "avif-native" ]
|
|||
version = "0.12.6"
|
||||
# I really wish the image crate was named better
|
||||
features = [ "image" ]
|
||||
|
||||
[dependencies.arboard]
|
||||
version = "3.6.1"
|
||||
features = [ "wayland-data-control" ]
|
||||
|
|
|
|||
51
src/main.rs
51
src/main.rs
|
|
@ -6,6 +6,7 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use arboard::Clipboard;
|
||||
use iced::{
|
||||
Alignment, Color, Element, Length, Renderer, Subscription, Task, Theme, event,
|
||||
keyboard::{self, Key, key},
|
||||
|
|
@ -26,7 +27,7 @@ enum Message {
|
|||
Event(iced::Event),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Default)]
|
||||
struct State {
|
||||
image: Option<RgbaImage>,
|
||||
image_display: Option<widget::image::Allocation>,
|
||||
|
|
@ -35,6 +36,8 @@ struct State {
|
|||
error: Option<String>,
|
||||
info: Option<String>,
|
||||
infobar_shown: bool,
|
||||
|
||||
clipboard: Option<Clipboard>,
|
||||
}
|
||||
impl State {
|
||||
fn new() -> (Self, Task<Message>) {
|
||||
|
|
@ -166,6 +169,52 @@ impl State {
|
|||
|
||||
Key::Character("q") => return window::latest().and_then(window::close),
|
||||
|
||||
Key::Character("y") | Key::Character("c") => {
|
||||
if let Some(image) = self.image.as_ref() {
|
||||
match match self.clipboard.take() {
|
||||
Some(c) => Ok(c),
|
||||
None => Clipboard::new(),
|
||||
} {
|
||||
Ok(mut clipboard) => {
|
||||
self.error = clipboard
|
||||
.set_image(utils::arboard_from_rgbaimage(image))
|
||||
.map_err(|e| e.to_string())
|
||||
.err();
|
||||
self.clipboard = Some(clipboard);
|
||||
}
|
||||
Err(e) => self.error = Some(e.to_string()),
|
||||
}
|
||||
} else {
|
||||
self.error = Some("no image to yank".into());
|
||||
}
|
||||
}
|
||||
Key::Character("p") | Key::Character("v") => {
|
||||
match match self.clipboard.take() {
|
||||
Some(c) => Ok(c),
|
||||
None => Clipboard::new(),
|
||||
} {
|
||||
Ok(mut clipboard) => {
|
||||
match clipboard.get_image().map(utils::rgbaimage_from_arboard) {
|
||||
Ok(image) => {
|
||||
self.error = None;
|
||||
self.clipboard = Some(clipboard);
|
||||
|
||||
self.info =
|
||||
Some(format!("{}x{}", image.width(), image.height(),));
|
||||
if image.dimensions() < (100, 100) {
|
||||
self.image_filter = widget::image::FilterMethod::Nearest;
|
||||
}
|
||||
self.image = Some(image);
|
||||
return self.allocate_image();
|
||||
}
|
||||
Err(e) => self.error = Some(e.to_string()),
|
||||
};
|
||||
self.clipboard = Some(clipboard);
|
||||
}
|
||||
Err(e) => self.error = Some(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
// ignore unused keys
|
||||
_ => {}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,3 +5,6 @@
|
|||
'b' to toggle the bar
|
||||
's' to save the image
|
||||
'q' to quit
|
||||
|
||||
'y' or 'c' to yank
|
||||
'p' or 'v' to put
|
||||
|
|
|
|||
21
src/utils.rs
21
src/utils.rs
|
|
@ -1,4 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use iced::widget;
|
||||
use image::{DynamicImage, ImageDecoder, ImageReader, ImageResult, RgbaImage};
|
||||
|
|
@ -52,3 +55,19 @@ pub const fn string_from_filter_type(f: widget::image::FilterMethod) -> &'static
|
|||
widget::image::FilterMethod::Nearest => "nearest neighbor",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arboard_from_rgbaimage<'a>(image: &'a RgbaImage) -> arboard::ImageData<'a> {
|
||||
arboard::ImageData {
|
||||
width: image.width() as usize,
|
||||
height: image.height() as usize,
|
||||
bytes: Cow::Borrowed(image.as_ref()),
|
||||
}
|
||||
}
|
||||
pub fn rgbaimage_from_arboard(image: arboard::ImageData) -> RgbaImage {
|
||||
RgbaImage::from_raw(
|
||||
image.width as u32,
|
||||
image.height as u32,
|
||||
image.bytes.into_owned(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue