conrod_core/widget/
mod.rs

1//! Widgets are the core building blocks for every conrod user interface.
2//!
3//! This module contains items related to the implementation of the `Widget` trait. It also
4//! re-exports all widgets (and their modules) that are provided by conrod.
5
6use graph::{Container, UniqueWidgetState};
7use position::{
8    Align, Depth, Dimension, Dimensions, Padding, Point, Position, Positionable, Rect, Relative,
9    Sizeable,
10};
11use std;
12use text::font;
13use theme::{self, Theme};
14use ui::{self, Ui, UiCell};
15
16pub use self::id::Id;
17
18pub use self::primitive::image::{self, Image};
19pub use self::primitive::line::{self, Line};
20pub use self::primitive::point_path::{self, PointPath};
21pub use self::primitive::shape::circle::{self, Circle};
22pub use self::primitive::shape::oval::{self, Oval};
23pub use self::primitive::shape::polygon::{self, Polygon};
24pub use self::primitive::shape::rectangle::{self, Rectangle};
25pub use self::primitive::shape::triangles::{self, Triangles};
26pub use self::primitive::text::{self, Text};
27
28pub use self::bordered_rectangle::BorderedRectangle;
29pub use self::button::Button;
30pub use self::canvas::Canvas;
31pub use self::collapsible_area::CollapsibleArea;
32pub use self::drop_down_list::DropDownList;
33pub use self::envelope_editor::EnvelopeEditor;
34pub use self::file_navigator::FileNavigator;
35pub use self::graph::Graph;
36pub use self::grid::Grid;
37pub use self::list::List;
38pub use self::list_select::ListSelect;
39pub use self::matrix::Matrix;
40pub use self::number_dialer::NumberDialer;
41pub use self::plot_path::PlotPath;
42pub use self::range_slider::RangeSlider;
43pub use self::rounded_rectangle::RoundedRectangle;
44pub use self::scrollbar::Scrollbar;
45pub use self::slider::Slider;
46pub use self::tabs::Tabs;
47pub use self::text_box::TextBox;
48pub use self::text_edit::TextEdit;
49pub use self::title_bar::TitleBar;
50pub use self::toggle::Toggle;
51pub use self::xy_pad::XYPad;
52
53// Macro providing modules.
54#[macro_use]
55mod builder;
56
57// Widget functionality modules.
58#[macro_use]
59pub mod id;
60pub mod scroll;
61
62// Primitive widget modules.
63pub mod primitive;
64
65// Widget modules.
66
67pub mod bordered_rectangle;
68pub mod button;
69pub mod canvas;
70pub mod collapsible_area;
71pub mod drop_down_list;
72pub mod envelope_editor;
73pub mod file_navigator;
74pub mod graph;
75pub mod grid;
76pub mod list;
77pub mod list_select;
78pub mod matrix;
79pub mod number_dialer;
80pub mod plot_path;
81pub mod range_slider;
82pub mod rounded_rectangle;
83pub mod scrollbar;
84pub mod slider;
85pub mod tabs;
86pub mod text_box;
87pub mod text_edit;
88pub mod title_bar;
89pub mod toggle;
90pub mod xy_pad;
91
92/// Arguments for the [**Widget::update**](./trait.Widget#method.update) method in a struct to
93/// simplify the method signature.
94pub struct UpdateArgs<'a, 'b: 'a, 'c, 'd: 'c, W>
95where
96    W: Widget,
97{
98    /// The **Widget**'s unique index.
99    pub id: Id,
100    /// The **Widget**'s parent unique index, if there is one.
101    pub maybe_parent_id: Option<Id>,
102    /// The **Widget**'s previous state. Specifically, the state that is common between all widgets,
103    /// such as positioning, floatability, draggability, etc.
104    pub prev: &'a CommonState,
105    /// A wrapper around the **Widget**'s unique state, providing methods for both immutably viewing
106    /// and mutably updating the state.
107    ///
108    /// We wrap mutation in a method so that we can keep track of whether or not the unique state
109    /// has been updated.
110    ///
111    /// If **State::update** is called, we assume that there has been some mutation and in turn
112    /// will require re-drawing the **Widget**. Thus, it is recommended that you *only* call
113    /// **State::update** if you need to update the unique state in some way.
114    pub state: &'a mut State<'b, W::State>,
115    /// The rectangle describing the **Widget**'s area.
116    pub rect: Rect,
117    /// The **Widget**'s current **Widget::Style**.
118    pub style: &'a W::Style,
119    /// Restricted access to the `Ui`.
120    ///
121    /// Provides methods for immutably accessing the `Ui`'s `Theme` and `GlyphCache`.  Also allows
122    /// calling `Widget::set` within the `Widget::update` method.
123    pub ui: &'c mut UiCell<'d>,
124}
125
126/// Arguments to the [**Widget::kid_area**](./trait.Widget#method.kid_area) method in a struct to
127/// simplify the method signature.
128pub struct KidAreaArgs<'a, W>
129where
130    W: Widget,
131{
132    /// The **Rect** describing the **Widget**'s position and dimensions.
133    pub rect: Rect,
134    /// Current **Widget::Style** of the **Widget**.
135    pub style: &'a W::Style,
136    /// The active **Theme** within the **Ui**.
137    pub theme: &'a Theme,
138    /// The **Font** (for determining text width).
139    pub fonts: &'a font::Map,
140}
141
142/// The area upon which a **Widget**'s child widgets will be placed.
143#[derive(Copy, Clone, Debug, PartialEq)]
144pub struct KidArea {
145    /// The **Rect** bounds describing the position and area.
146    pub rect: Rect,
147    /// The distance between the edge of the area and where the widgets will be placed.
148    pub pad: Padding,
149}
150
151/// The builder argument for the **Widget**'s parent.
152#[derive(Copy, Clone, Debug, PartialEq)]
153pub enum MaybeParent {
154    /// The user specified the widget should not have any parents, so the Root will be used.
155    None,
156    /// The user gave a specific parent widget.
157    Some(Id),
158    /// No parent widget was specified, so we will assume they want the last parent.
159    Unspecified,
160}
161
162impl MaybeParent {
163    /// Convert the **MaybeParent** into an **Option<Id>**.
164    ///
165    /// If `Unspecified`, check the positioning to retrieve the **Id** from there.
166    ///
167    /// If `None`, the `Ui`'s `window` widget will be used.
168    ///
169    /// **Note:** This method does not check whether or not using the `window` widget as the parent
170    /// would cause a cycle. If it is important that the inferred parent should not cause a cycle,
171    /// use `get` instead.
172    pub fn get_unchecked(&self, ui: &Ui, x_pos: Position, y_pos: Position) -> Id {
173        match *self {
174            MaybeParent::Some(id) => id,
175            MaybeParent::None => ui.window.into(),
176            MaybeParent::Unspecified => ui::infer_parent_unchecked(ui, x_pos, y_pos),
177        }
178    }
179
180    /// The same as `get_unchecked`, but checks whether or not the widget that we're inferring the
181    /// parent for is the `Ui`'s window (which cannot have a parent, without creating a cycle).
182    pub fn get(&self, id: Id, ui: &Ui, x_pos: Position, y_pos: Position) -> Option<Id> {
183        if id == ui.window {
184            None
185        } else {
186            Some(self.get_unchecked(ui, x_pos, y_pos))
187        }
188    }
189}
190
191/// State necessary for "floating" (pop-up style) widgets.
192#[derive(Copy, Clone, Debug, PartialEq)]
193pub struct Floating {
194    /// The time the **Widget** was last clicked (used for depth sorting in the widget **Graph**).
195    pub time_last_clicked: instant::Instant,
196}
197
198/// A struct containing builder data common to all **Widget** types.
199///
200/// This type also allows us to do a blanket impl of **Positionable** and **Sizeable** for `T: Widget`.
201///
202/// When Rust gets some sort of field inheritance feature, this will most likely be refactored to
203/// take advantage of that.
204#[derive(Clone, Copy, Debug)]
205pub struct CommonBuilder {
206    /// Styling and positioning data that is common between all widget types.
207    pub style: CommonStyle,
208    /// The parent widget of the Widget.
209    pub maybe_parent_id: MaybeParent,
210    /// Whether or not the Widget is a "floating" Widget.
211    pub is_floating: bool,
212    /// Whether or not the children of this **Widget** should be cropped to its `kid_area`.
213    ///
214    /// By default, the kid_area is the size of the entire widget, though it may be specified
215    /// otherwise via the `Widget::kid_area` method.
216    pub crop_kids: bool,
217    /// Arguments to the scrolling of the widget's *x* axis.
218    pub maybe_x_scroll: Option<scroll::Scroll>,
219    /// Arguments to the scrolling of the widget's *y* axis.
220    pub maybe_y_scroll: Option<scroll::Scroll>,
221    /// Whether or not the **Widget** should be placed on the kid_area.
222    ///
223    /// If `true`, the **Widget** will be placed on the `kid_area` of the parent **Widget** if the
224    /// **Widget** is given a **Place** variant for its **Position**.
225    ///
226    /// If `false`, the **Widget** will be placed on the parent **Widget**'s *total* area.
227    pub place_on_kid_area: bool,
228    /// Describes whether or not the **Widget** is instantiated as a graphical element for some
229    /// other **Widget**.
230    ///
231    /// When adding an edge *a -> b* where *b* is considered to be a graphical element of *a*,
232    /// several things are implied about *b*:
233    ///
234    /// - If *b* is picked within either **Graph::pick_widget** or
235    /// **Graph::pick_top_scrollable_widget**, it will instead return the index for *a*.
236    /// - When determining the **Graph::scroll_offset** for *b*, *a*'s scrolling (if it is
237    /// scrollable, that is) will be skipped.
238    /// - *b* will always be placed upon *a*'s total area, rather than its kid_area which is the
239    /// default.
240    /// - Any **Graphic** child of *b* will be considered as a **Graphic** child of *a*.
241    pub maybe_graphics_for: Option<Id>,
242}
243
244/// Styling and positioning data that is common between all widget types.
245#[derive(Clone, Copy, Debug, Default, PartialEq)]
246pub struct CommonStyle {
247    /// The width of a Widget.
248    pub maybe_x_dimension: Option<Dimension>,
249    /// The height of a Widget.
250    pub maybe_y_dimension: Option<Dimension>,
251    /// The position of a Widget along the *x* axis.
252    pub maybe_x_position: Option<Position>,
253    /// The position of a Widget along the *y* axis.
254    pub maybe_y_position: Option<Position>,
255    /// The rendering Depth of the Widget.
256    pub maybe_depth: Option<Depth>,
257}
258
259/// A wrapper around a **Widget**'s unique **Widget::State**.
260///
261/// This type is used to provide limited access to the **Widget::State** within the
262/// [**Widget::update**](./trait.Widget#method.update) method (to which it is passed via the
263/// [**UpdateArgs**](./struct.UpdateArgs)).
264///
265/// The type provides only two methods. One for viewing the state, the other for mutating it.
266///
267/// We do this so that we can keep track of whether or not the **Widget::State** has been mutated
268/// (using an internal `has_updated` flag). This allows us to know whether or not we need to
269/// re-draw the **Widget**, without having to compare the previous and new **Widget::State**s.
270pub struct State<'a, T: 'a> {
271    state: &'a mut T,
272    /// A flag indicating whether or not the widget's State has been updated.
273    has_updated: bool,
274}
275
276/// A wrapper around state that is common to all **Widget** types.
277#[derive(Copy, Clone, Debug, PartialEq)]
278pub struct CommonState {
279    /// The rectangle describing the `Widget`'s area.
280    pub rect: Rect,
281    /// The rendering depth for the Widget (the default is 0.0).
282    pub depth: Depth,
283    /// If widget is draggable and is being dragged, this is where it started
284    pub maybe_dragged_from: Option<Point>,
285    /// Floating state for the widget if it is floating.
286    pub maybe_floating: Option<Floating>,
287    /// The area of the widget upon which kid widgets are placed.
288    pub kid_area: KidArea,
289    /// If the widget is scrollable across the *x* axis.
290    pub maybe_x_scroll_state: Option<scroll::StateX>,
291    /// If the widget is scrollable across the *y* axis.
292    pub maybe_y_scroll_state: Option<scroll::StateY>,
293}
294
295// **Widget** data to be cached prior to the **Widget::update** call in the **widget::set_widget**
296// function.
297//
298// We do this so that if this **Widget** were to internally `set` some other **Widget**s, this
299// **Widget**'s positioning and dimension data already exists within the widget **Graph** for
300// reference.
301#[allow(missing_docs)]
302#[allow(missing_copy_implementations)]
303pub struct PreUpdateCache {
304    /// The **Widget**'s unique type identifier.
305    pub type_id: std::any::TypeId,
306    /// The **Widget**'s unique Id.
307    pub id: Id,
308    /// The **Widget**'s parent's unique index (if it has a parent).
309    pub maybe_parent_id: Option<Id>,
310    /// If this **Widget** is relatively positioned to another **Widget**, this will be the index
311    /// of the **Widget** to which this **Widget** is relatively positioned along the *x* axis.
312    pub maybe_x_positioned_relatively_id: Option<Id>,
313    /// If this **Widget** is relatively positioned to another **Widget**, this will be the index
314    /// of the **Widget** to which this **Widget** is relatively positioned along the *y* axis.
315    pub maybe_y_positioned_relatively_id: Option<Id>,
316    /// The **Rect** describing the **Widget**'s position and dimensions.
317    pub rect: Rect,
318    /// The z-axis depth - affects the render order of sibling widgets.
319    pub depth: Depth,
320    /// The area upon which the **Widget**'s children widgets will be placed.
321    pub kid_area: KidArea,
322    /// If **Widget** is draggable and is being dragged, this is where it started
323    pub maybe_dragged_from: Option<Point>,
324    /// Floating data for the **Widget** if there is some.
325    pub maybe_floating: Option<Floating>,
326    /// Whether or not the children of the **Widget** should be cropped to its `kid_area`.
327    pub crop_kids: bool,
328    /// Scrolling data for the **Widget**'s *x* axis if there is some.
329    pub maybe_x_scroll_state: Option<scroll::StateX>,
330    /// Scrolling data for the **Widget**'s *y* axis if there is some.
331    pub maybe_y_scroll_state: Option<scroll::StateY>,
332    /// Whether or not the **Widget** has been instantiated as a graphical element for some other
333    /// widget.
334    pub maybe_graphics_for: Option<Id>,
335    /// A function describing whether or not a given point is over the widget.
336    pub is_over: IsOverFn,
337}
338
339// **Widget** data to be cached after the **Widget::update** call in the **widget::set_widget**
340// function.
341//
342// We do this so that if this **Widget** were to internally **Widget::set** some other
343// **Widget**s, this **Widget**'s positioning and dimension data will already exist within the
344// widget **Graph** for reference.
345#[allow(missing_docs)]
346pub struct PostUpdateCache<W>
347where
348    W: Widget,
349{
350    /// The **Widget**'s unique **Id**.
351    pub id: Id,
352    /// The **Widget**'s parent's unique **Id** (if it has a parent).
353    pub maybe_parent_id: Option<Id>,
354    /// The newly produced unique **Widget::State** associated with the **Widget**.
355    pub state: W::State,
356    /// The newly produced unique **Widget::Style** associated with the **Widget**.
357    pub style: W::Style,
358}
359
360/// Returned by the `Widget::is_over` method.
361#[derive(Copy, Clone)]
362pub enum IsOver {
363    /// Whether or not the point was over the widget.
364    Bool(bool),
365    /// Check whether or not the point is over the widget at the given `Id` and if so, assume it is
366    /// over this widget.
367    Widget(Id),
368}
369
370impl From<bool> for IsOver {
371    fn from(b: bool) -> Self {
372        IsOver::Bool(b)
373    }
374}
375
376impl From<Id> for IsOver {
377    fn from(id: Id) -> Self {
378        IsOver::Widget(id)
379    }
380}
381
382/// A function type used to determine whether or not a given point is over a widget.
383pub type IsOverFn = fn(&Container, Point, &Theme) -> IsOver;
384
385/// The default `IsOverFn` used if the `Widget::is_over` method is not overridden.
386pub fn is_over_rect(container: &Container, point: Point, _: &Theme) -> IsOver {
387    container.rect.is_over(point).into()
388}
389
390/// The necessary bounds for a **Widget**'s associated **Style** type.
391pub trait Style: std::any::Any + std::fmt::Debug + PartialEq + Sized {}
392
393/// Auto-implement the **Style** trait for all applicable types.
394impl<T> Style for T where T: std::any::Any + std::fmt::Debug + PartialEq + Sized {}
395
396/// Determines the default **Dimension** for a **Widget**.
397///
398/// This function checks for a default dimension in the following order.
399/// 1. Check for a default value within the **Ui**'s **Theme**.
400/// 2. Otherwise attempts to copy the dimension of the previously set widget if there is one.
401/// 3. Otherwise attempts to copy the dimension of our parent widget.
402/// 4. If no parent widget can be inferred, the window dimensions are used.
403fn default_dimension<W, F>(widget: &W, ui: &Ui, f: F) -> Dimension
404where
405    W: Widget,
406    F: FnOnce(theme::UniqueDefault<W::Style>) -> Option<Dimension>,
407{
408    ui.theme
409        .widget_style::<W::Style>()
410        .and_then(f)
411        .or_else(|| ui.maybe_prev_widget().map(|id| Dimension::Of(id, None)))
412        .unwrap_or_else(|| {
413            let x_pos = widget.get_x_position(ui);
414            let y_pos = widget.get_y_position(ui);
415            let parent_id = widget
416                .common()
417                .maybe_parent_id
418                .get_unchecked(ui, x_pos, y_pos);
419            Dimension::Of(parent_id, None)
420        })
421}
422
423/// Determines the default **Dimension** for a **Widget**.
424///
425/// This function checks for a default dimension in the following order.
426/// 1. Check for a default value within the **Ui**'s **Theme**.
427/// 2. Otherwise attempts to copy the dimension of the previously set widget if there is one.
428/// 3. Otherwise attempts to copy the dimension of our parent widget.
429/// 4. If no parent widget can be inferred, the window dimensions are used.
430///
431/// This is called by the default implementations of **Widget::default_x_dimension**.
432///
433/// If you wish to override **Widget::default_x_dimension**, feel free to call this function
434/// internally if you partly require the bahaviour of the default implementations.
435pub fn default_x_dimension<W>(widget: &W, ui: &Ui) -> Dimension
436where
437    W: Widget,
438{
439    default_dimension(widget, ui, |default| default.common.maybe_x_dimension)
440}
441
442/// Determines the default **Dimension** for a **Widget**.
443///
444/// This function checks for a default dimension in the following order.
445/// 1. Check for a default value within the **Ui**'s **Theme**.
446/// 2. Otherwise attempts to copy the dimension of the previously set widget if there is one.
447/// 3. Otherwise attempts to copy the dimension of our parent widget.
448/// 4. If no parent widget can be inferred, the window dimensions are used.
449///
450/// This is called by the default implementations of **Widget::default_y_dimension**.
451///
452/// If you wish to override **Widget::default_y_dimension**, feel free to call this function
453/// internally if you partly require the bahaviour of the default implementations.
454pub fn default_y_dimension<W>(widget: &W, ui: &Ui) -> Dimension
455where
456    W: Widget,
457{
458    default_dimension(widget, ui, |default| default.common.maybe_y_dimension)
459}
460
461/// A trait implemented by all **Widget** types.
462///
463/// This trait provides access to a field of type **CommonBuilder** on the implementor. This allows
464/// the `Widget` trait to automatically provide a large number of methods including those from the
465/// **Positionable** and **Sizeable** traits.
466///
467/// The **Common** trait can be automatically derived for widgets like so:
468///
469/// ```ignore
470/// extern crate conrod_core;
471/// #[macro_use] extern crate conrod_derive;
472///
473/// #[derive(WidgetCommon)]
474/// struct MyWidget {
475///     #[conrod(common_builder)]
476///     common: conrod_core::widget::CommonBuilder,
477///     // etc
478/// }
479/// ```
480pub trait Common {
481    /// Borrows the `CommonBuilder` field.
482    fn common(&self) -> &CommonBuilder;
483    /// Mutably borrows the `CommonBuilder` field.
484    fn common_mut(&mut self) -> &mut CommonBuilder;
485}
486
487/// A trait to be implemented by all **Widget** types.
488///
489/// A type that implements **Widget** can be thought of as a collection of arguments to the
490/// **Widget**'s **Widget::update** method. They type itself is not stored between updates, but
491/// rather is used to update an instance of the **Widget**'s **Widget::State**, which *is* stored.
492///
493/// Methods that *must* be overridden:
494///
495/// - init_state
496/// - style
497/// - update
498///
499/// Methods that can be optionally overridden:
500///
501/// - default_x_position
502/// - default_y_position
503/// - default_width
504/// - default_height
505/// - drag_area
506/// - kid_area
507///
508/// Methods that should not be overridden:
509///
510/// - floating
511/// - scroll_kids
512/// - scroll_kids_vertically
513/// - scroll_kids_horizontally
514/// - place_widget_on_kid_area
515/// - parent
516/// - no_parent
517/// - set
518pub trait Widget: Common + Sized {
519    /// State to be stored within the `Ui`s widget cache.
520    ///
521    /// Take advantage of this type for any large allocations that you would like to avoid
522    /// repeating between updates, or any calculations that you'd like to avoid repeating between
523    /// calls to `update`.
524    ///
525    /// Conrod will never clone the state, it will only ever be moved.
526    type State: std::any::Any + Send;
527    /// Every widget is required to have its own associated `Style` type. This type is intended to
528    /// contain high-level styling information for the widget that can be *optionally specified* by
529    /// a user of the widget.
530    ///
531    /// All `Style` structs are typically `Copy` and contain simple, descriptive fields like
532    /// `color`, `font_size`, `line_spacing`, `border_width`, etc. These types are also required to
533    /// be `PartialEq`. This is so that the `Ui` may automatically compare the previous style to
534    /// the new style each time `.set` is called, allowing conrod to automatically determine
535    /// whether or not something has changed and if a re-draw is required.
536    ///
537    /// Each field in a `Style` struct is typically an `Option<T>`. This is so that each field may
538    /// be *optionally specified*, indicating to fall back to defaults if the fields are `None`
539    /// upon style retrieval.
540    ///
541    /// The reason this data is required to be in its own `Style` type (rather than in the widget
542    /// type itself) is so that conrod can distinguish between default style data that may be
543    /// stored within the `Theme`'s `widget_styling` field, and other data that is necessary for
544    /// the widget's behaviour logic. Having `Style` be an associated type makes it trivial to
545    /// retrieve unique, widget-specific styling data for each widget from a single method (see
546    /// [`Theme::widget_style`](./theme/struct.Theme.html#method.widget_style)).
547    ///
548    /// ## `#[derive(WidgetStyle)]`
549    ///
550    /// These `Style` types are often quite similar and their implementations can involve a lot of
551    /// boilerplate when written by hand. To get around this, conrod provides
552    /// `#[derive(WidgetStyle)]`.
553    ///
554    /// This procedural macro generates a "getter"-style method for each struct field that is
555    /// decorated with a `#[conrod(default = "expr")]` attribute. The generated methods have the
556    /// same name as their respective fields and behave as follows:
557    ///
558    /// 1. First, the method will attempt to return the value directly if the field is `Some`.
559    /// 2. If the field is `None`, the method will fall back to the `Widget::Style` stored within
560    ///    the `Theme`'s `widget_styling` map.
561    /// 3. If there are no style defaults for the widget in the `Theme`, or if there is but the
562    ///    default field is also `None`, the method will fall back to the expression specified
563    ///    within the field's `#[conrod(default = "expr")]` attribute.
564    ///
565    /// The given "expr" can be a string containing any expression that returns the type specified
566    /// within the field's `Option` type parameter. The expression may also utilise the `theme` and
567    /// `self` bindings, where `theme` is a binding to the borrowed `Theme` and `self` is a binding
568    /// to the borrowed instance of this `Style` type.
569    ///
570    /// # Examples
571    ///
572    /// ```
573    /// # extern crate conrod_core;
574    /// # #[macro_use] extern crate conrod_derive;
575    /// # use conrod_core::{Color, FontSize, Scalar};
576    /// # fn main() {}
577    /// /// Unique styling for a Button widget.
578    /// #[derive(Copy, Clone, Debug, Default, PartialEq, WidgetStyle)]
579    /// pub struct Style {
580    ///     /// Color of the Button's pressable area.
581    ///     #[conrod(default = "theme.shape_color")]
582    ///     pub color: Option<Color>,
583    ///     /// Width of the border surrounding the button.
584    ///     #[conrod(default = "1.0")]
585    ///     pub border: Option<Scalar>,
586    ///     /// The color of the Button's rectangular border.
587    ///     #[conrod(default = "conrod_core::color::BLACK")]
588    ///     pub border_color: Option<Color>,
589    ///     /// The color of the Button's label.
590    ///     #[conrod(default = "theme.label_color")]
591    ///     pub label_color: Option<Color>,
592    ///     /// The font size for the Button's label.
593    ///     #[conrod(default = "12")]
594    ///     pub label_font_size: Option<FontSize>,
595    /// }
596    /// ```
597    type Style: Style + Send;
598    /// The type of event yielded by the widget, returned via the `Widget::set` function.
599    ///
600    /// For a `Toggle` widget, this might be a `bool`.
601    ///
602    /// For a non-interactive, purely graphical widget, this might be `()`.
603    type Event;
604
605    /// Return the initial **State** of the Widget.
606    ///
607    /// The `Ui` will only call this once, immediately prior to the first time that
608    /// **Widget::update** is first called.
609    fn init_state(&self, id_gen: id::Generator) -> Self::State;
610
611    /// Return the styling of the widget.
612    ///
613    /// The `Ui` will call this once prior to each `update`. It does this so that it can check for
614    /// differences in `Style` in case we need to re-draw the widget.
615    fn style(&self) -> Self::Style;
616
617    /// Update our **Widget**'s unique **Widget::State** via the **State** wrapper type (the
618    /// `state` field within the [**UpdateArgs**](./struct.UpdateArgs)).
619    ///
620    /// Whenever [**State::update**](./struct.State.html#method.update) is called, a `has_updated`
621    /// flag is set within the **State**, indicating that there has been some change to the unique
622    /// **Widget::State** and that we require re-drawing the **Widget**. As a result, widget
623    /// designers should only call **State::update** when necessary, checking whether or not the
624    /// state has changed before invoking the method. See the custom_widget.rs example for a
625    /// demonstration of this.
626    ///
627    /// # Arguments
628    /// * id - The `Widget`'s unique index (whether `Public` or `Internal`).
629    /// * prev - The previous common state of the Widget. If this is the first time **update** is
630    /// called, `Widget::init_state` will be used to produce some initial state instead.
631    /// * state - A wrapper around the `Widget::State`. See the [**State** docs](./struct.State)
632    /// for more details.
633    /// * rect - The position (centered) and dimensions of the widget.
634    /// * style - The style produced by the `Widget::style` method.
635    /// * ui - A wrapper around the `Ui`, offering restricted access to its functionality. See the
636    /// docs for `UiCell` for more details.
637    fn update(self, args: UpdateArgs<Self>) -> Self::Event;
638
639    /// The default **Position** for the widget along the *x* axis.
640    ///
641    /// This is used when no **Position** is explicitly given when instantiating the Widget.
642    fn default_x_position(&self, ui: &Ui) -> Position {
643        ui.theme
644            .widget_style::<Self::Style>()
645            .and_then(|style| style.common.maybe_x_position)
646            .unwrap_or(ui.theme.x_position)
647    }
648
649    /// The default **Position** for the widget along the *y* axis.
650    ///
651    /// This is used when no **Position** is explicitly given when instantiating the Widget.
652    fn default_y_position(&self, ui: &Ui) -> Position {
653        ui.theme
654            .widget_style::<Self::Style>()
655            .and_then(|style| style.common.maybe_y_position)
656            .unwrap_or(ui.theme.y_position)
657    }
658
659    /// The default width for the **Widget**.
660    ///
661    /// This method is only used if no height is explicitly given.
662    ///
663    /// By default, this simply calls [**default_dimension**](./fn.default_dimension) with a
664    /// fallback absolute dimension of 0.0.
665    fn default_x_dimension(&self, ui: &Ui) -> Dimension {
666        default_x_dimension(self, ui)
667    }
668
669    /// The default height of the widget.
670    ///
671    /// By default, this simply calls [**default_dimension**](./fn.default_dimension) with a
672    /// fallback absolute dimension of 0.0.
673    fn default_y_dimension(&self, ui: &Ui) -> Dimension {
674        default_y_dimension(self, ui)
675    }
676
677    /// If the widget is draggable, implement this method and return the position and dimensions of
678    /// the draggable space. The position should be relative to the center of the widget.
679    fn drag_area(&self, _dim: Dimensions, _style: &Self::Style, _theme: &Theme) -> Option<Rect> {
680        None
681    }
682
683    /// The area on which child widgets will be placed when using the `Place` `Position` methods.
684    fn kid_area(&self, args: KidAreaArgs<Self>) -> KidArea {
685        KidArea {
686            rect: args.rect,
687            pad: Padding::none(),
688        }
689    }
690
691    /// Returns either of the following:
692    ///
693    /// - A `Function` that can be used to describe whether or not a given point is over the
694    /// widget.
695    /// - The `Id` of another `Widget` that can be used to determine if the point is over this
696    /// widget.
697    ///
698    /// By default, this is a function returns `true` if the given `Point` is over the bounding
699    /// `Rect` and returns `false` otherwise.
700    ///
701    /// *NOTE: It could be worth removing this in favour of adding a `widget::State` trait, adding
702    /// an `is_over` method to it and then refactoring the `Container` to store a
703    /// `Box<widget::State>` and `Box<widget::Style>` rather than `Box<Any>`. This would however
704    /// involve some significant breakage (which could perhaps be mitigated by adding a
705    /// `derive(WidgetState)` macro - a fair chunk of work) so this might be the easiest temporary
706    /// way forward for now.*
707    fn is_over(&self) -> IsOverFn {
708        is_over_rect
709    }
710
711    // None of the following methods should require overriding. Perhaps they should be split off
712    // into a separate trait which is impl'ed for W: Widget to make this clearer?
713    // Most of them would benefit by some sort of field inheritance as they are mainly just used to
714    // set common data.
715
716    /// Set the parent widget for this Widget by passing the WidgetId of the parent.
717    ///
718    /// This will attach this Widget to the parent widget.
719    fn parent(mut self, parent_id: Id) -> Self {
720        self.common_mut().maybe_parent_id = MaybeParent::Some(parent_id);
721        self
722    }
723
724    /// Specify that this widget has no parent widgets.
725    fn no_parent(mut self) -> Self {
726        self.common_mut().maybe_parent_id = MaybeParent::None;
727        self
728    }
729
730    /// Set whether or not the **Widget** should be placed on the kid_area.
731    ///
732    /// If `true`, the **Widget** will be placed on the `kid_area` of the parent **Widget** if the
733    /// **Widget** is given a **Place** variant for its **Position**.
734    ///
735    /// If `false`, the **Widget** will be placed on the parent **Widget**'s *total* area.
736    ///
737    /// By default, conrod will automatically determine this for you by checking whether or not the
738    /// **Widget** that our **Widget** is being placed upon returns `Some` from its
739    /// **Widget::kid_area** method.
740    fn place_on_kid_area(mut self, b: bool) -> Self {
741        self.common_mut().place_on_kid_area = b;
742        self
743    }
744
745    /// Indicates that the **Widget** is used as a non-interactive graphical element for some other
746    /// widget.
747    ///
748    /// This is useful for **Widget**s that are used to compose some other **Widget**.
749    ///
750    /// When adding an edge *a -> b* where *b* is considered to be a graphical element of *a*,
751    /// several things are implied about *b*:
752    ///
753    /// - If *b* is picked within either **Graph::pick_widget** or
754    /// **Graph::pick_top_scrollable_widget**, it will instead return the index for *a*.
755    /// - When determining the **Graph::scroll_offset** for *b*, *a*'s scrolling (if it is
756    /// scrollable, that is) will be skipped.
757    /// - *b* will always be placed upon *a*'s total area, rather than its kid_area which is the
758    /// default.
759    /// - Any **Graphic** child of *b* will be considered as a **Graphic** child of *a*.
760    fn graphics_for(mut self, id: Id) -> Self {
761        self.common_mut().maybe_graphics_for = Some(id);
762        self
763    }
764
765    /// Set whether or not the widget is floating (the default is `false`).
766    /// A typical example of a floating widget would be a pop-up or alert window.
767    ///
768    /// A "floating" widget will always be rendered *after* its parent tree and all widgets
769    /// connected to its parent tree. If two sibling widgets are both floating, then the one that
770    /// was last clicked will be rendered last. If neither are clicked, they will be rendered in
771    /// the order in which they were cached into the `Ui`.
772    fn floating(mut self, is_floating: bool) -> Self {
773        self.common_mut().is_floating = is_floating;
774        self
775    }
776
777    /// Indicates that all widgets who are children of this widget should be cropped to the
778    /// `kid_area` of this widget.
779    fn crop_kids(mut self) -> Self {
780        self.common_mut().crop_kids = true;
781        self
782    }
783
784    /// Makes the widget's `KidArea` scrollable.
785    ///
786    /// If a widget is scrollable and it has children widgets that fall outside of its `KidArea`,
787    /// the `KidArea` will become scrollable.
788    ///
789    /// This method calls `Widget::crop_kids` internally.
790    fn scroll_kids(self) -> Self {
791        self.scroll_kids_vertically()
792            .scroll_kids_horizontally()
793            .crop_kids()
794    }
795
796    /// Makes the widget's `KidArea` scrollable.
797    ///
798    /// If a widget is scrollable and it has children widgets that fall outside of its `KidArea`,
799    /// the `KidArea` will become scrollable.
800    ///
801    /// This method calls `Widget::crop_kids` internally.
802    fn scroll_kids_vertically(mut self) -> Self {
803        self.common_mut().maybe_y_scroll = Some(scroll::Scroll::new());
804        self.crop_kids()
805    }
806
807    /// Set whether or not the widget's `KidArea` is scrollable (the default is false).
808    ///
809    /// If a widget is scrollable and it has children widgets that fall outside of its `KidArea`,
810    /// the `KidArea` will become scrollable.
811    ///
812    /// This method calls `Widget::crop_kids` internally.
813    fn scroll_kids_horizontally(mut self) -> Self {
814        self.common_mut().maybe_x_scroll = Some(scroll::Scroll::new());
815        self.crop_kids()
816    }
817
818    /// A builder method that "lifts" the **Widget** through the given `build` function.
819    ///
820    /// This method is solely for providing slight ergonomic improvement by helping to maintain
821    /// the symmetry of the `builder` pattern in some cases.
822    #[inline]
823    fn and<F>(self, build: F) -> Self
824    where
825        F: FnOnce(Self) -> Self,
826    {
827        build(self)
828    }
829
830    /// A builder method that mutates the **Widget** with the given `mutate` function.
831    ///
832    /// This method is solely for providing slight ergonomic improvement by helping to maintain
833    /// the symmetry of the `builder` pattern in some cases.
834    #[inline]
835    fn and_mut<F>(mut self, mutate: F) -> Self
836    where
837        F: FnOnce(&mut Self),
838    {
839        mutate(&mut self);
840        self
841    }
842
843    /// A method that conditionally builds the **Widget** with the given `build` function.
844    ///
845    /// If `cond` is `true`, `build(self)` is evaluated and returned.
846    ///
847    /// If `false`, `self` is returned.
848    #[inline]
849    fn and_if<F>(self, cond: bool, build: F) -> Self
850    where
851        F: FnOnce(Self) -> Self,
852    {
853        if cond {
854            build(self)
855        } else {
856            self
857        }
858    }
859
860    /// A method that optionally builds the **Widget** with the given `build` function.
861    ///
862    /// If `maybe` is `Some(t)`, `build(self, t)` is evaluated and returned.
863    ///
864    /// If `None`, `self` is returned.
865    #[inline]
866    fn and_then<T, F>(self, maybe: Option<T>, build: F) -> Self
867    where
868        F: FnOnce(Self, T) -> Self,
869    {
870        if let Some(t) = maybe {
871            build(self, t)
872        } else {
873            self
874        }
875    }
876
877    /// Note: There should be no need to override this method.
878    ///
879    /// After building the widget, you call this method to set its current state into the given
880    /// `Ui`. More precisely, the following will occur when calling this method:
881    /// - The widget's previous state and style will be retrieved.
882    /// - The widget's current `Style` will be retrieved (from the `Widget::style` method).
883    /// - The widget's state will be updated (using the `Widget::udpate` method).
884    /// - If the widget's state or style has changed, the **Ui** will be notified that the widget
885    /// needs to be re-drawn.
886    /// - The new State and Style will be cached within the `Ui`.
887    fn set<'a, 'b>(self, id: Id, ui_cell: &'a mut UiCell<'b>) -> Self::Event {
888        set_widget(self, id, ui_cell)
889    }
890}
891
892/// Updates the given widget and caches it within the given `Ui`'s `widget_graph`.
893///
894/// If it is the first time a widget has been set, it will be cached into the `Ui`'s widget_graph.
895/// For all following occasions, the pre-existing cached state will be compared and updated.
896///
897/// Note that this is a very imperative, mutation oriented segment of code. We try to move as much
898/// imperativeness and mutation out of the users hands and into this function as possible, so that
899/// users have a clear, concise, purely functional `Widget` API. As a result, we try to keep this
900/// as verbosely annotated as possible. If anything is unclear, feel free to post an issue or PR
901/// with concerns/improvements to the github repo.
902fn set_widget<'a, 'b, W>(widget: W, id: Id, ui: &'a mut UiCell<'b>) -> W::Event
903where
904    W: Widget,
905{
906    let type_id = std::any::TypeId::of::<W::State>();
907
908    // Take the previous state of the widget from the cache if there is some to collect.
909    let (maybe_prev_unique_state, maybe_prev_common, maybe_prev_style) =
910        ui::widget_graph_mut(ui::ref_mut_from_ui_cell(ui))
911            .widget_mut(id)
912            .and_then(|container| {
913                // If the cache is already initialised for a different widget type, warn the user.
914                if container.type_id != type_id {
915                    use std::io::Write;
916                    writeln!(
917                        std::io::stderr(),
918                        "A widget of a different type already exists at the given WidgetId \
919                             ({:?}). You tried to insert a {:?}, however the existing widget is a \
920                             {:?}. Check your widgets' `WidgetId`s for errors.",
921                        id,
922                        type_id,
923                        container.type_id
924                    )
925                    .unwrap();
926                    return None;
927                }
928
929                // Destructure the cached state.
930                let Container {
931                    ref mut maybe_state,
932                    rect,
933                    depth,
934                    kid_area,
935                    maybe_dragged_from,
936                    maybe_floating,
937                    maybe_x_scroll_state,
938                    maybe_y_scroll_state,
939                    ..
940                } = *container;
941
942                let (state, style) = match maybe_state.take().and_then(|a| a.downcast().ok()) {
943                    Some(boxed) => {
944                        let unique: UniqueWidgetState<W::State, W::Style> = *boxed;
945                        let UniqueWidgetState { state, style } = unique;
946                        (state, style)
947                    }
948                    None => return None,
949                };
950
951                // Use the cached state to construct the prev_state (to be fed to Widget::update).
952                let prev_common = CommonState {
953                    rect: rect,
954                    depth: depth,
955                    maybe_dragged_from: maybe_dragged_from,
956                    maybe_floating: maybe_floating,
957                    kid_area: kid_area,
958                    maybe_x_scroll_state: maybe_x_scroll_state,
959                    maybe_y_scroll_state: maybe_y_scroll_state,
960                };
961
962                Some((Some(state), Some(prev_common), Some(style)))
963            })
964            .unwrap_or_else(|| (None, None, None));
965
966    // We need to hold onto the current "previously set widget", as this may change during our
967    // `Widget`'s update method (i.e. if it sets any of its own widgets, they will become the last
968    // previous widget).
969    let maybe_prev_widget_id = ui.maybe_prev_widget();
970
971    let new_style = widget.style();
972    let depth = widget.get_depth();
973    let dim = widget.get_wh(&ui).unwrap_or([0.0, 0.0]);
974    let x_pos = widget.get_x_position(ui);
975    let y_pos = widget.get_y_position(ui);
976    let place_on_kid_area = widget.common().place_on_kid_area;
977
978    // Determine the id of the canvas that the widget is attached to. If not given explicitly,
979    // check the positioning to retrieve the Id from there.
980    let maybe_parent_id = widget.common().maybe_parent_id.get(id, ui, x_pos, y_pos);
981
982    // Calculate the `xy` location of the widget, considering drag.
983    let (xy, maybe_dragged_from) = maybe_prev_common
984        .as_ref()
985        .and_then(|prev| {
986            if widget.common().maybe_graphics_for.is_some() {
987                return None;
988            }
989            let maybe_drag_area = widget.drag_area(dim, &new_style, &ui.theme);
990            maybe_drag_area.map(|drag_area| {
991                let mut current_dragged_from = prev.maybe_dragged_from;
992                let mut current_xy = prev.rect.xy();
993
994                for event in ui.widget_input(id).events() {
995                    match event {
996                        ::event::Widget::Drag(drag) => {
997                            if drag.button == input::MouseButton::Left {
998                                if current_dragged_from.is_none() && drag_area.is_over(drag.origin)
999                                {
1000                                    current_dragged_from = Some(prev.rect.xy());
1001                                }
1002
1003                                if let Some(dragged_from) = current_dragged_from {
1004                                    current_xy = [
1005                                        dragged_from[0] + drag.to[0] - drag.origin[0],
1006                                        dragged_from[1] + drag.to[1] - drag.origin[1],
1007                                    ];
1008                                }
1009                            }
1010                        }
1011                        ::event::Widget::Release(::event::Release {
1012                            button: ::event::Button::Mouse(input::MouseButton::Left, _),
1013                            ..
1014                        }) => {
1015                            current_dragged_from = None;
1016                        }
1017                        _ => {}
1018                    }
1019                }
1020                (current_xy, current_dragged_from)
1021            })
1022        })
1023        // If there is no previous state to compare for dragging, return an initial state.
1024        //
1025        // A function for generating the xy coords from the given alignment and Position.
1026        .unwrap_or_else(|| {
1027            (
1028                ui.calc_xy(
1029                    Some(id),
1030                    maybe_parent_id,
1031                    x_pos,
1032                    y_pos,
1033                    dim,
1034                    place_on_kid_area,
1035                ),
1036                None,
1037            )
1038        });
1039
1040    // Construct the rectangle describing our Widget's area.
1041    let rect = Rect::from_xy_dim(xy, dim);
1042
1043    // Check whether or not the widget is a "floating" (hovering / pop-up style) widget.
1044    let maybe_floating = if widget.common().is_floating {
1045        fn new_floating() -> Floating {
1046            Floating {
1047                time_last_clicked: instant::Instant::now(),
1048            }
1049        }
1050
1051        // If it is floating, check to see if we need to update the last time it was clicked.
1052        match maybe_prev_common.as_ref() {
1053            Some(prev) => {
1054                let maybe_mouse = ui.widget_input(id).mouse();
1055                match (prev.maybe_floating, maybe_mouse) {
1056                    (Some(prev_floating), Some(mouse)) => {
1057                        if mouse.buttons.left().is_down() {
1058                            Some(new_floating())
1059                        } else {
1060                            Some(prev_floating)
1061                        }
1062                    }
1063                    (Some(prev_floating), None) => Some(prev_floating),
1064                    _ => Some(new_floating()),
1065                }
1066            }
1067            None => Some(new_floating()),
1068        }
1069    } else {
1070        None
1071    };
1072
1073    // Retrieve the area upon which kid widgets will be placed.
1074    let kid_area = {
1075        let args: KidAreaArgs<W> = KidAreaArgs {
1076            rect: rect,
1077            style: &new_style,
1078            theme: &ui.theme,
1079            fonts: &ui.fonts,
1080        };
1081        widget.kid_area(args)
1082    };
1083
1084    // If either axis is scrollable, retrieve the up-to-date `scroll::State` for that axis.
1085    //
1086    // We must step the scrolling using the previous `kid_area` state so that the bounding box
1087    // around our kid widgets is in sync with the position of the `kid_area`.
1088    let prev_kid_area = maybe_prev_common
1089        .map(|common| common.kid_area)
1090        .unwrap_or_else(|| kid_area);
1091
1092    // If the widget is scrollable, check for given `Scroll` events.
1093    //
1094    // TODO: On the first time the widget is set (i.e. if `maybe_prev_*_scroll_state` is `None` and
1095    // `maybe_*_scroll` is `Some`) we should consider and handle the `scroll_args`'
1096    // `maybe_initial_alignment` field.
1097    let mut maybe_x_scroll_state = widget.common().maybe_x_scroll.map(|_scroll_args| {
1098        let maybe_prev = maybe_prev_common
1099            .as_ref()
1100            .and_then(|p| p.maybe_x_scroll_state);
1101        scroll::State::update(ui, id, &prev_kid_area, maybe_prev, 0.0)
1102    });
1103    let mut maybe_y_scroll_state = widget.common().maybe_y_scroll.map(|_scroll_args| {
1104        let maybe_prev = maybe_prev_common
1105            .as_ref()
1106            .and_then(|p| p.maybe_y_scroll_state);
1107        scroll::State::update(ui, id, &prev_kid_area, maybe_prev, 0.0)
1108    });
1109
1110    for scroll in ui.widget_input(id).scrolls() {
1111        if widget.common().maybe_x_scroll.is_some() {
1112            maybe_x_scroll_state = Some(scroll::State::update(
1113                ui,
1114                id,
1115                &prev_kid_area,
1116                maybe_x_scroll_state,
1117                scroll.x,
1118            ))
1119        }
1120
1121        if widget.common().maybe_y_scroll.is_some() {
1122            maybe_y_scroll_state = Some(scroll::State::update(
1123                ui,
1124                id,
1125                &prev_kid_area,
1126                maybe_y_scroll_state,
1127                scroll.y,
1128            ))
1129        }
1130    }
1131
1132    // Determine whether or not this is the first time set has been called.
1133    // We'll use this to determine whether or not we need to draw for the first time.
1134    let is_first_set = maybe_prev_common.is_none();
1135
1136    // Update all positioning and dimension related data prior to calling `Widget::update`.
1137    // We do this so that if this widget were to internally `set` some other `Widget`s, this
1138    // `Widget`s positioning and dimension data already exists within the `Graph`.
1139    {
1140        // Some widget to which this widget is relatively positioned (if there is one).
1141        let maybe_positioned_relatively_id = |pos: Position| match pos {
1142            Position::Relative(_, maybe_id) => maybe_id.or(maybe_prev_widget_id),
1143            Position::Absolute(_) => None,
1144        };
1145
1146        let maybe_x_positioned_relatively_id = maybe_positioned_relatively_id(x_pos);
1147        let maybe_y_positioned_relatively_id = maybe_positioned_relatively_id(y_pos);
1148
1149        // Retrieve whether or not the widget's children should be cropped to it.
1150        let crop_kids = widget.common().crop_kids;
1151
1152        // This will cache the given data into the `ui`'s `widget_graph`.
1153        let ui: &mut Ui = ui::ref_mut_from_ui_cell(ui);
1154        ui::pre_update_cache(
1155            ui,
1156            PreUpdateCache {
1157                type_id: type_id,
1158                id: id,
1159                maybe_parent_id: maybe_parent_id,
1160                maybe_x_positioned_relatively_id: maybe_x_positioned_relatively_id,
1161                maybe_y_positioned_relatively_id: maybe_y_positioned_relatively_id,
1162                rect: rect,
1163                depth: depth,
1164                kid_area: kid_area,
1165                maybe_dragged_from: maybe_dragged_from,
1166                maybe_floating: maybe_floating,
1167                crop_kids: crop_kids,
1168                maybe_y_scroll_state: maybe_y_scroll_state,
1169                maybe_x_scroll_state: maybe_x_scroll_state,
1170                maybe_graphics_for: widget.common().maybe_graphics_for,
1171                is_over: widget.is_over(),
1172            },
1173        );
1174    }
1175
1176    // Unwrap the widget's previous common state. If there is no previous common state, we'll
1177    // use the new state in it's place.
1178    let prev_common = maybe_prev_common.unwrap_or_else(|| CommonState {
1179        rect: rect,
1180        depth: depth,
1181        maybe_dragged_from: maybe_dragged_from,
1182        maybe_floating: maybe_floating,
1183        kid_area: kid_area,
1184        maybe_x_scroll_state: maybe_x_scroll_state,
1185        maybe_y_scroll_state: maybe_y_scroll_state,
1186    });
1187
1188    // Retrieve the widget's unique state and update it via `Widget::update`.
1189    let (unique_state, has_state_updated, event) = {
1190        // Unwrap our unique widget state. If there is no previous state to unwrap, call the
1191        // `init_state` method to construct some initial state.
1192        let mut unique_state =
1193            maybe_prev_unique_state.unwrap_or_else(|| widget.init_state(ui.widget_id_generator()));
1194        let (has_updated, event) = {
1195            // A wrapper around the widget's unique state in order to keep track of whether or not it
1196            // has been updated during the `Widget::update` method.
1197            let mut state = State {
1198                state: &mut unique_state,
1199                has_updated: false,
1200            };
1201
1202            let event = widget.update(UpdateArgs {
1203                id: id,
1204                maybe_parent_id: maybe_parent_id,
1205                state: &mut state,
1206                prev: &prev_common,
1207                rect: rect,
1208                style: &new_style,
1209                ui: ui,
1210            });
1211
1212            (state.has_updated, event)
1213        };
1214
1215        (unique_state, has_updated, event)
1216    };
1217
1218    // Determine whether or not the `State` has changed.
1219    let state_has_changed =
1220        has_state_updated || rect != prev_common.rect || depth != prev_common.depth || is_first_set;
1221
1222    // Determine whether or not the widget's `Style` has changed.
1223    let style_has_changed = maybe_prev_style
1224        .map(|style| style != new_style)
1225        .unwrap_or(false);
1226
1227    // We need to know if the scroll state has changed to see if we need to redraw.
1228    let scroll_has_changed = maybe_x_scroll_state
1229        != maybe_prev_common
1230            .as_ref()
1231            .and_then(|p| p.maybe_x_scroll_state)
1232        || maybe_y_scroll_state
1233            != maybe_prev_common
1234                .as_ref()
1235                .and_then(|p| p.maybe_y_scroll_state);
1236
1237    // We only need to redraw if some visible part of our widget has changed.
1238    let requires_redraw = style_has_changed || state_has_changed || scroll_has_changed;
1239
1240    let ui: &mut Ui = ui::ref_mut_from_ui_cell(ui);
1241
1242    // If we require a redraw, we should notify the `Ui`.
1243    if requires_redraw {
1244        ui.needs_redraw();
1245    }
1246
1247    // Finally, cache the `Widget`'s newly updated `State` and `Style` within the `ui`'s
1248    // `widget_graph`.
1249    ui::post_update_cache::<W>(
1250        ui,
1251        PostUpdateCache {
1252            id: id,
1253            maybe_parent_id: maybe_parent_id,
1254            state: unique_state,
1255            style: new_style,
1256        },
1257    );
1258
1259    event
1260}
1261
1262impl<'a, T> State<'a, T> {
1263    /// Mutate the internal widget state and set a flag notifying us that there has been a mutation.
1264    ///
1265    /// If this method is *not* called, we assume that there has been no mutation and in turn we do
1266    /// not need to re-draw the Widget.
1267    ///
1268    /// If this method *is* called, we assume that there has been some mutation and in turn will
1269    /// need to re-draw the Widget. Thus, it is recommended that you *only* call this method if you
1270    /// need to update the unique state in some way.
1271    pub fn update<F>(&mut self, f: F)
1272    where
1273        F: FnOnce(&mut T),
1274    {
1275        self.has_updated = true;
1276        f(self.state);
1277    }
1278}
1279
1280impl<'a, T> std::ops::Deref for State<'a, T> {
1281    type Target = T;
1282    fn deref(&self) -> &T {
1283        &self.state
1284    }
1285}
1286
1287impl Default for CommonBuilder {
1288    fn default() -> Self {
1289        CommonBuilder {
1290            style: CommonStyle::default(),
1291            maybe_parent_id: MaybeParent::Unspecified,
1292            place_on_kid_area: true,
1293            maybe_graphics_for: None,
1294            is_floating: false,
1295            maybe_x_scroll: None,
1296            maybe_y_scroll: None,
1297            crop_kids: false,
1298        }
1299    }
1300}
1301
1302impl<W> Positionable for W
1303where
1304    W: Widget,
1305{
1306    fn x_position(mut self, x: Position) -> Self {
1307        self.common_mut().style.maybe_x_position = Some(x);
1308        self
1309    }
1310    fn y_position(mut self, y: Position) -> Self {
1311        self.common_mut().style.maybe_y_position = Some(y);
1312        self
1313    }
1314    fn get_x_position(&self, ui: &Ui) -> Position {
1315        let from_y_position = || {
1316            self.common()
1317                .style
1318                .maybe_y_position
1319                .and_then(|y_pos| infer_position_from_other_position(y_pos, Align::Start))
1320        };
1321        self.common()
1322            .style
1323            .maybe_x_position
1324            .or_else(from_y_position)
1325            .unwrap_or(self.default_x_position(ui))
1326    }
1327    fn get_y_position(&self, ui: &Ui) -> Position {
1328        let from_x_position = || {
1329            self.common()
1330                .style
1331                .maybe_x_position
1332                .and_then(|x_pos| infer_position_from_other_position(x_pos, Align::End))
1333        };
1334        self.common()
1335            .style
1336            .maybe_y_position
1337            .or_else(from_x_position)
1338            .unwrap_or(self.default_y_position(ui))
1339    }
1340    fn depth(mut self, depth: Depth) -> Self {
1341        self.common_mut().style.maybe_depth = Some(depth);
1342        self
1343    }
1344    fn get_depth(&self) -> Depth {
1345        const DEFAULT_DEPTH: Depth = 0.0;
1346        self.common().style.maybe_depth.unwrap_or(DEFAULT_DEPTH)
1347    }
1348}
1349
1350/// In the case that a position hasn't been given for one of the axes, we must first check to see
1351/// if we can infer the missing axis position from the other axis.
1352///
1353/// This is used within the impl of **Positionable** for **Widget**.
1354fn infer_position_from_other_position(other_pos: Position, dir_align: Align) -> Option<Position> {
1355    match other_pos {
1356        Position::Relative(Relative::Direction(_, _), maybe_id) => {
1357            Some(Position::Relative(Relative::Align(dir_align), maybe_id))
1358        }
1359        Position::Relative(Relative::Place(_), maybe_id) => {
1360            Some(Position::Relative(Relative::Align(Align::Middle), maybe_id))
1361        }
1362        Position::Relative(Relative::Scalar(_), maybe_id) => {
1363            Some(Position::Relative(Relative::Scalar(0.0), maybe_id))
1364        }
1365        Position::Relative(Relative::Align(_), _) | Position::Absolute(_) => None,
1366    }
1367}
1368
1369impl<W> Sizeable for W
1370where
1371    W: Widget,
1372{
1373    fn x_dimension(mut self, w: Dimension) -> Self {
1374        self.common_mut().style.maybe_x_dimension = Some(w);
1375        self
1376    }
1377    fn y_dimension(mut self, h: Dimension) -> Self {
1378        self.common_mut().style.maybe_y_dimension = Some(h);
1379        self
1380    }
1381    /// We attempt to retrieve the `x` **Dimension** for the widget via the following:
1382    /// - Check for specified value at `maybe_x_dimension`
1383    /// - Otherwise, use the default returned by **Widget::default_x_dimension**.
1384    fn get_x_dimension(&self, ui: &Ui) -> Dimension {
1385        self.common()
1386            .style
1387            .maybe_x_dimension
1388            .unwrap_or_else(|| self.default_x_dimension(ui))
1389    }
1390    /// We attempt to retrieve the `y` **Dimension** for the widget via the following:
1391    /// - Check for specified value at `maybe_y_dimension`
1392    /// - Otherwise, use the default returned by **Widget::default_y_dimension**.
1393    fn get_y_dimension(&self, ui: &Ui) -> Dimension {
1394        self.common()
1395            .style
1396            .maybe_y_dimension
1397            .unwrap_or_else(|| self.default_y_dimension(ui))
1398    }
1399}