summaryrefslogtreecommitdiffstats
path: root/widget/src/helpers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'widget/src/helpers.rs')
-rw-r--r--widget/src/helpers.rs126
1 files changed, 110 insertions, 16 deletions
diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs
index 62343a55..51978823 100644
--- a/widget/src/helpers.rs
+++ b/widget/src/helpers.rs
@@ -4,7 +4,8 @@ use crate::checkbox::{self, Checkbox};
use crate::combo_box::{self, ComboBox};
use crate::container::{self, Container};
use crate::core;
-use crate::core::widget::operation;
+use crate::core::widget::operation::{self, Operation};
+use crate::core::window;
use crate::core::{Element, Length, Pixels, Widget};
use crate::keyed;
use crate::overlay;
@@ -12,7 +13,8 @@ use crate::pick_list::{self, PickList};
use crate::progress_bar::{self, ProgressBar};
use crate::radio::{self, Radio};
use crate::rule::{self, Rule};
-use crate::runtime::{Action, Task};
+use crate::runtime::task::{self, Task};
+use crate::runtime::Action;
use crate::scrollable::{self, Scrollable};
use crate::slider::{self, Slider};
use crate::text::{self, Text};
@@ -111,6 +113,19 @@ macro_rules! text {
};
}
+/// Creates some [`Rich`] text with the given spans.
+///
+/// [`Rich`]: text::Rich
+#[macro_export]
+macro_rules! rich_text {
+ () => (
+ $crate::Column::new()
+ );
+ ($($x:expr),+ $(,)?) => (
+ $crate::text::Rich::from_iter([$($crate::text::Span::from($x)),+])
+ );
+}
+
/// Creates a new [`Container`] with the provided content.
///
/// [`Container`]: crate::Container
@@ -275,7 +290,7 @@ where
state: &mut Tree,
layout: Layout<'_>,
renderer: &Renderer,
- operation: &mut dyn operation::Operation<()>,
+ operation: &mut dyn operation::Operation,
) {
self.content
.as_widget()
@@ -383,6 +398,7 @@ where
struct Hover<'a, Message, Theme, Renderer> {
base: Element<'a, Message, Theme, Renderer>,
top: Element<'a, Message, Theme, Renderer>,
+ is_top_focused: bool,
is_top_overlay_active: bool,
}
@@ -458,7 +474,9 @@ where
viewport,
);
- if cursor.is_over(layout.bounds()) || self.is_top_overlay_active
+ if cursor.is_over(layout.bounds())
+ || self.is_top_focused
+ || self.is_top_overlay_active
{
let (top_layout, top_tree) = children.next().unwrap();
@@ -477,7 +495,7 @@ where
tree: &mut Tree,
layout: Layout<'_>,
renderer: &Renderer,
- operation: &mut dyn operation::Operation<()>,
+ operation: &mut dyn operation::Operation,
) {
let children = [&self.base, &self.top]
.into_iter()
@@ -501,6 +519,24 @@ where
) -> event::Status {
let mut children = layout.children().zip(&mut tree.children);
let (base_layout, base_tree) = children.next().unwrap();
+ let (top_layout, top_tree) = children.next().unwrap();
+
+ if matches!(event, Event::Window(window::Event::RedrawRequested(_)))
+ {
+ let mut count_focused = operation::focusable::count();
+
+ self.top.as_widget_mut().operate(
+ top_tree,
+ top_layout,
+ renderer,
+ &mut operation::black_box(&mut count_focused),
+ );
+
+ self.is_top_focused = match count_focused.finish() {
+ operation::Outcome::Some(count) => count.focused.is_some(),
+ _ => false,
+ };
+ }
let top_status = if matches!(
event,
@@ -509,9 +545,9 @@ where
| mouse::Event::ButtonReleased(_)
)
) || cursor.is_over(layout.bounds())
+ || self.is_top_focused
+ || self.is_top_overlay_active
{
- let (top_layout, top_tree) = children.next().unwrap();
-
self.top.as_widget_mut().on_event(
top_tree,
event.clone(),
@@ -597,6 +633,7 @@ where
Element::new(Hover {
base: base.into(),
top: top.into(),
+ is_top_focused: false,
is_top_overlay_active: false,
})
}
@@ -645,8 +682,6 @@ where
}
/// Creates a new [`Text`] widget with the provided content.
-///
-/// [`Text`]: core::widget::Text
pub fn text<'a, Theme, Renderer>(
text: impl text::IntoFragment<'a>,
) -> Text<'a, Theme, Renderer>
@@ -658,8 +693,6 @@ where
}
/// Creates a new [`Text`] widget that displays the provided value.
-///
-/// [`Text`]: core::widget::Text
pub fn value<'a, Theme, Renderer>(
value: impl ToString,
) -> Text<'a, Theme, Renderer>
@@ -670,6 +703,34 @@ where
Text::new(value.to_string())
}
+/// Creates a new [`Rich`] text widget with the provided spans.
+///
+/// [`Rich`]: text::Rich
+pub fn rich_text<'a, Link, Theme, Renderer>(
+ spans: impl AsRef<[text::Span<'a, Link, Renderer::Font>]> + 'a,
+) -> text::Rich<'a, Link, Theme, Renderer>
+where
+ Link: Clone + 'static,
+ Theme: text::Catalog + 'a,
+ Renderer: core::text::Renderer,
+ Renderer::Font: 'a,
+{
+ text::Rich::with_spans(spans)
+}
+
+/// Creates a new [`Span`] of text with the provided content.
+///
+/// [`Span`]: text::Span
+pub fn span<'a, Link, Font>(
+ text: impl text::IntoFragment<'a>,
+) -> text::Span<'a, Link, Font> {
+ text::Span::new(text)
+}
+
+#[cfg(feature = "markdown")]
+#[doc(inline)]
+pub use crate::markdown::view as markdown;
+
/// Creates a new [`Checkbox`].
///
/// [`Checkbox`]: crate::Checkbox
@@ -706,15 +767,13 @@ where
///
/// [`Toggler`]: crate::Toggler
pub fn toggler<'a, Message, Theme, Renderer>(
- label: impl Into<Option<String>>,
is_checked: bool,
- f: impl Fn(bool) -> Message + 'a,
) -> Toggler<'a, Message, Theme, Renderer>
where
Theme: toggler::Catalog + 'a,
Renderer: core::text::Renderer,
{
- Toggler::new(label, is_checked, f)
+ Toggler::new(is_checked)
}
/// Creates a new [`TextInput`].
@@ -889,6 +948,41 @@ where
crate::Svg::new(handle)
}
+/// Creates an [`Element`] that displays the iced logo with the given `text_size`.
+///
+/// Useful for showing some love to your favorite GUI library in your "About" screen,
+/// for instance.
+#[cfg(feature = "svg")]
+pub fn iced<'a, Message, Theme, Renderer>(
+ text_size: impl Into<Pixels>,
+) -> Element<'a, Message, Theme, Renderer>
+where
+ Message: 'a,
+ Renderer: core::Renderer
+ + core::text::Renderer<Font = core::Font>
+ + core::svg::Renderer
+ + 'a,
+ Theme: text::Catalog + crate::svg::Catalog + 'a,
+{
+ use crate::core::{Alignment, Font};
+ use crate::svg;
+ use once_cell::sync::Lazy;
+
+ static LOGO: Lazy<svg::Handle> = Lazy::new(|| {
+ svg::Handle::from_memory(include_bytes!("../assets/iced-logo.svg"))
+ });
+
+ let text_size = text_size.into();
+
+ row![
+ svg(LOGO.clone()).width(text_size * 1.3),
+ text("iced").size(text_size).font(Font::MONOSPACE)
+ ]
+ .spacing(text_size.0 / 3.0)
+ .align_y(Alignment::Center)
+ .into()
+}
+
/// Creates a new [`Canvas`].
///
/// [`Canvas`]: crate::Canvas
@@ -930,12 +1024,12 @@ where
/// Focuses the previous focusable widget.
pub fn focus_previous<T>() -> Task<T> {
- Task::effect(Action::widget(operation::focusable::focus_previous()))
+ task::effect(Action::widget(operation::focusable::focus_previous()))
}
/// Focuses the next focusable widget.
pub fn focus_next<T>() -> Task<T> {
- Task::effect(Action::widget(operation::focusable::focus_next()))
+ task::effect(Action::widget(operation::focusable::focus_next()))
}
/// A container intercepting mouse events.