pub use iced_core::keyboard::*;
use crate::UserInterface;
use crate::core;
use crate::core::widget::operation::{self, Operation as _};
fn run_operation<Message, Theme, Renderer>(
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
mut op: Box<dyn operation::Operation>,
) where
Renderer: core::Renderer,
{
loop {
ui.operate(renderer, op.as_mut());
match op.finish() {
operation::Outcome::Chain(next) => {
op = next;
}
_ => break,
}
}
}
fn focus_and_scroll<Message, Theme, Renderer>(
shift: bool,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
) where
Renderer: core::Renderer,
{
let op: Box<dyn operation::Operation> = if shift {
Box::new(operation::focusable::focus_previous::<()>())
} else {
Box::new(operation::focusable::focus_next::<()>())
};
run_operation(ui, renderer, op);
run_operation(
ui,
renderer,
Box::new(operation::focusable::scroll_focused_into_view::<()>()),
);
}
fn focus_and_scroll_within<Message, Theme, Renderer>(
shift: bool,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
scope: core::widget::Id,
) where
Renderer: core::Renderer,
{
let op: Box<dyn operation::Operation> = if shift {
Box::new(operation::focusable::focus_previous_within::<()>(scope))
} else {
Box::new(operation::focusable::focus_next_within::<()>(scope))
};
run_operation(ui, renderer, op);
run_operation(
ui,
renderer,
Box::new(operation::focusable::scroll_focused_into_view::<()>()),
);
}
pub fn handle_ctrl_tab<Message, Theme, Renderer>(
event: &core::Event,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
) -> bool
where
Renderer: core::Renderer,
{
if let core::Event::Keyboard(core::keyboard::Event::KeyPressed {
key: core::keyboard::Key::Named(core::keyboard::key::Named::Tab),
modifiers,
..
}) = event
&& modifiers.control()
{
focus_and_scroll(modifiers.shift(), ui, renderer);
return true;
}
false
}
pub fn handle_tab<Message, Theme, Renderer>(
event: &core::Event,
status: core::event::Status,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
) -> bool
where
Renderer: core::Renderer,
{
if status != core::event::Status::Ignored {
return false;
}
if let core::Event::Keyboard(core::keyboard::Event::KeyPressed {
key: core::keyboard::Key::Named(core::keyboard::key::Named::Tab),
modifiers,
..
}) = event
{
focus_and_scroll(modifiers.shift(), ui, renderer);
return true;
}
false
}
pub fn handle_ctrl_tab_within<Message, Theme, Renderer>(
event: &core::Event,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
scope: core::widget::Id,
) -> bool
where
Renderer: core::Renderer,
{
if let core::Event::Keyboard(core::keyboard::Event::KeyPressed {
key: core::keyboard::Key::Named(core::keyboard::key::Named::Tab),
modifiers,
..
}) = event
&& modifiers.control()
{
focus_and_scroll_within(modifiers.shift(), ui, renderer, scope);
return true;
}
false
}
pub fn handle_tab_within<Message, Theme, Renderer>(
event: &core::Event,
status: core::event::Status,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
scope: core::widget::Id,
) -> bool
where
Renderer: core::Renderer,
{
if status != core::event::Status::Ignored {
return false;
}
if let core::Event::Keyboard(core::keyboard::Event::KeyPressed {
key: core::keyboard::Key::Named(core::keyboard::key::Named::Tab),
modifiers,
..
}) = event
{
focus_and_scroll_within(modifiers.shift(), ui, renderer, scope);
return true;
}
false
}
pub fn handle_mnemonic<Message, Theme, Renderer>(
event: &core::Event,
status: core::event::Status,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
) -> Option<core::Rectangle>
where
Renderer: core::Renderer,
{
if status != core::event::Status::Ignored {
return None;
}
if let core::Event::Keyboard(core::keyboard::Event::KeyPressed {
key: core::keyboard::Key::Character(smol),
modifiers,
..
}) = event
{
if !modifiers.alt() || modifiers.control() || modifiers.logo() {
return None;
}
let ch = smol.chars().next()?;
let mut op = operation::focusable::find_mnemonic(ch);
ui.operate(renderer, &mut operation::black_box::<_, ()>(&mut op));
if let operation::Outcome::Some(target) = op.finish() {
if let Some(id) = target.id {
run_operation(
ui,
renderer,
Box::new(operation::focusable::focus::<()>(id)),
);
}
return Some(target.bounds);
}
}
None
}
pub fn handle_scroll_keys<Message, Theme, Renderer>(
event: &core::Event,
status: core::event::Status,
ui: &mut UserInterface<'_, Message, Theme, Renderer>,
renderer: &Renderer,
) -> bool
where
Renderer: core::Renderer,
{
if status != core::event::Status::Ignored {
return false;
}
if let core::Event::Keyboard(core::keyboard::Event::KeyPressed {
key: core::keyboard::Key::Named(named),
modifiers,
..
}) = event
{
use operation::focusable::ScrollAction;
let action = match named {
core::keyboard::key::Named::PageDown if modifiers.shift() => {
Some(ScrollAction::PageRight)
}
core::keyboard::key::Named::PageDown => Some(ScrollAction::PageDown),
core::keyboard::key::Named::PageUp if modifiers.shift() => Some(ScrollAction::PageLeft),
core::keyboard::key::Named::PageUp => Some(ScrollAction::PageUp),
core::keyboard::key::Named::ArrowDown if modifiers.shift() => {
Some(ScrollAction::LineRight)
}
core::keyboard::key::Named::ArrowDown => Some(ScrollAction::LineDown),
core::keyboard::key::Named::ArrowUp if modifiers.shift() => {
Some(ScrollAction::LineLeft)
}
core::keyboard::key::Named::ArrowUp => Some(ScrollAction::LineUp),
core::keyboard::key::Named::ArrowRight => Some(ScrollAction::LineRight),
core::keyboard::key::Named::ArrowLeft => Some(ScrollAction::LineLeft),
core::keyboard::key::Named::Home if modifiers.shift() => Some(ScrollAction::ShiftHome),
core::keyboard::key::Named::Home => Some(ScrollAction::Home),
core::keyboard::key::Named::End if modifiers.shift() => Some(ScrollAction::ShiftEnd),
core::keyboard::key::Named::End => Some(ScrollAction::End),
_ => None,
};
if let Some(action) = action {
run_operation(
ui,
renderer,
Box::new(operation::focusable::scroll_focused_ancestor::<()>(action)),
);
return true;
}
}
false
}