Chromium UI Platform
- Chromium UI Platform
- View 是一个UI元素,类似于HTML DOM元素。每个View 占据一个矩形,称为其边界,在其父View 的坐标系中表示。View 可以有子Views,它们根据View 的布局管理器进行布局,尽管单个View 也可以覆盖
View::Layout
来实现自己的布局逻辑。每个视图也可以有一个边框和/或一个背景。- 每个View 都可以计算出不同的尺寸,这些尺寸被View 的父View 用来决定如何定位和确定其大小。
- 通常情况下,边界是由父View 的Layout方法或父View 的LayoutManager计算的,而不是手动显示的修改边界。
- border
- border通常是围绕View 的边界(bound)矩形绘制的,同时也定义了视图的内容边界(content bounds),这是绘制视图内容的区域。例如,一个位于[(0,0) 100x100]的视图有一个厚度为2的实心border,其内容边界为[(2,2) 96x96] 。
- Background
- 背景被画在View 的任何其他部分之下,包括border。任何View 都可以有一个背景,但大多数View 都没有。一个背景通常负责填充View 的整个边界。背景通常是一种颜色
- Content
- The content is the area inside the content bounds of the View. View的子View(如果它有的话)也被定位并绘制在View的内容边界内。没有代表View的内容区域的类;它只作为View的边框所包围的空间而存在,其形状由边框的嵌入物定义。
- Layout & Layout Managers
- View‘s layout manager 定义了View的子View应该如何在View的content范围内进行布局.
- View有几个布局管理器。最简单的是FillLayout,它将一个View的所有子View布置在该View的整个内容范围内。FlexLayout为View的水平和垂直排列提供了一个类似于CSS的布局。
- Painting
- 视图是通过对视图树的预顺序遍历来绘制的–也就是说,父视图在其子视图之前被绘制。每个视图按Z顺序绘制其所有的子代,这由View::GetChildrenInZOrder()决定,所以Z顺序中的最后一个子代最后被绘制,因此在前面的子代之上。默认的z-order是孩子们被添加到父视图中的顺序。
- 不同的视图子类在View::OnPaint中实现它们自己的绘制逻辑,默认情况下,它只是调用View::OnPaintBackground和View::OnPaintBorder。一般来说,View::OnPaint的子类实现从调用superclass 的View::OnPaint开始。
- 如果你需要为一个视图子类提供特殊的Background 或Border ,最好是创建一个Background 或Border 的子类并安装它(继承?),而不是覆盖::OnPaintBackground或::OnPaintBorder。这样做有助于保持将视图分离成上述的三个部分,并使绘画代码更容易理解。
- Widgets
- View需要一个底层canvas 来绘制。这必须由操作系统提供,通常是通过创建某种本地 drawing surface ,View 称其为Widget。一个Widget是一个Views 树和某种本地窗口之间的桥梁,Views称之为本地Widget。每个Widget都有一个 root view,它是一个特殊的view子类,可以帮助实现这种桥接; root view又有一个单一的子view,称为Widget的contents view,它填充了整个 root view。一个给定的Widget内的所有其他 views 都是该Widget contents view的子视图。
- Widgets 主要要做:
- Keyboard focus management, via FocusManager
- Window resizing/minimization/maximization
- Window shaping, for non-rectangular windows
- Input event routing
- Client and Non-Client Views
-
大多数Widgets的 contents view 是一个Non-Client View,,它要么是一个NonClientView,要么是它的一个后代。Non-Client View有两个子代,即Non-Client Frame View (一个NonClientFrameView)和Client Frame View(一个ClientView)。Non-Client Frame View负责绘制窗口装饰、Widget的边框、阴影等;Client Frame View则负责绘制Widget的content。Client Frame View 占用的区域有时被称为Widget的 “client area”。non-client frame view可以随着系统主题的改变而被替换,而不影响client view.
-
Dialogs
- 一个常用的client view类型是dialog client view,,它有一个contents view,右下方有可选的按钮,左下方有可选的额外视图。对话框通常是通过子类化DialogDelegate或DialogDelegateView,然后调用DialogDelegate::CreateDialogWidget来创建。对话框的contents view 填满了widget’s client view的整个上半部分,而下半部分则被对话框的按钮和额外视图所占据。
-
// +- views::Widget ------------------------------------+
// | +- views::RootView ------------------------------+ |
// | | +- views::NonClientView ---------------------+ | |
// | | | +- views::NonClientFrameView subclass ---+ | | |
// | | | | | | | |
// | | | | << all painting and event receiving >> | | | |
// | | | | << of the non-client areas of a >> | | | |
// | | | | << views::Widget. >> | | | |
// | | | | | | | |
// | | | | +- views::ClientView or subclass ----+ | | | |
// | | | | | | | | | |
// | | | | | << all painting and event >> | | | | |
// | | | | | << receiving of the client >> | | | | |
// | | | | | << areas of a views::Widget. >> | | | | |
// | | | | +------------------------------------+ | | | |
// | | | +----------------------------------------+ | | |
// | | +--------------------------------------------+ | |
// | +------------------------------------------------+ |
// +----------------------------------------------------+
- nonclientview 和client view 中间有填充,比如系统原生的最小化、最大化、关闭窗口,以及四周的border。
- 可以在继承的views::WidgetDelegateView::CreateNonClientFrameView 中,自己创建NonClientFrameView,里面空实现以及空border即可。
views
-
user interfaces由一个组件树组成,称作 views 。(树上的每个view 代表了用户界面的一个不同组件)(就像是HTML 的分层结构)
- 代码目录:
src/ui/views/
- views 负责rendering, layout, and event handling。
- 在View hierarchy 的根部是一个Widget,它是一个native window 。native window 接收来自Windows的消息,将其转换为View hierarchy可以理解的内容,然后将其传递给RootView。然后,RootView开始将事件传播到View hierarchy 中。
- Painting and layout 以类似的方式进行的。View tree 中的一个View 有它自己的边界(通常由其包含的View 的布局方法赋予它),因此当它被要求画图时,它将画在一个与其边界相接的画布上,渲染的原点被转换到View 的左上方。当Widget收到Paint消息时,整个View树的渲染是在一个由Widget设置和拥有的单一画布中进行的。
- 渲染本身是通过对Skia和GDI的调用 来完成的,GDI用于文本,Skia用于其他的东西。
- 代码目录:
-
Chromium的用户界面中的一些UI控件并不是使用View渲染的,它们是托管在一种特殊的视图中的本地Windows控件,这种视图知道如何显示和调整本地小部件的大小。因为它们使用本地控件,所以这些视图也不是可移植的,也许在API中除外。
- 除了特定平台的渲染代码、基于系统指标的尺寸代码等,View系统的其余部分基本可移植,因为大多数渲染是使用跨平台的Skia库完成的。由于历史原因,View的许多函数采用Windows或ATL类型,但现在使用许多平台独立的类型增强了ui/gfx/,最终可以用这些类型取代它们。
Class
View Class
- view.h
- View 是视图层次结构中的一个矩形。它是所有Views 的基类。
- 一个View 是其他Views 的容器(container )
- View 包含大小(边界)、布局(弯曲、方向等)、绘制 Child 和事件调度的基本属性。
Widget Class
- widget.h
- Widget is a platform-independent type that communicates with a platform or context specific NativeWidget implementation.
- Widget是一个独立于平台的类型,它与平台或上下文特定的NativeWidget实现进行通信
- 根据InitParams的所有权字段的值,Widget拥有NativeWidget
ownership = WIDGET_OWNS_NATIVE_WIDGET (非默认)
,或者被NativeWidget所拥有ownership = NATIVE_WIDGET_OWNS_WIDGET (默认)
。