Universal VisioViewer 1.0组件的接口设计

来源:互联网 发布:福州极客网络 编辑:程序博客网 时间:2024/05/01 17:30

Universal VisioViewer 1.0组件的接口设计

阮俊杰

一、Universal VisioViewer组件结构概述

    本系统与Visio XML文档的解析、转换、显示、打印等功能相关的Java包被封装成一个组件,即“VisioCom.jar”档案文件,其中的包结构如下面的图1所示:

如图所示,与用户应用程序进行对接所密切相关的只有其中的“Inteferace”和“Viewer”两个包。

二、“Interface”包

    “Interface”包主要由两个Java接口组成,其类图如下面的图2所示。

1.“VisioPanel”接口

    如图1所示,用户应用嵌入本组件并调用其中功能是以实例化“Viewer”包中的“VisioViewer”类作为起点的(下面将更加详细地叙述),而该类的构造函数要求父对象传递一个“VisioPanel”接口类型的引用作为参数,一般来说,这个引用对象即为父对象本身,前题是父对象的类需用语句“implements VisioPanel”来进行声明并实现图2所示的两个方法。

    如图2所示,“VisioPanel”接口声明了两个方法,第一个方法“public getPanel()”要求返回一个“java.awt.Component”类型的对象,以便本组件的各功能包掌握Visio文档显示的缺省图形界面。由于“java.awt.Component”类是Java AWT中具有图形显示(支持getGraphics()方法)及交互能力的高级类,因此几乎可以包容Java AWT的所有输出界面。

    需要说明的是,实现“VisioPanel”接口并非是本组件定向输出界面的唯一方法,“VisioViewer”对象的父对象还可以在引用该对象的“Draw()”方法时指定具体的输出界面,如本说明后续内容所述。

    本接口的第二个方法为“getPanelBkColor()”,返回的类型是“java.awt.Color”,用来指定输出界面的背景色彩。

2.“CoordTransfer”接口

    为了支持用户的应用程序在屏幕坐标和诸如地理坐标等逻辑坐标间进行相互转换,增强系统的可用性并降低耦合度,本组件设计了一个坐标转换接口,即“CoordTransfer”接口,如图2所示其中包括了三个回调函数。

    第一个函数的原型为“Rectangle2D.Float transCoord(Rectangle2D.Float equiRec)”,用于将本组件所提供的屏幕坐标区域(equiRec)转换为具体应用的坐标区域,如将屏幕坐标转换为电子地图上的经纬度坐标等,并返回给本组件。

    第二个函数的原型为“Rectangle2D.Float inverseTransCoord (Rectangle2D.Float geomRec),是与第一个函数相对的,即将本组件给出的应用相关坐标区域(geomRec)转换为屏幕坐标,并返回给本组件。

    第三个函数的原型为“boolean ifIntersectWithWin(Rectangle2D.Float bound)”,要求应用程序判断本组件给出的应用相关坐标区域(bound)是否与屏幕当前显示的区域相交,并以boolean类型的值返回结果。这样,本组件便可决定是否输出相应区域内的Visio文档内容,以提高显示效率。如果用户的应用认为对效率没有影响,则以下面的语句实现本方法即可:

        public boolean ifIntersectWithWin(Rectangle2D.Float bound) {

              return true;

       }

    与上一个接口即“VisioPanel”接口必须由应用程序予以实现所不同的是,本接口是可选的,即应用程序可以实现,也可以不必实现。而一旦予以实现,则需要在实例化“Viewer”包中的“VisioViewer”类后调用该对象的方法“setTransfer(CoordTransfer par)”来予以注册。

