Added scroll zoom commands.
This commit is contained in:
parent
3b917a9391
commit
d883982a24
|
@ -28,11 +28,13 @@
|
|||
|
||||
# Scroll
|
||||
|
||||
* Click in thumb drag and release outside thumb causes it to stay pressed.
|
||||
* Implement touch scroll inertia.
|
||||
* Implement `ScrollMode::ZOOM`.
|
||||
- Touch gesture.
|
||||
- Scroll wheel zoom.
|
||||
- Commands.
|
||||
- Scroll-to-fill.
|
||||
|
||||
# Touch Events
|
||||
|
||||
|
|
|
@ -461,8 +461,8 @@ fn center_viewport(msg: impl UiNode) -> impl UiNode {
|
|||
// the large images can take a moment to decode in debug builds, but the size
|
||||
// is already known after read, so the "loading.." message ends-up off-screen
|
||||
// because it is centered on the image.
|
||||
x = zero_ui::widgets::scroll::SCROLL_HORIZONTAL_OFFSET_VAR.map(|&fct| Length::Relative(fct) - 1.vw() * fct);
|
||||
y = zero_ui::widgets::scroll::SCROLL_VERTICAL_OFFSET_VAR.map(|&fct| Length::Relative(fct) - 1.vh() * fct);
|
||||
x = zero_ui::widgets::scroll::SCROLL.horizontal_offset().map(|&fct| Length::Relative(fct) - 1.vw() * fct);
|
||||
y = zero_ui::widgets::scroll::SCROLL.vertical_offset().map(|&fct| Length::Relative(fct) - 1.vh() * fct);
|
||||
zero_ui::core::widget_base::can_auto_hide = false;
|
||||
max_size = (1.vw(), 1.vh());
|
||||
child_align = Align::CENTER;
|
||||
|
|
|
@ -105,7 +105,7 @@ fn scroll_to_btn(target: WidgetId, mode: ScrollToMode) -> impl UiNode {
|
|||
child = Text!("Scroll To {} {}", target, if let ScrollToMode::Minimal{..} = &mode { "(minimal)" } else { "(center)" });
|
||||
enabled = cmd.is_enabled();
|
||||
on_click = hn!(|_| {
|
||||
cmd.notify_param(commands::ScrollToRequest { widget_id: target, mode: mode.clone() });
|
||||
cmd.notify_param(commands::ScrollToRequest { widget_id: target, mode: mode.clone(), zoom: None, });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,9 @@ fn on_build(wgt: &mut WidgetBuilding) {
|
|||
let child = with_context_var(child, SCROLL_HORIZONTAL_OFFSET_VAR, var(0.fct()));
|
||||
|
||||
let child = with_context_var(child, OVERSCROLL_VERTICAL_OFFSET_VAR, var(0.fct()));
|
||||
with_context_var(child, OVERSCROLL_HORIZONTAL_OFFSET_VAR, var(0.fct()))
|
||||
let child = with_context_var(child, OVERSCROLL_HORIZONTAL_OFFSET_VAR, var(0.fct()));
|
||||
|
||||
with_context_var(child, SCROLL_SCALE_VAR, var(1.fct()))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,8 @@ command! {
|
|||
shortcut_filter: ShortcutFilter::FOCUSED | ShortcutFilter::CMD_ENABLED,
|
||||
};
|
||||
|
||||
/// Represents the action of scrolling until a child widget is fully visible.
|
||||
/// Represents the action of scrolling until a child widget is fully visible, the command can
|
||||
/// also adjust the zoom scale.
|
||||
///
|
||||
/// # Metadata
|
||||
///
|
||||
|
@ -178,6 +179,25 @@ command! {
|
|||
///
|
||||
/// You can use the [`scroll_to`] function to invoke this command in all parent scrolls automatically.
|
||||
pub static SCROLL_TO_CMD;
|
||||
|
||||
/// Represents the **zoom in** action.
|
||||
pub static ZOOM_IN_CMD = {
|
||||
name: "Zoom In",
|
||||
shortcut: shortcut!(CTRL+'+'),
|
||||
shortcut_filter: ShortcutFilter::FOCUSED | ShortcutFilter::CMD_ENABLED,
|
||||
};
|
||||
|
||||
/// Represents the **zoom out** action.
|
||||
pub static ZOOM_OUT_CMD = {
|
||||
name: "Zoom Out",
|
||||
shortcut: shortcut!(CTRL+'-'),
|
||||
shortcut_filter: ShortcutFilter::FOCUSED | ShortcutFilter::CMD_ENABLED,
|
||||
};
|
||||
|
||||
/// Represents the **reset zoom** action.
|
||||
pub static ZOOM_RESET_CMD = {
|
||||
name: "Reset Zoom",
|
||||
};
|
||||
}
|
||||
|
||||
/// Parameters for the scroll and page commands.
|
||||
|
@ -250,6 +270,13 @@ pub struct ScrollToRequest {
|
|||
|
||||
/// How much the scroll position will change to showcase the target widget.
|
||||
pub mode: ScrollToMode,
|
||||
|
||||
/// Optional zoom scale target.
|
||||
///
|
||||
/// If set the offsets and scale will animate so that the `mode`
|
||||
/// is fullfilled when this zoom factor is reached. If not set the scroll will happen in
|
||||
/// the current zoom scale.
|
||||
pub zoom: Option<Factor>,
|
||||
}
|
||||
impl ScrollToRequest {
|
||||
/// Pack the request into a command parameter.
|
||||
|
@ -265,6 +292,7 @@ impl ScrollToRequest {
|
|||
p.downcast_ref::<WidgetId>().map(|id| ScrollToRequest {
|
||||
widget_id: *id,
|
||||
mode: ScrollToMode::default(),
|
||||
zoom: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -287,7 +315,8 @@ impl_from_and_into_var! {
|
|||
fn from(widget_id: WidgetId) -> ScrollToRequest {
|
||||
ScrollToRequest {
|
||||
widget_id,
|
||||
mode: ScrollToMode::default()
|
||||
mode: ScrollToMode::default(),
|
||||
zoom: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,13 +403,12 @@ impl IntoValue<Option<ScrollToMode>> for ScrollToMode {}
|
|||
///
|
||||
/// [`is_scroll`]: WidgetInfoExt::is_scroll
|
||||
pub fn scroll_to(target: impl Into<WidgetId>, mode: impl Into<ScrollToMode>) {
|
||||
let target = target.into();
|
||||
for w in crate::core::window::WINDOWS.widget_trees() {
|
||||
if let Some(target) = w.get(target) {
|
||||
scroll_to_info(&target, mode.into());
|
||||
break;
|
||||
}
|
||||
}
|
||||
scroll_to_impl(target.into(), mode.into(), None)
|
||||
}
|
||||
|
||||
/// Like [`scroll_to`], but also adjusts the zoom scale.
|
||||
pub fn scroll_to_zoom(target: impl Into<WidgetId>, mode: impl Into<ScrollToMode>, zoom: impl Into<Factor>) {
|
||||
scroll_to_impl(target.into(), mode.into(), Some(zoom.into()))
|
||||
}
|
||||
|
||||
/// Scroll all parent [`is_scroll`] widgets of `target` so that it becomes visible.
|
||||
|
@ -389,13 +417,31 @@ pub fn scroll_to(target: impl Into<WidgetId>, mode: impl Into<ScrollToMode>) {
|
|||
///
|
||||
/// [`is_scroll`]: WidgetInfoExt::is_scroll
|
||||
pub fn scroll_to_info(target: &crate::core::widget_info::WidgetInfo, mode: impl Into<ScrollToMode>) {
|
||||
scroll_to_info_impl(target, mode.into(), None)
|
||||
}
|
||||
|
||||
/// Like [`scroll_to_info`], but also adjusts the zoom scale.
|
||||
pub fn scroll_to_info_zoom(target: &crate::core::widget_info::WidgetInfo, mode: impl Into<ScrollToMode>, zoom: impl Into<Factor>) {
|
||||
scroll_to_info_impl(target, mode.into(), Some(zoom.into()))
|
||||
}
|
||||
|
||||
fn scroll_to_impl(target: WidgetId, mode: ScrollToMode, zoom: Option<Factor>) {
|
||||
for w in crate::core::window::WINDOWS.widget_trees() {
|
||||
if let Some(target) = w.get(target) {
|
||||
scroll_to_info_impl(&target, mode, zoom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn scroll_to_info_impl(target: &crate::core::widget_info::WidgetInfo, mode: ScrollToMode, zoom: Option<Factor>) {
|
||||
let mut t = target.id();
|
||||
let mode = mode.into();
|
||||
for a in target.ancestors() {
|
||||
if a.is_scroll() {
|
||||
SCROLL_TO_CMD.scoped(a.id()).notify_param(ScrollToRequest {
|
||||
widget_id: t,
|
||||
mode: mode.clone(),
|
||||
zoom,
|
||||
});
|
||||
t = a.id();
|
||||
}
|
||||
|
|
|
@ -209,6 +209,8 @@ pub fn define_viewport_unit(child: impl UiNode, enabled: impl IntoVar<bool>) ->
|
|||
}
|
||||
|
||||
/// Smooth scrolling config.
|
||||
///
|
||||
/// Defines the easing animation applied to scroll offset and zoom value changes.
|
||||
#[property(CONTEXT, default(SMOOTH_SCROLLING_VAR), widget_impl(Scroll))]
|
||||
pub fn smooth_scrolling(child: impl UiNode, config: impl IntoVar<SmoothScrolling>) -> impl UiNode {
|
||||
with_context_var(child, SMOOTH_SCROLLING_VAR, config)
|
||||
|
|
|
@ -54,13 +54,11 @@ impl_from_and_into_var! {
|
|||
context_var! {
|
||||
/// Vertical offset of the parent scroll.
|
||||
///
|
||||
/// The value is a percentage of `content.height - viewport.height`. This variable is usually read-write,
|
||||
/// scrollable content can modify it to scroll the parent.
|
||||
/// The value is a percentage of `content.height - viewport.height`.
|
||||
pub(super) static SCROLL_VERTICAL_OFFSET_VAR: Factor = 0.fct();
|
||||
/// Horizontal offset of the parent scroll.
|
||||
///
|
||||
/// The value is a percentage of `content.width - viewport.width`. This variable is usually read-write,
|
||||
/// scrollable content can modify it to scroll the parent.
|
||||
/// The value is a percentage of `content.width - viewport.width`.
|
||||
pub(super) static SCROLL_HORIZONTAL_OFFSET_VAR: Factor = 0.fct();
|
||||
|
||||
/// Extra vertical offset requested that could not be fulfilled because [`SCROLL_VERTICAL_OFFSET_VAR`]
|
||||
|
@ -91,8 +89,13 @@ context_var! {
|
|||
pub(super) static SCROLL_VIEWPORT_SIZE_VAR: PxSize = PxSize::zero();
|
||||
|
||||
/// Latest computed content size of the parent scroll.
|
||||
///
|
||||
/// The size is scaled if zoom is set.
|
||||
pub(super) static SCROLL_CONTENT_SIZE_VAR: PxSize = PxSize::zero();
|
||||
|
||||
/// Zoom scaling of the parent scroll.
|
||||
pub(super) static SCROLL_SCALE_VAR: Factor = 1.fct();
|
||||
|
||||
}
|
||||
|
||||
context_local! {
|
||||
|
@ -594,6 +597,7 @@ impl SCROLL {
|
|||
todo!()
|
||||
}
|
||||
|
||||
/// Returns `true` if the content can be scaled and the current scale is more than the min.
|
||||
pub fn can_zoom_out(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue