| # Views Overview |
| |
| This document is an overview of Views concepts, terminology, and architecture. |
| The target audience is engineers using or working on Views. |
| |
| ## General Things |
| |
| Points in this document are written as `(x,y)`, and rectangles are written as |
| `[(x,y) wxh]`. For example, the rectangle `[(100,100) 50x20]` contains the point |
| `(130,110)`. |
| |
| Views uses a coordinate system with `(0,0)` at the top-left, with increasing |
| x-coordinates moving rightwards and increasing y-coordinates moving downwards. |
| This is the same as the Windows and GTK coordinate systems, but *different from* |
| the Cocoa coordinate system, which has `(0,0)` at the bottom-left. Coordinates |
| in this document use the Views coordinate system. |
| |
| Views generally *take ownership* of objects passed to them even via raw |
| pointers, although there are some exceptions, such as delegates. |
| |
| ## Views |
| |
| A **View** is a UI element, similar to an HTML DOM element. Each View occupies a |
| rectangle, called its **bounds**, which is expressed in the coordinate system of |
| its parent View. Views may have child Views, which are laid out according to the |
| View's **layout manager**, although individual Views may also override |
| `View::Layout` to implement their own layout logic. Each View may also have a |
| **border** and/or a **background**. |
| |
| Each View can calculate different sizes, which are used by the View's parent |
| View to decide how to position and size it. Views may have any or all of a |
| preferred size, a minimum size, and a maximum size. These may instead be |
| calculated by the View's LayoutManager, and may be used by the parent View's |
| LayoutManager. |
| |
| It is generally not a good idea to explicitly change the bounds of a View. |
| Typically, bounds are computed by the parent View's Layout method or the parent |
| View's LayoutManager. It is better to build a LayoutManager that does what you |
| want than to hand-layout Views by changing their bounds. |
| |
| For more details about Views, see [view.h]. |
| |
| ### Border |
| |
| The **border** is conventionally drawn around the edges of the View's bounding |
| rectangle, and also defines the View's **content bounds**, which are the area |
| inside which the View's content is drawn. For example, a View that is at |
| `[(0,0) 100x100]` which has a solid border of thickness 2 will have content |
| bounds of `[(2,2) 96x96]`. |
| |
| For more details, see [border.h]. |
| |
| ### Background |
| |
| The **background** is drawn below any other part of the View, including the |
| border. Any View can have a background, but most Views do not. A background is |
| usually responsible for filling the View's entire bounds. Backgrounds are |
| usually a color, but can be a gradient or something else entirely. |
| |
| For more details, see [background.h]. |
| |
| ### Content |
| |
| The **content** is the area inside the content bounds of the View. A View's |
| child Views, if it has any, are also positioned and drawn inside the content |
| bounds of a View. There is no class representing the content area of a View; it |
| only exists as the space enclosed by the View's border, and its shape is defined |
| by the border's insets. |
| |
| ### Layout & Layout Managers |
| |
| A View's **layout manager** defines how the View's child views should be laid |
| out within the View's content bounds. There are a few layout managers supplied |
| with Views. The simplest is [FillLayout], which lays out all a View's children |
| occupying the View's entire content bounds. [FlexLayout] provides a CSS-like |
| layout for horizontal and vertical arrangements of views. |
| |
| Other commonly-used layouts managers are [BoxLayout], a predecessor of |
| FlexLayout, and [TableLayout], which provides a flexible row-and-column |
| system. |
| |
| ### Painting |
| |
| Views are painted by pre-order traversal of the View tree - i.e., a parent View |
| is painted before its child Views are. Each View paints all its children in |
| z-order, as determined by `View::GetChildrenInZOrder()`, so the last child in |
| z-order is painted last and therefore over the previous children. The default |
| z-order is the order in which children were added to the parent View. |
| |
| Different View subclasses implement their own painting logic inside |
| `View::OnPaint`, which by default simply calls `View::OnPaintBackground` and |
| `View::OnPaintBorder`. Generally, subclass implementations of `View::OnPaint` |
| begin by calling the superclass `View::OnPaint`. |
| |
| If you need a special background or border for a View subclass, it is better to |
| create a subclass of `Background` or `Border` and install that, rather than |
| overriding `::OnPaintBackground` or `::OnPaintBorder`. Doing this helps preserve |
| the separation of Views into the three parts described above and makes painting |
| code easier to understand. |
| |
| ### Debugging |
| |
| See [page](../ui_devtools/index.md) for details. |
| |
| ## Widgets |
| |
| Views need an underlying canvas to paint onto. This has to be supplied by the |
| operating system, usually by creating a native drawing surface of some kind. |
| Views calls these **widgets**. A Widget is the bridge between a tree of Views |
| and a native window of some sort, which Views calls a **native widget**. Each |
| Widget has a **root view**, which is a special subclass of View that helps with |
| this bridging; the root view in turn has a single child view, called the |
| Widget's **contents view**, which fills the entire root view. All other Views |
| inside a given Widget are children of that Widget's contents view. |
| |
| Widgets have many responsibilities, including but not limited to: |
| |
| 1. Keyboard focus management, via [FocusManager] |
| 2. Window resizing/minimization/maximization |
| 3. Window shaping, for non-rectangular windows |
| 4. Input event routing |
| |
| For more details, see [widget.h]. |
| |
| ### Client and Non-Client Views |
| |
| The contents view of most Widgets is a **Non-Client View**, which is either a |
| [NonClientView] or one of its descendants. The Non-Client View has two children, |
| which are the **Non-Client Frame View** (a [NonClientFrameView]) and the |
| **Client View** (a [ClientView]). The non-client frame view is responsible for |
| painting window decorations, the Widget's border, the shadow, and so on; the |
| client view is responsible for painting the Widget's contents. The area the |
| client view occupies is sometimes referred to as the Widget's "client area". The |
| non-client frame view may be swapped out as the system theme changes without |
| affecting the client view. |
| |
| The overall structure of a Widget and its helper Views looks like this: |
| |
|  |
| |
| ## Dialogs |
| |
| A commonly-used type of client view is a **dialog client view**, which has a |
| **contents view**, optional buttons on the lower-right, and an optional extra |
| view on the lower-left. Dialogs are usually created by subclassing |
| [DialogDelegate] or [DialogDelegateView] and then calling |
| `DialogDelegate::CreateDialogWidget`. The dialog's contents view fills the |
| entire top part of the widget's client view, and the bottom part is taken over |
| by the dialog's buttons and extra view. |
| |
| ## Bubbles |
| |
| A common type of dialog is a **bubble**, which is a dialog that is anchored to a |
| parent View and moves as the parent View moves. Bubbles are usually created by |
| subclassing [BubbleDialogDelegateView] and then calling |
| `BubbleDialogDelegateView::CreateBubble`. Bubbles can have a title, which is |
| drawn alongside the window controls as part of the Bubble's Widget's |
| NonClientFrameView. |
| |
| [BoxLayout]: https://cs.chromium.org/chromium/src/ui/views/layout/box_layout.h |
| [BubbleDialogDelegateView]: https://cs.chromium.org/chromium/src/ui/views/bubble/bubble_dialog_delegate_view.h |
| [ClientView]: https://cs.chromium.org/chromium/src/ui/views/window/client_view.h |
| [DialogDelegate]: https://cs.chromium.org/chromium/src/ui/views/window/dialog_delegate.h |
| [DialogDelegateView]: https://cs.chromium.org/chromium/src/ui/views/window/dialog_delegate.h |
| [FillLayout]: https://cs.chromium.org/chromium/src/ui/views/layout/fill_layout.h |
| [FlexLayout]: https://cs.chromium.org/chromium/src/ui/views/layout/flex_layout.h |
| [FocusManager]: https://cs.chromium.org/chromium/src/ui/views/focus/focus_manager.h |
| [TableLayout]: https://cs.chromium.org/chromium/src/ui/views/layout/table_layout.h |
| |
| [NonClientView]: https://cs.chromium.org/chromium/src/ui/views/window/non_client_view.h |
| [NonClientFrameView]: https://cs.chromium.org/chromium/src/ui/views/window/non_client_view.h |
| [background.h]: https://cs.chromium.org/chromium/src/ui/views/background.h |
| [border.h]: https://cs.chromium.org/chromium/src/ui/views/border.h |
| [canvas.h]: https://cs.chromium.org/chromium/src/ui/gfx/canvas.h |
| [view.h]: https://cs.chromium.org/chromium/src/ui/views/view.h |
| [widget.h]: https://cs.chromium.org/chromium/src/ui/views/widget/widget.h |