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

Duplicate Text struct and adapt for KAS themes; remove TextApi* traits #446

Merged
merged 13 commits into from
Mar 12, 2024
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,4 @@ members = [

[patch.crates-io.kas-text]
git = "https://github.com/kas-gui/kas-text.git"
rev = "d9d2a99b7d94deeea48d67f3b7ba9237a12cea6d"
rev = "8828bb3df7c34559e18429a18a38974ddc3e905f"
34 changes: 13 additions & 21 deletions crates/kas-core/src/decorations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
//! Note: due to definition in kas-core, some widgets must be duplicated.

use crate::event::{CursorIcon, ResizeDirection};
use crate::text::{NotReady, Text};
use crate::theme::TextClass;
use crate::theme::{Text, TextClass};
use kas::prelude::*;
use kas::theme::MarkStyle;
use kas_macros::impl_scope;
Expand Down Expand Up @@ -107,59 +106,52 @@ impl_scope! {
}]
pub struct Label {
core: widget_core!(),
label: Text<String>,
text: Text<String>,
}

impl Self {
/// Construct from `label`
/// Construct from `text`
#[inline]
fn new(label: impl ToString) -> Self {
fn new(text: impl ToString) -> Self {
Label {
core: Default::default(),
label: Text::new(label.to_string()),
text: Text::new(text.to_string(), TextClass::Label(false)),
}
}

/// Text class
pub const CLASS: TextClass = TextClass::Label(false);
}

impl Layout for Self {
fn size_rules(&mut self, sizer: SizeCx, mut axis: AxisInfo) -> SizeRules {
axis.set_default_align_hv(Align::Center, Align::Center);
sizer.text_rules(&mut self.label, axis)
sizer.text_rules(&mut self.text, axis)
}

fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect) {
self.core.rect = rect;
cx.text_set_size(&mut self.label, rect.size);
cx.text_set_size(&mut self.text, rect.size);
}

fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.label, Self::CLASS);
draw.text(self.rect(), &self.text);
}
}

impl Events for Self {
fn configure(&mut self, cx: &mut ConfigCx) {
cx.text_configure(&mut self.label, Self::CLASS);
cx.text_configure(&mut self.text);
}
}

impl HasStr for Self {
fn get_str(&self) -> &str {
self.label.as_str()
self.text.as_str()
}
}

