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

ScrollText widget, font sizes in pixels, AdaptWidget::on_messages, misc fixes #419

Merged
merged 5 commits into from
Nov 22, 2023
Merged
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
3 changes: 2 additions & 1 deletion crates/kas-core/src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ enum ProxyAction {
#[cfg(test)]
mod test {
use super::*;
use raw_window_handle as raw;
use std::time::Instant;

struct Draw;
Expand Down Expand Up @@ -231,7 +232,7 @@ mod test {

fn new<W>(_: &mut Self::Shared, _: W) -> Result<Self>
where
W: raw_window_handle::HasRawWindowHandle + raw_window_handle::HasRawDisplayHandle,
W: raw::HasWindowHandle + raw::HasDisplayHandle,
Self: Sized,
{
todo!()
Expand Down
8 changes: 5 additions & 3 deletions crates/kas-core/src/theme/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Config {
#[cfg_attr(feature = "serde", serde(skip))]
dirty: bool,

/// Standard font size, in units of points-per-Em
/// Standard font size, in units of pixels-per-Em
#[cfg_attr(feature = "serde", serde(default = "defaults::font_size"))]
font_size: f32,

Expand Down Expand Up @@ -146,7 +146,9 @@ impl Default for RasterConfig {
impl Config {
/// Standard font size
///
/// Units: points per Em. Pixel size depends on the screen's scale factor.
/// Units: logical (unscaled) pixels per Em.
///
/// To convert to Points, multiply by three quarters.
#[inline]
pub fn font_size(&self) -> f32 {
self.font_size
Expand Down Expand Up @@ -279,7 +281,7 @@ mod defaults {
}

pub fn font_size() -> f32 {
10.0
14.0
}

pub fn color_schemes() -> BTreeMap<String, ColorsSrgb> {
Expand Down
5 changes: 2 additions & 3 deletions crates/kas-core/src/theme/dimensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,8 @@ pub struct Dimensions {
}

impl Dimensions {
pub fn new(params: &Parameters, pt_size: f32, scale: f32) -> Self {
let dpp = scale * (96.0 / 72.0);
let dpem = dpp * pt_size;
pub fn new(params: &Parameters, font_size: f32, scale: f32) -> Self {
let dpem = scale * font_size;

let text_m0 = (params.m_text.0 * scale).cast_nearest();
let text_m1 = (params.m_text.1 * scale).cast_nearest();
Expand Down
11 changes: 7 additions & 4 deletions crates/kas-macros/src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
let (fn_set_rect, fn_nav_next, fn_find_id);
let mut fn_nav_next_err = None;
let mut fn_draw = None;
let mut gen_layout = false;

if let Some(inner) = opt_derive {
required_layout_methods = quote! {
Expand Down Expand Up @@ -693,7 +692,6 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
self.rect().contains(coord).then(|| self.id())
};
if let Some((_, layout)) = args.layout.take() {
gen_layout = true;
fn_nav_next = match layout.nav_next(children.iter().map(|(ident, _, _)| ident)) {
Ok(toks) => Some(toks),
Err((span, msg)) => {
Expand Down Expand Up @@ -913,9 +911,8 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
if !has_item("nav_next") {
if let Some(method) = fn_nav_next {
layout_impl.items.push(Verbatim(method));
} else if gen_layout {
} else if let Some((span, msg)) = fn_nav_next_err {
// We emit a warning here only if nav_next is not explicitly defined
let (span, msg) = fn_nav_next_err.unwrap();
emit_warning!(span, "unable to generate `fn Layout::nav_next`: {}", msg,);
}
}
Expand Down Expand Up @@ -957,6 +954,12 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
layout_impl.items.push(Verbatim(method));
}
} else if let Some(fn_size_rules) = fn_size_rules {
if fn_nav_next.is_none() {
if let Some((span, msg)) = fn_nav_next_err {
emit_warning!(span, "unable to generate `fn Layout::nav_next`: {}", msg,);
}
}

scope.generated.push(quote! {
impl #impl_generics ::kas::Layout for #impl_target {
#required_layout_methods
Expand Down
39 changes: 34 additions & 5 deletions crates/kas-widgets/src/adapt/adapt_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

//! Event adapters

use kas::event::ConfigCx;
use kas::event::{ConfigCx, EventCx};
use kas::{autoimpl, impl_scope, widget_index, Events, Widget};
use std::fmt::Debug;

impl_scope! {
/// Wrapper to call a closure on update
Expand All @@ -21,6 +22,7 @@ impl_scope! {
pub inner: W,
on_configure: Option<Box<dyn Fn(&mut ConfigCx, &mut W)>>,
on_update: Option<Box<dyn Fn(&mut ConfigCx, &mut W, &W::Data)>>,
message_handlers: Vec<Box<dyn Fn(&mut EventCx, &mut W, &W::Data)>>,
}

impl Self {
Expand All @@ -32,12 +34,11 @@ impl_scope! {
inner,
on_configure: None,
on_update: None,
message_handlers: vec![],
}
}

/// Call the given closure on [`Events::configure`]
///
/// Returns a wrapper around the input widget.
#[must_use]
pub fn on_configure<F>(mut self, f: F) -> Self
where
Expand All @@ -48,8 +49,6 @@ impl_scope! {
}

/// Call the given closure on [`Events::update`]
///
/// Returns a wrapper around the input widget.
#[must_use]
pub fn on_update<F>(mut self, f: F) -> Self
where
Expand All @@ -58,6 +57,30 @@ impl_scope! {
self.on_update = Some(Box::new(f));
self
}

/// Add a handler on message of type `M`
#[must_use]
pub fn on_message<M, H>(self, handler: H) -> Self
where
M: Debug + 'static,
H: Fn(&mut EventCx, &mut W, &W::Data, M) + 'static,
{
self.on_messages(move |cx, w, data| {
if let Some(m) = cx.try_pop() {
handler(cx, w, data, m);
}
})
}

/// Add a generic message handler
#[must_use]
pub fn on_messages<H>(mut self, handler: H) -> Self
where
H: Fn(&mut EventCx, &mut W, &W::Data) + 'static,
{
self.message_handlers.push(Box::new(handler));
self
}
}

impl Events for Self {
Expand All @@ -83,5 +106,11 @@ impl_scope! {
f(cx, &mut self.inner, data);
}
}

fn handle_messages(&mut self, cx: &mut EventCx, data: &W::Data) {
for handler in self.message_handlers.iter() {
handler(cx, &mut self.inner, data);
}
}
}
}
28 changes: 26 additions & 2 deletions crates/kas-widgets/src/adapt/adapt_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
use super::{Map, MapAny, OnUpdate, Reserve, WithLabel};
use kas::cast::{Cast, CastFloat};
use kas::dir::Directional;
use kas::event::ConfigCx;
use kas::event::{ConfigCx, EventCx};
use kas::geom::Vec2;
use kas::layout::{AxisInfo, SizeRules};
use kas::text::AccessString;
use kas::theme::SizeCx;
#[allow(unused)] use kas::Events;
use kas::Widget;
#[allow(unused)] use kas::{Events, Layout};
use std::fmt::Debug;

/// Provides `.map_any()`
///
Expand Down Expand Up @@ -66,6 +67,29 @@ pub trait AdaptWidget: Widget + Sized {
OnUpdate::new(self).on_update(f)
}

/// Add a handler on message of type `M`
///
/// Returns a wrapper around the input widget.
#[must_use]
fn on_message<M, H>(self, handler: H) -> OnUpdate<Self>
where
M: Debug + 'static,
H: Fn(&mut EventCx, &mut Self, &Self::Data, M) + 'static,
{
OnUpdate::new(self).on_message(handler)
}

/// Add a generic message handler
///
/// Returns a wrapper around the input widget.
#[must_use]
fn on_messages<H>(self, handler: H) -> OnUpdate<Self>
where
H: Fn(&mut EventCx, &mut Self, &Self::Data) + 'static,
{
OnUpdate::new(self).on_messages(handler)
}

/// Construct a wrapper, setting minimum size in pixels
///
/// The input size is scaled by the scale factor.
Expand Down
6 changes: 5 additions & 1 deletion crates/kas-widgets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@
//! - [`Filler`]: an empty widget, sometimes used to fill space
//! - [`Image`]: a pixmap image
//! - [`Label`], [`AccessLabel`]: are static text labels
//! - [`Text`]: a dynamic (input-data derived) text label
//! - [`Mark`]: a small mark
//! - [`ScrollLabel`]: text label supporting scrolling and selection
//! - [`ScrollLabel`]: static text label supporting scrolling and selection
//! - [`ScrollText`]: dynamic text label supporting scrolling and selection
//! - [`Separator`]: a visible bar to separate things
//! - [`format_value`] and [`format_data`] are constructors for [`Text`],
//! displaying a text label derived from input data
Expand Down Expand Up @@ -84,6 +86,7 @@ mod radio_box;
mod scroll;
mod scroll_bar;
mod scroll_label;
mod scroll_text;
mod separator;
mod slider;
mod spinner;
Expand Down Expand Up @@ -111,6 +114,7 @@ pub use radio_box::{RadioBox, RadioButton};
pub use scroll::ScrollRegion;
pub use scroll_bar::{ScrollBar, ScrollBarRegion, ScrollBars, ScrollMsg};
pub use scroll_label::ScrollLabel;
pub use scroll_text::ScrollText;
pub use separator::Separator;
pub use slider::{Slider, SliderValue};
pub use spinner::{Spinner, SpinnerValue};
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-widgets/src/scroll_label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use kas::text::{SelectionHelper, Text};
use kas::theme::TextClass;

impl_scope! {
/// A text label supporting scrolling and selection
/// A static text label supporting scrolling and selection
///
/// Line-wrapping is enabled; default alignment is derived from the script
/// (usually top-left).
Expand Down
Loading