132 lines
3.4 KiB
Rust
132 lines
3.4 KiB
Rust
use crate::model::categories::{self, CatEntry, CATEGORIES};
|
|
use crate::state::{DictFocus, UiState};
|
|
|
|
use CatEntry::{Category, Section};
|
|
|
|
pub fn toggle_focus(ui: &mut UiState) {
|
|
ui.dict_focus = match ui.dict_focus {
|
|
DictFocus::Categories => DictFocus::Words,
|
|
DictFocus::Words => DictFocus::Categories,
|
|
};
|
|
}
|
|
|
|
pub fn select_category(ui: &mut UiState, index: usize) {
|
|
if index < categories::category_count() {
|
|
ui.dict_category = index;
|
|
ui.dict_on_section = None;
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
enum VisibleItem {
|
|
Category(usize),
|
|
Section(usize),
|
|
}
|
|
|
|
fn visible_items(collapsed: &[bool]) -> Vec<VisibleItem> {
|
|
let mut result = Vec::new();
|
|
let mut section_idx = 0usize;
|
|
let mut cat_idx = 0usize;
|
|
let mut skipping = false;
|
|
for entry in CATEGORIES.iter() {
|
|
match entry {
|
|
Section(_) => {
|
|
let is_collapsed = collapsed.get(section_idx).copied().unwrap_or(false);
|
|
if is_collapsed {
|
|
result.push(VisibleItem::Section(section_idx));
|
|
}
|
|
skipping = is_collapsed;
|
|
section_idx += 1;
|
|
}
|
|
Category(_) => {
|
|
if !skipping {
|
|
result.push(VisibleItem::Category(cat_idx));
|
|
}
|
|
cat_idx += 1;
|
|
}
|
|
}
|
|
}
|
|
result
|
|
}
|
|
|
|
fn find_current(items: &[VisibleItem], ui: &UiState) -> usize {
|
|
if let Some(s) = ui.dict_on_section {
|
|
items
|
|
.iter()
|
|
.position(|v| matches!(v, VisibleItem::Section(idx) if *idx == s))
|
|
.unwrap_or(0)
|
|
} else {
|
|
items
|
|
.iter()
|
|
.position(|v| matches!(v, VisibleItem::Category(idx) if *idx == ui.dict_category))
|
|
.unwrap_or(0)
|
|
}
|
|
}
|
|
|
|
fn apply_selection(ui: &mut UiState, item: VisibleItem) {
|
|
match item {
|
|
VisibleItem::Category(idx) => {
|
|
ui.dict_category = idx;
|
|
ui.dict_on_section = None;
|
|
}
|
|
VisibleItem::Section(idx) => {
|
|
ui.dict_on_section = Some(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn next_category(ui: &mut UiState) {
|
|
let items = visible_items(&ui.dict_collapsed);
|
|
if items.is_empty() {
|
|
return;
|
|
}
|
|
let cur = find_current(&items, ui);
|
|
let next = (cur + 1) % items.len();
|
|
apply_selection(ui, items[next]);
|
|
}
|
|
|
|
pub fn prev_category(ui: &mut UiState) {
|
|
let items = visible_items(&ui.dict_collapsed);
|
|
if items.is_empty() {
|
|
return;
|
|
}
|
|
let cur = find_current(&items, ui);
|
|
let next = (cur + items.len() - 1) % items.len();
|
|
apply_selection(ui, items[next]);
|
|
}
|
|
|
|
pub fn scroll_down(ui: &mut UiState, n: usize) {
|
|
let s = ui.dict_scroll_mut();
|
|
*s = s.saturating_add(n);
|
|
}
|
|
|
|
pub fn scroll_up(ui: &mut UiState, n: usize) {
|
|
let s = ui.dict_scroll_mut();
|
|
*s = s.saturating_sub(n);
|
|
}
|
|
|
|
pub fn activate_search(ui: &mut UiState) {
|
|
ui.dict_search_active = true;
|
|
ui.dict_focus = DictFocus::Words;
|
|
}
|
|
|
|
pub fn clear_search(ui: &mut UiState) {
|
|
ui.dict_search_query.clear();
|
|
ui.dict_search_active = false;
|
|
*ui.dict_scroll_mut() = 0;
|
|
}
|
|
|
|
pub fn search_input(ui: &mut UiState, c: char) {
|
|
ui.dict_search_query.push(c);
|
|
*ui.dict_scroll_mut() = 0;
|
|
}
|
|
|
|
pub fn search_backspace(ui: &mut UiState) {
|
|
ui.dict_search_query.pop();
|
|
*ui.dict_scroll_mut() = 0;
|
|
}
|
|
|
|
pub fn search_confirm(ui: &mut UiState) {
|
|
ui.dict_search_active = false;
|
|
}
|