Skip to content

Commit

Permalink
Merge pull request #406 from kas-gui/work1
Browse files Browse the repository at this point in the history
ROADMAP, Response → IsUsed
  • Loading branch information
dhardy committed Sep 2, 2023
2 parents e449c6a + 9b47f93 commit fed0ff9
Show file tree
Hide file tree
Showing 58 changed files with 461 additions and 442 deletions.
127 changes: 64 additions & 63 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,36 +129,47 @@ This release responds to three key criticisms of KAS: (1) slow compile times,
not fully solved, they are significantly improved. Additionally,
the latest version of WGPU now gives us a working OpenGL backend.

### 0.11.0 — September 2022

Future work
-----------
Widget trait revision: remove `Handler::Msg` associated type, replacing with a
variadic message stack: `EventMgr::push_msg` and `try_pop_msg`. Notify of data
model updates via broadcast.

These items are not versioned and appear only roughly in the expected order.
Each should be a decently sized work item (roughly one release).
New `#[autoimpl]` and `impl_scope!` macros, published in the
[impl-tools crate](https://crates.io/crates/impl-tools).

### Standard geometry types
Added a domain-specific macro-driven language for widget layout, thus permitting
complex layout from a single widget.

KAS has ad-hoc geometry types. *Possibly* it would be useful to use third-party
types instead. See [#95](https://github.com/kas-gui/kas/issues/95).
Support sub-tree configuration. Make `WidgetId` a path.

Support theme- and widget-driven animations. Support momentum scrolling.

### 0.12.0 — December 2022

### Images and icons
Stabilised support for Generic Associated Types, allowing some changes to data
models.

Support display of images in the GUI:
### 0.13.0 — February 2023

- image display using a target size and multiple rastered versions, with
the option of scaling to the target size or using the nearest size
Async rendering for `Canvas` and `Svg` widgets.

Possibly as part of this topic, implement colour management
[#59](https://github.com/kas-gui/kas/issues/59).
Support Linux's primary buffer. Support transparent and borderless windows
with very basic support for a toolkit-drawn titlebar.

### Standard resource sets
Removal of `kas-theme` crate (most contents merged into `kas-core`).

Ideally, KAS should provide an identifier for common icons and either map these
to a system-provided icon set or provide its own, so that apps can use icons
like "save" or "undo" without having to provide the icon themselves.

Colour schemes and short-cuts are similar in that potentially they can be
inherited from the desktop, but otherwise KAS should provide them.
Future work
-----------

These items are not versioned and appear only roughly in the expected order.
Each should be a decently sized work item (roughly one release).

### Standard geometry types

KAS has ad-hoc geometry types. *Possibly* it would be useful to use third-party
types instead. See [#95](https://github.com/kas-gui/kas/issues/95).

### Context menu and undo

Expand All @@ -173,36 +184,6 @@ stored in some shared state.
Slightly related to this is support for global and standard shortcuts such as
undo, copy selection, save file, quit app.

### Script-driven UIs

So far, KAS only supports statically defined widgets and (more limited, without
event handlers) programmatically added widgets. We should aim to support
script-driven UIs: support all layouts with dynamic containers, add direct
integration with a Rust-centric scripting language for building UIs, and add
support for event handlers using dynamic typing.

This should aim both to allow rapid prototyping of UIs and to make KAS easier
to use (especially for those less familiar with Rust's traits, generics and
macros).

### Widget identifiers

Currently widgets are identified simply by enumerating all widgets. See
[#91](https://github.com/kas-gui/kas/issues/91).

### Widget library

Although the current widget set covers a good portion of the "full complement"
mentioned by [#2](https://github.com/kas-gui/kas/issues/2), its primary purpose
is to prototype requirements for other APIs
(including the widget trait family, event handling, draw model).

Once other APIs are more stable, this focus should shift to providing the full
complement of standard GUI widgets, likely within a dedicated crate.

Additionally, several standard dialog boxes / pop-ups should be added, e.g. a
colour picker, a date picker, and a file-open dialog.

### Desktop integration

This is less a separate work item than it is a long-term goal, one which will
Expand All @@ -216,19 +197,45 @@ also security (e.g. a container may not let an app explore the filesystem).
Such dialogs should automatically use desktop-provided equivalents where
available.

### Input Method Editors and virtual keyboards

External dependencies
----------------------
Winit has at least partial support for IME now. Kas should add support for this
(mostly this means an additional `Event` variant, one or two API calls to
enable IME input for the current widget, and adjusting `EditField`).

### Accessibility tools

`AccessKit` would appear to be the defacto Rust API for accessibility tools with
(limited) support from egui and Xilem toolkits. Widgets could support this via
additional code in the `update` method, possibly with additional tracking to
avoid unnecessarily replacing nodes.

### WGPU and CPU rasterisation
### Internationalisation (i18n)

Currently, KAS can only draw via `wgpu`, which currently does not support OpenGL
or CPU-rendered graphics, making KAS unusable on many older systems.
[Project Fluent](https://projectfluent.org/) offers the core functionality
required for localisation (l10n). We may need additional code for loading
resources and selecting languages; potentially also for fallbacks (in case of
incomplete translations). Widgets could translate their strings in the
`configure` method when `fluent` integration is enabled with labels treating
their input as a message key.

It seems likely that `wgpu` will support OpenGL in the future.
### Embedded video

Additionally, KAS should provide a CPU-based renderer. See
[#33](https://github.com/kas-gui/kas/issues/33).
To investigate. Gstreamer integration should be viable when using a (new) OpenGL
shell.

Integrating any video player as a child window should be possible (see Winit's
`WindowBuilder::with_parent_window`, which is not yet supported everywhere).

### Embedded web browser

To investigate. Possibly use Servo (components), though it may not matter much.

The browser should probably be integrated via a child window (see Winit's `WindowBuilder::with_parent_window`, which is not yet supported everywhere).


External dependencies
----------------------

### Clipboard support

Expand All @@ -250,9 +257,3 @@ its current event model it is difficult or impossible to determine the widget
receiving a drop or under a hovered drop.
See [#98](https://github.com/kas-gui/kas/issues/98) and
[winit#1550](https://github.com/rust-windowing/winit/issues/1550).

### (winit) key-bindings and text input

This needs revision, allowing more generic key bindings and supporting Input
Method Editors (IME). Winit has an on-going effort here which will require
support in KAS: <https://github.com/rust-windowing/winit/issues/1806>.
24 changes: 12 additions & 12 deletions crates/kas-core/src/core/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

//! Widget method implementations

use crate::event::{ConfigCx, Event, EventCx, FocusSource, Response, Scroll};
use crate::event::{ConfigCx, Event, EventCx, FocusSource, IsUsed, Scroll, Unused, Used};
#[cfg(debug_assertions)] use crate::util::IdentifyWidget;
use crate::{Erased, Events, Layout, NavAdvance, Node, Widget, WidgetId};

Expand Down Expand Up @@ -53,39 +53,39 @@ pub fn _send<W: Widget + Events<Data = <W as Widget>::Data>>(
id: WidgetId,
disabled: bool,
event: Event,
) -> Response {
let mut response = Response::Unused;
) -> IsUsed {
let mut is_used = Unused;
let do_handle_event;

if id == widget.id_ref() {
if disabled {
return response;
return is_used;
}

match &event {
Event::MouseHover(state) => {
response |= widget.mouse_hover(cx, *state);
is_used |= widget.handle_hover(cx, *state);
}
Event::NavFocus(FocusSource::Key) => {
cx.set_scroll(Scroll::Rect(widget.rect()));
response |= Response::Used;
is_used |= Used;
}
_ => (),
}

do_handle_event = true;
} else {
if event.is_reusable() {
response = widget.steal_event(cx, data, &id, &event);
is_used = widget.steal_event(cx, data, &id, &event);
}
if response.is_unused() {
if !is_used {
cx.assert_post_steal_unused();

if let Some(index) = widget.find_child_index(&id) {
let translation = widget.translation();
let mut _found = false;
widget.as_node(data).for_child(index, |mut node| {
response = node._send(cx, id.clone(), disabled, event.clone() + translation);
is_used = node._send(cx, id.clone(), disabled, event.clone() + translation);
_found = true;
});

Expand All @@ -105,18 +105,18 @@ pub fn _send<W: Widget + Events<Data = <W as Widget>::Data>>(
}
}

do_handle_event = response.is_unused() && event.is_reusable();
do_handle_event = !is_used && event.is_reusable();
}

if do_handle_event {
response = widget.handle_event(cx, data, event);
is_used = widget.handle_event(cx, data, event);
}

if cx.has_msg() {
widget.handle_messages(cx, data);
}

response
is_used
}

/// Generic implementation of [`Widget::_replay`]
Expand Down
8 changes: 4 additions & 4 deletions crates/kas-core/src/core/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Node API for widgets

use super::Widget;
use crate::event::{ConfigCx, Event, EventCx, Response};
use crate::event::{ConfigCx, Event, EventCx, IsUsed};
use crate::geom::{Coord, Rect};
use crate::layout::{AxisInfo, SizeRules};
use crate::theme::{DrawCx, SizeCx};
Expand Down Expand Up @@ -34,7 +34,7 @@ trait NodeT {
fn _configure(&mut self, cx: &mut ConfigCx, id: WidgetId);
fn _update(&mut self, cx: &mut ConfigCx);

fn _send(&mut self, cx: &mut EventCx, id: WidgetId, disabled: bool, event: Event) -> Response;
fn _send(&mut self, cx: &mut EventCx, id: WidgetId, disabled: bool, event: Event) -> IsUsed;
fn _replay(&mut self, cx: &mut EventCx, id: WidgetId, msg: Erased);
fn _nav_next(
&mut self,
Expand Down Expand Up @@ -94,7 +94,7 @@ impl<'a, T> NodeT for (&'a mut dyn Widget<Data = T>, &'a T) {
self.0._update(cx, self.1);
}

fn _send(&mut self, cx: &mut EventCx, id: WidgetId, disabled: bool, event: Event) -> Response {
fn _send(&mut self, cx: &mut EventCx, id: WidgetId, disabled: bool, event: Event) -> IsUsed {
self.0._send(cx, self.1, id, disabled, event)
}
fn _replay(&mut self, cx: &mut EventCx, id: WidgetId, msg: Erased) {
Expand Down Expand Up @@ -344,7 +344,7 @@ impl<'a> Node<'a> {
id: WidgetId,
disabled: bool,
event: Event,
) -> Response {
) -> IsUsed {
cfg_if::cfg_if! {
if #[cfg(feature = "unsafe_node")] {
self.0._send(cx, self.1, id, disabled, event)
Expand Down
Loading

0 comments on commit fed0ff9

Please sign in to comment.