Updates from 四月, 2011 Toggle Comment Threads | 键盘快捷键

  • Roger 11:48 pm on April 11, 2011 固定链接 | 回复
    Tags: , , Minijoe   

    MiniJoe UI架构和样式标注部分代码分析 



    image

    上图显示一个较为完整的HtmlBrowser的UI的部分类,其中:

    1. 在uibase包下面的xxxWidget是一组基本UI组件
    2. 在html包下面的xxxWidget是页面元素对应的UI组件
    3. css包下面的类用于CSS解析,生成解析后的结果

    一些类的具体职责如下:

    Widget

    1. 所有UI组件的根类
    2. 也包含了容器部分的逻辑

    TextWidget

    1. 用于显示文本的Widget

    ScrollWidget

    1. 在Widget的基础上提供了滚动支持的逻辑

    Window

    1. 定义了一个顶层窗口的接口,由具体的窗口类实现
    2. (minijoe的Window的实现跟其它GUI框架稍微有些不一样,Window不是一个继承自Widget的UI组件,而是一个接口,具体的实现类需要在自己内部定义一个默认的UI组件布局和对应的事件路由逻辑)

    HtmlScreen

    1. 实现了Window接口,作为顶层窗口
    2. 继承Canvas,提供屏幕输出和事件处理相关的逻辑
    3. 包含一个HtmlWidget,用于展现一个HTML/XML页面

    HtmlBrowser

    1. 继承MIDlet
    2. 处理命令

    TextFragmentWidget

    1. 用于显示文本片段的UI组件
    2. 包含一个Element的引用回溯对应的文档树的Element节点

    BlockWidget

    1. 对应页面的Block元素
    2. 可以包含其它BlockWidgets(包括InputWidget 和 TableWidget)和TextFragmentWidget
    3. 包含一个Element的引用回溯对应的文档树的Element节点

    InputWidget

    1. 对应页面的Input元素,包含输入框,组合框,按钮等

    TableWidget

    1. 对应页面的Table元素,展现一个表格

    HtmlWidget

    1. 对应整个页面(可以看作是对应Body元素)
    2. 包含一个Body元素的Element成员,该Element展开构成了一颗文档树(Body Element还不是根节点,它的父亲为Html Element)
    3. 包含一个样式树的根节点styleSheet,该成员用来读取样式表数据生成完整的全局样式树
    4. 负责整个页面的资源加载和管理,如图像资源,CSS/JavaScript脚本等
    5. 包含一颗由BlockWidgets/TextFragmentWidget组成的UI组件树
    6. 负责处理用户跟页面的交互(可能委托外部的处理器进行处理)
    7. 负责处理JavaScript,提供一个JavaScript执行的环境

    Element

    1. 作为文档树的一个节点,包含该节点的内容和属性(如class, id 等)
    2. 可以包含子节点,在minijoe里面只区分两种节点,最简单的文本直接用String表示,其它则用Element表示,Element的子节点可以是其它Element或者String,所以文档树任意一个非叶子节点一定是一个Element,而叶子节点可能是一个String也可能是一个Element
    3. 同时包含样式数据,所以Element构成的树,即做为文档树,在进行样式标注后也做为作为渲染树而存在,在minijoe里面没有像DOM一样的单独的文档树

    CSSTokenizer

    1. 识别CSS文本中的标记的解析器

    Style

    1. 对一个规则集合块(Rule Set Block)或者仅仅一条声明进行解析后产生的结果
    2. 包含一条或者多条声明的数据,每条声明对应一个属性和值对
    3. 可以通过set方法将两个Style按覆盖模式进行合并
    4. 可以通过inherit方法将两个Style按继承模式进行合并

    StyleSheet

    1. 包含多个Style,对应同一个选择符(Selector)
    2. 包含多个StyleSheet的哈希表,对应不同的选择符和不同类型的选择符,形成一颗样式树
    3. HtmlWidget里面的styleSheet成员为该页面的样式表数据解析后所产生的样式树的根节点

    HtmlWidget页面解析和渲染的一个简略过程:

    1. 解析页面数据生成文档树
    2. 解析CSS数据生成样式树(1,2可以交错进行)
    3. 使用样式树对文档树进行节点样式标注,自顶向下,先根遍历,最后产生的完整节点的样式数据保存在computedStyle成员中(minijoe支持多遍样式标注,每次更新样式树时都会重新标注,并根据一些条件判断是否需要重新生成UI组件树)
    4. 使用样式标注后的渲染树(样式化的文档树)生成UI组件树,每个UI组件都包括一个Element的引用回溯对应的文档树节点
    5. 生成UI组件树之后,HtmlWidget需要重新计算布局,确定每个UI组件的位置和大小
    6. 在HtmlWidget内部显示这颗对应页面渲染树(样式化的文档树)的UI组件树
    7. 在UI组件绘制自身的过程中,它需要从对应的Element的computedStyle取出绘制所需要的样式数据

    HtmlWidget生成样式树的过程:

    1. 在解析页面数据生成文档树的过程中,如果碰到STYLE元素,并且媒体类型(media type)匹配 ,Element会请求HtmlWidget将这段样式直接读入它的styleSheet成员
    2. 在解析页面数据生成文档树的过程中,如果碰到LINK元素,并且媒体类型(media type)匹配 ,Element会请求HtmlWidget加载该外部资源
      1. HtmlWidget会请求资源读取线程读取该资源文件(异步)
      2. 当资源读取完毕,资源读取线程会调用HtmlWidget的addResource方法加载资源
      3. 当资源是CSS样式表时,HtmlWidget会将该资源读入styleSheet成员
      4. 如果这时文档树已经生成完毕,则进行样式标注,否则等待文档树生成完毕后进行样式标注
      5. 如果文档树已经标注过,则重新进行样式标注,并且根据需要选择是否重新生成UI组件树
    3. 如果在解析样式表的时候碰到at规则 import,并且媒体类型(media type)匹配,StyleSheet会请求HtmlWidget加载该外部资源,执行第2步的操作

    HtmlWidget对文档树进行样式标注的过程(实际上对文档树的样式标注可以从任意元素节点进行,不过对于HtmlWidget来说,要对整个文档树进行完整的样式标注是从Body元素节点开始):


    1. 当文档树生成完毕或者styleSheet成员所指向的样式树更新时,则进行样式标注(applyStyle),支持多遍标注
    2. 调用Body Element的apply方法进行样式标注,对文档树的样式标注是一个对树进行先根遍历的过程
    3. Element的apply方法接收applyHere和applyAnywhere两个参数,它们都是StyleSheet的队列,applyHere表示可用于当前元素的样式表,applyAnywhere表示可用于当前元素和它的所有子元素的样式表,HtmlWidget在调用Body Element的apply方法时,就把styleSheet成员放入applyAnywhere中作为参数
    4. 元素节点的样式标注最重要的一个步骤就是从通过参数传递的可用样式表集合中收集样式(StyleSheet的collectStyles方法):
      1. 可以应用于当前元素的样式集合(queue)
      2. 可用于子节点和后代节点的样式表集合(childStyles和descendantStyles)
      3. 其中applyAnywhere里面的样式表会直接放入descendantStyles中传给子节点
      4. 在collectStyles方法里面,需要对元素的name,id,class和其它属性进行查询,以收集到匹配的样式,如果不需要支持其它属性,理论上可以传name,id,class Strings来代替Element实例
    5. 产生当前元素的最终样式
      1. 对收集的可以应用于当前元素的样式集合进行覆盖式合并,按照权重由低到高的优先序(权重高的样式覆盖权重低的样式)
      2. 如果当前元素有style属性,用该属性的样式数据对第1步结果得到的样式进行覆盖式合并(style优先)
      3. 使用第2步的结果跟父元素的计算后样式computedStyle进行继承式合并
      4. 如果当前元素有其它inline的样式数据,将这部分数据抽取合并到第3步的样式结果里面(applyHtmlAttributes)
      5. 把最后的结果作为当前元素的计算后样式computedStyle,当前元素的样式标注就结束了
      6. computedStyle里面的数据会用于UI组件树的布局和渲染,如果没有UI组件树,则需要直接从computedStyle里面把样式数据逐个取出来放到确定的地方
      7. 其中还有一些值的计算可能需要依赖于外部传入的参数,如使用的字体的高度,宽度,盒子的大小,使用的DPI值等
    6. 继续标注当前元素的子元素,childStyles变量作为applyHere参数,descendantStyles变量作为applyAnywhere参数
    7. 决定是否需要重新生成UI组件树
     
  • Roger 10:58 am on April 2, 2011 固定链接 | 回复
    Tags:   

    用Mongoose 搭建WML服务器 

    修改配置文件

    用Mongoose搭建WML服务器很简单,只需要修改mongoose.conf配置文件,加入下面这行即可。

    extra_mime_types .wml=text/vnd.wap.wml .wmls=text/vnd.wap.wmlscript .wbmp=image/vnd.wap.wbmp

     

    实验一个简单的WML

    <?xml version=”1.0″?>

    <!DOCTYPE wml PUBLIC “-//WAPFORUM//DTD WML 1.1//EN”

    http://www.wapforum.org/DTD/wml_1.1.xml”&gt;

    <wml>

    <card id=”Card1″ title=”Sample “>

    <p>Hello World</p>

    </card>

    </wml>

     

    通过火狐的WML插件显示的效果

     
  • Roger 9:17 am on March 28, 2011 固定链接 | 回复
    Tags:   

    使用Mongoose 5分钟搭建本机Web服务器 

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
回复
e
编辑
o
Show/Hide comments
t
返回顶部
l
Go to login
h
Show/Hide help
shift + esc
取消