三、“Viewer”包

    “Viewer”包中含有5个类,其类图如图3所示,其中为了逻辑上清晰起见包括了一个“Docs”包中的类,即“VisioDoc”。

    如图所示,其中与用户应用紧密相联的,或者说对用户“可见”的类主要有两个,即“VisioViewer”和“VisioObjectsContainer”,在图中以实线予以标示,而其他“不可见”的类则用虚线描绘。

    利用下面图4所示的序列图,可以更清晰地说明用户的应用程序利用本组件“Viewer”包中的对象对Visio XML文档进行读取和标绘等功能的具体执行过程。

    如前所述,用户的应用程序以实例化“VisioViewer”类作为使用本组件的起点,并以一个实现“VisioPanel”接口类型的引用作为调用其构造函数的参数。尔后,可调用该实例的“setLanguage()”方法来设定交互语言,调用“setTransfer()”方法来指定坐标变换接口的引用实例,调用“setInternetMode()”及“setContextURL()”来指定Visio文档的Internet浏览方式及对应的URL上下文(该上下文对应于Java.net.URL的构造函数URL(URL context, String spec)中的“context”部分),或调用“setNativeMode()”方法以恢复缺省的本地浏览方式。在Visio文档的显示界面(Java.AWT.Component类或其子类的实例)中,可调用“Component.AddMouseListener()”和“Component. addMouseMotionListener()”将该实例加入到事件队列。通过以上设定,VisioViewer的基本工作环境予以确立。

    “VisioViewer”类在实例化的过程中,即创建一个“VisioLib”对象、一个缺省的“VisioObjectsContainer”对象和一个“ObjPopMenu”对象,并以其私有属性的方式予以保存。其中的“VisioLib”对象作为“Visio文档库”可保存多个打开的Visio文档对象,即“VisioDoc”类的实例,而为了满足地图标绘等应用需求每个Visio文档应具备在多个位置上以多种方式进行显示的功能,因此本组件设计了一个“VisioObject”类,其与“VisioDoc”类可建立起多对一的关系,即以“VisioDoc”对象的标识保持对其的引用,同时本身又拥有区域、转角等位置变换相关的私有属性。而这些“VisioObject”对象又需要一个容器进行管理,这便是“VisioObjectsContainer”对象的功能。

    如上所述“VisioViewer”类在实例过程化中创建一个“VisioObjectsContainer”对象,即缺省的VisioObject对象的容器对象,它是由“VisioViewer”直接管理、不建议接受其他对象直接控制的对象,对其中Visio对象的新增、删除、显示等操作均由“VisioViewer”的特定函数来实现,而在显示时“VisioViewer”对象则通过“VisioPanel”接口的“getPanel()”方法获取输出的图形设备,亦不要求用户应用程序直接指定。

    除了上面缺省的“VisioObjectsContainer”对象外,为支持用户应用程序对Visio对象分类显示以及“预览→选择→浏览”的展现需求,本组件设计了以命名的方法创建多个“VisioObjectsContainer”实例并由用户应用程序直接进行管理的功能。创建命名对象既可以通过直接调用“VisioObjectsContainer”的构造函数来完成,亦可以通过“VisioViewer”对象的“newContainer(name)”的方法予以实现,而且后者是我们所建议使用的方法。

    通过“VisioViewer”对象打开Visio XML文档的过程,即图4中“addDocument(name,fn)”方法的实现过程,我们可以更清晰地了解如上几个对象间的相互协作及依赖关系。该方法的功能可以描述为“读取文件名为‘fn’的文件,并将生成的文档对象加入到命名为‘name’的‘VisioObjectsContainer’实例中。”该方法具有多种可重载形式,其中之一即缺少第一个参数“name”的变形,在这种情况下其语义为:“将文件名为‘fn’的文档对象加入到缺省的‘VisioObjectsContainer’实例中。”

    在不出现任何异常的情况下,“VisioViewer”对象在接到上面方法的调用后,立即调用“Docs”包中 “VisioDoc” 的类方法“readDocFromXML(fn)”,以读取网络服务器或本地上名称为“fn”的文件,并创建一个“VisioDoc”实例作为返回值。“VisioViewer”对象在接收到返回的实例后,立即将其加入到“VisioLib”对象的文档库中,并利用该对象的“UUID”创建一个“VisioObject”对象,再将该对象加入到命名为“name”的“VisioObjectsContainer”实例中,或者在“name”省略的情况下加入到缺省的容器中。

    如上所述的作为“VisioObjectsContainer”实例的“缺省容器”和“命名容器”彼此之间不是孤立的,而是相互联系、可以交换内容的。一般来说,这种联系可以表达丰富的应用逻辑。例如,假设我们将一个命名为“List”的容器对应于文件目录窗口(或MS Visio软件的“模具”窗口),而将缺省容器对应于文件内容浏览主窗口,那么,从命名为“List”的容器中选取一个Visio对象并将其加入到缺省容器之中,在应用中便可以代表从目录窗口中选择一个文件并在主窗口打开,或者是利用MS Visio软件将一个模具拖曳到绘图窗口中等操作。而在“VisioViewer”类中实现上述功能的函数是极其简单的,其形式为“addVisioObject(name, index)”,在语义上可理解为“将命名为‘name’的容器中顺序号为‘index’的对象加入到缺省容器之中。”

   至于图4中下部所标示的“VisioViewer”对象对于文档对象的诸多操作,例如:绘图(“draw()”函数)、平铺(“layout()”函数)及事件处理(“handleMouseEvent()”函数)等,事实上均将相应的处理请求传递到缺省或特定的“VisioObjectsContainer”容器对象上予以执行,而用户的应用程序亦可以针对所创建的“VisioObjectsContainer”命名对象直接调用如上的请求。类似的方法还有放大(“increaseCurrentObj()”函数)、缩小(“decreaseCurrentObj ()”函数)、显示下页(“nextPageCurrentObj ()”函数)、显示上页(“previousPageCurrentObj ()”函数)等等。

    除了创建上面两个类的实例及调用其中的诸多方法外,用户的应用程序还可以对它们进行继承与拓展,以实现更加客户化的应用。

四、结束语

    通过如上所述精心设计的接口包,使得用户的应用对Uiversal Visioviewer组件的嫁接变得非常容易。对图形展示层面上,用户应用程序嵌入本组件的语句不超过10行Java源代码。对于嵌入到类似于地理信息系统(GIS)并充当地图标绘这样的复杂功能来说,现对于该组件进行操作的全部语句亦不超过100行,真正做到了众所熟知的“高内聚、低耦合”的现代程序设计思想。

原创粉丝点击