DuiEditor高级教程
这一章主要介绍DuiEditor的设计技巧和说明。
一,duilib.xml属性文件。
这个文件标注了duilib的所有控件和属性,在老版的DuiDesigner里面,控件和属性都是写死的,不方便扩展,如果你改动了属性默认值或者增加控件等等,修改设计器会变成很烦躁的工作,不仅复杂还不好维护。为此,DuiEditor在原版的属性文件上做了一些扩展,设计器仅从这个文件载入控件和属性。比如你为duilib写了一个IconButton的扩展类,只需要在duilib.xml中Controlls下面增加一个子节点。
<Controls>
................
<IconButton parent="Button" notifies="setfocus killfocus timer menu dropdown itemselect windowinit(root)">
<Attribute name="name" default="" type="STRING" comment="控件名字,如(testbtn)" />
<Attribute name="iconsize" default="16,16" type="SIZE" comment="图标大小,如(16,16)" />
<Attribute name="iconnormalimage" default="" type="IMAGE" comment="按钮图标,普通状态图片" />
<Attribute name="iconhotimage" default="" type="IMAGE" comment="按钮图标,鼠标悬浮的状态图片" />
<Attribute name="iconpushedimage" default="" type="IMAGE" comment="按钮图标,鼠标按下的状态图片" />
<Attribute name="iconfocusedimage" default="" type="IMAGE" comment="按钮图标,获得焦点时的状态图片" />
<Attribute name="icondisabledimage" default="" type="IMAGE" comment="按钮图标,禁用的状态图片" />
</IconButton>
..................
</Controls>
保存duilib.xml,重新打开设计器,控件箱中就会出现一个IconButton。图标是个问号,要是看着问号图标不爽,只好去改动设计器源码了。
大多情况下,修改了duilib库,需要重新编译设计器。
DuiEditor写入ui文件时,会强制对属性进行排序,排序顺序是本控件 --> 父控件 -> 父控件的父控件。方便于手动修改xml文件。至于父控件的属性是否适用于本控件,这个需要人工判断,设计器不干预。
设计器根据default值,过滤冗余属性。譬如上面的iconsize,<IconButton iconsize="16,16" />,iconsize属性不会写入ui文件。
二,工具栏。
1,重新打开,这个经常会用到,比如你改动了Default或者Style,这个可能无法实时更新的,只能重新打开文件。
2,测试窗体。测试窗体采用辅助进程的方式,因为CPaintManager有大量的静态属性,在设计器中是全局存在的,不注意的话就变的奇奇怪怪的了,辅助进程的方式则不受影响。测试窗体中点击按钮等事件,会在设计器输出窗口中显示,对新手会有一定的帮助。
3,对齐方式。类似VC的界面设计,需要注意的是,对齐方式只针对float控件。
4,显示UI效果。设计界面中可以体现鼠标悬停点击等UI效果。设计界面其实是一个继承于CUIWindow的子窗口,并不是调用CPaintManager::GetRoot()->Paint出来的,老版的DuiDeisiner是这么干的。什么时候才是需要这个功能? 鼠标悬停点击UI效果虽然风骚可是没意义,我使用中发现Tab切换动画效果才是最有用的。在前面的教程介绍的在控件树中切换tab页面,如果是动画效果的tab,切换不了。需要先选中“显示UI效果”,再进行切换。
5,auto和float。一般情况下,不使用float属性,不然就失去自动布局的意义了。默认是auto方式插入控件,选中float时,插入的控件是带float属性的,即float=true。一般使用于不需要伸缩的对话框中。
6,设计、代码、拆分。字面意思,设计界面和手写xml。需要注意的是,代码页面不能保存文件。手写xml时写错了,切换到设计界面,啥都没了,怎么办? 不急,切换回代码页面,多点几次撤销操作。尽量不要写错吧,虽然设计器有检查xml格式,但是也不太保险。新版的已经改掉了,undo/redo使用Scintilla自带的功能,更倾向于编辑器了,而不是设计器。
三,属性窗口。属性窗口中,鼠标右键点击属性名,有个菜单可以复制控件名。在设计界面中,右键也有这个菜单。写程序时很好用的。
四,设计器默认载入一个叫config.xml的配置文件,文件中集中定义Font,default,style信息。这样定义的原因是,我们经常写一些子窗口,然而设计器单独打开子窗口的时候,字体等信息都没载入,又要打开主窗口才有,这样很痛苦。一般来说,应该把Shared属性的放config里面,但是并不强求。 项目文件打开后,config只能被载入一次。 注意原版的duilib并不支持build一个无控件的UI文件。同样的,DuiPreviewer也会默认的载入config.xml。
如果你的duilib不支持。切记,不要出现config.xml这样的文件名。
五,还是关于手撸xml代码。
1,在设计界面中选择控件时,切换到代码页面,会自动定位到代码中控件所在行,这应该会起到一定的帮助。
2,软件下方输出窗口增加了一个标签,即时编辑xml代码,也有自动定位代码行,修改之后右键菜单应用到设计视图。
原理其实很简单,我自己写了一个xml打印函数,输出每个节点时,保存代码页面行号。这样代码和xml对应了,而xml和控件本来就是对应的,这样三方都是可寻的。很明显的bug是,你如果在即时编辑页面中改变了行号,比如敲了几次回车,而且没有应用到设计视图,鼠标点击代码行时,可能无法选中设计视图中的对应控件。
六,Tab切换页面。
空间树中点击Tab的子控件,自动切换Tab页面到对应的子控件页面。原先的Tab控件右键菜单中切换,有时候不太方便。
七,这次有一个大的更新,几乎每个文件都改动了。以前的版本undo/redo的处理有问题,设计模式与编辑模式有各自的Undo/Redo,切换设计和编辑之后,设计模式的Undo/Redo就是被清空了,而编辑模式的Undo/Redo也变的奇奇怪怪的了,虽然大部分情况并不影响使用,但总是不完美的。折腾来折腾去,还是回到了传统的文档多视图结构,类似于DreamWeaver的架构。有历史原因,也有偷懒的原因,毕竟也是小众使用的软件,没有任何收益,甚至想看看点赞数字都不可得。
这个版本中,去除了原先的DuiLib的Undo/Redo,统一使用Scintilla的undo/redo。这要求设计与编辑必须同步更新。比如设计模式修改一个属性时,必须找到Scintilla的对应位置插入xml;修改xml时,实时反映到设计界面。也就是同步增量更新。这有两个问题,第一个是,找到插入位置,想当然以为解析一遍Scintilla的文档就行了,其实不然。我的做法是,载入CDocument文档时,就计算每个Node、Attribute的位置,这必须与Scintilla窗口的字符位置严格对应起来。然后令我最恶心的事情发生了,pugixml解析xml时,把uft8文件转码为unicode进行解析,输出也是unicode。可是Scintilla内部仅支持uft8编码。XML文档中出现中文字符时,位置就错开了,因为UFT8的中文字符长度不同,有2字节、3字节、4字节的,而Unicode的中文字符长度固定为2。然后就进入了无穷的字符编码转换过程,这也是为什么几乎会改动每个文件的原因了。
第二个是,CDocument的文档与Scintilla的文档如何增量更新,也就是两份xml的异同比较。更新的CDocument文档增量更新的设计界面,同时每个Node、Attribute的位置都需要更新。这也是一个不大不小的难度。
所幸还是实现了,只是我也不知道在某个角落是不是还隐藏着乱码,也不知道某个位置更新描点又错了,又或者是某个XML的书写方式是我没有预想到的。
八,增加了自动生成语言包,兼容2种多语言实现方案。
后续有更新,会在这篇中补上,如果你有什么建议,请联系我,QQ:53751257。QQ群:819272442。