在前面的六篇文章之中,我们详细的讲解了甘特图使用的数据结构以及提供的接口,我们可以知道,对于SFData接口的调用方来讲,最主要的就是实体+属性的模式,可是,对于甘特图组件来讲,怎样将这些实体的属性显示在界面上并提供必要的操作,是必须解决的问题。
例如,我们需要定义一个用来显示UID的列的时候,可以这样使用:
这里就介绍完成了所有目前向日葵甘特图支持的数据列的信息,每一个数据列都可以对属性进行重新设置或重写,从而实现自己需要的复杂的功能逻辑,假如需要自定义数据列类型,需要自定义一个继承 SFGanttField的类,而这个过程相对比较复杂,因此,不在这里做详细的介绍。
针对这个问题,向日葵甘特组件的SFGantt模块使用了"数据列"的概念,"数据列"很多时候和"属性"和"节点"混淆了,我们在这里来使用简单的图说明一下这三者的关系:
从上面的图可以看出,XML节点是数据的存储来源,而实体属性是数据在SFData运行过程之中的数据形式,而数据列则是属性在界面上的表现形式,通常为了程序逻辑易于处理,也为了用户方便记忆,这三者的名称都是相同的(这也就是为什么容易混淆的原因),例如任务的开始时间,在我们定义的XML格式之中,对应的XML节点名称为Start,而在数据初始化之后,对这项进行读写的属性名称也为Start,而为这个属性定义的数据列名称同样也是Start。
简单的说,数据列就是显示在甘特图列表左侧的一列一列的数据,左侧列表之中每一列都是一个数据列,但是数据列并不只是在左侧的列表之中使用,实际上,甘特图之中的大部分数据显示都采用数据列的机制,一旦采用此机制,意味着可以完全配置该区域数据的显示内容,例如,在甘特图一下位置同样也使用了数据列:
1.当用户拖动右侧滚动条的时候,显示在右上角(实时显示当前滚动到何处)的一个或者多个字段名称
2.甘特图最左侧显示的灰色用来作为标识的列(Logo下方的列)
3.鼠标放在任务、链接等内容的上的时候弹出的浮动提示上显示的内容
4.甘特图图表右侧显示的任务名称
实际上,除了涉及到复杂的绘制逻辑之外(例如甘特图的图形和箭头的形状等),甘特图上的数据显示都应该尽量使用数据列的定义来完成,这样可以保证完全的可灵活的配置显示的内容。下面我们来说明一下数据列的功能和实现。
每一个数据列必须完成以下功能的定义:
1.如何显示数据列的表头;
2.如何显示数据内容;
3.如果该列需要编辑,如何显示编辑界面;
同时,数据列还提供了一些方法来提供给用户自定义显示的前景色、背景色、对齐方式等样式。
当前甘特图之中,提供了SFGanttField类来自定义和管理系统之中的所有数据列的定义,所有的列都应该是SFGanttField的实例,当前,SFGanttField,构造的时候,可以指定以下参数:
参数名称 | 参数默认值 | 参数说明 |
headText | '' | 默认该列的列表头文本 |
bodyData | 必须指定 | 数据显示需要的属性名称,如果有多个用逗号分隔,当其中一个属性发生变化的时候,将自动引发该数据列的重绘 |
inputData | 可以编辑的时候必须指定 | 编辑模式写入的属性名称,只能是一个 |
width | 100 | 默认该列的显示宽度 |
ReadOnly | false | 当设置为 |
headStyle | {textAlign:'center'} | 默认列表头的显示y |
bodyStyle | {textAlign:'left'} | 默认内容显示和编辑时的的样式 |
inputStyle | {} | 默认内容编辑时的附加样式 |
SFGanttField.setTaskField("UID", new SFGanttField({width:36,bodyData:'UID',headText:"UID",ReadOnly:true,bodyStyle:{textAlign:'center'}}));
这样,这个数据列被命名为"UID",这个列宽度为36,显示UID属性的内容,在列表头之中显示"UID",同时这个字段只读(UID是不允许变化的),默认数据居中显示,在定义之后,可以通过SFGanttField.getTaskField("UID")来返回这个数据列;
一个数据列定义完成之后,还可以使用如下的方法来对数据列进行设置(注意,这些设置不能影响已经绘制完成的内容):
方法名称 | 方法介绍 |
setWidth(width) | 设置列的显示宽度 |
setHeadText(text) | 设置列表头文本 |
setHeadAlign(align) | 设置列表头对齐方式 |
setHeadColor(color) | 设置列表头颜色 |
setHeadBgColor(color) | 设置列表头背景色 |
setBodyAlign(align) | 设置列内容对齐方式 |
setBodyColor(color) | 设置列内容颜色 |
setBodyBgColor(color) | 设置列内容背景颜色 |
setReadOnly(ReadOnly) | 设置列是否只读 |
以上通过new SFGanttField来生成的列通常是采用默认的模式来进行列表头、数据内容、输入模式的绘制,实际上很多情况下,存在需要自定义绘制模式的数据列,因此,系统提供了几个其他的类,这些类继承了SFGanttField,而包含自己的数据显示逻辑,下面逐一的介绍这些类:
1.SFGanttFieldBool,这个类用来进行Bool类型属性的显示和编辑,如果该数据列不是ReadOnly,则无论是输入模式还是显示模式,都是显示为一个复选框,点击复选框就更改了该属性,如果是ReadOnly模式,直接显示文字"是"或"否",该类使用方法如下:
SFGanttField.setTaskField("Critical", new SFGanttFieldBool({width:30,bodyData:'Critical',headText:'关键'}));
2.SFGanttFieldPercent,这个类用来进行百分比数值的显示和编辑,该数据列会在显界面上显示一个进度条,进度条上显示着进度的数值,如果该数据列并不是ReadOnly,则可以拖动进度条右侧的竖线更改进度的值,该类的使用方法如下:
SFGanttField.setTaskField("PercentComplete", new SFGanttFieldPercent({width:100,bodyData:'PercentComplete',headText:'完成百分比'}));
3.SFGanttFieldSelected,这个是一个特殊的列定义,这个列用来代表某一列在甘特图上的选中状态,任何方式造成某一列被选中的时候,这一列的复选框将会被勾上,而点击该复选框,也会修改该列的选中状态,当然,如果这一列被设置为只读,和SFGanttFieldBool一样,也只会显示一个文字"是"或"否",该类的用法如下:
SFGanttField.setTaskField("Selected", new SFGanttFieldSelected({width:30,headText:'选中'}));//因为甘特图对选中的支持属性是一定的,因此,不需要指定字段
4.SFGanttFieldLongText,这个类是用来支持多行文本的编辑的类,该字段在进入编辑状态的时候,将会显示一个多行的输入框,该类的使用方法如下:
SFGanttField.setTaskField("Notes", new SFGanttFieldLongText({width:100,bodyData:'Notes',headText:'备注'}));
5.SFGanttFieldDateTime,这个类用来支持对日期时间字段的显示和编辑,需要说明的是,向日葵甘特图开发过程之中主要转准于向日葵的核心逻辑,因此并没有集成任何辅助输入日期时间的控件,当然,向日葵甘特图可以轻松的和这些控件结合来编辑日期,这一点在后面会专门提到,而这里的日期编辑,依然是需要用户手工输入日期格式的,该类使用方法如下:
SFGanttField.setTaskField("Start", new SFGanttFieldDateTime({width:100,bodyData:'Start',headText:'开始时间',disableSummaryEdit:true}));
可以看出,这个类多了一个disableSummaryEdit参数,这个参数可以指定是否允许对大纲任务的日期进行编辑;
6.SFGanttFieldDuration,这个类用来实现工期的计算,也就是计算两个日期时间字段期间的工期,需要说明的是,这里的工期计算是非常简单的去除周末的计算方法,并没有考虑节假日,也没有通过甘特图之中的工作日历进行计算,该类的使用方法如下:
SFGanttField.setTaskField("Duration", new SFGanttFieldDuration({width:60,bodyData:'Start,Finish',headText:'工期'}));
7.SFGanttFieldSelecter,这个类用来实现一个字典类的显示和选择,例如任务的限制类型字段,该字段在XML节点之中之中通常是一个数字,而在显示界面上应该显示成清晰易懂的格式,而这个类就是用来做这个处理的,例如们要实现一个限制类型的数据列,应该采用这个方式:
var list={0:'越早越好','越晚越好',1:'必须开始于',2:'必须完成于',3:'不得早于...开始',4:'不得晚于...开始',5:'不得早于...完成',6:'不得晚于...完成'};
SFGanttField.setTaskField("ConstraintType", new SFGanttFieldSelecter({width:120,bodyData:'ConstraintType',headText:names.ConstraintType,options:list}));
首先按照key-value的模式建立一个object对象,每个key是该任务的属性值,可以为数字也可以为字符串,而每个value是显示的内容,然后将这个对象作为该字段的options参数即可,这个列在进入编辑状态的时候,会显示一个下拉选单供用户编辑。
8.SFGanttFieldTreeName,这个就是对树形结构的数据实现显示可折叠的+/-树的字段类型,该类型比较固定,能够配置的参数比较少,该字段在进入编辑状态的时候,所编辑的字段是该实体的名称,该类的使用方法如下:
SFGanttField.setTaskField("Name", new SFGanttFieldTreeName({width:120,'名称'}));
9.SFGanttFieldIcon,这个类是实现任务的状态图标列的功能,当前支持了如下图标的显示:
a.当任务已经完成的时候(PercentComplete为100),显示一个已完成的对钩图标,鼠标放在图标上,显示何时完成了该任务
b.当任务存在1以上的约束类型(ConstraintType,ConstraintDate)的时候,会显示约束图标,鼠标放在图标上,会显示约束详细信息
c.当任务存在备注信息的时候,显示一个备注图标,鼠标放在图标上,显示备注详细信息
d.当任务指定了超级链接的时候(HyperlinkAddress,Hyperlink)显示超级链接图标,鼠标放在图标上,显示链接信息,点击图标将会在新窗口之中打开此链接
虽然从理论上讲可以为这个类添加更多的图标支持,但是因为比较复杂,不在这里做详细的介绍,仅仅提供一个这个类的使用范例(演示任务已完成的实现方法):
var field=new SFGanttFieldIcon({width:32,headText:'状态'});//这一列默认就是只读的,并且根据支持的图标个数来确定bodyData的值
field.addIcon(function(element,gantt)//从这里添加一个图标支持函数
{
if(element.PercentComplete!=100){return;}//如果任务没有完成,则返回空,不显示任何图标
var img=this.createImage();//创建一个图标
img.src="http://……"//在这里指定图标文件的地址
SFTooltip.setTooltip(img,function()//这里指定鼠标放在图标上之后如何生成浮动提示信息
{
var tooltip=gantt.getTooltip();//获得甘特图的默认工具条提示类
var str="该任务在某年月日完成"//这里是提示信息的内容
tooltip.setContent(document.createTextNode(str));//设置显示该提示内容
return tooltip;
});
return img;
},"PercentComplete");//最后一个参数定义了当任务的PercentComplete属性变化的时候,该图标需要重绘,如果有多个,用逗号分隔
以上介绍了现在甘特图之中的所有支持的数据列类型,为了使用上的方便,实际上我们也已经定义好了一些数据列可以供直接使用,在下面的列表之中,我们列出了系统集成的数据列类型和相关信息,作为参考:
实体类型 | 数据列名称 | 实现类 | bodyData | inputData | 是否只读 | 说明 | |
任务 | Empty | SFGanttField | true | 一个完全空的列,用来实现什么都不显示 | |||
任务 | UID | SFGanttField | UID | true | 显示UID | ||
任务 | ID | SFGanttField | ID | true | 显示ID | ||
任务 | name | SFGanttField | Name | Name | 显示一个简单的名称,并允许更改 | ||
任务 | Name | SFGanttField | Name,Summary,Collapse | Name | 显示并更改名称,并按照大纲级别留空,并给大纲提供可折叠的图标 | ||
任务 | OutlineNumber | SFGanttField | OutlineNumber | true | 显示大纲级别 | ||
任务 | StatusIcon | SFGanttFieldIcon | 动态实现 | true | 显示任务的状态图标 | ||
任务 | Duration | SFGanttFieldDuration | Start,Finish | true | 显示工期 | ||
任务 | Start | SFGanttFieldDateTime | Start | Start | 显示并更改任务开始时间 | ||
任务 | Finish | SFGanttFieldDateTime | Finish | Finish | 显示并更改任务结束时间 | ||
任务 | Notes | SFGanttFieldLongText | Notes | Notes | 显示并更改任务的备注信息 | ||
任务 | ClassName | SFGanttFieldSelecter | ClassName | ClassName | 显示并更改任务的显示样式 | ||
任务 | ConstraintType | SFGanttFieldSelecter | ConstraintType | ConstraintType | 显示并更改任务的约束类型 | ||
任务 | ConstraintDate | SFGanttFieldDateTime | ConstraintDate | ConstraintDate | 显示并更改任务的约束时间 | ||
任务 | Critical | SFGanttFieldBool | Critical | Critical | 显示并切换该任务是否是关键任务 | ||
任务 | Selected | SFGanttFieldSelected | 内部实现 | true | 显示并切换任务的选中状态 | ||
任务 | Resource | SFGanttField | 内部实现 | true | 显示给任务分配的资源 | ||
任务 | PercentComplete | SFGanttFieldPercent | PercentComplete | PercentComplete | 显示并调整任务的完成百分比 | ||
任务 | ActualStart | SFGanttFieldDateTime | ActualStart | ActualStart | 显示并更改任务实际开始时间 | ||
任务 | ActualFinish | SFGanttFieldDateTime | ActualFinish | ActualFinish | 显示并更改任务实际完成时间 | ||
任务 | ActualDuration | SFGanttFieldDuration | ActualStart,ActualFinish | true | 显示任务的实际工期 | ||
任务 | BaselineStart | SFGanttFieldDateTime | BaselineStart | BaselineStart | 显示并更改任务的基准开始时间 | ||
任务 | BaselineFinish | SFGanttFieldDateTime | BaselineFinish | BaselineFinish | 显示并更改任务的基准结束时间 | ||
链接 | Type | SFGanttFieldSelecter | Type | Type | 显示并更改链接的类型 | ||
链接 | FromTask | SFGanttFieldElement | 内部实现 | true | 显示链接的起始任务 | ||
链接 | ToTask | SFGanttFieldElement | 内部实现 | true | 显示链接的结束任务 |