impl HasString for Self {
fn set_string(&mut self, string: String) -> Action {
self.label.set_string(string);
match self.label.prepare() {
Err(NotReady) => Action::empty(),
Ok(false) => Action::REDRAW,
Ok(true) => Action::RESIZE,
}
self.text.set_string(string);
self.text.reprepare_action()
}
}
}
Expand Down Expand Up @@ -252,7 +244,7 @@ impl_scope! {

/// Get the title
pub fn title(&self) -> &str {
self.title.label.as_str()
self.title.text.as_str()
}

/// Set the title
Expand Down
13 changes: 6 additions & 7 deletions crates/kas-core/src/draw/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use super::{color::Rgba, AnimationState};
#[allow(unused)] use super::{DrawRounded, DrawRoundedImpl};
use super::{DrawShared, DrawSharedImpl, ImageId, PassId, PassType, SharedState, WindowCommon};
use crate::geom::{Offset, Quad, Rect};
#[allow(unused)] use crate::text::TextApi;
use crate::text::{Effect, TextDisplay};
use std::any::Any;
use std::time::Instant;
Expand Down Expand Up @@ -208,8 +207,8 @@ pub trait Draw {
/// Text is drawn from `rect.pos` and clipped to `rect`. If the text
/// scrolls, `rect` should be the size of the whole text, not the window.
///
/// It is required to call [`TextApi::prepare`] or equivalent
/// prior to this method to select a font, font size and perform layout.
/// The `text` object must be configured and prepared prior to calling this
/// method (see [`crate::theme::Text`] or [`crate::text::Text`]).
fn text(&mut self, rect: Rect, text: &TextDisplay, col: Rgba);

/// Draw text with a single color and effects
Expand All @@ -220,8 +219,8 @@ pub trait Draw {
/// The effects list does not contain colour information, but may contain
/// underlining/strikethrough information. It may be empty.
///
/// It is required to call [`TextApi::prepare`] or equivalent
/// prior to this method to select a font, font size and perform layout.
/// The `text` object must be configured and prepared prior to calling this
/// method (see [`crate::theme::Text`] or [`crate::text::Text`]).
fn text_effects(&mut self, rect: Rect, text: &TextDisplay, col: Rgba, effects: &[Effect<()>]);

/// Draw text with effects (including [`Rgba`] color)
Expand All @@ -233,8 +232,8 @@ pub trait Draw {
/// If the `effects` list is empty or the first entry has `start > 0`, a
/// default entity will be assumed.
///
/// It is required to call [`TextApi::prepare`] or equivalent
/// prior to this method to select a font, font size and perform layout.
/// The `text` object must be configured and prepared prior to calling this
/// method (see [`crate::theme::Text`] or [`crate::text::Text`]).
fn text_effects_rgba(&mut self, rect: Rect, text: &TextDisplay, effects: &[Effect<Rgba>]);
}

Expand Down
12 changes: 6 additions & 6 deletions crates/kas-core/src/event/cx/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::event::{EventState, FocusSource};
use crate::geom::{Rect, Size};
use crate::layout::AlignPair;
use crate::messages::Erased;
use crate::text::TextApi;
use crate::theme::{Feature, SizeCx, TextClass, ThemeSize};
use crate::text::format::FormattableText;
use crate::theme::{Feature, SizeCx, Text, ThemeSize};
use crate::{Id, Node};
use cast::Cast;
use std::fmt::Debug;
Expand Down Expand Up @@ -125,11 +125,12 @@ impl<'a> ConfigCx<'a> {

/// Configure a text object
///
/// This selects a font given the [`TextClass`],
/// This selects a font given the [`TextClass`][crate::theme::TextClass],
/// [theme configuration][crate::theme::Config] and
/// the loaded [fonts][crate::text::fonts].
#[inline]
pub fn text_configure(&self, text: &mut dyn TextApi, class: TextClass) {
pub fn text_configure<T: FormattableText>(&self, text: &mut Text<T>) {
let class = text.class();
self.sh.text_configure(text, class);
}

Expand All @@ -139,8 +140,7 @@ impl<'a> ConfigCx<'a> {
///
/// Call [`text_configure`][Self::text_configure] before this method.
#[inline]
pub fn text_set_size(&self, text: &mut dyn TextApi, size: Size) {
text.set_wrap_width(size.0.cast());
pub fn text_set_size<T: FormattableText>(&self, text: &mut Text<T>, size: Size) {
text.set_bounds(size.cast());
text.prepare().expect("not configured");
}
Expand Down
24 changes: 10 additions & 14 deletions crates/kas-core/src/hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use crate::classes::HasStr;
use crate::event::{ConfigCx, Event, EventCx, IsUsed};
use crate::geom::{Coord, Offset, Rect};
use crate::layout::{Align, AxisInfo, SizeRules};
use crate::text::{Text, TextApi};
use crate::theme::{DrawCx, SizeCx, TextClass};
use crate::theme::{DrawCx, SizeCx, Text, TextClass};
use crate::{Events, Id, Layout, NavAdvance, Node, Widget};
use kas_macros::{autoimpl, impl_scope};

Expand All @@ -30,49 +29,46 @@ impl_scope! {
}]
pub struct StrLabel {
core: widget_core!(),
label: Text<&'static str>,
text: Text<&'static str>,
}

impl Self {
/// Construct from `label`
/// Construct from `text`
#[inline]
pub fn new(label: &'static str) -> Self {
pub fn new(text: &'static str) -> Self {
StrLabel {
core: Default::default(),
label: Text::new(label),
text: Text::new(text, TextClass::Label(false)),
}
}

/// Text class
pub const CLASS: TextClass = TextClass::Label(false);
}

impl Layout for Self {
#[inline]
fn size_rules(&mut self, sizer: SizeCx, mut axis: AxisInfo) -> SizeRules {
axis.set_default_align_hv(Align::Default, Align::Center);
sizer.text_rules(&mut self.label, axis)
sizer.text_rules(&mut self.text, axis)
}

fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect) {
self.core.rect = rect;
cx.text_set_size(&mut self.label, rect.size);
cx.text_set_size(&mut self.text, rect.size);
}

fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.label, Self::CLASS);
draw.text(self.rect(), &self.text);
}
}

impl Events for Self {
fn configure(&mut self, cx: &mut ConfigCx) {
cx.text_configure(&mut self.label, Self::CLASS);
cx.text_configure(&mut self.text);
}
}

impl HasStr for Self {
fn get_str(&self) -> &str {
self.label.as_str()
self.text.as_str()
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions crates/kas-core/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ pub use crate::layout::{
Align, AlignHints, AlignPair, AxisInfo, LayoutVisitor, SizeRules, Stretch,
};
#[doc(no_inline)] pub use crate::text::AccessString;
#[doc(no_inline)]
pub use crate::text::{EditableTextApi, TextApi, TextApiExt};
#[doc(no_inline)] pub use crate::theme::{DrawCx, SizeCx};
#[doc(no_inline)] pub use crate::Action;
#[doc(no_inline)]
Expand Down
7 changes: 2 additions & 5 deletions crates/kas-core/src/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
//! Most of this module is simply a re-export of the [KAS Text] API, hence the
//! lower level of integration than other parts of the library.
//!
//! [`Text`] objects *must* be configured and prepared before usage, otherwise
//! they may appear empty. Call [`ConfigCx::text_config`] from
//! [`Events::configure`] and [`ConfigCx::text_set_size`] from
//! [`Layout::set_rect`] to set text position and prepare.
//! If text is adjusted, one may use e.g. [`TextApi::prepare`] to update.
//! See also [`crate::theme::Text`] which provides better integration with KAS
//! theming and widget sizing operations.
//!
//! [KAS Text]: https://github.com/kas-gui/kas-text/

Expand Down
8 changes: 5 additions & 3 deletions crates/kas-core/src/text/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

//! Tools for text selection

use super::{TextApi, TextApiExt};
use kas_text::format::FormattableText;
use std::ops::Range;
use unicode_segmentation::UnicodeSegmentation;

use crate::theme::Text;

/// Action used by [`crate::event::components::TextInput`]
#[derive(Default)]
pub struct SelectionAction {
Expand Down Expand Up @@ -129,7 +131,7 @@ impl SelectionHelper {
/// If `repeats <= 2`, the selection is expanded by words, otherwise it is
/// expanded by lines. Line expansion only works if text is line-wrapped
/// (layout has been solved).
pub fn expand<T: TextApi>(&mut self, text: &T, repeats: u32) {
pub fn expand<T: FormattableText>(&mut self, text: &Text<T>, repeats: u32) {
let string = text.as_str();
let mut range = self.edit_pos..self.anchor_pos;
if range.start > range.end {
Expand Down Expand Up @@ -173,7 +175,7 @@ impl SelectionHelper {
}

/// Handle an action
pub fn action<T: TextApi>(&mut self, text: &T, action: SelectionAction) {
pub fn action<T: FormattableText>(&mut self, text: &Text<T>, action: SelectionAction) {
if action.anchor {
self.set_anchor();
}
Expand Down
16 changes: 8 additions & 8 deletions crates/kas-core/src/text/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::text::{Effect, EffectFlags};
/// may support keyboard access via e.g. `Alt+X`
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct AccessString {
label: String,
text: String,
effects: SmallVec<[Effect<()>; 2]>,
key: Option<Key>,
}
Expand Down Expand Up @@ -88,7 +88,7 @@ impl AccessString {
}
buf.push_str(s);
AccessString {
label: buf,
text: buf,
effects,
key,
}
Expand All @@ -101,7 +101,7 @@ impl AccessString {

/// Get the text
pub fn text(&self) -> &str {
&self.label
&self.text
}
}

Expand All @@ -110,7 +110,7 @@ impl FormattableText for AccessString {

#[inline]
fn as_str(&self) -> &str {
&self.label
&self.text
}

#[inline]
Expand All @@ -124,13 +124,13 @@ impl FormattableText for AccessString {
}

impl From<String> for AccessString {
fn from(input: String) -> Self {
if input.as_bytes().contains(&b'&') {
Self::parse(&input)
fn from(text: String) -> Self {
if text.as_bytes().contains(&b'&') {
Self::parse(&text)
} else {
// fast path: we can use the raw input
AccessString {
label: input,
text,
..Default::default()
}
}
Expand Down
Loading