working focus
This commit is contained in:
57
examples/focus_advanced.rs
Normal file
57
examples/focus_advanced.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
extern crate alloc;
|
||||
|
||||
use tui_orchestrator::focus::{FocusBuilder, FocusId, FocusManager, Focusable};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
enum FormElement {
|
||||
Username,
|
||||
Password,
|
||||
RememberMe,
|
||||
Submit,
|
||||
}
|
||||
|
||||
struct FormPage {
|
||||
username: alloc::string::String,
|
||||
password: alloc::string::String,
|
||||
remember: bool,
|
||||
}
|
||||
|
||||
impl Focusable<FormElement> for FormPage {
|
||||
fn focus_targets(&self) -> alloc::vec::Vec<FormElement> {
|
||||
alloc::vec![
|
||||
FormElement::Username,
|
||||
FormElement::Password,
|
||||
FormElement::RememberMe,
|
||||
FormElement::Submit,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let form = FormPage {
|
||||
username: alloc::string::String::new(),
|
||||
password: alloc::string::String::new(),
|
||||
remember: false,
|
||||
};
|
||||
|
||||
let mut focus_manager = FocusManager::new();
|
||||
focus_manager.set_targets(form.focus_targets());
|
||||
println!("Current focus: {:?}", focus_manager.current());
|
||||
|
||||
focus_manager.next();
|
||||
println!("After next: {:?}", focus_manager.current());
|
||||
|
||||
focus_manager.last();
|
||||
println!("After last: {:?}", focus_manager.current());
|
||||
|
||||
println!("Is first: {}", focus_manager.is_first());
|
||||
println!("Is last: {}", focus_manager.is_last());
|
||||
|
||||
println!("\n--- FocusBuilder Demo ---");
|
||||
let builder = FocusBuilder::new()
|
||||
.target(FormElement::Username)
|
||||
.target(FormElement::Password)
|
||||
.target(FormElement::Submit);
|
||||
let targets = builder.build();
|
||||
println!("Built targets: {:?}", targets);
|
||||
}
|
||||
26
src/focus/builder.rs
Normal file
26
src/focus/builder.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct FocusBuilder<F: super::FocusId> {
|
||||
targets: alloc::vec::Vec<F>,
|
||||
}
|
||||
|
||||
impl<F: super::FocusId> FocusBuilder<F> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
targets: alloc::vec::Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target(mut self, target: F) -> Self {
|
||||
self.targets.push(target);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn targets(mut self, targets: &[F]) -> Self {
|
||||
self.targets.extend_from_slice(targets);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> alloc::vec::Vec<F> {
|
||||
self.targets
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
// path_from_the_root: src/focus/id.rs
|
||||
|
||||
pub trait FocusId: Clone + PartialEq + Eq + core::hash::Hash {}
|
||||
|
||||
impl<T: Clone + PartialEq + Eq + core::hash::Hash> FocusId for T {}
|
||||
|
||||
@@ -133,4 +133,39 @@ impl<F: FocusId> FocusManager<F> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.targets.is_empty()
|
||||
}
|
||||
|
||||
pub fn current_index(&self) -> Option<usize> {
|
||||
if self.targets.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.index)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrap_next(&mut self) {
|
||||
if !self.targets.is_empty() {
|
||||
self.index = (self.index + 1) % self.targets.len();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrap_prev(&mut self) {
|
||||
if !self.targets.is_empty() {
|
||||
self.index = if self.index == 0 {
|
||||
self.targets.len() - 1
|
||||
} else {
|
||||
self.index - 1
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_first(&self) -> bool {
|
||||
self.current_index() == Some(0)
|
||||
}
|
||||
|
||||
pub fn is_last(&self) -> bool {
|
||||
match self.current_index() {
|
||||
Some(idx) => idx == self.targets.len().saturating_sub(1),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
src/focus/mode.rs
Normal file
9
src/focus/mode.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
pub trait FocusModeHint<F: super::FocusId> {
|
||||
fn focus_modes(&self) -> &[&'static str];
|
||||
}
|
||||
|
||||
impl<F: super::FocusId> FocusModeHint<F> for super::FocusManager<F> {
|
||||
fn focus_modes(&self) -> &[&'static str] {
|
||||
&["general"]
|
||||
}
|
||||
}
|
||||
11
src/focus/navigation.rs
Normal file
11
src/focus/navigation.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
pub trait FocusNavigation<F: super::FocusId> {
|
||||
type Error;
|
||||
|
||||
fn can_navigate_forward(&self, from: &F) -> bool;
|
||||
|
||||
fn can_navigate_backward(&self, from: &F) -> bool;
|
||||
|
||||
fn navigate_forward(&mut self) -> Result<Option<F>, Self::Error>;
|
||||
|
||||
fn navigate_backward(&mut self) -> Result<Option<F>, Self::Error>;
|
||||
}
|
||||
Reference in New Issue
Block a user