1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
// https://www.apache.org/licenses/LICENSE-2.0
//! Library macros
//!
//! This documentation is provided as a reference. It may also be useful to
//! refer to the widget library and example apps for examples of usage.
//!
//! The following macros are provided:
//!
//! - [`derive(Widget)`] is used to implement the [`Widget`] trait family
//! - [`derive(VoidMsg)`] is a convenient way to implement `From<VoidMsg>`
//! - [`make_widget`] allows a custom widget to be defined and instantiated
//! simultaneously
//!
//! Note that these macros are defined in the external crate, `kas-macros`, only
//! because procedural macros must be defined in a special crate. The
//! `kas-macros` crate should not be used directly.
//!
//! [`make_widget`]: #the-make_widget-macro
//! [`derive(Widget)`]: #the-derivewidget-macro
//! [`derive(VoidMsg)`]: #the-derivevoidmsg-macro
//!
//!
//! ## The `derive(Widget)` macro
//!
//! The [`Widget`] trait is one of a family, all of which must be
//! implemented by a widget. This family may be extended with additional traits
//! in the future, and users are forbidden (to avoid breakage) from directly
//! implementing the [`Widget`] and [`WidgetCore`] traits. This `derive(Widget)`
//! macro is key to making this trait-family design possible: it (potentially)
//! implements all traits in the family at once, on an opt-out basis
//! (exception: the [`Layout`] trait is opt-in).
//!
//! It is recommended to use **nightly rustc** when developing code using this
//! macro for improved diagnostics using
//! [`proc_macro_diagnostics`](https://github.com/rust-lang/rust/issues/54140)
//! (this is enabled automatically). It is safe to use a stable Rust compiler
//! but debugging macros will be harder.
//!
//! The behaviour of this macro is controlled by attributes on struct fields and
//! on the widget struct itself.
//!
//! These attributes may be used on the struct: `widget`, `widget_derive`, `layout`, `handler`.
//! These may each appear zero or once (except `handler`; see below).
//! They support multiple parameters, e.g. `#[widget(config=noauto, children=noauto)]`.
//!
//! These attributes may be used on fields: `widget`, `widget_core`,
//! `widget_derive`, `layout_data`.
//! The `widget` attribute supports multiple parameters,
//! discussed below (e.g. `#[widget(row=1, handler=f)]`).
//! Fields without attributes (plain data fields) are fine too.
//!
//! A simple example:
//! ```
//! use kas::{event, prelude::*};
//!
//! #[derive(Clone, Debug, Widget)]
//! #[layout(single)]
//! #[handler(generics = <> where W: Widget<Msg = event::VoidMsg>)]
//! struct WrapperWidget<W: Widget> {
//! #[widget_core] core: CoreData,
//! #[widget] child: W,
//! }
//! ```
//!
//! We will now discuss each member of the [`Widget`] trait family in turn.
//!
//! ### Widget and WidgetCore
//!
//! The [`Widget`] and [`WidgetCore`] traits are always derived by this macro.
//! No configuration is available.
//!
//! One struct field with specification `#[widget_core] core: CoreData` is
//! required to support [`WidgetCore`]. The field may be accessed directly.
//!
//! ### WidgetChildren
//!
//! The [`WidgetChildren`] trait is used to enumerate child widgets. Any struct
//! field with the `#[widget]` attribute is identified as a child widget, and
//! will be enumerated by the derived implementation of this trait, in the order
//! of definition.
//!
//! In case child widgets are stored within a container (e.g. `Vec`), this macro
//! is unable to enumerate the widgets correctly. In that case one must opt out
//! of deriving this trait with `#[widget(children = noauto)]` on the struct.
//!
//! ### Layout
//!
//! The [`Layout`] trait is used to define size, structure and appearance of a
//! widget. Unlike other members of the trait family, this trait is not derived
//! by default, and the derived implementation is only useful for widgets with
//! at least one child and which don't directly draw themselves.
//!
//! The trait may be derived via a `layout` attribute, e.g. `#[layout(single)]`.
//! One of the following values must appear first in the parameter list:
//!
//! - `single` — the widget wraps a single child, with no border or margin
//! - `col`, `column` or `down` — child widgets are arranged in a vertical
//! column, top-to-bottom
//! - `up` — reversed column
//! - `row` or `right` — child widgets are arranged in a horizontal row,
//! left-to-right
//! - `left` — reversed row
//! - `grid` — child widgets are arranged in a grid; position is specified
//! via parameters to the `#[widget]` attribute on child fields
//!
//! Additional parameters are optional:
//!
//! - `area=FIELD` where `FIELD` is the name of a child widget — in this case,
//! the [`Layout::find_id`] method maps any coordinate within the widget's
//! `rect` to this child (thus forwarding coordinate-driven events to this
//! child)
//! - `draw=METHOD` where `METHOD` is a method — in this case [`Layout::draw`]
//! calls the given method (with identical parameters to [`Layout::draw`])
//! instead of the usual implementation (drawing child widgets)
//!
//! **Child widget placement**
//!
//! All fields with attribute `#[widget]` are considered child widgets. For most
//! layouts, these are placed in order of definition.
//!
//! For the `grid` layout, parameters are used to specify position
//! (e.g. `#[widget(col=1, cspan=2)]`). These each have a default value:
//!
//! - `col=0` or `column=0` — grid column, from left, counting from 0
//! - `row=0` — grid row, from top, counting from 0
//! - `cspan=1` — number of columns to span
//! - `rspan=1` — number of rows to span
//!
//! Alignment may also be specified for children. The exact behaviour depends
//! on the child widget, and usually is only relevant when the available space
//! is greater than the child's ideal size. These parameters are used to
//! construct an [`AlignHints`] which is passed into [`Layout::set_rect`].
//!
//! - `align = ...` — one of `centre`, `center`, `stretch`
//! - `halign = ...` — one of `default`, `left`, `centre`, `center`, `right`, `stretch`
//! - `valign = ...` — one of `default`, `top`, `centre`, `center`, `bottom`, `stretch`
//!
//! **Layout data storage**
//!
//! When deriving [`Layout`], data storage is required (exception: layout
//! `single` requires no storage, but defining it anyway is harmless).
//! The [`LayoutData`] trait is also derived and used to specify the required
//! data type. The `#[layout_data]` attribute is required to identify this
//! storage, resulting in a field like the following:
//! ```none
//! #[layout_data] layout_data: <Self as kas::LayoutData>::Data,
//! ```
//! This field supports `Default` and `Clone`, thus may be constructed with
//! `layout_data: Default::default()`.
//!
//! ### WidgetConfig
//!
//! The [`WidgetConfig`] trait allows additional configuration of widget
//! behaviour. It is derived by default but may be customised via a `config`
//! parameter to the `widget` attribute on the struct.
//!
//! `#[widget(config = noauto)]` or `#[widget(config(noauto))]` opts-out of
//! deriving this trait.
//!
//! The `config` parameter itself accepts parameters, which may be used to
//! modify the derived implementation, e.g. `#[widget(config(key_nav = true))]`.
//! Parameter description with default values:
//!
//! - `key_nav = false`: a boolean, describing whether the widget supports
//! keyboard navigation (see [`WidgetConfig::key_nav`])
//! - `hover_highlight = false`: a boolean, describing whether to request a
//! redraw when mouse-hover status changes (see [`WidgetConfig::hover_highlight`])
//! - `cursor_icon = kas::event::CursorIcon::Default`: the cursor icon to use
//! when the mouse hovers over this widget (see [`WidgetConfig::cursor_icon`])
//!
//! ### Handler and SendEvent
//!
//! The [`Handler`] and [`SendEvent`] traits are derived, unless opted out.
//! The `#[handler]` attribute allows control over this via the following
//! arguments, all of which are optional:
//!
//! - `noauto` — do not derive [`Handler`] or [`SendEvent`]
//! - `handle=noauto` — do not derive [`Handler`] (whose main method is [`Handler::handle`])
//! - `send=noauto` — do not derive [`SendEvent`] (whose main method is [`SendEvent::send`])
//! - `msg = TYPE` — the [`Handler::Msg`] associated type; if not
//! specified, this type defaults to [`crate::event::VoidMsg`]
//! - `generics = ...`; this parameter must appear last in the
//! list and allows extra type parameters and/or restrictions to appear on
//! the implementations of [`Handler`], [`SendEvent`] and [`Widget`].
//! It accepts any of the following:
//!
//! - `<TYPE_PARAMS>`, for example `<T, W: Widget>` (these type parameters
//! are *added* to those appearing on the struct definition)
//! - `<TYPE_PARAMS> where CONDS`, for example
//! `<> where W: Widget<Msg = event::VoidMsg>`; note that conditions may
//! apply to type parameters from the struct signature (in this example, `W`)
//! - `SUBS` where `SUBS` is a list of substitutions; e.g. if `M` is a
//! type parameter of the struct, then `M => MyMsg` will substitute the
//! parameter `M` for concrete type `MyMsg`.
//! (Once [rust#20041](https://github.com/rust-lang/rust/issues/20041) is
//! fixed, substitutions will no longer be required.)
//! - `SUBS <TYPE_PARAMS> where CONDS`; e.g. if `M` is a type parameter
//! of the struct, one might use `M => <W as Handler>::Msg, <W: Widget>`
//!
//! Commonly, implementations of the [`Handler`] and [`Layout`] traits require
//! extra type bounds on the
//! `impl` which do not appear on the struct, for example a struct may be
//! parametrised with `W: Widget`, but the [`Handler`] impl may require
//! `W: Layout`. This may be achieved as follows:
//! ```
//! # use kas::macros::Widget;
//! # use kas::{CoreData, Layout, Widget, event::Handler};
//! #[derive(Clone, Debug, Default, Widget)]
//! #[layout(single)]
//! #[handler(msg = <W as Handler>::Msg, generics = <> where W: Layout)]
//! pub struct Frame<W: Widget> {
//! #[widget_core]
//! core: CoreData,
//! #[widget]
//! child: W,
//! }
//! ```
//!
//! Exceptionally, multiple `#[handler]` attributes may be used to generate
//! multiple implementations. These must use `generics` parameters which result
//! in non-overlapping bounds. This functionality is not well tested.
//!
//! **Handling response messages from children**
//!
//! The [`Handler`] trait supports a user-defined message type, `Msg`.
//! A "handler" maps a child's message type into the parent's message type.
//!
//! Where the child's message type can be converted into the parent's message
//! type using [`From`], no explicit handler is needed.
//! (This is why all message types must support `From<VoidMsg>`.)
//! In other cases, if no explicit handler is provided, an error will result:
//!
//! ```none
//! error[E0277]: the trait bound `kas::event::VoidMsg: std::convert::From<Item>` is not satisfied
//! ```
//!
//! A handler is a method on the parent struct with signature
//! `fn f(&mut self, mgr: &mut Manager, item: Item) -> Response<Out>`
//! (where `Item` is the child's message type and `Out` is the parent's message
//! type).
//!
//! A handler is bound to a child via the `widget` attribute, for example
//! `#[widget(handler = f)] child: ChildType`.
//!
//! ### widget_derive
//!
//! The `#[widget_derive]` attribute may optionally appear on a field, and may
//! also appear on the struct. The attribute has two possible effects:
//!
//! 1. If used on a field *instead of* a field marked with `#[widget_core]`,
//! this field must implement [`Widget`] and the widget traits are
//! implemented for the struct as wrappers around this field. This
//! may be useful to implement a wrapper struct as a widget, for example
//! [`crate::widgets::ScrollBarRegion`] (shown below).
//! 2. If used on the struct *and* on a field, the attribute allows deriving
//! various traits: [`std::ops::Deref`], [`std::ops::DerefMut`], and the
//! "class traits": [`crate::class`]. The traits to derive must be specified
//! as parameters to the attribute applied to the struct. The parameter
//! `class_traits` may be used to imply all [`crate::class`] traits, where
//! available. These traits will be derived to refer to the marked field.
//!
//! An example showing both effects simultaneously to implement [`Widget`],
//! [`std::ops::Deref`], [`std::ops::DerefMut`] and the [`crate::class`] traits:
//! ```
//! # use kas::prelude::*;
//! # use kas::widgets::{ScrollBars, ScrollRegion};
//! #[derive(Clone, Debug, Default, Widget)]
//! #[widget_derive(class_traits, Deref, DerefMut)]
//! #[handler(msg = <W as Handler>::Msg)]
//! pub struct ScrollBarRegion<W: Widget>(#[widget_derive] ScrollBars<ScrollRegion<W>>);
//! ```
//!
//! ### Examples
//!
//! A simple example is included above.
//! The example below includes multiple children and custom event handling.
//!
//! ```
//! use kas::event::{Manager, Response, VoidMsg};
//! use kas::macros::Widget;
//! use kas::widgets::StrLabel;
//! use kas::{CoreData, LayoutData, Widget};
//!
//! #[derive(Debug)]
//! enum ChildMessage { A }
//!
//! #[derive(Debug, Widget)]
//! #[layout(column)]
//! #[handler(generics = <> where W: Widget<Msg = ChildMessage>)]
//! struct MyWidget<W: Widget> {
//! #[widget_core] core: CoreData,
//! #[layout_data] layout_data: <Self as LayoutData>::Data,
//! #[widget] label: StrLabel,
//! #[widget(handler = handler)] child: W,
//! }
//!
//! impl<W: Widget> MyWidget<W> {
//! fn handler(&mut self, mgr: &mut Manager, msg: ChildMessage) -> Response<VoidMsg> {
//! match msg {
//! ChildMessage::A => { println!("handling ChildMessage::A"); }
//! }
//! Response::None
//! }
//! }
//! ```
//!
//!
//! ## The `derive(VoidMsg)` macro
//!
//! This macro implements `From<VoidMsg>` for the given type (see [`VoidMsg`]).
//!
//! [`VoidMsg`]: crate::event::VoidMsg
//!
//! ### Example
//!
//! ```
//! use kas::macros::VoidMsg;
//!
//! #[derive(VoidMsg)]
//! enum MyMessage { A, B };
//! ```
//!
//!
//! ## The `make_widget` macro
//!
//! The [`make_widget`] allows a custom widget to be defined and instantiated
//! simultaneously. In syntax, it is largely similar to [`derive(Widget)`] but
//! allows several details to be omitted, including field names and types.
//! Its usage is convenient (and widespread in the examples) but not required.
//!
//! But first, a **warning**: this macro is complex (especially with regards to
//! elided types) and tends to produce terrible error messages. Accessing fields
//! of the generated widgets from outside code is complicated. It would be much
//! improved with [RFC 2524](https://github.com/rust-lang/rfcs/pull/2524)
//! (essentially, anonymous types).
//!
//! Lets start with some examples:
//!
//! ```
//! use kas::prelude::*;
//! use kas::widgets::{Label, TextButton, Window};
//!
//! let message = "A message to print.";
//!
//! #[derive(Copy, Clone, Debug, VoidMsg)]
//! enum OkCancel {
//! Ok,
//! Cancel,
//! }
//!
//! let button_box = make_widget!{
//! #[layout(row)]
//! #[handler(msg = OkCancel)]
//! #[derive(Clone)] // optional
//! struct {
//! #[widget] _ = TextButton::new_msg("Ok", OkCancel::Ok),
//! #[widget] _ = TextButton::new_msg("Cancel", OkCancel::Cancel),
//! }
//! };
//!
//! let window = Window::new("Question", make_widget! {
//! #[layout(column)]
//! #[handler(msg = VoidMsg)]
//! struct {
//! #[widget] _ = Label::new("Would you like to print a message?"),
//! #[widget(handler = buttons)] _ = button_box,
//! message: String = message.into(),
//! }
//! impl {
//! fn buttons(&mut self, mgr: &mut Manager, msg: OkCancel) -> Response<VoidMsg> {
//! match msg {
//! OkCancel::Ok => {
//! println!("Message: {}", self.message);
//! }
//! _ => (),
//! }
//! // Whichever button was pressed, we close the window:
//! *mgr |= TkAction::CLOSE;
//! Response::None
//! }
//! }
//! });
//! ```
//!
//! In both `button_box` and the window we see widgets without name or type.
//! Often enough, we don't need a name and the type can be inferred from the
//! initialiser, hence we only need `_ = Label::new(...)`.
//!
//! The `button_box`'s widgets both have message type `OkCancel`; since this
//! matches the parent's message type no handler is needed (the messages are
//! simply forwarded). However, where `button_box` appears in the window, a
//! handler is needed; this works exactly as [above](#handler-and-sendevent).
//!
//! We see both the `struct` and the `impl` block lack a name and lack generics
//! parameters. `make_widget!` defines an *anonymous* type. This type in fact
//! usually has generic parameters, but you don't see them anywhere (except for
//! error messages). Any `impl` items appearing within `make_widget!` are
//! assumed to be on this struct. Multiple `impl` items may
//! appear, including trait impls (`impl HasText { ... }`).
//!
//! The structs are both defined with `layout` and `handler` attributes which
//! are forwarded to the [`derive(Widget)]` macro. Attributes may be applied
//! like usual, however `#[derive(Debug, kas::macros::Widget)]` is implied.
//!
//! Different from [`derive(Widget)`], one must specify the message type via
//! either `#[handler(msg = ..)]` or a [`Handler`] implementation. The type does
//! not default to [`VoidMsg`] (purely to avoid some terrible error messages).
//!
//! ### Struct fields
//!
//! Field specifications allow both the field name and the field type to be
//! elided. For example, all of the following are equivalent:
//!
//! ```nocompile
//! #[widget] l1: Label = Label::new("label 1"),
//! #[widget] _: Label = Label::new("label 2"),
//! #[widget] l3 = Label::new("label 3"),
//! #[widget] _ = Label::new("label 4"),
//! ```
//!
//! Omitting field names is fine, so long as you don't need to refer to them.
//! Omitting types, however, comes at a small cost: Rust does not support fields
//! of unspecified types, thus this must be emulated with generics. The macro
//! deals with the necessary type arguments to implementations, however macro
//! expansions (as sometimes seen in error messages) are ugly and, perhaps worst
//! of all, any code outside the `make_widget` macro instance will see the
//! field type as generic with only the declared bounds.
//!
//! Type bounds may be specified using "impl Trait" syntax:
//! ```nocompile
//! #[widget] display: impl HasText = EditBox::new("editable"),
//! ```
//!
//! For widgets, the message type may be specified as follows:
//! ```nocompile
//! #[widget] buttons -> MyMessage = make_buttons(),
//! ```
//!
//! Alternatively, generics can be introduced explicitly:
//! ```nocompile
//! #[widget] display: for<W: Widget<Msg = VoidMsg>> Frame<W> =
//! Frame::new(Label::new("example")),
//! ```
// Imported for doc-links
#[allow(unused)]
use crate::{
event::{Handler, SendEvent},
layout::AlignHints,
CoreData, Layout, LayoutData, Widget, WidgetChildren, WidgetConfig, WidgetCore, WidgetId,
};
pub use kas_core::macros::*;