guiver tries to make GUI programming with Rust simple, but perhaps without perfect efficiency.
guiver can be used in immediate mode, which is inspired by egui. In this case it is just a thin wrapper around druid-shell for event handling/windowing and Piet for rendering.
There are retained mode widgets that can be used with the help of an optional widget manager. The widgets are decoupled from the application data via message passing. This is inspired by Tk commands and egui. The widget size constraint system and some layout widgets are influenced by Flutter.
The example code may appear a bit verbose. On the upside you get simple setup and simple control flow.
- Operating systems:
- macOS: tested intensively
- Windows: works in general, probably has rough edges
- other: testers are welcome
- Widget manager:
- handles widget lifetimes
- handles a main widget
- handles widget focussing – including tab order
- handles copy/paste
- Widgets:
- Button
- Hyperlink
- Placeholder
- Text
- TextInput
- Layout widgets:
- Center
- Column
- Expanded
- Grid
- Padding
- Row
- SizedBox
Widgets are decoupled from the developers code via the WidgetManager
. It owns the widgets and manages their lifetimes.
Widgets are created via new_*()
methods and are modified and composed via Command
s.
Commands allow transactional modification, where a re-layout happens once at the end.
Widgets implement the Widget
trait. The methods can be used by the WidgetManager
and by other widgets (e.g. the
TextInput
widget contains a Text
widget).
A widget reacts to user Event
s and possibly creates WidgetEvent
s accordingly.
The developer code can handle those widget events.
-
guiver-wasm
:- add
WidgetManager
- add
-
guiver-piet
: bundle theCommand
s perWidgetId
: addCommand::ToWidget<Vec<WidgetCommand>>
- add
WidgetCommand
- add
-
guiver-piet
: unify widgets:- add
fn core(&self) -> &WidgetCore
toPietWidget
orWidget
? - add a method to return an iterator over th child widgets
- default implement
PietWidget::paint()
usingcore()
and the child widgets iterator yielding method
- add
-
guiver-piet
: add support toPietWidget
for the concept of layers/z-order for dropdown boxes, tooltips etc.- how?
-
add selectors:
- add
Command::SetClass(Option<C>)
- add
WidgetSelector
:All
WithId(WidgetId)
ChildrenOf(WidgetId)
ParentOf(WidgetId)
- use it in
-
Command::Destroy
-
Command::RemoveChild
- remove
Command::RemoveChildren
- remove
-
Command::RemoveEventObservation
-
Command::AddEventObservation
-
Command::SetDebugRendering
-
Command::SetFill
-
Command::SetFont
-
Command::SetHorizontalAlignment
-
Command::SetIsDisabled
-
Command::SetIsHidden
-
Command::SetStroke
-
Command::SetValue
-
Command::SetVerticalAlignment
-
- add
-
add
Widget::class() -> Option<C>
- implement in
Core
- add
WidgetSelector::WithClass(C)
- implement in
-
sketch a WASM backend?
-
sketch a
cacao
backend? -
sketch a
egui
backend? -
guiver-piet
: text:test_selected_text_replaced()
:- fix
- add a test case using umlauts
-
test_selected_text()
: add a test case using umlauts -
test_text_inserted()
: implement- add a test case using umlauts
-
TextInput::set_selected_value()
: implement - determine the graphical positions:
- TextLayout::hit_test_text_position(())
- text cursor
- text selection
-
paint()
: paint the cursor -
paint()
: paint the text selection -
TextInput::handle_event()
: adjust the text cursor on arrow left/right -
TextInput::handle_event()
: adjust the text selection on Shift + arrow left/right -
TextInput::update_caret_character_index()
: implement -
TextInput
: Meta+X should cut the selected text -
TextInput
: if a text is too large to fit in, the size of the text input should not increase but truncate -
TextInput::handle_event()
: select the whole text on double click
-
guiver-piet
: add support for scrolling- how?
-
test::widgets_layout()
: add remaining layout widgets -
test::widgets()
: add child widgets to the layout widgets -
move
WidgetManager::focused_widget
toWidgetFocusOrder
? -
publish 0.1.1, once the updated
druid-shell
>0.7.0 is released -
make
Text
selectable:- via double click
- how?
- via click + drag
- via double click
-
add
WidgetCore::is_disabled
?- makes sense for non-layout widgets:
Button
Hyperlink
Text
TextInput
- does it make sense for layout widgets?
- should they pass the command down to its child widgets?
- makes sense for non-layout widgets:
-
Widget
: removeflex_factor()
?- Pro:
- for
Grid
it needs to be held externally (GridColumnProperties
,GridRowProperties
)
- for
- Cons:
- does it make usage of
Column
,Row
less pleasant?
- does it make usage of
- Pro:
-
should all container widgets clip the child widget's painting?
- Pro:
- restricts misbehaving widgets paint
- Con:
- performance impact if clipping is unnecessary?
- Pro:
-
add integration tests:
widgets()
:- add
Column
- add
Padding
- add
Row
- add
- add for
Column
:-
test_apply_size_constraints()
-
test_handle_command()
-
test_handle_event()
-
- add for
Row
:-
test_apply_size_constraints()
-
test_handle_command()
-
test_handle_event()
-
- add for
Center
:-
test_apply_size_constraints()
-
test_handle_command()
-
test_handle_event()
-
- add for
Padding
:-
test_apply_size_constraints()
-
test_handle_command()
-
test_handle_event()
-
-
add unit tests:
- add for
Button
:-
test_apply_size_constraints()
-
test_handle_command()
-
test_handle_event()
-
- add for
Placeholder
:-
test_handle_command()
-
test_handle_event()
-
- add for
Text
:-
test_handle_command()
-
test_handle_event()
-
- add for
TextInput
:-
test_apply_size_constraints()
-
test_handle_command()
-
test_handle_event()
-
- add for
-
add a
Table
widget -
example
layout_expanded_row_column.rs
: make the row not grab all height -
all layout widgets need to clip too big child widgets
-
add layout widget
Stacked
+Positioned
-
Hyperlink
: make it possible to remember/pass "was visited" status across widget lifetimes -
support text selection:
- Shift + cursor movement
- Meta+A
-
support Drag and drop
druid-shell
has no support
-
implement 7GUIs
- 7GUIs "Flight Booker"
- implement
DropdownBox
(needs 2 layers)
- implement
- 7GUIs "Timer"
- 7GUIs "CRUD"
- 7GUIs "Circle Drawer"
- 7GUIs "Cells"
- 7GUIs "Flight Booker"
-
optimize: do not paint on every event. Make the widgets request the repaint in a region/Rect
-
add Redmond 31 widgets?
-
add Python bindings?
-
provide wrappers to native widgets?
-
provide a WebAssembly demo
-
consider decoupling from druid-shell/piet
See also "So you want to write a GUI framework"
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT) at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.