From c8778a282e613f75861e0cdb257361af4a98add8c5705c0d96b2e8edd4dd7d05 Mon Sep 17 00:00:00 2001 From: Alex Wied <2+alex@noreply.code.graphofliberty.org> Date: Tue, 28 Jul 2026 15:09:33 -0400 Subject: [PATCH] . --- publish/src/app.rs | 10 +++++++++- publish/src/main.rs | 1 + publish/src/theme/mod.rs | 1 + publish/src/theme/styles.rs | 19 +++++++++++++++++++ publish/src/widget/iri_input.rs | 18 +++++++++++++----- 5 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 publish/src/theme/mod.rs create mode 100644 publish/src/theme/styles.rs diff --git a/publish/src/app.rs b/publish/src/app.rs index 311323c..6338016 100644 --- a/publish/src/app.rs +++ b/publish/src/app.rs @@ -100,6 +100,7 @@ pub(crate) struct Publisher { abbreviated_datatypes: Vec, window_id: window::Id, url_input: String, + url_input_valid: bool, navigator: Navigator, document: RdfSource>, hovered_row: Option, @@ -157,6 +158,7 @@ impl Publisher { abbreviated_datatypes, window_id: id, url_input: starting_url.to_string(), + url_input_valid: true, navigator, document, hovered_row: None, @@ -268,6 +270,11 @@ impl Publisher { } } Message::URLInputChanged(value) => { + if Url::parse(&value).is_ok() { + self.url_input_valid = true; + } else { + self.url_input_valid = false; + } self.url_input = value; } Message::URLInputSubmitted => { @@ -868,7 +875,8 @@ impl Publisher { let address_input = iri_input(&self.curie_helper, "URL", None, &self.url_input) .on_input(Message::URLInputChanged) .on_submit(Message::URLInputSubmitted) - .on_control_click(Message::OpenQueryWindow(SearchResultClickAction::URLInput)); + .on_control_click(Message::OpenQueryWindow(SearchResultClickAction::URLInput)) + .style(crate::theme::styles::text_input::required(!self.url_input_valid)); let mut rows: Vec> = vec![]; rows = self diff --git a/publish/src/main.rs b/publish/src/main.rs index 1c96292..6b3ae73 100644 --- a/publish/src/main.rs +++ b/publish/src/main.rs @@ -4,6 +4,7 @@ mod rdf; mod windows; mod widget; mod navigator; +mod theme; use crate::app::Publisher; use tracing_subscriber::layer::SubscriberExt; diff --git a/publish/src/theme/mod.rs b/publish/src/theme/mod.rs new file mode 100644 index 0000000..00d9633 --- /dev/null +++ b/publish/src/theme/mod.rs @@ -0,0 +1 @@ +pub mod styles; \ No newline at end of file diff --git a/publish/src/theme/styles.rs b/publish/src/theme/styles.rs new file mode 100644 index 0000000..b38062b --- /dev/null +++ b/publish/src/theme/styles.rs @@ -0,0 +1,19 @@ +pub mod text_input { + use iced::{color, Theme}; + use iced::widget::text_input; + use iced::widget::text_input::{Status, Style}; + + pub fn required(invalid: bool) -> impl Fn(&Theme, Status) -> Style { + move |theme: &Theme, status| { + let danger = color!(255, 88, 97); + let default = text_input::default(theme, status); + let border = if invalid && matches!(status, Status::Focused { .. }) { + default.border.color(danger) + } else { + default.border + }; + + Style { border, ..default } + } + } +} \ No newline at end of file diff --git a/publish/src/widget/iri_input.rs b/publish/src/widget/iri_input.rs index be0c144..7c7820e 100644 --- a/publish/src/widget/iri_input.rs +++ b/publish/src/widget/iri_input.rs @@ -1,12 +1,11 @@ -use iced::{alignment, keyboard, widget, Element, Event, Length, Rectangle, Size}; -use iced::advanced::{mouse, text, Shell}; +use iced::{alignment, keyboard, widget, Element, Event, Length, Rectangle, Size, Theme, Background, Border}; +use iced::advanced::{mouse, text, Shell, renderer}; use iced::advanced::layout::{Limits, Node}; -use iced::advanced::renderer::Style; use iced::advanced::{Layout, Widget}; use iced::advanced::widget::{tree, Tree}; use iced::clipboard::Content; use iced::mouse::{Cursor, Interaction}; -use iced::widget::text_input::Catalog; +use iced::widget::text_input::{Catalog, Status, Style, StyleFn}; use crate::rdf::curie::CurieHelper; pub struct State { @@ -79,6 +78,15 @@ where self.text_input = self.text_input.on_submit(message); self } + + #[must_use] + pub fn style(mut self, style: impl Fn(&Theme, Status) -> Style + 'a) -> Self + where + Theme::Class<'a>: From>, + { + self.text_input = self.text_input.style(style); + self + } } impl<'a, Message, Theme, Renderer> From> @@ -116,7 +124,7 @@ where Widget::layout(&mut self.text_input, &mut tree.children[0], renderer, limits) } - fn draw(&self, tree: &Tree, renderer: &mut Renderer, theme: &Theme, style: &Style, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle) { + fn draw(&self, tree: &Tree, renderer: &mut Renderer, theme: &Theme, style: &renderer::Style, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle) { Widget::draw(&self.text_input, &tree.children[0], renderer, theme, style, layout, cursor, viewport) }