Skip to content

Commit

Permalink
Merge pull request #347 from kas-gui/work
Browse files Browse the repository at this point in the history
Revise [usage of] Command; remove examples/custom-theme
  • Loading branch information
dhardy committed Aug 13, 2022
2 parents a5911eb + 3b3f997 commit 6249117
Show file tree
Hide file tree
Showing 22 changed files with 247 additions and 261 deletions.
26 changes: 16 additions & 10 deletions crates/kas-core/src/event/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,18 @@ impl Event {

/// Command input ([`Event::Command`])
///
/// The exact command sent depends on the type of focus a widget has.
/// `Command` events are mostly produced as a result of OS-specific keyboard
/// bindings; for example, [`Command::Copy`] is produced by pressing
/// <kbd>Command+C</kbd> on MacOS or <kbd>Ctrl+C</kbd> on other platforms.
/// See [`crate::event::config::Shortcuts`] for more on these bindings.
///
/// Handling may depend on the state of the Shift key.
/// A `Command` event does not necessarily come from keyboard input; for example
/// some menu widgets send [`Command::Activate`] to trigger an entry as a result
/// of mouse input.
///
/// The exact mapping between the keyboard and these commands is OS-specific.
/// In the future it should be customisable (see `shortcuts` module).
/// *Most* `Command` entries represent an action (such as `Copy` or `FindNext`)
/// but some represent an important key whose action may be context-dependent
/// (e.g. `Escape`, `Space`).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Command {
Expand All @@ -320,8 +326,8 @@ pub enum Command {
/// Return / enter key
///
/// This may insert a line-break or may activate something.
Return,
/// Space key
Enter,
/// Space bar key
Space,
/// Tab key
///
Expand Down Expand Up @@ -482,10 +488,10 @@ impl Command {
Right => Command::Right,
Down => Command::Down,
Back => Command::DelBack,
Return => Command::Return,
Return => Command::Enter,
NavigateForward => Command::NavNext,
NavigateBackward => Command::NavPrev,
NumpadEnter => Command::Return,
NumpadEnter => Command::Enter,
Tab => Command::Tab,
Cut => Command::Cut,
Copy => Command::Copy,
Expand All @@ -499,11 +505,11 @@ impl Command {
/// This matches:
///
/// - [`Self::Activate`] — programmatic activation
/// - [`Self::Return`] — <kbd>Enter</kbd> and <kbd>Return</kbd> keys
/// - [`Self::Enter`] — <kbd>Enter</kbd> and <kbd>Return</kbd> keys
/// - [`Self::Space`] — <kbd>Space</kbd> key
pub fn is_activate(self) -> bool {
use Command::*;
matches!(self, Activate | Return | Space)
matches!(self, Activate | Enter | Space)
}

/// Convert to selection-focus command
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-core/src/event/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ impl EventState {
}

fn clear_char_focus(&mut self) {
log::trace!("clear_char_focus");
if let Some(id) = self.char_focus() {
log::trace!("clear_char_focus");
// If widget has char focus, this is lost
self.char_focus = false;
self.pending.push_back(Pending::LostCharFocus(id));
Expand Down
37 changes: 37 additions & 0 deletions crates/kas-core/src/event/manager/config_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,43 @@ impl<'a> ConfigMgr<'a> {
false
}
}

/// Advance the keyboard navigation focus
///
/// This is similar to [`Self::next_nav_focus`], but looks for the next
/// widget from `id` which is [`Widget::navigable`].
#[inline]
pub fn next_nav_focus_from(
&mut self,
widget: &mut dyn Widget,
id: WidgetId,
key_focus: bool,
) -> bool {
if id == self.nav_focus {
return true;
} else if !self.config.nav_focus {
return false;
}

self.send_action(TkAction::REDRAW);
if let Some(old_id) = self.nav_focus.take() {
self.pending.push_back(Pending::LostNavFocus(old_id));
}
self.clear_char_focus();
if widget
.find_widget(&id)
.map(|w| w.navigable())
.unwrap_or(false)
{
log::trace!(target: "kas_core::event::manager", "set_nav_focus: {id}");
self.nav_focus = Some(id.clone());
self.pending.push_back(Pending::SetNavFocus(id, key_focus));
true
} else {
self.nav_focus = Some(id);
self.next_nav_focus(widget, false, key_focus)
}
}
}

impl<'a> std::ops::BitOrAssign<TkAction> for ConfigMgr<'a> {
Expand Down
41 changes: 38 additions & 3 deletions crates/kas-core/src/event/manager/mgr_pub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,9 +440,7 @@ impl EventState {
if let Some(old_id) = self.nav_focus.take() {
self.pending.push_back(Pending::LostNavFocus(old_id));
}
if id != self.sel_focus {
self.clear_char_focus();
}
self.clear_char_focus();
self.nav_focus = Some(id.clone());
log::trace!(target: "kas_core::event::manager", "set_nav_focus: {id}");
self.pending.push_back(Pending::SetNavFocus(id, key_focus));
Expand Down Expand Up @@ -849,4 +847,41 @@ impl<'a> EventMgr<'a> {
) -> bool {
self.config_mgr(|mgr| mgr.next_nav_focus(widget, reverse, key_focus))
}

/// Advance the keyboard navigation focus
///
/// This is similar to [`Self::next_nav_focus`], but looks for the next
/// widget from `id` which is [`Widget::navigable`].
#[inline]
pub fn next_nav_focus_from(
&mut self,
widget: &mut dyn Widget,
id: WidgetId,
key_focus: bool,
) -> bool {
if id == self.nav_focus {
return true;
} else if !self.config.nav_focus {
return false;
}

self.send_action(TkAction::REDRAW);
if let Some(old_id) = self.nav_focus.take() {
self.pending.push_back(Pending::LostNavFocus(old_id));
}
self.clear_char_focus();
if widget
.find_widget(&id)
.map(|w| w.navigable())
.unwrap_or(false)
{
log::trace!(target: "kas_core::event::manager", "set_nav_focus: {id}");
self.nav_focus = Some(id.clone());
self.pending.push_back(Pending::SetNavFocus(id, key_focus));
true
} else {
self.nav_focus = Some(id);
self.next_nav_focus(widget, false, key_focus)
}
}
}
12 changes: 4 additions & 8 deletions crates/kas-core/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,19 @@ pub use crate::class::*;
#[doc(no_inline)]
pub use crate::dir::{Direction, Directional};
#[doc(no_inline)]
pub use crate::draw::{DrawShared, ImageHandle};
#[doc(no_inline)]
pub use crate::event::{components, ConfigMgr, Event, EventMgr, EventState, Response};
pub use crate::event::{ConfigMgr, Event, EventMgr, EventState, Response};
#[doc(no_inline)]
pub use crate::geom::{Coord, Offset, Rect, Size};
#[doc(no_inline)]
pub use crate::layout::{Align, AlignHints, AxisInfo, LogicalSize, Margins, SizeRules, Stretch};
pub use crate::layout::{Align, AlignHints, AxisInfo, SizeRules, Stretch};
#[doc(no_inline)]
pub use crate::macros::*;
pub use crate::macros::{autoimpl, impl_default, impl_scope, impl_singleton, widget, widget_index};
#[doc(no_inline)]
pub use crate::text::AccelString;
#[doc(no_inline)]
pub use crate::text::{EditableTextApi, Text, TextApi, TextApiExt};
#[doc(no_inline)]
pub use crate::theme::{DrawMgr, SizeMgr, ThemeControl};
#[doc(no_inline)]
pub use crate::CoreData;
pub use crate::theme::{DrawMgr, SizeMgr};
#[doc(no_inline)]
pub use crate::TkAction;
#[doc(no_inline)]
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-core/src/theme/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ impl<'a> std::ops::BitOrAssign<TkAction> for DrawMgr<'a> {
///
/// Most themes will not want to implement *everything*, but rather derive
/// not-explicitly-implemented methods from a base theme. This may be achieved
/// with the [`kas_macros::extends`] macro:
/// with the [`kas::macros::extends`](crate::macros::extends) macro:
/// ```ignore
/// #[extends(ThemeDraw, base = self.base())]
/// impl ThemeDraw {
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-resvg/src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Canvas widget

use kas::draw::{ImageFormat, ImageHandle};
use kas::layout::PixmapScaling;
use kas::layout::{LogicalSize, PixmapScaling};
use kas::prelude::*;
use tiny_skia::{Color, Pixmap};

Expand Down
2 changes: 1 addition & 1 deletion crates/kas-resvg/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use kas::draw::{ImageFormat, ImageHandle};
use kas::geom::Size;
use kas::layout::PixmapScaling;
use kas::layout::{LogicalSize, PixmapScaling};
use kas::prelude::*;
use std::io::Result;
use std::path::Path;
Expand Down
20 changes: 13 additions & 7 deletions crates/kas-view/src/list_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,20 @@ impl_scope! {
fn update_widgets(&mut self, mgr: &mut ConfigMgr) {
let time = Instant::now();
let solver = self.position_solver(mgr);

let mut action = TkAction::empty();
for (i, key) in self

let keys = self
.data
.iter_vec_from(solver.first_data, solver.cur_len)
.into_iter()
.enumerate()
{
.iter_vec_from(solver.first_data, solver.cur_len);
if keys.len() < solver.cur_len {
log::warn!(
"{}: data.iter_vec_from({}, {}) yielded insufficient items (possibly incorrect data.len())", self.identify(),
solver.first_data,
solver.cur_len,
);
}

for (i, key) in keys.into_iter().enumerate() {
let i = solver.first_data + i;
let id = self.data.make_id(self.id_ref(), &key);
let w = &mut self.widgets[i % solver.cur_len];
Expand Down Expand Up @@ -693,7 +699,7 @@ impl_scope! {
}
Event::Command(cmd) => {
let last = self.data.len().wrapping_sub(1);
if last == usize::MAX || !self.widgets[0].widget.navigable() {
if last == usize::MAX {
return Response::Unused;
}

Expand Down
23 changes: 20 additions & 3 deletions crates/kas-view/src/matrix_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,24 @@ impl_scope! {
let cols = self
.data
.col_iter_vec_from(solver.first_col, solver.col_len);
if cols.len() < solver.col_len {
log::warn!(
"{}: data.col_iter_vec_from({}, {}) yielded insufficient items (possibly incorrect data.len())", self.identify(),
solver.first_col,
solver.col_len,
);
}

let rows = self
.data
.row_iter_vec_from(solver.first_row, solver.row_len);
if rows.len() < solver.row_len {
log::warn!(
"{}: data.row_iter_vec_from({}, {}) yielded insufficient items (possibly incorrect data.len())", self.identify(),
solver.first_row,
solver.row_len,
);
}

let mut action = TkAction::empty();
for (rn, row) in rows.iter().enumerate() {
Expand Down Expand Up @@ -690,7 +705,7 @@ impl_scope! {
}
}
Event::Command(cmd) => {
if self.data.is_empty() || !self.widgets[0].widget.navigable() {
if self.data.is_empty() {
return Response::Unused;
}
let (d_cols, d_rows) = self.data.len();
Expand Down Expand Up @@ -731,8 +746,10 @@ impl_scope! {

let index = solver.data_to_child(ci, ri);
#[cfg(debug_assertions)] {
let rk = &self.data.row_iter_vec_from(ri, 1)[0];
let ck = &self.data.col_iter_vec_from(ci, 1)[0];
let rv = self.data.row_iter_vec_from(ri, 1);
let rk = rv.get(0).expect("data row len > data.row_iter_vec len");
let cv = self.data.col_iter_vec_from(ci, 1);
let ck = cv.get(0).expect("data col len > data.col_iter_vec len");
let key = T::make_key(ck, rk);
assert_eq!(
self.widgets[index].widget.id(),
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-widgets/src/adapter/adapt_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub trait AdaptWidget: Widget {
/// use kas::prelude::*;
///
/// let label = Filler::new().with_reserve(|mgr, axis| {
/// LogicalSize(5.0, 5.0).to_rules(axis, mgr.scale_factor())
/// kas::layout::LogicalSize(5.0, 5.0).to_rules(axis, mgr.scale_factor())
/// });
///```
/// The resulting `SizeRules` will be the max of those for the inner widget
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-widgets/src/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl_scope! {
fn handle_event(&mut self, mgr: &mut EventMgr, event: Event) -> Response {
match event {
Event::Command(Command::Escape) => self.close(mgr, false),
Event::Command(Command::Return) => self.close(mgr, true),
Event::Command(Command::Enter) => self.close(mgr, true),
_ => Response::Unused,
}
}
Expand Down
Loading

0 comments on commit 6249117

Please sign in to comment.