diff --git a/src/module/screen_shotter.rs b/src/module/screen_shotter.rs index 2145e1a..5a7d7a8 100644 --- a/src/module/screen_shotter.rs +++ b/src/module/screen_shotter.rs @@ -14,6 +14,12 @@ use pin_win::PinWin; use pin_win::PinWindow; use toolbar::Toolbar; +pub enum PinOperation { + Close(), + Hide(), + Save(), + Copy(), +} pub enum ShotterMessage { Move(u32), @@ -21,6 +27,7 @@ pub enum ShotterMessage { ShowToolbar(u32, i32, i32), MoveToolbar(u32, f32, f32), FinishToolbar(u32), + OperatePin(u32, PinOperation), } pub struct ScreenShotter { @@ -72,8 +79,6 @@ impl ScreenShotter{ } let mask_win = MaskWindow::new().unwrap(); // init MaskWindow - let toolbar = Toolbar::new(); - mask_win.window().set_position(slint::PhysicalPosition::new(0, 0) ); mask_win.set_state(0); @@ -82,6 +87,8 @@ impl ScreenShotter{ let pin_windows: Arc>>> = Arc::new(Mutex::new(HashMap::new())); let (message_sender, message_reciever) = mpsc::channel::(); + let toolbar = Toolbar::new(message_sender.clone()); + let primary_screen = primary_screen_op.unwrap(); let physical_width = primary_screen.display_info.width; let physical_height = primary_screen.display_info.height; @@ -225,6 +232,33 @@ impl ScreenShotter{ win.invoke_finish(id as i32); }).unwrap(); }, + ShotterMessage::OperatePin(id, operation) => { + let pin_windows = pin_windows_clone.lock().unwrap(); + if let Some(pin_win) = pin_windows.get(&id) { + match operation { + PinOperation::Close() => { + pin_win.upgrade_in_event_loop(move |win| { + win.invoke_close(); + }).unwrap(); + }, + PinOperation::Hide() => { + pin_win.upgrade_in_event_loop(move |win| { + win.invoke_hide(); + }).unwrap(); + }, + PinOperation::Save() => { + pin_win.upgrade_in_event_loop(move |win| { + win.invoke_save(); + }).unwrap(); + }, + PinOperation::Copy() => { + pin_win.upgrade_in_event_loop(move |win| { + win.invoke_copy(); + }).unwrap(); + }, + } + } + } } } } diff --git a/src/module/screen_shotter/pin_win.rs b/src/module/screen_shotter/pin_win.rs index 3c38307..52cc8ab 100644 --- a/src/module/screen_shotter/pin_win.rs +++ b/src/module/screen_shotter/pin_win.rs @@ -226,6 +226,8 @@ slint::slint! { in-out property is_stick_x: false; in-out property is_stick_y: false; in-out property is_shown_toolbar: false; + in-out property toolbar_center_x; + in-out property toolbar_center_y; callback win_move(length, length); callback key_release(KeyEvent); @@ -273,6 +275,8 @@ slint::slint! { root.can_move = true; } else if (event.button == PointerEventButton.right){ root.is_shown_toolbar = true; + root.toolbar_center_x = self.mouse-x; + root.toolbar_center_y = self.mouse-y; root.show_toolbar(self.mouse-x / 1px, self.mouse-y / 1px); } } else if (event.kind == PointerEventKind.up) { @@ -284,7 +288,7 @@ slint::slint! { } } else if (event.kind == PointerEventKind.move) { if (root.is_shown_toolbar) { - root.move_toolbar(self.mouse-x / 1px, self.mouse-y / 1px); + root.move_toolbar(((self.mouse-x) - root.toolbar_center_x) / 1px, ((self.mouse-y) - root.toolbar_center_y) / 1px); } } } diff --git a/src/module/screen_shotter/toolbar.rs b/src/module/screen_shotter/toolbar.rs index 65d86fc..a9e8939 100644 --- a/src/module/screen_shotter/toolbar.rs +++ b/src/module/screen_shotter/toolbar.rs @@ -1,18 +1,22 @@ +use std::sync::mpsc::Sender; + use i_slint_backend_winit::WinitWindowAccessor; +use super::{PinOperation, ShotterMessage}; + pub struct Toolbar { pub toolbar_window: ToolbarWindow, } impl Toolbar { - pub fn new() -> Toolbar { + pub fn new(message_sender: Sender) -> Toolbar { let toolbar_window = ToolbarWindow::new().unwrap(); let toolbar_window_clone = toolbar_window.as_weak(); toolbar_window.on_show_pos(move |id, x, y| { - println!("show_pos: x={}, y={}", x, y); let toolbar_window = toolbar_window_clone.unwrap(); + let height = toolbar_window.get_win_height() as f32; let width = toolbar_window.get_win_width() as f32; let scale = toolbar_window.window().scale_factor(); @@ -28,12 +32,34 @@ impl Toolbar { let toolbar_window_clone = toolbar_window.as_weak(); toolbar_window.on_move(move |id, x, y| { - // TODO - println!("move: x={}, y={}", x, y); + let toolbar_window = toolbar_window_clone.unwrap(); + let r = x * x + y * y; + let mut angle = y.atan2(x) * 180.0 / 3.14 + 135.0; + if angle < 0.0 { angle += 360.0; } + if r < (50 * 50) as f32 { + toolbar_window.set_active_num(-1); + } else { + let active_num = (angle / 90.0) as i32; + toolbar_window.set_active_num(active_num); + } }); let toolbar_window_clone = toolbar_window.as_weak(); + let message_sender_clone = message_sender.clone(); toolbar_window.on_finish(move |id| { + let toolbar_window = toolbar_window_clone.unwrap(); + let active_num = toolbar_window.get_active_num(); + + if active_num == 0 { + message_sender_clone.send(ShotterMessage::OperatePin(id as u32, PinOperation::Hide())).unwrap(); + } else if active_num == 1 { + message_sender_clone.send(ShotterMessage::OperatePin(id as u32, PinOperation::Copy())).unwrap(); + } else if active_num == 2 { + message_sender_clone.send(ShotterMessage::OperatePin(id as u32, PinOperation::Close())).unwrap(); + } else if active_num == 3 { + message_sender_clone.send(ShotterMessage::OperatePin(id as u32, PinOperation::Save())).unwrap(); + } + toolbar_window_clone.unwrap().hide().unwrap(); }); @@ -49,15 +75,85 @@ impl Toolbar { slint::slint! { import { Button, Palette} from "std-widgets.slint"; + + component Arc inherits Path { + in-out property active: false; + in-out property out_radius: 100; + in-out property inner_radius: 50; + in-out property out_start_x; + in-out property out_start_y; + in-out property out_end_x; + in-out property out_end_y; + in-out property inner_start_x; + in-out property inner_start_y; + in-out property inner_end_x; + in-out property inner_end_y; + + width: 100%; + height: 100%; + viewbox-width: self.width / 1px; + viewbox-height: self.height / 1px; + fill: active ? rgb(0, 175, 255).with-alpha(0.5) : transparent; + stroke: rgb(0, 175, 255); + stroke-width: 2px; + + MoveTo { x: inner_start_x; y: inner_start_y; } + LineTo { x: out_start_x; y: out_start_y; } + + ArcTo { + x: out_end_x; y: out_end_y; + radius-x: out_radius; radius-y: out_radius; sweep: true; + } + + LineTo { x: inner_end_x; y: inner_end_y; } + + ArcTo { + x: inner_start_x; y: inner_start_y; + radius-x: inner_radius; radius-y: inner_radius; + } + } + + component ArcBtn inherits Rectangle{ + in-out property icon; + in-out property out_radius: 100; + in-out property inner_radius: 50; + in-out property begin_angle; + in-out property end_angle; + in-out property active: false; + + Arc { + active: active; + out_radius: out_radius; + inner_radius: inner_radius; + out_start_x: 100 + sin(begin_angle * 1deg) * out_radius; + out_start_y: 100 - cos(begin_angle * 1deg) * out_radius; + out_end_x: 100 + sin(end_angle * 1deg) * out_radius; + out_end_y: 100 - cos(end_angle * 1deg) * out_radius; + inner_start_x: 100 + sin(begin_angle * 1deg) * inner_radius; + inner_start_y: 100 - cos(begin_angle * 1deg) * inner_radius; + inner_end_x: 100 + sin(end_angle * 1deg) * inner_radius; + inner_end_y: 100 - cos(end_angle * 1deg) * inner_radius; + } + + Image { + colorize: active ? rgb(0, 175, 255) : Palette.foreground; + source: icon; + height: root.height / 8; + width: root.width / 8; + x: 100px + sin((begin_angle + end_angle) / 2 * 1deg) * (out_radius + inner_radius) / 2 * 1px - self.width / 2; + y: 100px - cos((begin_angle + end_angle) / 2 * 1deg) * (out_radius + inner_radius) / 2 * 1px - self.height / 2; + } + } + export component ToolbarWindow inherits Window { background: transparent; no-frame: true; + title: "菜单栏"; always-on-top: true; in-out property win_height: 200; in-out property win_width: 200; - - // pure callback lose_focus_trick(bool) -> bool; + in-out property active_num: -1; width: win_width * 1px; height: win_height * 1px; @@ -70,22 +166,34 @@ slint::slint! { height: 100%; width: 100%; border-radius: self.height / 2; - background: Palette.background; - - TouchArea { - pointer-event(event) => { - debug(event); - if (event.button == PointerEventButton.right) { - debug(event); - } - } - - Button { - text: "Capture"; - clicked => { - debug("Capture button clicked"); - } - } + background: Palette.background.with-alpha(0.5); + + ArcBtn{ + icon: @image-url("./assets/icon/min.svg"); + begin_angle: -45; + end_angle: 45; + active: active_num == 0; + } + + ArcBtn{ + icon: @image-url("./assets/icon/right.svg"); + begin_angle: 45; + end_angle: 135; + active: active_num == 1; + } + + ArcBtn{ + icon: @image-url("./assets/icon/close.svg"); + begin_angle: 135; + end_angle: 225; + active: active_num == 2; + } + + ArcBtn{ + icon: @image-url("./assets/icon/save.svg"); + begin_angle: 225; + end_angle: 315; + active: active_num == 3; } } }