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::*;