[−][src]Module coffee::ui
Build a responsive graphical user interface for your game.
Basic concepts
The user interface runtime in Coffee is heavily inspired by Elm and The Elm Architecture.
Basically, user interfaces in Coffee are split into four different concepts:
- state — data owned by the implementor of
UserInterface
- messages — user interactions or meaningful events that you care about
- update logic — a way to react to messages and update your state
- layout logic — a way to transform your state into widgets that may produce messages on user interaction
Getting started
Once you have implemented the Game
trait, you can easily add a user
interface to your game by implementing the UserInterface
trait.
Let's take a look at a simple example with basic user interaction: an interactive counter that can be incremented and decremented using two different buttons.
use coffee::graphics::{Color, Window}; use coffee::ui::{button, Button, Column, Element, Renderer, Text, UserInterface}; // The state of our user interface struct Counter { // The counter value value: i32, // Local state of the two counter buttons // This is internal widget state that may change outside our update // logic increment_button: button::State, decrement_button: button::State, } // The messages, user interactions that we are interested on #[derive(Debug, Clone, Copy)] pub enum Message { IncrementPressed, DecrementPressed, } impl UserInterface for Counter { // We use the message enum we just defined type Message = Message; // We can use the the built-in `Renderer` type Renderer = Renderer; // The update logic, called when a message is produced fn react(&mut self, message: Message) { // We update the counter value after an interaction here match message { Message::IncrementPressed => { self.value += 1; } Message::DecrementPressed => { self.value -= 1; } } } // The layout logic, describing the different components of the user interface fn layout(&mut self, window: &Window) -> Element<Message> { // We use a column so the elements inside are laid out vertically Column::new() .push( // The increment button. We tell it to produce an // `IncrementPressed` message when pressed Button::new(&mut self.increment_button, "+") .on_press(Message::IncrementPressed), ) .push( // We show the value of the counter here Text::new(&self.value.to_string()).size(50), ) .push( // The decrement button. We tell it to produce a // `DecrementPressed` message when pressed Button::new(&mut self.decrement_button, "-") .on_press(Message::DecrementPressed), ) .into() // We need to return a generic `Element` } }
The Game
implementation is mostly irrelevant and was omitted in order to
keep the example short. You can find the full source code of this example
(and other examples too!) in the examples
directory on GitHub.
Notice how UserInterface::react
focuses on processing messages and
updating state. On the other hand, UserInterface::layout
only focuses on
building the user interface from the current state. This separation of
concerns will help you build composable user interfaces that are easy to
debug and test!
Customization
Coffee provides some widgets and a Renderer
out-of-the-box. However,
you can build your own! Check out the core
module to learn more!
Re-exports
pub use self::core::Align; |
pub use self::core::Justify; |
pub use widget::button; |
pub use widget::slider; |
pub use widget::Button; |
pub use widget::Checkbox; |
pub use widget::Radio; |
pub use widget::Slider; |
pub use widget::Text; |
Modules
core | Customize your user interface with your own widgets and renderers. |
widget | Use the built-in widgets in your user interface. |
Structs
Configuration | The |
Renderer | A renderer capable of drawing all the built-in widgets. |
Traits
UserInterface | The user interface of your game. |
Type Definitions
Column | |
Element | |
Row |