Dorado 5 : 5.3.Dorado5新建Control 类型以及使用 (T32)

扩展Dorado5原有Control

我们想对DataTable增加多一个marmotProfileKey属性,我需要做以下步骤:

  1. 新增MarmotDataTable.java,该类继承com.bstek.dorado.view.control.table.DataTable:

    package org.marmot.framework.dorado;

    import com.bstek.dorado.view.ViewModel;

    public class MarmotDataTable extends
    com.bstek.dorado.view.control.table.DataTable {
    private String marmotProfileKey;

    public MarmotDataTable(ViewModel viewModel, String id) {
    super(viewModel, id);
    }

    public String getMarmotProfileKey() {
    return marmotProfileKey;
    }

    public void setMarmotProfileKey(String marmotProfileKey) {
    this.marmotProfileKey = marmotProfileKey;
    }

    }

    代码 5.2:MarmotDataTable.java
  2. 对DataTable对应类的定义,在home下新建controls.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <controls>
    <control type="DataTable" clazz="org.marmot.framework.dorado.MarmotDataTable"/>
    </controls>

    代码 5.3:controls.xml
    经过上面的处理,就可以给DataTable增加了marmotProfileKey属性,在开发器或者Java代码中就可以对marmotProfileKey赋值。
    如我们想把marmotProfileKey通过Js赋值给客户端的DataTable,那我们就要通过DataTable的Outputter来实现:
  3. 新增MarmotDataTableOutputter.java,该类继承com.bstek.dorado.view.smartweb.v2.output. DataTableOutputter:

    public class MarmotDataTableOutputter extends
    com.bstek.dorado.view.smartweb.v2.output. DataTableOutputter {
    public void doOutputRegisterSection(Writer writer, Object object, ServletRequest request)
    throws Exception
    {
    super.doOutputRegisterSection(writer, object, request);
    DataTable table = (DataTable)object;
    writer.write(JavaScriptHelper.scirptSetProperty(table, "marmotProfileKey"));
    }
    }

    代码 5.4:MarmotDataTableOutputter.java
  4. 对DataTable Outputter对应类的定义,在home下新建outputters.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <elements>
    <element clazz="org.marmot.framework.dorado.MarmotDataTable">
    <outputter type="smartweb2" clazz="com.bstek.dorado.view.smartweb.v2.output.MarmotDataTableOutputter"/>
    </element>
    </elements>

    代码 5.5:outputters.xml
    如想对DataTable的Html输出作出改变,那就在MarmotDataTableOutputter里对doOutputStartSection和doOutputEndSection做修改。

    扩展Dorado5原有Control为新Control

    根5.3.1的设置一样,只是在定义类型的时候,定义新的Control类型而不是覆盖旧的Control类型定义。
  5. 首先要修改controls.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <controls>
    <control type="MarmotDataTable" clazz="org.marmot.framework.dorado.MarmotDataTable"/>
    </controls>

    代码 5.6:controls.xml
  6. 打开sutdio/configs/user-view-rules.xml文件(如果没有请在该目录下创建一个,如已存在,请把每个子项放在对应的位置下),添加如下代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <rules>
    <rule name="Controls" expanded="true" showDetail="false">
    <children>
    <child name="Control-MarmotDataTable" insertable="true" defaultNamePrefix="marmotDataTable "/>
    </children>
    <palette>
    <item label="CustomControls" icon="folder-opened.png">
    <item name="Control-MarmotDataTable"/>
    </item>
    </palette>
    </rule>

    <rule name="Control-MarmotDataTable" text="MarmotDataTable" tagName="Control" object=" org.marmot.framework.dorado.MarmotDataTable" nameAttribute="id" editable="true" icon="view/datatable.png">
    <properties>
    <property name="type" visible="false" defaultValue=" MarmotDataTable"/>
    <property name="id" required="true"/>
    </properties>
    <children>
    <child name="Column" insertable="true" defaultNamePrefix="group"/>
    </children>
    <functions>
    <function text="Auto create columns" icon="view/create-element.png" clazz="com.bstek.designer.impl.view.DataTableCreateColumnFunction"/>
    </functions>
    </rule>
    </rules>

    代码 5.7:user-view-rules.xml

    图 5.1:
    重启IDE,打开任意一个ViewModel,我们会发现在左边的工具条上多了一个MarmotDataTable的图标。
  7. 最后一步,在我们的JSP里面要使用我们的MarmotDataTable,标签需要采用如下方式进行定义:

    <d:Control id="marmotDataTable1" type="MarmotDataTable"/>

    代码 5.8:jsp

    新建页面不带控制的静态Control

    对于一些静态的Html输出到页面,最经常使用的就是通过标签来实现,在继承TagSupport下在doStartTag和doEndTag对Html输出就可以了。
    在Dorado5里我们把这些步骤放在了Outputter里,这样为了方便Dorado5进行统一管理,也不需要再定义标签等等。
    比如我做一个静态Table输出到页面,数据来至于Dataset。页面如下:

    图 5.2:
  8. 先定义初始化控件的类,因为新的控件是一个页面可见的控件,那该类就继承于com.bstek.dorado.view.control.PlaceableDataControl:

    package test;

    import com.bstek.dorado.view.ViewModel;
    import com.bstek.dorado.view.control.PlaceableDataControl;

    public class TestCustomTable extends PlaceableDataControl{

    public TestCustomTable(ViewModel viewModel, String id) {
    super(viewModel, id);
    }

    }

    代码 5.9:TestCustomTable.java
  9. 把上面java代码打包成jar包放在sutdio/lib文件夹下:


图 5.3:

  1. 打开sutdio/configs/user-view-rules.xml文件(如果没有请在该目录下创建一个,如已存在,请把每个子项放在对应的位置下),添加如下代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <rules>
    <rule name="Controls">
    <children>
    <child name="Control-TestCustomTable" insertable="true" defaultNamePrefix="testCustomTable"/>
    </children>
    <palette>
    <item label="CustomControls" icon="folder-opened.png">
    <item name="Control-TestCustomTable"/>
    </item>
    </palette>
    </rule>
    <rule name="Control-TestCustomTable" text="TestCustomTable" tagName="Control" object="test.TestCustomTable" nameAttribute="id" editable="true" icon="view/table.png">
    <properties>
    <property name="type" visible="false" defaultValue="TestCustomTable"/>
    <property name="id" required="true"/>
    </properties>
    </rule>
    </rules>

    代码 5.9:user-view-rules.xml
  2. 重启IDE,打开任意一个ViewModel,我们会发现在左边的工具条上多了一个TestCustomTable的图标。


图 5.4:

  1. 打开Dorado工程的home/ controls.xml文件(如果您的目录下没有,请创建一个新的),添加下列代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <controls>
    <control type="TestCustomTable" clazz="test.TestCustomTable"/>
    </controls>

    代码 5.10:controls.xml
  2. 打开Dorado工程下home/ outputters.xml文件,添加下列代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <elements>
    <element clazz="test.TestCustomTable">
    <outputter type="smartweb2" clazz="test.TestCustomTableOutputter"/>
    </element>
    </elements>

    代码 5.11:outputters.xml
  3. TestCustomTableOutputter类的代码为:

    package test;

    import java.io.IOException;
    import java.io.Writer;

    import javax.servlet.ServletRequest;

    import com.bstek.dorado.data.Dataset;
    import com.bstek.dorado.data.Record;
    import com.bstek.dorado.data.RecordIterator;
    import com.bstek.dorado.view.smartweb.v2.output.AbstractPlaceableControlOutputter;
    import com.bstek.dorado.view.smartweb.v2.output.HtmlHelper;
    import com.bstek.dorado.view.smartweb.v2.output.JavaScriptHelper;

    public class TestCustomTableOutputter extends AbstractPlaceableControlOutputter{

    public TestCustomTableOutputter()
    {
    }

    public void doOutputStartSection(Writer writer, Object object, ServletRequest request)
    throws Exception
    {
    TestCustomTable testCustomTable = (TestCustomTable)object;
    String namespace = testCustomTable.getViewModel().getNamespace();
    writer.write("<table id=\"");
    writer.write(JavaScriptHelper.getReadId(namespace, testCustomTable.getId()));
    writer.write("\" ");
    writer.write("<table ");
    writer.write(HtmlHelper.tagProperty("border","1"));
    writer.write(HtmlHelper.tagProperty("height",testCustomTable.getHeight()));//在设计器里定义
    writer.write(HtmlHelper.tagProperty("width",testCustomTable.getWidth()));//在设计器里定义
    writer.write("><tr>");
    String dsid = testCustomTable.getDataset();
    Dataset ds = testCustomTable.getViewModel().getDataset(dsid);
    int fieldCount = ds.getFieldCount();
    for (int i = 0; i < fieldCount; i++) {
    writer.write("<td>");

    writer.write(ds.getField(info).getLabel());

    writer.write("</td>");
    }
    writer.write("</tr>");
    }

    public void doOutputEndSection(Writer writer, Object object,ServletRequest servletrequest) throws Exception {
    //这里还可以做成有Column,根据Column属性来输出html
    TestCustomTable testCustomTable = (TestCustomTable)object;
    String dsid = testCustomTable.getDataset();
    Dataset ds = testCustomTable.getViewModel().getDataset(dsid);
    Record current = ds.getCurrent();//for test
    if(current == null){
    ds.load();
    }
    int fieldCount = ds.getFieldCount();
    RecordIterator ri = ds.recordIterator();
    ri.setVisibility(Dataset.FILTER_ALL);

    while(ri.hasNext()) {
    Record record = ri.nextRecord();
    writer.write("<tr>");
    for (int i = 0; i < fieldCount; i++) {
    writer.write("<td>");

    writer.write(record.getString(ds.getField(info).getName()));

    writer.write("</td>");
    }
    writer.write("</tr>");
    }
    writer.write("</table>");
    }

    public void doOutputRegisterSection(Writer writer, Object object, ServletRequest request)throws IOException
    {//js
    }

    }

    代码 5.12:TestCustomTableOutputter.java
  4. 在我们的JSP里面要使用我们的TestCustomTable,标签需要采用如下方式进行定义:

    <d:Control id="testCustomTable1" type="TestCustomTable"/>

    代码 5.13:jsp
  5. 例子中的view.xm代码为:

    <?xml version="1.0" encoding="UTF-8"?>
    <view>
    <Datasets>
    <Dataset id="dataset1" type="Custom" listener="test.test_dataset1Listener">
    <MasterLink />
    <Fields>
    <Field name="field1" label="字段1">
    <Properties />
    </Field>
    <Field name="field2" label="字段2">
    <Properties />
    </Field>
    <Field name="field3" label="字段3">
    <Properties />
    </Field>
    </Fields>
    <Parameters />
    <Properties />
    </Dataset>
    </Datasets>
    <Controls>
    <Control id="testCustomTable1" type="TestCustomTable" dataset="dataset1" />
    </Controls>
    <Properties />
    </view>

    代码 5.13:view.xml

    新建页面带事件控制的Control

    我们根据5.3.3实现的静态Table来实现点击Table的时候弹出Table对应Dataset的信息出来。我只需要在TestCustomTableOutputter类里增加doOutputRegisterSection方法来输出js就可以了:

    。。。
    public void doOutputRegisterSection(Writer writer, Object object, ServletRequest request)throws IOException
    {
    TestCustomTable testCustomTable = (TestCustomTable)object;
    String dsid = testCustomTable.getDataset();
    writer.write("EventManager.addSystemEvent("testCustomTable.getId()",\"onmousedown\",function(event){alert("dsid");});");
    }
    。。。

    代码 5.14:TestCustomTableOutputter.java
    出来的页面效果是:

    新建页面动态Control

    这个需要Dhtml技术和页面事件来实现,一般是对Dorado5新增一些控件才能用到,对于一般客户做扩展和封装会存在很大的难度,这里就不写出来。

    新建通过Dataset驱动的动态Control

    请结合上面的内容和《dorado5组件扩展----自定义组件对象client端编程》。
    我们把5.3.4的实现放在js中,再加上通过Dataset驱动简单实现。
  6. 修改TestCustomTableOutputter类里的doOutputRegisterSection方法来改变输出js内容:

    。。。
    public void doOutputRegisterSection(Writer writer, Object object, ServletRequest request)throws Exception
    {
    TestCustomTable testCustomTable = (TestCustomTable)object;
    //String dsid = testCustomTable.getDataset();
    //writer.write("EventManager.addSystemEvent("testCustomTable.getId()",\"onmousedown\",function(event){alert("dsid");});");
    outputCreateSection(writer, testCustomTable, "TestCustomTable");
    ViewModel viewModel = testCustomTable.getViewModel();
    writer.write(JavaScriptHelper.scirptSetDataset(viewModel, testCustomTable, "dataset"));
    writer.write(JavaScriptHelper.scirptSetProperty(testCustomTable, "tag"));
    outputEvent(writer, testCustomTable, "__t");
    }
    。。。

    代码 5.15:TestCustomTableOutputter.java
    这里为了输出根据id创建一个TestCustomTable控件(js),还有Js TestCustomTable控件所需要的属性。
  7. 在home/smartweb/v2/lib文件夹下新建TestCustomTable.js,内容是注册新的控件类型(TestCustomTable):

    /**
    * 定义TestCustomTable控件的属性和控制等
    * @param {Object} id
    * @param {Object} n
    */
    function TestCustomTableF(id, n) {
    var testCustomTable = document.getElementById(id);

    testCustomTable.setDataset=__DataControl_setDataset;
    testCustomTable.getDataset=__DataControl_getDataset;
    testCustomTable.establishBinding = __DataControl_establishBinding;
    testCustomTable.disableBinding = __DataControl_disableBinding;
    testCustomTable.enableBinding = __DataControl_enableBinding;
    testCustomTable.activate = __DataControl_activate;

    EventManager.addSystemEvent(testCustomTable,"onmousedown",function(event){alert(testCustomTable.getDataset());});

    testCustomTable.processDatasetMessage=testCustomTable_processDatasetMessage;

    return testCustomTable;
    }

    /**
    * TestCustomTable控件运行时消息处理机制
    * @param {Object} message
    * @param {Object} dataset
    * @param {Object} args
    */
    function testCustomTable_processDatasetMessage(message, dataset, args) {
    switch (message) {
    case __Dataset_MSG_REFRESH: {
    alert(dataset.getId()+" REFRESH!");
    break;
    }
    case __Dataset_MSG_REFRESH_RECORD: {
    alert(dataset.getId()+" REFRESH_RECORD!");
    alert(args[0]);
    break;
    }
    case __Dataset_MSG_DATA_CHANGED: {
    alert(dataset.getId()+" DATA_CHANGED!");
    alert(args[0]);
    alert(args[1]);
    alert(args[2]);
    break;
    }
    case __Dataset_MSG_CURRENT_CHANGED: {
    alert(dataset.getId()+" CURRENT_CHANGED!");
    break;
    }
    case __Dataset_MSG_GAINING_CHANGE: {
    alert(dataset.getId()+" GAINING_CHANGE!");
    break;
    }
    case __Dataset_MSG_RECORD_DELETED: {
    alert(dataset.getId()+" RECORD_DELETED!");
    alert(args[0]);
    break;
    }
    case __Dataset_MSG_STATE_CHANGED: {
    alert(dataset.getId()+" STATE_CHANGED!");
    break;
    }
    case __Dataset_MSG_RECORD_STATE_CHANGED: {
    alert(dataset.getId()+" RECORD_STATE_CHANGED!");
    alert(args[0]);
    break;
    }
    }
    }

    DoradoFactory.registerComponentType("TestCustomTable",TestCustomTableF);

    代码 5.16:TestCustomTable.js
    上面代码通过DoradoFactory.registerComponentType("TestCustomTable",TestCustomTableF);来注册了新的控件(TestCustomTable),TestCustomTableF是对新控件的属性定义和初始化设置等。testCustomTable_processDatasetMessage方法是由于Dataset的消息机制执行了该方法,所以可以在这个方法里实现对本控件的一些控件处理等等。原本在5.3.4中处理的方法现在放在了初始化这个控件的时候给onmousedown事件它,跟原来的实现是一样的。
  8. 在home文件夹下新建javascript-lib.xml,用来输出TestCustomTable.js:

    <?xml version="1.0" encoding="UTF-8"?>
    <libraries>
    <library name="TestCustomTable" path="TestCustomTable.js" />
    </libraries>

    代码 5.17:javascript-lib.xml
  9. 运行效果:


初始化页面的时候会弹出"dataset1 REFRESH!"对话框,是因为dataset1刚进来页面的时候做了一次刷新动作,触发了processDatasetMessage,从而进入了testCustomTable_processDatasetMessage方法处理弹出对话框。

尝试在Dorado Client Debugger里对dataset做一些操作,看能不能触发TestCustomTable控件的处理。






从上面由于对dataset1改变field1的值(原来值为field11,现在变成""),所以触发了processDatasetMessage,弹出的对话框也很符合testCustomTable_processDatasetMessage的代码逻辑。
通过上面的一些例子,我们就可以自己去实现各种各样的控件,从简单到复杂,只要你能想到就可能做到,这个要看写代码的程度。上面还有很多功能没有说到,但最基本和最基础的内容都罗列了出来,通过这些简单的例子,就可以实现复杂的控件出来了。一般复杂的控件需要结合Dhtml、事件触发和消息机制等等技术来实现。