diff --git a/README.md b/README.md index c888a7f..09c3baf 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,12 @@ fn main() { For more thorough examples, check the `examples/` folder - for each UI control that's supported there will (ideally) be an example to accompany it. +If you're interested in a more "kitchen sink" example, check out the todos_list with: + +``` sh +cargo run --example todos_list +``` + ## Initialization Due to the way that AppKit and UIKit programs typically work, you're encouraged to do the bulk of your work starting from the `did_finish_launching()` method of your `AppDelegate`. This diff --git a/examples/todos_list/README.md b/examples/todos_list/README.md new file mode 100644 index 0000000..069604f --- /dev/null +++ b/examples/todos_list/README.md @@ -0,0 +1,21 @@ +# Tasks Example +This example implements a "full featured" macOS app, completely in Rust. Notably, it showcases the following: + +- Working menu(s), with dispatchable actions. +- A cached, reusable `ListView`. + - Cell configuration and styling. + - Row actions: complete a task, mark a task as incomplete. + - Basic animation support. + - Self-sizing rows based on autolayout. +- Custom widget composition (see `preferences/toggle_option_view.rs`. +- Multiple windows. +- Toolbars per-window. +- Button and Toolbar Items, with actions. +- Running a window as a modal sheet. +- Autolayout to handle UI across the board. +- Message dispatch (a bit jank, but hey, that's fine for now). +- Standard "Preferences" screens + - A general and advanced pane, with pane selection. + - Looks correct on both Big Sur, as well as Catalina and earlier. + +While the Cacao API is still subject to changes and revisions, this hopefully illustrates what's possible with everything as it currently exists, and provides an entry point for outside contributors to get their feet wet. diff --git a/examples/todos_list/add/mod.rs b/examples/todos_list/add/mod.rs new file mode 100644 index 0000000..d94ac77 --- /dev/null +++ b/examples/todos_list/add/mod.rs @@ -0,0 +1,44 @@ +//! Implements a window for adding a new Todo. + +use cacao::macos::window::{Window, WindowDelegate}; +use cacao::view::ViewController; + +use crate::storage::{dispatch_ui, Message}; + +mod view; +use view::AddNewTodoContentView; + +pub struct AddNewTodoWindow { + pub content: ViewController, +} + +impl AddNewTodoWindow { + pub fn new() -> Self { + let content = ViewController::new(AddNewTodoContentView::default()); + + AddNewTodoWindow { + content: content + } + } + + pub fn on_message(&self, message: Message) { + if let Some(delegate) = &self.content.view.delegate { + delegate.on_message(message); + } + } +} + +impl WindowDelegate for AddNewTodoWindow { + const NAME: &'static str = "AddNewTodoWindow"; + + fn did_load(&mut self, window: Window) { + window.set_autosave_name("AddNewTodoWindow"); + window.set_minimum_content_size(300, 100); + window.set_title("Add a New Task"); + window.set_content_view_controller(&self.content); + } + + fn cancel(&self) { + dispatch_ui(Message::CloseSheet); + } +} diff --git a/examples/todos_list/add/view.rs b/examples/todos_list/add/view.rs new file mode 100644 index 0000000..f6ef23b --- /dev/null +++ b/examples/todos_list/add/view.rs @@ -0,0 +1,75 @@ +//! Implements a view for adding a new task/todo. This is still a bit cumbersome as patterns are +//! worked out, but a quick explainer: when the user clicks the "add" button, we dispatch a message +//! which flows back through here, and then we grab the value and process it. +//! +//! Ownership in Rust makes it tricky to do this right, and the TextField widget may undergo more +//! changes before version 0.1. This approach is unlikely to break as an example while those +//! changes are poked and prodded at, even if it is a bit verbose and confusing. + +use cacao::text::Label; +use cacao::layout::{Layout, LayoutConstraint}; +use cacao::view::{View, ViewDelegate}; + +use cacao::button::Button; +use cacao::input::TextField; + +use crate::storage::{dispatch_ui, Message}; + +#[derive(Debug, Default)] +pub struct AddNewTodoContentView { + pub view: Option, + pub input: Option, + pub button: Option