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