Updated word display #19

Merged
micialware merged 13 commits from updated-word-display into master 2026-09-13 17:42:58 +03:00
3 changed files with 127 additions and 123 deletions
Showing only changes of commit adb6388ee2 - Show all commits

No files matched your search

-6
View File
@@ -21,7 +21,6 @@ use crate::pages::repetition_settings::{RepetitionSettingsMessage, RepetitionSet
use crate::pages::repetitions::{RepetitionsMessage, RepetitionsState}; use crate::pages::repetitions::{RepetitionsMessage, RepetitionsState};
use crate::pages::selector::{SelectorMessage, SelectorState}; use crate::pages::selector::{SelectorMessage, SelectorState};
use crate::pages::sync::{SyncMessage, SyncState}; use crate::pages::sync::{SyncMessage, SyncState};
use crate::pages::word::{WordMessage, WordState};
use crate::pages::writing::{WritingMessage, WritingState}; use crate::pages::writing::{WritingMessage, WritingState};
use crate::state_navigate_handle; use crate::state_navigate_handle;
use crate::state_update; use crate::state_update;
@@ -56,7 +55,6 @@ pub enum RootMessage {
Randomizer(RandomizerMessage), Randomizer(RandomizerMessage),
Repetitions(RepetitionsMessage), Repetitions(RepetitionsMessage),
Repetition(RepetitionMessage), Repetition(RepetitionMessage),
Word(WordMessage),
Sync(SyncMessage), Sync(SyncMessage),
History(HistoryMessage), History(HistoryMessage),
RepetitionSettings(RepetitionSettingsMessage), RepetitionSettings(RepetitionSettingsMessage),
@@ -78,7 +76,6 @@ pub enum Page {
Randomizer(RandomizerState), Randomizer(RandomizerState),
Repetitions(RepetitionsState), Repetitions(RepetitionsState),
Repetition(RepetitionState), Repetition(RepetitionState),
Word(WordState),
Sync(SyncState), Sync(SyncState),
History(HistoryState), History(HistoryState),
RepetitionSettings(RepetitionSettingsState), RepetitionSettings(RepetitionSettingsState),
@@ -182,7 +179,6 @@ impl ScreenState {
Randomizer, Randomizer,
Repetitions, Repetitions,
Repetition, Repetition,
Word,
Sync, Sync,
History, History,
RepetitionSettings, RepetitionSettings,
@@ -206,7 +202,6 @@ impl ScreenState {
Randomizer, Randomizer,
Repetitions, Repetitions,
Repetition, Repetition,
Word,
Sync, Sync,
History, History,
RepetitionSettings, RepetitionSettings,
@@ -227,7 +222,6 @@ impl ScreenState {
Randomizer, Randomizer,
Repetitions, Repetitions,
Repetition, Repetition,
Word,
Sync, Sync,
History, History,
RepetitionSettings, RepetitionSettings,
+121 -100
View File
@@ -1,16 +1,18 @@
use crate::app::AppState; use crate::app::AppState;
use crate::data::Id;
use crate::data::entities::{EntityHandle, WordData, WordGroup}; use crate::data::entities::{EntityHandle, WordData, WordGroup};
use crate::data::repositories::{Query, Repository}; use crate::data::repositories::{Query, Repository};
use crate::data::Id;
use crate::data_provider::word_groups::{WordGroupDataLayer, WordGroupRepositoryInner}; use crate::data_provider::word_groups::{WordGroupDataLayer, WordGroupRepositoryInner};
use crate::data_provider::words::WordDataLayer; use crate::data_provider::words::WordDataLayer;
use crate::data_provider::words::WordRepositoryInner; use crate::data_provider::words::WordRepositoryInner;
use crate::navigation::Page::{Import, Word}; use crate::navigation::Page::Import;
use crate::navigation::{KeyPressedPage, NavigatedPage, Page, RootMessage}; use crate::navigation::{KeyPressedPage, NavigatedPage, Page, RootMessage};
use crate::pages::dictionary::BasicWordFields::*;
use crate::pages::dictionary::DictionaryMessage::*; use crate::pages::dictionary::DictionaryMessage::*;
use crate::pages::dictionary::SelectionChangeDirection::*;
use crate::pages::dictionary_quiz::DictionaryQuizState; use crate::pages::dictionary_quiz::DictionaryQuizState;
use crate::pages::import::ImportState; use crate::pages::import::ImportState;
use crate::pages::word::WordState; use crate::pages::word::{WordEditor, WordMessage};
use crate::push_error_task; use crate::push_error_task;
use crate::styling::*; use crate::styling::*;
use crate::widgets::hard_mouse_area::hard_mouse_area; use crate::widgets::hard_mouse_area::hard_mouse_area;
@@ -22,22 +24,20 @@ use iced::widget::button::Style;
use iced::widget::button::{danger, text}; use iced::widget::button::{danger, text};
use iced::widget::operation::focus; use iced::widget::operation::focus;
use iced::widget::space::horizontal; use iced::widget::space::horizontal;
use iced::widget::text_input::Status::Active;
use iced::widget::text_input::default; use iced::widget::text_input::default;
use iced::widget::text_input::Status::Active;
use iced::widget::*; use iced::widget::*;
use iced::{Border, Color, Shadow, Task}; use iced::{Border, Color, Shadow, Task};
use iced_core::Length::Fill;
use iced_core::keyboard; use iced_core::keyboard;
use iced_core::keyboard::Event;
use iced_core::keyboard::Key::Named;
use iced_core::keyboard::key::Physical::Code; use iced_core::keyboard::key::Physical::Code;
use iced_core::keyboard::{Event, Modifiers};
use iced_core::keyboard::Key::Named;
use iced_core::Length::{Fill, FillPortion};
use log::info; use log::info;
use rand::random_range; use rand::random_range;
use std::ops::Add; use std::ops::Add;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use crate::pages::dictionary::BasicWordFields::*;
use crate::pages::dictionary::SelectionChangeDirection::*;
pub struct DictionaryState { pub struct DictionaryState {
state: AppState, state: AppState,
@@ -53,6 +53,7 @@ pub struct DictionaryState {
displayed_words_query: Query<WordData, WordRepositoryInner, WordDataLayer>, displayed_words_query: Query<WordData, WordRepositoryInner, WordDataLayer>,
groups_query: Query<WordGroup, WordGroupRepositoryInner, WordGroupDataLayer>, groups_query: Query<WordGroup, WordGroupRepositoryInner, WordGroupDataLayer>,
selected_cell: Option<(EntityHandle<WordData>, BasicWordFields, usize)>, selected_cell: Option<(EntityHandle<WordData>, BasicWordFields, usize)>,
word_editor: Option<WordEditor>,
} }
#[derive(Clone)] #[derive(Clone)]
@@ -61,7 +62,8 @@ pub enum DictionaryMessage {
SetTags(EntityHandle<WordData>, String), SetTags(EntityHandle<WordData>, String),
SetKey(EntityHandle<WordData>, String), SetKey(EntityHandle<WordData>, String),
SetValue(EntityHandle<WordData>, String), SetValue(EntityHandle<WordData>, String),
WordAction(EntityHandle<WordData>), ExtendedEdit(EntityHandle<WordData>),
DeleteWord(EntityHandle<WordData>),
NewWord, NewWord,
Include(EntityHandle<WordData>, bool), Include(EntityHandle<WordData>, bool),
IncludeTag(String, bool), IncludeTag(String, bool),
@@ -81,6 +83,7 @@ pub enum DictionaryMessage {
SelectField(EntityHandle<WordData>, BasicWordFields, usize), SelectField(EntityHandle<WordData>, BasicWordFields, usize),
EditField(String), EditField(String),
ChangeSelectedField(SelectionChangeDirection), ChangeSelectedField(SelectionChangeDirection),
EditorAction(WordMessage),
} }
#[derive(Clone, PartialEq, Eq, Hash, Copy)] #[derive(Clone, PartialEq, Eq, Hash, Copy)]
@@ -122,11 +125,7 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
self.state.clone(), self.state.clone(),
))); )));
} }
if let WordAction(handle) = message
&& handle.real()
{
return Some(Word(WordState::new(*handle, self.state.clone())));
}
if let GotoImport = message { if let GotoImport = message {
return Some(Import(ImportState::new(self.state.clone()))); return Some(Import(ImportState::new(self.state.clone())));
} }
@@ -186,14 +185,8 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
return self.launch_auto_save_offset(i); return self.launch_auto_save_offset(i);
} }
WordAction(i) => { ExtendedEdit(i) => {
let mut dictionary = self.state.dictionary.write(); self.word_editor = Some(WordEditor::new(i, self.state.clone()));
if let Err(err) = dictionary.delete(i) {
return push_error_task!(err);
}
self.displayed_words_query.load(&dictionary);
} }
Include(i, b) => { Include(i, b) => {
if b { if b {
@@ -308,13 +301,13 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
let mut dictionary = self.state.dictionary.write(); let mut dictionary = self.state.dictionary.write();
let word = dictionary.get_mut_static(selected.0).unwrap(); let word = dictionary.get_mut_static(selected.0).unwrap();
match selected.1 { match selected.1 {
BasicWordFields::Key => { Key => {
word.key = value; word.key = value;
} }
BasicWordFields::Value => { Value => {
word.value = value; word.value = value;
} }
BasicWordFields::Tags => { Tags => {
word.key = value; word.key = value;
} }
} }
@@ -324,14 +317,22 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
} }
} }
ChangeSelectedField(change) => { ChangeSelectedField(change) => {
return if let Some(selected) = self.selected_cell.clone() { return if let Some(selected) = self.selected_cell {
let update_vertical = move |mut dir: bool| { let update_vertical = move |mut dir: bool| {
if self.reverse_list { if self.reverse_list {
dir = !dir; dir = !dir;
} }
let new_index = if dir { selected.2.saturating_add(1) } else { selected.2.saturating_sub(1) }; let new_index = if dir {
selected.2.saturating_add(1)
} else {
selected.2.saturating_sub(1)
};
if new_index < self.displayed_words_query.len() { if new_index < self.displayed_words_query.len() {
return SelectField(self.displayed_words_query.get(new_index).unwrap(), selected.1, new_index); return SelectField(
self.displayed_words_query.get(new_index).unwrap(),
selected.1,
new_index,
);
} }
SelectField(selected.0, selected.1, selected.2) SelectField(selected.0, selected.1, selected.2)
@@ -340,7 +341,8 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
let update_horizontal = move |dir: bool| { let update_horizontal = move |dir: bool| {
let current = selected.1; let current = selected.1;
let delta = if dir { 1 } else { -1 }; let delta = if dir { 1 } else { -1 };
let mut index = FIELDS.iter().position(|&f| f == current).unwrap() as i8 + delta; let mut index =
FIELDS.iter().position(|&f| f == current).unwrap() as i8 + delta;
if index < 0 { if index < 0 {
index = (FIELDS.len() - 1) as i8; index = (FIELDS.len() - 1) as i8;
} }
@@ -351,22 +353,26 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
}; };
Task::done(RootMessage::Dictionary(match change { Task::done(RootMessage::Dictionary(match change {
Next => { Next => update_vertical(true),
update_vertical(true) Previous => update_vertical(false),
} Forward => update_horizontal(true),
Previous => { Backward => update_horizontal(false),
update_vertical(false)
}
Forward => {
update_horizontal(true)
}
Backward => {
update_horizontal(false)
}
})) }))
} else { } else {
Task::none() Task::none()
};
} }
DeleteWord(i) => {
let mut dictionary = self.state.dictionary.write();
if let Err(err) = dictionary.delete(i) {
return push_error_task!(err);
}
self.displayed_words_query.load(&dictionary);
}
EditorAction(action) => {
self.word_editor.as_mut().unwrap().update(action);
} }
} }
@@ -379,37 +385,15 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
iced::widget::column![ iced::widget::column![
self.groups_panel(), self.groups_panel(),
row![horizontal().width(8), self.words_list(),], row![horizontal().width(8), self.words_list(),],
{ self.selection_editor(),
let mut display = "".to_string();
if let Some(selected) = self.selected_cell.as_ref() {
let mut dictionary = self.state.dictionary.write();
let word = dictionary.get_mut_static(selected.0).unwrap();
match selected.1 {
BasicWordFields::Key => {
display = word.key.clone();
}
BasicWordFields::Value => {
display = word.value.clone();
}
BasicWordFields::Tags => {
display = word.tags.clone();
}
}
}
text_input("", display.as_str())
.width(Fill)
.id(iced::widget::Id::new("editor"))
.on_input(EditField)
},
row![ row![
self.add_word_button(), self.add_word_button(),
horizontal().width(Fill), horizontal().width(Fill),
button("Импорт").style(text).on_press(GotoImport), button("Импорт").style(text).on_press(GotoImport),
] ]
] ]
.spacing(5), .spacing(5).width(FillPortion(4)),
self.filters(), self.right_panel(),
] ]
.spacing(DEFAULT_SPACING) .spacing(DEFAULT_SPACING)
.into(), .into(),
@@ -436,6 +420,7 @@ impl DictionaryState {
displayed_words_query: words_query, displayed_words_query: words_query,
groups_query, groups_query,
selected_cell: None, selected_cell: None,
word_editor: None,
}; };
result.init(); result.init();
@@ -496,11 +481,11 @@ impl DictionaryState {
let mut selection = None; let mut selection = None;
if let Some(cell) = self.selected_cell.as_ref() { if let Some(cell) = self.selected_cell.as_ref()
if cell.0 == *word_handle { && cell.0 == *word_handle
{
selection = Some(cell.1); selection = Some(cell.1);
} }
}
let word_line_data = WordLineState { let word_line_data = WordLineState {
is_included: self.included.contains(word_handle), is_included: self.included.contains(word_handle),
@@ -540,7 +525,7 @@ impl DictionaryState {
default_style.border.radius = 0.0.into(); default_style.border.radius = 0.0.into();
if selected { if selected {
default_style.border.color = x.extended_palette().secondary.base.color; default_style.border.color = x.extended_palette().secondary.base.color;
default_style.border.width = 3.0_f32.into(); default_style.border.width = 3.0_f32;
} }
default_style default_style
}) })
@@ -550,36 +535,32 @@ impl DictionaryState {
hard_mouse_area(field( hard_mouse_area(field(
"Слово", "Слово",
&data.key, &data.key,
data.selection.is_some() && data.selection.unwrap() == BasicWordFields::Key, data.selection.is_some() && data.selection.unwrap() == Key,
)) ))
.on_press(SelectField(data.handle, BasicWordFields::Key, data.number)), .on_press(SelectField(data.handle, Key, data.number)),
); );
line = line.push( line = line.push(
hard_mouse_area(field( hard_mouse_area(field(
"Перевод", "Перевод",
&data.value, &data.value,
data.selection.is_some() && data.selection.unwrap() == BasicWordFields::Value, data.selection.is_some() && data.selection.unwrap() == Value,
)) ))
.on_press(SelectField( .on_press(SelectField(data.handle, Value, data.number)),
data.handle,
BasicWordFields::Value,
data.number,
)),
); );
line = line.push( line = line.push(
hard_mouse_area(field( hard_mouse_area(field(
"Теги", "Теги",
&data.tags, &data.tags,
data.selection.is_some() && data.selection.unwrap() == BasicWordFields::Tags, data.selection.is_some() && data.selection.unwrap() == Tags,
)) ))
.on_press(SelectField(data.handle, BasicWordFields::Tags, data.number)), .on_press(SelectField(data.handle, Tags, data.number)),
); );
let line_button = || { let line_button = || {
if !data.handle.real() { if !data.handle.real() {
return button("-") return button("-")
.on_press(WordAction(data.handle)) .on_press(ExtendedEdit(data.handle))
.style(|_x: &Theme, _status: button::Status| Style { .style(|_x: &Theme, _status: button::Status| Style {
background: None, background: None,
text_color: Color::BLACK, text_color: Color::BLACK,
@@ -591,13 +572,21 @@ impl DictionaryState {
} }
button("") button("")
.on_press(WordAction(data.handle)) .on_press(ExtendedEdit(data.handle))
.style(button::primary) .style(button::primary)
.width(15) .width(15)
}; };
line.push(line_button()).push(space().width(10)) line.push(line_button()).push(space().width(10))
} }
fn right_panel(&self) -> iced::Element<'_, DictionaryMessage> {
if let Some(editor) = &self.word_editor {
container(editor.view().map(EditorAction)).width(FillPortion(3)).into()
} else {
self.filters()
}
}
fn filters(&self) -> iced::Element<'_, DictionaryMessage> { fn filters(&self) -> iced::Element<'_, DictionaryMessage> {
let dict = &self.state.dictionary.read(); let dict = &self.state.dictionary.read();
@@ -619,7 +608,7 @@ impl DictionaryState {
.on_press(GotoTest) .on_press(GotoTest)
.width(Fill), .width(Fill),
] ]
.width(250) .width(FillPortion(1))
.spacing(DEFAULT_SPACING) .spacing(DEFAULT_SPACING)
.into() .into()
} }
@@ -719,6 +708,31 @@ impl DictionaryState {
info!("Time {}", time.elapsed().as_micros()); info!("Time {}", time.elapsed().as_micros());
} }
fn selection_editor(&self) -> iced::Element<'_, DictionaryMessage> {
let mut display = "".to_string();
if let Some(selected) = self.selected_cell.as_ref() {
let mut dictionary = self.state.dictionary.write();
let word = dictionary.get_mut_static(selected.0).unwrap();
match selected.1 {
Key => {
display = word.key.clone();
}
Value => {
display = word.value.clone();
}
Tags => {
display = word.tags.clone();
}
}
}
text_input("", display.as_str())
.width(Fill)
.id(iced::widget::Id::new("editor"))
.on_input(EditField)
.into()
}
fn groups_panel(&self) -> iced::Element<'_, DictionaryMessage> { fn groups_panel(&self) -> iced::Element<'_, DictionaryMessage> {
let mut row = Row::new(); let mut row = Row::new();
row = row.push(button("+").style(text).on_press(CreateGroup)); row = row.push(button("+").style(text).on_press(CreateGroup));
@@ -779,29 +793,36 @@ impl KeyPressedPage for DictionaryState {
modified_key: modifier, modified_key: modifier,
physical_key: pk, physical_key: pk,
location: _, location: _,
modifiers: _, modifiers: mods,
text: _, text: _,
repeat: _, repeat: _,
} = message } = message
&& let Code(code) = pk && let Code(code) = pk
{ {
return match code { return match code {
keyboard::key::Code::ArrowDown => Task::done(RootMessage::Dictionary( keyboard::key::Code::ArrowDown => {
ChangeSelectedField(SelectionChangeDirection::Next), Task::done(RootMessage::Dictionary(ChangeSelectedField(Next)))
)),
keyboard::key::Code::ArrowUp => Task::done(RootMessage::Dictionary(
ChangeSelectedField(SelectionChangeDirection::Previous),
)),
keyboard::key::Code::Tab => {
if let Named(keyboard::key::Named::Alt) = modifier {
Task::done(RootMessage::Dictionary(ChangeSelectedField(
SelectionChangeDirection::Backward,
)))
} else {
Task::done(RootMessage::Dictionary(ChangeSelectedField(
SelectionChangeDirection::Forward,
)))
} }
keyboard::key::Code::ArrowUp => {
Task::done(RootMessage::Dictionary(ChangeSelectedField(Previous)))
}
keyboard::key::Code::Tab => {
return if *mods == Modifiers::CTRL && let Some(selected) = self.selected_cell {
Task::done(RootMessage::Dictionary(ExtendedEdit(selected.0)))
} else if let Named(keyboard::key::Named::Alt) = modifier {
Task::done(RootMessage::Dictionary(ChangeSelectedField(Backward)))
} else {
Task::done(RootMessage::Dictionary(ChangeSelectedField(Forward)))
}
}
keyboard::key::Code::Escape => {
if self.word_editor.is_some() {
self.word_editor = None;
}else if self.selected_cell.is_some() {
self.selected_cell = None;
}
Task::none()
} }
_ => Task::none(), _ => Task::none(),
}; };
+6 -17
View File
@@ -8,22 +8,13 @@ use iced::widget::button::danger;
use iced::widget::{button, column, row, space, text, text_input}; use iced::widget::{button, column, row, space, text, text_input};
use iced::{Element, Fill, Task}; use iced::{Element, Fill, Task};
pub struct WordState { pub struct WordEditor {
state: AppState, state: AppState,
handle: EntityHandle<WordData>, handle: EntityHandle<WordData>,
} }
impl NavigatedPage<WordMessage> for WordState { impl WordEditor {
fn navigate(&mut self, message: &WordMessage) -> Option<Page> { pub(crate) fn update(&mut self, message: WordMessage) {
if let Back = message {
Some(PreviousPage)
} else {
None
}
}
fn navigated(&mut self) {}
fn update(&mut self, message: WordMessage) -> Task<RootMessage> {
// match message { // match message {
// Back => {} // Back => {}
// Save => { // Save => {
@@ -60,10 +51,9 @@ impl NavigatedPage<WordMessage> for WordState {
// self.word.additional.remove(key.as_str()); // self.word.additional.remove(key.as_str());
// } // }
// } // }
Task::none()
} }
fn view(&self) -> Element<'_, WordMessage> { pub(crate) fn view(&self) -> Element<'_, WordMessage> {
// let mut fast_add = row![]; // let mut fast_add = row![];
// if !self.word.additional.contains_key("reading") { // if !self.word.additional.contains_key("reading") {
// fast_add = fast_add.push( // fast_add = fast_add.push(
@@ -129,13 +119,13 @@ impl NavigatedPage<WordMessage> for WordState {
} }
} }
impl WordState { impl WordEditor {
pub fn new(handle: EntityHandle<WordData>, state: AppState) -> Self { pub fn new(handle: EntityHandle<WordData>, state: AppState) -> Self {
Self { state, handle } Self { state, handle }
} }
} }
impl WordState { impl WordEditor {
fn get_view_for_more(&self, value: (&String, &String)) -> Element<'_, WordMessage> { fn get_view_for_more(&self, value: (&String, &String)) -> Element<'_, WordMessage> {
match value.0.as_str() { match value.0.as_str() {
"reading" => self.reading_field(value.1), "reading" => self.reading_field(value.1),
@@ -180,7 +170,6 @@ impl WordState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum WordMessage { pub enum WordMessage {
Save, Save,
Back,
Delete, Delete,
SetTags(String), SetTags(String),
SetKey(String), SetKey(String),