mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-12-23 11:25:54 +00:00
feat: add popup bind anchored
This commit is contained in:
parent
7f99f13c09
commit
64a18153b6
6 changed files with 159 additions and 7 deletions
|
|
@ -13,6 +13,7 @@ pub use builder::LayerShika;
|
||||||
pub use layer_shika_adapters::PopupWindow;
|
pub use layer_shika_adapters::PopupWindow;
|
||||||
pub use layer_shika_adapters::platform::{slint, slint_interpreter};
|
pub use layer_shika_adapters::platform::{slint, slint_interpreter};
|
||||||
pub use layer_shika_domain::entities::output_registry::OutputRegistry;
|
pub use layer_shika_domain::entities::output_registry::OutputRegistry;
|
||||||
|
pub use layer_shika_domain::prelude::AnchorStrategy;
|
||||||
pub use layer_shika_domain::value_objects::anchor::AnchorEdges;
|
pub use layer_shika_domain::value_objects::anchor::AnchorEdges;
|
||||||
pub use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
pub use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
||||||
pub use layer_shika_domain::value_objects::layer::Layer;
|
pub use layer_shika_domain::value_objects::layer::Layer;
|
||||||
|
|
@ -48,10 +49,10 @@ pub enum Error {
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
AnchorEdges, App, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika,
|
AnchorEdges, AnchorStrategy, App, EventLoopHandle, KeyboardInteractivity, Layer,
|
||||||
OutputGeometry, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry, PopupAt,
|
LayerShika, OutputGeometry, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry,
|
||||||
PopupBuilder, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize, PopupWindow,
|
PopupAt, PopupBuilder, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize,
|
||||||
Result, ShellContext, ShellControl,
|
PopupWindow, Result, ShellContext, ShellControl,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};
|
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::system::App;
|
use crate::system::App;
|
||||||
use layer_shika_adapters::platform::slint_interpreter::Value;
|
use layer_shika_adapters::platform::slint_interpreter::Value;
|
||||||
|
use layer_shika_domain::prelude::AnchorStrategy;
|
||||||
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
|
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
|
||||||
use layer_shika_domain::value_objects::popup_request::{PopupAt, PopupRequest, PopupSize};
|
use layer_shika_domain::value_objects::popup_request::{PopupAt, PopupRequest, PopupSize};
|
||||||
|
|
||||||
|
|
@ -196,6 +197,104 @@ impl<'a> PopupBuilder<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bind_anchored(self, trigger_callback: &str, strategy: AnchorStrategy) -> Result<()> {
|
||||||
|
let component_name = self.component.clone();
|
||||||
|
let grab = self.grab;
|
||||||
|
let close_callback = self.close_callback.clone();
|
||||||
|
let resize_callback = self.resize_callback.clone();
|
||||||
|
let control = self.app.control();
|
||||||
|
|
||||||
|
self.app.with_all_component_instances(|instance| {
|
||||||
|
let component_clone = component_name.clone();
|
||||||
|
let control_clone = control.clone();
|
||||||
|
let close_cb = close_callback.clone();
|
||||||
|
let resize_cb = resize_callback.clone();
|
||||||
|
|
||||||
|
if let Err(e) = instance.set_callback(trigger_callback, move |args| {
|
||||||
|
if args.len() < 4 {
|
||||||
|
log::error!(
|
||||||
|
"bind_anchored callback expects 4 arguments (x, y, width, height), got {}",
|
||||||
|
args.len()
|
||||||
|
);
|
||||||
|
return Value::Void;
|
||||||
|
}
|
||||||
|
|
||||||
|
let anchor_x = args
|
||||||
|
.first()
|
||||||
|
.and_then(|v| v.clone().try_into().ok())
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
let anchor_y = args
|
||||||
|
.get(1)
|
||||||
|
.and_then(|v| v.clone().try_into().ok())
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
let anchor_w = args
|
||||||
|
.get(2)
|
||||||
|
.and_then(|v| v.clone().try_into().ok())
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
let anchor_h = args
|
||||||
|
.get(3)
|
||||||
|
.and_then(|v| v.clone().try_into().ok())
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
|
||||||
|
log::debug!(
|
||||||
|
"Anchored popup triggered for '{}' at rect: ({}, {}, {}, {})",
|
||||||
|
component_clone,
|
||||||
|
anchor_x,
|
||||||
|
anchor_y,
|
||||||
|
anchor_w,
|
||||||
|
anchor_h
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut builder = PopupRequest::builder(component_clone.clone())
|
||||||
|
.at(PopupAt::AnchorRect {
|
||||||
|
x: anchor_x,
|
||||||
|
y: anchor_y,
|
||||||
|
w: anchor_w,
|
||||||
|
h: anchor_h,
|
||||||
|
})
|
||||||
|
.size(PopupSize::Content)
|
||||||
|
.grab(grab);
|
||||||
|
|
||||||
|
let mode = match strategy {
|
||||||
|
AnchorStrategy::CenterBottom => PopupPositioningMode::TopCenter,
|
||||||
|
AnchorStrategy::CenterTop => PopupPositioningMode::BottomCenter,
|
||||||
|
AnchorStrategy::RightBottom => PopupPositioningMode::TopRight,
|
||||||
|
AnchorStrategy::LeftTop => PopupPositioningMode::BottomLeft,
|
||||||
|
AnchorStrategy::RightTop => PopupPositioningMode::BottomRight,
|
||||||
|
AnchorStrategy::LeftBottom | AnchorStrategy::Cursor => {
|
||||||
|
PopupPositioningMode::TopLeft
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
builder = builder.mode(mode);
|
||||||
|
|
||||||
|
if let Some(ref close_cb) = close_cb {
|
||||||
|
builder = builder.close_on(close_cb.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref resize_cb) = resize_cb {
|
||||||
|
builder = builder.resize_on(resize_cb.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = builder.build();
|
||||||
|
|
||||||
|
if let Err(e) = control_clone.show_popup(&request) {
|
||||||
|
log::error!("Failed to show anchored popup: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Void
|
||||||
|
}) {
|
||||||
|
log::error!(
|
||||||
|
"Failed to bind anchored popup callback '{}': {}",
|
||||||
|
trigger_callback,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn build_request(&self) -> PopupRequest {
|
fn build_request(&self) -> PopupRequest {
|
||||||
let mut builder = PopupRequest::builder(self.component.clone())
|
let mut builder = PopupRequest::builder(self.component.clone())
|
||||||
.at(self.reference)
|
.at(self.reference)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ pub use crate::entities::output_registry::OutputRegistry;
|
||||||
pub use crate::errors::{DomainError, Result};
|
pub use crate::errors::{DomainError, Result};
|
||||||
pub use crate::surface_dimensions::SurfaceDimensions;
|
pub use crate::surface_dimensions::SurfaceDimensions;
|
||||||
pub use crate::value_objects::anchor::AnchorEdges;
|
pub use crate::value_objects::anchor::AnchorEdges;
|
||||||
|
pub use crate::value_objects::anchor_strategy::AnchorStrategy;
|
||||||
pub use crate::value_objects::dimensions::{PopupDimensions, WindowHeight};
|
pub use crate::value_objects::dimensions::{PopupDimensions, WindowHeight};
|
||||||
pub use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
pub use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
||||||
pub use crate::value_objects::layer::Layer;
|
pub use crate::value_objects::layer::Layer;
|
||||||
|
|
|
||||||
49
crates/domain/src/value_objects/anchor_strategy.rs
Normal file
49
crates/domain/src/value_objects/anchor_strategy.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum AnchorStrategy {
|
||||||
|
CenterBottom,
|
||||||
|
CenterTop,
|
||||||
|
LeftBottom,
|
||||||
|
RightBottom,
|
||||||
|
LeftTop,
|
||||||
|
RightTop,
|
||||||
|
Cursor,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnchorStrategy {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn calculate_position(
|
||||||
|
self,
|
||||||
|
anchor_x: f64,
|
||||||
|
anchor_y: f64,
|
||||||
|
anchor_w: f64,
|
||||||
|
anchor_h: f64,
|
||||||
|
popup_w: f64,
|
||||||
|
popup_h: f64,
|
||||||
|
) -> (f64, f64) {
|
||||||
|
match self {
|
||||||
|
Self::CenterBottom => {
|
||||||
|
let center_x = anchor_x + (anchor_w / 2.0);
|
||||||
|
let x = center_x - (popup_w / 2.0);
|
||||||
|
let y = anchor_y + anchor_h;
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
Self::CenterTop => {
|
||||||
|
let center_x = anchor_x + (anchor_w / 2.0);
|
||||||
|
let x = center_x - (popup_w / 2.0);
|
||||||
|
let y = anchor_y - popup_h;
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
Self::LeftBottom => (anchor_x, anchor_y + anchor_h),
|
||||||
|
Self::RightBottom => (anchor_x + anchor_w - popup_w, anchor_y + anchor_h),
|
||||||
|
Self::LeftTop => (anchor_x, anchor_y - popup_h),
|
||||||
|
Self::RightTop => (anchor_x + anchor_w - popup_w, anchor_y - popup_h),
|
||||||
|
Self::Cursor => (anchor_x, anchor_y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AnchorStrategy {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::CenterBottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod anchor;
|
pub mod anchor;
|
||||||
|
pub mod anchor_strategy;
|
||||||
pub mod dimensions;
|
pub mod dimensions;
|
||||||
pub mod keyboard_interactivity;
|
pub mod keyboard_interactivity;
|
||||||
pub mod layer;
|
pub mod layer;
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,10 @@
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
||||||
pub use layer_shika_composition::{
|
pub use layer_shika_composition::{
|
||||||
AnchorEdges, App, Error, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika,
|
AnchorEdges, AnchorStrategy, App, Error, EventLoopHandle, KeyboardInteractivity, Layer,
|
||||||
OutputGeometry, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry, PopupAt, PopupHandle,
|
LayerShika, OutputGeometry, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry, PopupAt,
|
||||||
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, ShellContext, ShellControl,
|
PopupHandle, PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, ShellContext,
|
||||||
|
ShellControl,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use layer_shika_composition::{slint, slint_interpreter};
|
pub use layer_shika_composition::{slint, slint_interpreter};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue