Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work2 #283

Merged
merged 17 commits into from
Feb 14, 2022
Merged

Work2 #283

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions crates/kas-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,8 @@ version = "0.10.1"
path = "../kas-macros"

[dependencies.kas-text]
# version = "0.4.0"
git = "https://github.com/kas-gui/kas-text.git"
rev = "818515e"
version = "0.4.2"
#git = "https://github.com/kas-gui/kas-text.git"

[dependencies.winit]
# Provides translations for several winit types
Expand Down
73 changes: 25 additions & 48 deletions crates/kas-core/src/event/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Event handling components

use super::ScrollDelta::{LineDelta, PixelDelta};
use super::{Command, Event, EventMgr, PressSource, Response, VoidMsg};
use super::{Command, CursorIcon, Event, EventMgr, PressSource, Response, VoidMsg};
use crate::cast::CastFloat;
use crate::geom::{Coord, Offset, Rect, Size, Vec2};
#[allow(unused)]
Expand Down Expand Up @@ -218,51 +218,23 @@ impl ScrollComponent {
/// Implements scroll by Home/End, Page Up/Down and arrow keys, by mouse
/// wheel and touchpad.
///
/// If the `on_press_start` closure requests a mouse grab, this also
/// implements scrolling on `PressMove` mouse/touch events. On release
/// (`PressEnd`), given sufficient speed, momentum scrolling commences.
/// The `on_press_start` closure may choose to request a mouse grab only
/// given certain conditions, e.g. only on the primary mouse button:
/// ```
/// # use kas_core::prelude::*;
/// # use kas_core::event::{self, components::ScrollComponent};
/// # type Msg = ();
/// fn dummy_event_handler(
/// id: WidgetId,
/// scroll: &mut ScrollComponent,
/// mgr: &mut EventMgr,
/// event: Event
/// )
/// -> Response<Msg>
/// {
/// let window_size = Size(100, 80);
/// let (action, response) = scroll.scroll_by_event(
/// mgr,
/// event,
/// id.clone(),
/// window_size,
/// |mgr, source, _, coord| if source.is_primary() {
/// let icon = Some(event::CursorIcon::Grabbing);
/// mgr.grab_press_unique(id, source, coord, icon);
/// }
/// );
/// *mgr |= action;
/// response.void_into()
/// }
/// ```
/// `PressStart` is consumed only if the maximum scroll offset is non-zero
/// and event configuration enables panning for this press `source` (may
/// depend on modifiers), and if so grabs press events from this `source`.
/// `PressMove` is used to scroll by the motion delta and to track speed;
/// `PressEnd` initiates momentum-scrolling if the speed is high enough.
///
/// If the returned [`TkAction`] is `None`, the scroll offset has not changed and
/// the returned [`Response`] is either `Used` or `Unused`.
/// If the returned [`TkAction`] is not `None`, the scroll offset has been
/// updated and the second return value is `Response::Used`.
#[inline]
pub fn scroll_by_event<PS: FnOnce(&mut EventMgr, PressSource, Option<WidgetId>, Coord)>(
pub fn scroll_by_event(
&mut self,
mgr: &mut EventMgr,
event: Event,
id: WidgetId,
window_size: Size,
on_press_start: PS,
) -> (TkAction, Response<VoidMsg>) {
let mut action = TkAction::empty();
let mut response = Response::Used;
Expand Down Expand Up @@ -311,11 +283,12 @@ impl ScrollComponent {
Response::Scrolled
};
}
Event::PressStart {
source,
start_id,
coord,
} => on_press_start(mgr, source, start_id, coord),
Event::PressStart { source, coord, .. }
if self.max_offset != Offset::ZERO && mgr.config_enable_pan(source) =>
{
let icon = Some(CursorIcon::Grabbing);
mgr.grab_press_unique(id, source, coord, icon);
}
Event::PressMove { mut delta, .. } => {
self.glide.move_delta(delta);
let old_offset = self.offset;
Expand Down Expand Up @@ -416,19 +389,23 @@ impl TextInput {
use TextInputAction as Action;
match event {
Event::PressStart { source, coord, .. } if source.is_primary() => {
mgr.grab_press_unique(w_id.clone(), source, coord, None);
match source {
let (action, icon) = match source {
PressSource::Touch(touch_id) => {
self.touch_phase = TouchPhase::Start(touch_id, coord);
let delay = mgr.config().touch_select_delay();
mgr.update_on_timer(delay, w_id, PAYLOAD_SELECT);
Action::Focus
mgr.update_on_timer(delay, w_id.clone(), PAYLOAD_SELECT);
(Action::Focus, None)
}
PressSource::Mouse(..) if mgr.config_enable_mouse_text_pan() => Action::Focus,
PressSource::Mouse(_, repeats) => {
Action::Cursor(coord, true, !mgr.modifiers().shift(), repeats)
PressSource::Mouse(..) if mgr.config_enable_mouse_text_pan() => {
(Action::Focus, Some(CursorIcon::Grabbing))
}
}
PressSource::Mouse(_, repeats) => (
Action::Cursor(coord, true, !mgr.modifiers().shift(), repeats),
None,
),
};
mgr.grab_press_unique(w_id, source, coord, icon);
action
}
Event::PressMove {
source,
Expand Down
5 changes: 3 additions & 2 deletions crates/kas-core/src/event/manager/mgr_pub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ impl EventState {

/// Is mouse panning enabled?
#[inline]
pub fn config_enable_mouse_pan(&self) -> bool {
self.config.mouse_pan().is_enabled_with(self.modifiers())
pub fn config_enable_pan(&self, source: PressSource) -> bool {
source.is_touch()
|| source.is_primary() && self.config.mouse_pan().is_enabled_with(self.modifiers())
}

/// Is mouse text panning enabled?
Expand Down
128 changes: 64 additions & 64 deletions crates/kas-core/src/geom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@

//! Geometry data types

use crate::cast::Conv;
use crate::cast::{Cast, Conv};
use crate::dir::Directional;
#[cfg(feature = "winit")]
use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize, Pixel};

mod vector;
pub use vector::{DVec2, Quad, Vec2, Vec3};
Expand Down Expand Up @@ -151,15 +149,6 @@ impl Coord {
pub const fn splat(n: i32) -> Self {
Self(n, n)
}

/// Convert from a logical position
#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
pub fn from_logical<X: Pixel>(logical: LogicalPosition<X>, dpi_factor: f64) -> Self {
let pos = PhysicalPosition::<i32>::from_logical(logical, dpi_factor);
let pos: (i32, i32) = pos.into();
Coord(pos.0, pos.1)
}
}

impl std::ops::Sub for Coord {
Expand Down Expand Up @@ -239,26 +228,6 @@ impl From<Coord> for kas_text::Vec2 {
}
}

#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
impl<X: Pixel> From<PhysicalPosition<X>> for Coord {
#[inline]
fn from(pos: PhysicalPosition<X>) -> Coord {
let pos: (i32, i32) = pos.cast::<i32>().into();
Coord(pos.0, pos.1)
}
}

#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
impl<X: Pixel> From<Coord> for PhysicalPosition<X> {
#[inline]
fn from(coord: Coord) -> PhysicalPosition<X> {
let pos: PhysicalPosition<i32> = (coord.0, coord.1).into();
pos.cast()
}
}

/// A 2D size, also known as an extent
///
/// This is both a size and a relative position. One can add or subtract a size
Expand Down Expand Up @@ -406,6 +375,11 @@ impl From<Offset> for Size {
}

// used for marigns
impl From<Size> for (u16, u16) {
fn from(size: Size) -> (u16, u16) {
(size.0.cast(), size.1.cast())
}
}
impl From<(u16, u16)> for Size {
fn from(v: (u16, u16)) -> Self {
Self(i32::conv(v.0), i32::conv(v.1))
Expand All @@ -431,38 +405,6 @@ impl From<Size> for kas_text::Vec2 {
}
}

#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
impl<X: Pixel> From<PhysicalSize<X>> for Size {
#[inline]
fn from(size: PhysicalSize<X>) -> Size {
let size: (i32, i32) = size.cast::<i32>().into();
debug_assert!(size.0 >= 0 && size.1 >= 0);
Size(size.0, size.1)
}
}

#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
impl<X: Pixel> From<Size> for PhysicalSize<X> {
#[inline]
fn from(size: Size) -> PhysicalSize<X> {
debug_assert!(size.0 >= 0 && size.1 >= 0);
let pos: PhysicalSize<i32> = (size.0, size.1).into();
pos.cast()
}
}

#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
impl From<Size> for winit::dpi::Size {
#[inline]
fn from(size: Size) -> winit::dpi::Size {
debug_assert!(size.0 >= 0 && size.1 >= 0);
winit::dpi::Size::Physical((size.0, size.1).into())
}
}

/// A `(x, y)` offset, also known as a **vector**
///
/// This is a relative position. It can be added to or subtracted from a
Expand Down Expand Up @@ -669,3 +611,61 @@ impl std::ops::SubAssign<Offset> for Rect {
self.pos -= offset;
}
}

#[cfg(feature = "winit")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
mod winit_impls {
use super::{Coord, Size};
use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize, Pixel};

impl Coord {
/// Convert from a logical position
pub fn from_logical<X: Pixel>(logical: LogicalPosition<X>, dpi_factor: f64) -> Self {
let pos = PhysicalPosition::<i32>::from_logical(logical, dpi_factor);
let pos: (i32, i32) = pos.into();
Coord(pos.0, pos.1)
}
}

impl<X: Pixel> From<PhysicalPosition<X>> for Coord {
#[inline]
fn from(pos: PhysicalPosition<X>) -> Coord {
let pos: (i32, i32) = pos.cast::<i32>().into();
Coord(pos.0, pos.1)
}
}

impl<X: Pixel> From<Coord> for PhysicalPosition<X> {
#[inline]
fn from(coord: Coord) -> PhysicalPosition<X> {
let pos: PhysicalPosition<i32> = (coord.0, coord.1).into();
pos.cast()
}
}

impl<X: Pixel> From<PhysicalSize<X>> for Size {
#[inline]
fn from(size: PhysicalSize<X>) -> Size {
let size: (i32, i32) = size.cast::<i32>().into();
debug_assert!(size.0 >= 0 && size.1 >= 0);
Size(size.0, size.1)
}
}

impl<X: Pixel> From<Size> for PhysicalSize<X> {
#[inline]
fn from(size: Size) -> PhysicalSize<X> {
debug_assert!(size.0 >= 0 && size.1 >= 0);
let pos: PhysicalSize<i32> = (size.0, size.1).into();
pos.cast()
}
}

impl From<Size> for winit::dpi::Size {
#[inline]
fn from(size: Size) -> winit::dpi::Size {
debug_assert!(size.0 >= 0 && size.1 >= 0);
winit::dpi::Size::Physical((size.0, size.1).into())
}
}
}
31 changes: 24 additions & 7 deletions crates/kas-core/src/layout/size_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Types used by size rules

use super::{Align, AlignHints, AxisInfo, SizeRules};
use crate::cast::{Cast, CastFloat, Conv, ConvFloat};
use crate::cast::{CastFloat, Conv, ConvFloat};
use crate::dir::Directional;
use crate::geom::{Rect, Size, Vec2};

Expand All @@ -33,7 +33,7 @@ impl Margins {
/// Margins with equal size on each edge.
#[inline]
pub const fn splat(size: u16) -> Self {
Margins::hv_splat(size, size)
Margins::hv_splat((size, size))
}

/// Margins via horizontal and vertical sizes
Expand All @@ -44,7 +44,7 @@ impl Margins {

/// Margins via horizontal and vertical sizes
#[inline]
pub const fn hv_splat(h: u16, v: u16) -> Self {
pub const fn hv_splat((h, v): (u16, u16)) -> Self {
Margins {
horiz: (h, h),
vert: (v, v),
Expand Down Expand Up @@ -83,7 +83,7 @@ impl Margins {

impl From<Size> for Margins {
fn from(size: Size) -> Self {
Margins::hv_splat(size.0.cast(), size.1.cast())
Margins::hv_splat(size.into())
}
}

Expand Down Expand Up @@ -283,8 +283,8 @@ impl FrameRules {

/// Generate rules for content surrounded by this frame
///
/// It is assumed that the content's margins apply inside this frame, and
/// that the margin is at least as large as self's `inner_margin`.
/// The content's margins apply inside this frame. External margins come
/// from this type.
///
/// Returns the tuple `(rules, offset, size)`:
///
Expand All @@ -308,7 +308,7 @@ impl FrameRules {
(rules, offset, size)
}

/// Variant: frame surrounds content
/// Variant: frame is content margin
///
/// The content's margin is reduced by the size of the frame, with any
/// residual margin applying outside the frame (using the max of the
Expand All @@ -330,4 +330,21 @@ impl FrameRules {
);
(rules, offset, size)
}

/// Variant: frame replaces content margin
///
/// The content's margin is ignored. In other respects,
/// this is the same as [`FrameRules::surround_with_margin`].
pub fn surround_no_margin(self, content: SizeRules) -> (SizeRules, i32, i32) {
let offset = self.offset + self.inner_margin;
let size = self.size + 2 * self.inner_margin;

let rules = SizeRules::new(
content.min_size() + size,
content.ideal_size() + size,
self.m,
content.stretch(),
);
(rules, offset, size)
}
}
Loading