Skip to content

Commit

Permalink
Merge pull request #283 from kas-gui/work2
Browse files Browse the repository at this point in the history
Work2
  • Loading branch information
dhardy committed Feb 14, 2022
2 parents 5afee82 + 3111e97 commit a81610c
Show file tree
Hide file tree
Showing 29 changed files with 476 additions and 562 deletions.
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

0 comments on commit a81610c

Please sign in to comment.