diff --git a/Cargo.lock b/Cargo.lock index d4c511d..1a3f6b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2099,6 +2099,7 @@ dependencies = [ "dirs", "hex", "iced", + "iced_core", "rand", "reqwest", "rhai", diff --git a/Cargo.toml b/Cargo.toml index 552253b..2bf81cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.1" edition = "2024" [dependencies] -iced = { version = "0.14.0", features = ["tokio"]} +iced = { version = "0.14.0", features = ["tokio",]} +iced_core = "0.14.0" rand = "0.10.1" dirs = "6.0.0" serde = { version = "1.0.228", features = ["derive"] } diff --git a/ibmplex.ttf b/ibmplex.ttf new file mode 100644 index 0000000..9add875 Binary files /dev/null and b/ibmplex.ttf differ diff --git a/src/dictionary.rs b/src/dictionary.rs index ad549f7..cea0347 100644 --- a/src/dictionary.rs +++ b/src/dictionary.rs @@ -6,7 +6,7 @@ use crate::dictionary_test::DictionaryQuizState; use crate::lang::{WordData, WordGroup}; use crate::word::WordState; use crate::Page::Word; -use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use crate::{jl_text_input, AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; use chrono::{DateTime, TimeDelta, Utc}; use iced::alignment::Vertical::Center; use iced::widget::button::Style; @@ -308,7 +308,6 @@ impl DictionaryState { } fn words_list(&self) -> iced::Element<'_, DictionaryMessage> { - let time = Instant::now(); let mut col = Column::new().width(Length::Fill); let mut range = (0..self.include_map.len()).collect::>(); @@ -346,21 +345,21 @@ impl DictionaryState { .push(space().width(10)); line = line.push( - text_input("Слово", &word.key) + jl_text_input("Слово", &word.key) .size(20) .width(Length::Fill) .on_input(move |string| DictionaryMessage::SetKey(i, string)) .on_submit(DictionaryMessage::SubmitWord(i)), ); line = line.push( - text_input("Перевод", &word.value) + jl_text_input("Перевод", &word.value) .size(20) .width(Length::Fill) .on_input(move |string| DictionaryMessage::SetValue(i, string)) .on_submit(DictionaryMessage::SubmitWord(i)), ); line = line.push( - text_input("Тэги", &word.tags) + jl_text_input("Тэги", &word.tags) .size(20) .width(Length::Fill) .on_input(move |string| DictionaryMessage::SetTags(i, string)) @@ -390,7 +389,6 @@ impl DictionaryState { col = col.push(line); } - println!("Words rendering time: {:?}", time.elapsed()); scrollable(col).height(Length::Fill).into() } @@ -398,7 +396,7 @@ impl DictionaryState { let dict = &self.state.lock().unwrap().dictionary; iced::widget::column![ - text_input("Поиск", &self.search) + jl_text_input("Поиск", &self.search) .on_input(DictionaryMessage::Search) .width(Length::Fill), text!("Всего слов: {}", dict.len()), @@ -533,7 +531,7 @@ impl DictionaryState { scrollable(row).width(Length::Fill).horizontal(), row![ button("⇳").on_press(ChangeDirection), - text_input("Название группы слов", &group.name) + jl_text_input("Название группы слов", &group.name) .on_input(EditGroup) .width(250) .on_submit(SaveGroup), diff --git a/src/dictionary_test.rs b/src/dictionary_test.rs index 52eeb58..5f93e57 100644 --- a/src/dictionary_test.rs +++ b/src/dictionary_test.rs @@ -1,11 +1,11 @@ use crate::dictionary::{split_with_coma}; use crate::quiz::Score; use crate::Page::PreviousPage; -use crate::{RootMessage, DEFAULT_SPACING}; +use crate::{jl_text_input, RootMessage, DEFAULT_SPACING}; use crate::{NavigatedPage, Page}; use iced::border::Radius; use iced::widget::container::Style; -use iced::widget::{button, container, row, space, text, text_input, Row}; +use iced::widget::{button, container, row, space, text, Row}; use iced::Background::Color; use iced::{alignment, Border, Element, Fill, Task, Theme}; use rand::prelude::SliceRandom; @@ -88,7 +88,7 @@ impl DictionaryQuizState { ] .align_x(alignment::Horizontal::Center) .spacing(5), - text_input("Перевод", &self.answer) + jl_text_input("Перевод", &self.answer) .size(28) .width(250) .on_input(DictionaryQuizMessage::AnswerChanged) diff --git a/src/main.rs b/src/main.rs index 01265f4..141048b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ use crate::writing::{WritingMessage, WritingState}; use crate::Page::{Dictionary, DictionaryQuiz, History, Quiz, Randomizer, Repetition, Repetitions, Selector, Sync, Word, Writing}; use crate::RootMessage::Keyboard; use iced::keyboard::Event; -use iced::widget::text; +use iced::widget::{text, text_input, TextInput}; use iced::{keyboard, Element, Program, Subscription, Theme}; use iced::{Font, Task}; use rusqlite::Connection; @@ -47,13 +47,13 @@ fn main() -> iced::Result { .subscription(subscription) .title("Kana learn app") .settings(iced::Settings{ - default_text_size: iced::Pixels(16.0), + default_text_size: iced::Pixels(20.0), ..iced::Settings::default() }) .font(include_bytes!("../ibmplex.ttf")) .font(include_bytes!("../noto.ttf")) - .default_font(USER_FONT) - .scale_factor(|x| 1.5) + .default_font(Font::with_name("IBM Plex Sans")) + // .scale_factor(|x| 1.5) .theme(Theme::GruvboxDark) .run() @@ -63,6 +63,38 @@ fn subscription(_state: &ScreenState) -> Subscription { keyboard::listen().map(|e| Keyboard(e)) } +pub fn jl_text_input<'a, Message, Theme, Renderer>(placeholder: &str, value: &str) -> TextInput<'a, Message, Theme, Renderer> +where +Message: Clone, +Theme: text_input::Catalog + 'a, Renderer: iced_core::text::Renderer{ + text_input(placeholder, value).font(USER_FONT) +} + +pub struct AppState { + pub dictionary: Vec, + pub card_sets: Vec, + pub word_groups: Vec, + pub connection: Connection, + pub sync_data: AppSettings, +} + +impl AppState { + pub fn new() -> Self { + let path = app_data_dir(); + let db_file = path.join("data.db"); + let connection = Connection::open(db_file).unwrap(); + connection.execute("PRAGMA foreign_keys = ON;", []).unwrap(); + + Self{ + dictionary: vec![], + card_sets: vec![], + word_groups: vec![], + connection, + sync_data: AppSettings { key: None }, + } + } +} + #[derive(Clone)] pub enum RootMessage { Selector(SelectorMessage), @@ -98,31 +130,6 @@ pub struct ScreenState { stack: Vec, } -pub struct AppState { - pub dictionary: Vec, - pub card_sets: Vec, - pub word_groups: Vec, - pub connection: Connection, - pub sync_data: AppSettings, -} - -impl AppState { - pub fn new() -> Self { - let path = app_data_dir(); - let db_file = path.join("data.db"); - let connection = Connection::open(db_file).unwrap(); - connection.execute("PRAGMA foreign_keys = ON;", []).unwrap(); - - Self{ - dictionary: vec![], - card_sets: vec![], - word_groups: vec![], - connection, - sync_data: AppSettings { key: None }, - } - } -} - impl Default for ScreenState { fn default() -> Self { let mut state = AppState::new(); diff --git a/src/quiz.rs b/src/quiz.rs index 3425618..30f6d8e 100644 --- a/src/quiz.rs +++ b/src/quiz.rs @@ -1,6 +1,6 @@ use crate::lang::KanaSet; use crate::Page::PreviousPage; -use crate::{NavigatedPage, Page, RootMessage, DEFAULT_SPACING, USER_FONT}; +use crate::{jl_text_input, NavigatedPage, Page, RootMessage, DEFAULT_SPACING, USER_FONT}; use iced::widget::*; use iced::{alignment, Element, Fill, Task}; use rand::seq::SliceRandom; @@ -113,7 +113,7 @@ impl QuizState { ] .align_y(alignment::Vertical::Center) .spacing(20), - text_input("Романдзи", &self.current_roman) + jl_text_input("Романдзи", &self.current_roman) .size(28) .width(150) .on_input(QuizMessage::ContentChanged), diff --git a/src/repetition.rs b/src/repetition.rs index 5f78643..5b54278 100644 --- a/src/repetition.rs +++ b/src/repetition.rs @@ -2,7 +2,7 @@ use crate::data_provider::voice::get_voice; use crate::lang::{CardSet, CardStatistics, WordData, WordOpenMode}; use crate::repetitions::CardSetSettings; use crate::Page::PreviousPage; -use crate::{AppState, KeyPressedPage, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use crate::{AppState, KeyPressedPage, NavigatedPage, Page, RootMessage, DEFAULT_SPACING, USER_FONT}; use iced::alignment::Horizontal::Center; use iced::keyboard::key::Physical::Code; use iced::widget::{button, column, container, row, rule, space, text, Column}; @@ -201,10 +201,10 @@ impl RepetitionState { } fn draw_key(&self, word: &WordData) -> Element<'_, RepetitionMessage> { - text!("{}", word.key).size(36).into() + text!("{}", word.key).size(36).font(USER_FONT).into() } fn draw_value(&self, word: &WordData) -> Element<'_, RepetitionMessage> { - text!("{}", word.value).size(24).into() + text!("{}", word.value).size(24).font(USER_FONT).into() } fn draw_voice(&self) -> Element<'_, RepetitionMessage> { @@ -216,13 +216,13 @@ impl RepetitionState { fn draw_reading(&self, word: &WordData) -> Element<'_, RepetitionMessage> { match word.additional.get("reading") { None => space().into(), - Some(reading) => text!("{}", reading).size(24).into(), + Some(reading) => text!("{}", reading).size(24).font(USER_FONT).into(), } } fn draw_context(&self, word: &WordData) -> Element<'_, RepetitionMessage> { match word.additional.get("context") { None => space().into(), - Some(context) => text!("{}", context).size(24).into(), + Some(context) => text!("{}", context).size(24).font(USER_FONT).into(), } } } diff --git a/src/repetitions.rs b/src/repetitions.rs index 4cc268e..d27c7e7 100644 --- a/src/repetitions.rs +++ b/src/repetitions.rs @@ -3,11 +3,11 @@ use crate::data_provider::card_stats::load_stats_of_set; use crate::lang::{SetOrderMode, WordData}; use crate::repetition::RepetitionState; use crate::Page::{History, PreviousPage, Repetition}; -use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use crate::{jl_text_input, AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING, USER_FONT}; use iced::widget::button::danger; pub use iced::widget::button::{Catalog, Style}; use iced::widget::container::bordered_box; -use iced::widget::{button, column, container, radio, row, scrollable, space, text, text_input, Column}; +use iced::widget::{button, column, container, radio, row, scrollable, space, text, Column}; use iced::{Border, Center, Element, Fill, Left, Length, Shadow, Task, Theme}; use rhai::{Engine, Scope}; use std::sync::{Arc, Mutex}; @@ -166,14 +166,14 @@ impl RepetitionsState { return column![ scrollable( column![ - text_input("Название набора", &set.name) + jl_text_input("Название набора", &set.name) .on_input(RepetitionsMessage::SetName), - text_input("Передняя сторона", &set.forward) + jl_text_input("Передняя сторона", &set.forward) .on_input(RepetitionsMessage::SetForward), - text_input("Задняя сторона", &set.backward) + jl_text_input("Задняя сторона", &set.backward) .on_input(RepetitionsMessage::SetBackward), text!("Фильтр"), - text_input("", &set.filter).on_input(RepetitionsMessage::SetFilter), + jl_text_input("", &set.filter).on_input(RepetitionsMessage::SetFilter), button("Проверить фильтр").on_press(RepetitionsMessage::TryFilter), self.count_view(&set), radio("Обычный режим", SetOrderMode::Default, Some(set.open_mode), RepetitionsMessage::SetOpenMode), @@ -215,7 +215,7 @@ impl RepetitionsState { let mut column = Column::new(); for word in set.worst_words_list.clone().unwrap() { - column = column.push(text!("{} | {}", &word.key, &word.value)); + column = column.push(text!("{} | {}", &word.key, &word.value).font(USER_FONT)); } column.into() } diff --git a/src/selector.rs b/src/selector.rs index 75f1d3e..d5ac733 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -6,7 +6,7 @@ use crate::repetitions::RepetitionsState; use crate::selector::SelectorMessage::ChangeMode; use crate::writing::WritingState; use crate::Page::{Quiz, Writing}; -use crate::{AppState, NavigatedPage, Page, QuizState, RootMessage, DEFAULT_SPACING}; +use crate::{AppState, NavigatedPage, Page, QuizState, RootMessage, DEFAULT_SPACING, USER_FONT}; use iced::widget::*; use iced::{alignment, Element, Task}; use crate::sync::SyncState; @@ -113,7 +113,7 @@ impl SelectorState { for v in &self.set.dictionary[i] { chars_column = chars_column.push( - container(text!("{}", v.0.clone().to_uppercase()).size(36)) + container(text!("{}", v.0.clone().to_uppercase()).size(36).font(USER_FONT)) .padding(20) .style(container::rounded_box), ); diff --git a/src/word.rs b/src/word.rs index 08fea52..6ab28b1 100644 --- a/src/word.rs +++ b/src/word.rs @@ -1,9 +1,9 @@ use crate::data_provider::words::{delete_word, update_word}; use crate::lang::WordData; use crate::Page::PreviousPage; -use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use crate::{jl_text_input, AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; use iced::widget::button::danger; -use iced::widget::{button, column, container, row, rule, scrollable, space, text, text_input}; +use iced::widget::{button, column, container, row, rule, scrollable, space, text}; use iced::{Element, Fill, Task}; use std::sync::{Arc, Mutex}; @@ -93,11 +93,11 @@ impl WordState { let mut col = iced::widget::column![ button("Назад").on_press(WordMessage::Back), text!("Ключ"), - text_input("key", &self.word.key).on_input(WordMessage::SetKey), + jl_text_input("key", &self.word.key).on_input(WordMessage::SetKey), text!("Значение"), - text_input("value", &self.word.value).on_input(WordMessage::SetValue), + jl_text_input("value", &self.word.value).on_input(WordMessage::SetValue), text!("Теги"), - text_input("tags", &self.word.tags).on_input(WordMessage::SetTags), + jl_text_input("tags", &self.word.tags).on_input(WordMessage::SetTags), rule::horizontal(2), scrollable(fast_add), ]; @@ -146,7 +146,7 @@ impl WordState { fn additional_field(&self, value: (&String, &String), name: String, id: String) -> Element<'_, WordMessage> { column![ text!("{}", name), - text_input(id.clone().as_str(), &value.1) + jl_text_input(id.clone().as_str(), &value.1) .on_input(move |string| WordMessage::SetAdditional(id.clone(), string)) ] .spacing(DEFAULT_SPACING) diff --git a/src/writing.rs b/src/writing.rs index 376c75d..3e32c41 100644 --- a/src/writing.rs +++ b/src/writing.rs @@ -1,6 +1,6 @@ use crate::lang::KanaSet; use crate::Page::PreviousPage; -use crate::{NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use crate::{NavigatedPage, Page, RootMessage, DEFAULT_SPACING, USER_FONT}; use iced::widget::*; use iced::{alignment, Element, Fill, Task}; use rand::seq::SliceRandom; @@ -90,7 +90,7 @@ impl WritingState { .label("Показывать все сразу") .on_toggle(WritingMessage::SwitchShowMode), text!("{}", self.roman_total).size(34), - text!("{}", self.kana).size(48), + text!("{}", self.kana).size(48).font(USER_FONT), self.answers(), row![ button(text!("{}", self.next_text)).on_press(WritingMessage::Next),