This commit is contained in:
Alex Wied
2026-06-26 11:28:44 -04:00
parent 42dea77976
commit 2ef8a74b5f
3 changed files with 122 additions and 62 deletions
+10 -14
View File
@@ -8,10 +8,7 @@ use iced::widget::button::Style;
use iced::widget::grid::Sizing;
use iced::widget::{button, center, column, combo_box, container, grid, mouse_area, opaque, pick_list, row, scrollable, space, stack, table, text, text_input, toggler};
use iced::window::Settings;
use iced::{Background, Color, Element, Length, Subscription, Task, color, window, keyboard};
//use iced::advanced::Widget;
use iced::keyboard::{Event, Key};
use iced::keyboard::key::Named::Control;
use iced::{Background, Color, Element, Length, Subscription, Task, color, window};
use iced::widget::text::Wrapping;
use ldp::middleware::BasicAuthMiddleware;
use ldp::model::{KeyedDataset, QuadKey};
@@ -28,7 +25,6 @@ use crate::widget::iri_input::iri_input;
#[derive(Debug, Clone)]
pub(crate) enum Message {
None,
Foo(QuadKey),
Traverse,
IndexRdfSource(RdfSource<Dataset>),
CommitIndex,
@@ -554,7 +550,8 @@ impl Publisher {
let value = term
.value_as_named_node()
.map(|node| self.ontology.abbreviate(node))
//.map(|node| self.ontology.abbreviate(node))
.map(|node| node.as_str().to_string())
.unwrap_or(term.value().to_string());
let value_alignment = term
@@ -565,10 +562,10 @@ impl Publisher {
})
.unwrap_or(Horizontal::Left);
let value_input_base = text_input("Value", value.as_str())
.align_x(value_alignment);
/*let value_input_base = text_input("Value", value.as_str())
.align_x(value_alignment);*/
let value_input = if !state.read_only {
/*let value_input = if !state.read_only {
let is_named_node = term.is_named_node();
value_input_base.on_input(move |input| {
let expanded_input = if is_named_node {
@@ -584,12 +581,11 @@ impl Publisher {
})
} else {
value_input_base
};
};*/
let foo = iri_input(value_input)
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(
key,
)));
let foo = iri_input(self.ontology.prefixes(), "Object", value.as_str())
.on_input(move |value| Message::ValueUpdated(key, value))
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(key)));
/*let search_launcher = if term.is_named_node() && !state.read_only {
Some(container(
+39 -32
View File
@@ -4,43 +4,46 @@ use oxigraph::io::{RdfFormat, RdfParser};
use oxigraph::model::vocab::{rdf, rdfs, xsd};
use oxigraph::model::{Dataset, GraphName, LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term, TermRef, Triple, TripleRef};
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
use std::collections::{HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::fmt::Display;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use oxigraph::store::Store;
use crate::rdf::materialize;
const PREFIXES: &[(&str, &str)] = &[
("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"),
("rdfs", "http://www.w3.org/2000/01/rdf-schema#"),
("owl", "http://www.w3.org/2002/07/owl#"),
("xsd", "http://www.w3.org/2001/XMLSchema#"),
("ldp", "http://www.w3.org/ns/ldp#"),
("dc", "http://purl.org/dc/elements/1.1/"),
("posix", "http://www.w3.org/ns/posix/stat#"),
(
"ebucore",
"http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#",
),
("premis", "http://www.loc.gov/premis/rdf/v1#"),
("premis3", "http://www.loc.gov/premis/rdf/v3/"),
("dcterms", "http://purl.org/dc/terms/"),
("fedora", "http://fedora.info/definitions/v4/repository#"),
("rdaa", "http://rdaregistry.info/Elements/a/"),
("rdaad", "http://rdaregistry.info/Elements/a/datatype/"),
("rdac", "http://rdaregistry.info/Elements/c/"),
("rdae", "http://rdaregistry.info/Elements/e/"),
("rdai", "http://rdaregistry.info/Elements/i/"),
("rdam", "http://rdaregistry.info/Elements/m/"),
("rdan", "http://rdaregistry.info/Elements/n/"),
("rdap", "http://rdaregistry.info/Elements/p/"),
("rdat", "http://rdaregistry.info/Elements/t/"),
("rdaw", "http://rdaregistry.info/Elements/w/"),
("rdax", "http://rdaregistry.info/Elements/x/"),
("schema", "https://schema.org/"),
("quill", "http://fedora.quill.lan/rest/"),
("gl", "https://graphofliberty.org/2026/04/ont/"),
];
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
BTreeMap::from_iter([
("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"),
("rdfs", "http://www.w3.org/2000/01/rdf-schema#"),
("owl", "http://www.w3.org/2002/07/owl#"),
("xsd", "http://www.w3.org/2001/XMLSchema#"),
("ldp", "http://www.w3.org/ns/ldp#"),
("dc", "http://purl.org/dc/elements/1.1/"),
("posix", "http://www.w3.org/ns/posix/stat#"),
(
"ebucore",
"http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#",
),
("premis", "http://www.loc.gov/premis/rdf/v1#"),
("premis3", "http://www.loc.gov/premis/rdf/v3/"),
("dcterms", "http://purl.org/dc/terms/"),
("fedora", "http://fedora.info/definitions/v4/repository#"),
("rdaa", "http://rdaregistry.info/Elements/a/"),
("rdaad", "http://rdaregistry.info/Elements/a/datatype/"),
("rdac", "http://rdaregistry.info/Elements/c/"),
("rdae", "http://rdaregistry.info/Elements/e/"),
("rdai", "http://rdaregistry.info/Elements/i/"),
("rdam", "http://rdaregistry.info/Elements/m/"),
("rdan", "http://rdaregistry.info/Elements/n/"),
("rdap", "http://rdaregistry.info/Elements/p/"),
("rdat", "http://rdaregistry.info/Elements/t/"),
("rdaw", "http://rdaregistry.info/Elements/w/"),
("rdax", "http://rdaregistry.info/Elements/x/"),
("schema", "https://schema.org/"),
("quill", "http://fedora.quill.lan/rest/"),
("gl", "https://graphofliberty.org/2026/04/ont/"),
].map(|(k, v)| (k.to_string(), v.to_string())))
});
pub struct OntologyBuilder {
path: Option<PathBuf>,
@@ -256,6 +259,10 @@ impl Ontology {
}
}
pub fn prefixes(&self) -> &BTreeMap<String, String> {
&*PREFIXES
}
/*pub fn info(&self, node: NamedNodeRef<'_>) -> Option<&IriInformation> {
let node = node.into_owned();
self.iri_info.get(&node)
+73 -16
View File
@@ -1,3 +1,4 @@
use std::collections::BTreeMap;
use iced::{keyboard, Element, Event, Length, Rectangle, Size};
use iced::advanced::{mouse, text, Shell};
use iced::advanced::layout::{Limits, Node};
@@ -7,28 +8,79 @@ use iced::advanced::widget::{tree, Tree};
use iced::mouse::{Cursor, Interaction};
use iced::widget::text_input::Catalog;
use iced::widget::TextInput;
use tracing::info;
pub struct State {
value: String,
control: bool,
}
pub struct IriInput<'a, Message, Theme = iced::Theme, Renderer = iced::Renderer>
where
Theme: Catalog,
Renderer: text::Renderer {
text_input: TextInput<'a, Message, Theme, Renderer>,
on_control_click: Option<Message>,
}
impl<'a, Message, Theme, Renderer> IriInput<'a, Message, Theme, Renderer>
pub struct IriInput<'a, Message, Theme, Renderer>
where
Theme: Catalog,
Renderer: text::Renderer,
{
prefixes: &'a BTreeMap<String, String>,
placeholder: String,
iri: String,
on_control_click: Option<Message>,
on_input: Option<Box<dyn Fn(String) -> Message + 'a>>,
text_input: TextInput<'a, Message, Theme, Renderer>,
}
fn abbreviate(prefixes: &BTreeMap<String, String>, iri: &str) -> Option<String> {
for (name, base) in prefixes {
if let Some(local_name) = iri.strip_prefix(base) {
return if local_name.is_empty() {
Some(format!("{name}:"))
} else {
Some(format!("{name}:{local_name}"))
};
}
}
None
}
fn expand(prefixes: &BTreeMap<String, String>, abbreviated_iri: &str) -> Option<String> {
let (prefix, name) = abbreviated_iri.split_once(':')?;
prefixes
.get(prefix)
.map(|base| format!("{base}{name}"))
}
impl<'a, Message, Theme, Renderer> IriInput<'a, Message, Theme, Renderer>
where
Message: Clone,
Theme: Catalog,
Renderer: text::Renderer,
{
pub fn new(prefixes: &'a BTreeMap<String, String>, placeholder: &str, iri: &str) -> Self {
let display_value = abbreviate(prefixes, iri).unwrap_or_else(|| iri.to_string());
let text_input = TextInput::new(placeholder, &display_value);
Self {
prefixes,
placeholder: placeholder.to_string(),
iri: iri.to_string(),
on_control_click: None,
on_input: None,
text_input,
}
}
pub fn on_control_click(mut self, on_control_click: Message) -> Self {
self.on_control_click = Some(on_control_click);
self
}
pub fn on_input(mut self, on_input: impl Fn(String) -> Message + 'a) -> Self {
let iri = self.iri.clone();
let wrapped = move |value: String| {
let expanded_value = expand(self.prefixes, &value);
on_input(expanded_value.unwrap_or_else(|| iri.clone()))
};
self.text_input = self.text_input.on_input(wrapped);
self
}
}
impl<'a, Message, Theme, Renderer> From<IriInput<'a, Message, Theme, Renderer>>
@@ -43,16 +95,13 @@ where
}
}
pub fn iri_input<Message, Theme, Renderer>(text_input: TextInput<Message, Theme, Renderer>) -> IriInput<Message, Theme, Renderer>
pub fn iri_input<'a, Message, Theme, Renderer>(prefixes: &'a BTreeMap<String, String>, placeholder: &str, iri: &str) -> IriInput<'a, Message, Theme, Renderer>
where
Message: Clone,
Theme: Catalog,
Renderer: text::Renderer,
{
IriInput {
text_input,
on_control_click: None,
}
IriInput::new(prefixes, placeholder, iri)
}
impl <Message, Theme, Renderer> Widget<Message, Theme, Renderer> for IriInput<'_, Message, Theme, Renderer>
@@ -64,6 +113,7 @@ where
fn size(&self) -> Size<Length> {
Widget::size(&self.text_input)
}
fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
Widget::layout(&mut self.text_input, &mut tree.children[0], renderer, limits)
}
@@ -78,6 +128,7 @@ where
fn state(&self) -> tree::State {
tree::State::new(State {
value: String::new(),
control: false,
})
}
@@ -96,6 +147,12 @@ where
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
if cursor.is_over(layout.bounds()) && state.control && let Some(on_control_click) = &self.on_control_click {
shell.publish(on_control_click.clone());
shell.capture_event();
}
}
Event::Keyboard(keyboard::Event::KeyPressed { text, .. }) => {
if let Some(text) = text {
state.value = text.to_string();
}
}
_ => {}
@@ -104,12 +161,12 @@ where
Widget::update(&mut self.text_input, &mut tree.children[0], event, layout, cursor, renderer, shell, viewport)
}
fn mouse_interaction(&self, tree: &Tree, layout: Layout<'_>, cursor: Cursor, _viewport: &Rectangle, _renderer: &Renderer) -> Interaction {
fn mouse_interaction(&self, tree: &Tree, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle, renderer: &Renderer) -> Interaction {
let state = tree.state.downcast_ref::<State>();
if cursor.is_over(layout.bounds()) && state.control {
Interaction::Pointer
} else {
Interaction::None
Widget::mouse_interaction(&self.text_input, tree, layout, cursor, viewport, renderer)
}
}
}