Skip to content

Commit

Permalink
Merge pull request #446 from kas-gui/work1
Browse files Browse the repository at this point in the history
Duplicate Text struct and adapt for KAS themes; remove TextApi* traits
  • Loading branch information
dhardy committed Mar 12, 2024
2 parents b808a8e + 2be7b34 commit a403cbc
Show file tree
Hide file tree
Showing 20 changed files with 1,005 additions and 320 deletions.
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

0 comments on commit a403cbc

Please sign in to comment.