GEF中自带有Directeditrequest,所以实现Directedit还是比较容易的,八进制的gef例子里面就有实现.但我在给directedit加上content assist的时候却发现由一个小bug不太好弄,费了两天才搞定,现在先记下来,以供参考
directedit是通过一个text celleditor来实现编辑功能的,所以可以在directeditmanager类里面的initCellEditor方法里面加上ContentAssistHandler来实现auto complete.但是加上去之后却发现有一个问题:不支持用鼠标来选择proposal.只能用键盘上的上下箭头来选择.虽然也可以用,但是终究不是那么的人性化.
为了修复这个bug,走了不少的弯路,一开始以为是contentassist的问题,因为它是deprecated,所以换了3.3里面的assist api,发现还是不行.后来才知道是因为celleditor有一个focus listener,当用户点击proposals 来选择一行的时候,celleditor的focus就lost了,就会调用focusLost方法,导致directedit编辑失败.所以我重写了celleditor的focusLost方法,把它设成当focus在contentassist的popup dialog就什么都不干,否则调用父类的focusLost方法.理论上是一个好的解决方法,但是contentassist的hasPopupFocus居然一直都返回false,这个方法也失败了.
最后,在bug.eclipse.org上面有人提到GMF里面的TextDirectEditManager是可以做到用鼠标选择proposal的,于是又去看gmf的这个类,它也是继承自DirectEditManager,不过它消除这个bug不是在listener上作文章,而是在commit方法里面,在这个方法里面判断popup dialog是否是active的,如果是的话则给celleditor加上deactive lock,不允许它deactive,这样来实现用鼠标选择proposal.
下面是TextDirectEditManager的方法commit里面的部分代码:
Shell activeShell = Display.getCurrent().getActiveShell();
if (activeShell != null
&& getCellEditor().getControl().getShell().equals(
activeShell.getParent())) {
Control[] children = activeShell.getChildren();
if (children.length == 1 && children[0] instanceof Table) {
/*
* CONTENT ASSIST: focus is lost to the content assist pop up -
* stay in focus
*/
getCellEditor().getControl().setVisible(true);
((MyTextCellEditor) getCellEditor()).setDeactivationLock(true);
return;
}
}
下面是MyTextCellEditor里面对于deactive lock的应用,MyTextCellEditor的deactive之前会判断一下deactive lock是否为true:
public boolean isDeactivationLocked() {
return deactivationLock;
}
public void deactivate() {
if (! isDeactivationLocked())
super.deactivate();
setDeactivationLock(false);
}
public void setDeactivationLock(boolean deactivationLock) {
this.deactivationLock = deactivationLock;
}
Java 对文件进行读写操作的例子很多,让初学者感到十分困惑,我觉得有必要将各种方法进行
一次分析,归类,理清不同方法之间的异同点。
一.在 JDK 1.0 中,通常是用 InputStream & OutputStream 这两个基类来进行读写操作的。
InputStream 中的 FileInputStream 类似一个文件句柄,通过它来对文件进行操作,类似的,在
OutputStream 中我们有 FileOutputStream 这个对象。
用FileInputStream 来读取数据的常用方法是:
FileInputStream fstream = new FileInputStream(args[0]);
DataInputStream in = new DataInputStream(fstream);
用 in.readLine() 来得到数据,然后用 in.close() 关闭输入流。
完整代码见 Example 1。
用FileOutputStream 来写入数据的常用方法是:
FileOutputStream out out = new FileOutputStream("myfile.txt");
PrintStream p = new PrintStream( out );
用 p.println() 来写入数据,然后用 p.close() 关闭输入。
完整代码见 Example 2。
二.在 JDK 1.1中,支持两个新的对象 Reader & Writer, 它们只能用来对文本文件进行操作,而
JDK1.1中的 InputStream & OutputStream 可以对文本文件或二进制文件进行操作。
用FileReader 来读取文件的常用方法是:
FileReader fr = new FileReader("mydata.txt");
BufferedReader br = new BufferedReader(fr);
用 br.readLing() 来读出数据,然后用br.close() 关闭缓存,用fr.close() 关闭文件。
完整代码见 Example 3。
用 FileWriter 来写入文件的常用方法是:
FileWriter fw = new FileWriter("mydata.txt");
PrintWriter out = new PrintWriter(fw);
在用out.print 或 out.println 来往文件中写入数据,out.print 和 out.println的唯一区别是后者写
入数据或会自动开一新行。写完后要记得 用out.close() 关闭输出,用fw.close() 关闭文件。
完整代码见 Example 4。
-------------------------------------------------------------- following is the source code of examples------------------------------------------------------
Example 1:
// FileInputDemo
// Demonstrates FileInputStream and DataInputStream
import java.io.*;
class FileInputDemo {
public static void main(String args[]) {
// args.length is equivalent to argc in C
if (args.length == 1) {
try {
// Open the file that is the first command line parameter
FileInputStream fstream = new FileInputStream(args[0]);
// Convert our input stream to a DataInputStream
DataInputStream in = new DataInputStream(fstream);
// Continue to read lines while there are still some left to read
while (in.available() !=0) {
// Print file line to screen
System.out.println (in.readLine());
}
in.close();
} catch (Exception e) {
System.err.println("File input error");
}
}
else
System.out.println("Invalid parameters");
}
}
Example 2:
// FileOutputDemo
// Demonstration of FileOutputStream and PrintStream classes
import java.io.*;
class FileOutputDemo
{
public static void main(String args[]) {
FileOutputStream out; // declare a file output object
PrintStream p; // declare a print stream object
try {
// connected to "myfile.txt"
out = new FileOutputStream("myfile.txt");
// Connect print stream to the output stream
p = new PrintStream( out );
p.println ("This is written to a file");
p.close();
} catch (Exception e) {
System.err.println ("Error writing to file");
}
}
}
Example 3:
// FileReadTest.java
// User FileReader in JDK1.1 to read a file
import java.io.*;
class FileReadTest {
public static void main (String[] args) {
FileReadTest t = new FileReadTest();
t.readMyFile();
}
void readMyFile() {
String record = null;
int recCount = 0;
try {
FileReader fr = new FileReader("mydata.txt");
BufferedReader br = new BufferedReader(fr);
record = new String();
while ((record = br.readLine()) != null) {
recCount++;
System.out.println(recCount + ": " + record);
}
br.close();
fr.close();
} catch (IOException e) {
System.out.println("Uh oh, got an IOException error!");
e.printStackTrace();
}
}
}
Example 4:
// FileWriteTest.java
// User FileWriter in JDK1.1 to writer a file
import java.io.*;
class FileWriteTest {
public static void main (String[] args) {
FileWriteTest t = new FileWriteTest();
t.WriteMyFile();
}
void WriteMyFile() {
try {
FileWriter fw = new FileWriter("mydata.txt");
PrintWriter out = new PrintWriter(fw);
out.print(“hi,this will be wirte into the file!”);
out.close();
fw.close();
} catch (IOException e) {
System.out.println("Uh oh, got an IOException error!");
e.printStackTrace();
}
}
}
不知道你是否注意过,当你安装java jdk的时候,当你安装微软office的时候,当你装db2的时候,你都会看到一个熟悉的标记---installshield。installshield可以说是当今安装程序解决方案的巨无霸了,功能十分强大,你可以用它制作出你想要的安装程序。但是功能的强大也带来一个坏处,就是要上手非常难。所以公司特意请macrovision(就是制作installshield的公司)的人给我们进行了一个training,感觉收获还是很大的,所以把我认为重要的地方纪录下来,一方面万一自己忘了可以查一查,另一方面说不定对别人也有帮助。
先从版本说起。installshield有专门用于制作java安装程序的产品,由于java是跨平台的语言,所以installshield对应的产品就叫installshield multiple platform,简称ismp。我接触的最早版本是ismp 5.0,后来又出了ismp 11.5,再后来ismp改名字叫Install Anywhere(以下简称IA)。目前我们training用的版本是IA 8.0,相信应该是最新的版本了。IA是共享软件,不注册的话有21天的试用期。
安装程序是一个可定制性非常强的东西,每个软件作者的需求都不一样。有的推崇简单就是美,一般只需要用户选择安装的目录,然后就一路next就装完了;但有的软件非常复杂,比如需要设置参数,需要选择安装哪些部分,甚至需要启动windows的系统服务。这时候就需要比较复杂的配置了。installshield针对两种用户设计了不同的开发环境:一种是common designer,另一种是Advanced Designer。当你第一次打开IA的时候,缺省的是common designer,你只需要做一些简单的配置,比如产品的名称,需要安装的文件,要不要绑定虚拟机等等,然后就可以build出一个安装程序了。Advanced Designer是为高级用户设置的,提供了更多,更丰富的功能,你可以用它来打造你所需要的安装程序。本文主要是针对Advanced Designer进行一些说明。
1)安装模式(install modes)
gui:这是最常用的一种模式,在安装过程中会弹出若干个panel,比如welcome panel,license panel,destination panel等等。
console:用这种模式安装程序时,不会出现panel。它的所有信息都在控制台中出现。说的再通俗一点,就是整个安装过程只有一个dos窗口,这个窗口先会显示一行信息欢迎你安装本软件,然后是让你选择destination,再安装,最后会显示一行安装成功的信息
silent:顾名思义,这种模式在安装的时候不会弹出任何窗口,它会安静地装上软件,所以用户也不能自己设定安装目录,一般都市由安装程序安装到固定的目录上
2)install sets
很多安装程序都有完全安装,最小安装,自定义安装等选项,这一般是用features来实现的。你可以把你的产品分成几个features,然后由用户来选择一部分进行安装。
3)actions
IA中很多操作被称为actions,常见的有copy files,delete files,modifying registry, creating service, modifying configurations files等
4)variable
IA中很重要的一个概念,你可以用variable来存放属性信息,比如安装目录,用户名等等。比如
安装目录可能会在很多地方都用到,如果你安装目录是硬编码的,万一将来要修改就要改
很多地方,容易出错;如果用variable来保存的话,只要修改变量值就可以了。注意一点:variable
的值基本上都是string类型的
5)magic folders
IA里面独有的概念,但感觉没什么新意,就是variables的一种,专门用于定义folder的
variable而已
6)InstallAnywhere registry
不同于windows的registry,这是InstallAnywhere自己的registry。每个用IA制作的安装程序,在安装的过程中
都会把自己注册到这个InstallAnywhere registry(注意:你只能在InstallAnywhere registry找到安装的
component,找不到product)。它的一个典型应用就是当你需要检查这个机器上是否安装过某个软件的时候,就可以
用search这个IA registry。不过如果你是用其他工具制作的安装程序,IA registry就不会有记录了。
7)execute command&execute script
execute command是用来执行command,常用的dos命令(copy,cd等)你都可以写在这里。execute script其实就是
execute command的加强版:如果你有多个命令,不需要建多个execute command,把它们写在execute script就好了
8)计算所需空间
在IA中,默认的空间大小是用byte来计算的,所以如果你的软件比较大的话,那一长串的阿拉伯数字会把用户吓倒的
解决方法是,在pre-install summary panel的配置项中,有一个是Edit Custom Field。在那里新建一个field。Variable
name是显示给用户看的内容,比如你可以写disk space。variable value是你的软件所需的硬盘大小。你可以先算出来
,存在一个变量中,然后让variable value等于这个变量就可以了。
9)results variable
用来存放用户的选择。比如在show message dialog中,有一个results variable是$CHOSEN_DIALOG_BUTTON$
它用来存放用户按的是OK 还是Cancel
很多人在开发RCP时,发现开发时都没问题,但导出成包时却报找不到第三方库中类的错误。主要原因就是没有将第三方库配置好。现在我给出一个实现项目的配置为示例,以供参考。 原文出处:http://www.eclipseworld.org/bbs/read.php?tid=1133 环境:Eclipse3.2M3 一个RCP的实际项目
一、
最关键的就是plugin.xml和MANIFEST.MF 所有界面上的最后操作,结果都是保存在这两个文件中。注意:“.classpath”文件只是开发时对引用第三库有用,打包发行之后它的作用就没有了,还得靠plugin.xml和MANIFEST.MF。
1、plugin.xml文件
<?xml version="1.0" encoding="GB2312"?>
<?eclipse version="3.0"?>
<plugin>
<extension
id="AdminConsole"
point="org.eclipse.core.runtime.applications">
<application>
<run class="com.wxxr.management.admin.console.AdminConsole"/>
</application>
</extension>
<extension id="AdminConsole" point="org.eclipse.core.runtime.products">
<product name="%productName" application="com.wxxr.management.admin.console.AdminConsole">
<property name="appName" value="%swtAppName"/>
<property name="windowImages" value="icons/eclipse.gif,icons/eclipse32.gif"/>
<property name="aboutText" value="%aboutText"/>
<property name="aboutImage" value="icons/eclipse_lg.gif"/>
<property name="windowImages" value="icons/alt16.gif,icons/eclipse.gif"/>
</product>
</extension>
<extension
point="org.eclipse.ui.perspectives">
<perspective
class="com.wxxr.management.admin.console.monitor.MonitorPerspective"
name="%perspectiveName"
id="com.wxxr.management.admin.console.monitor.MonitorPerspective"/>
<perspective
class="com.wxxr.management.admin.console.configure.ConfigurePerspective"
name="%configurePerspectiveName"
id="com.wxxr.management.admin.console.configure.ConfigurePerspective"/>
<perspective
class="com.wxxr.management.admin.console.jmx.JMXPerspective"
name="%jmxPerspectiveName"
id="com.wxxr.management.admin.console.jmx.JMXPerspective"/>
</extension>
<extension
point="org.eclipse.ui.editors">
<editor
name="事件列表"
icon="icons/alt16.gif"
class="com.wxxr.management.admin.console.log.ui.LogEditor"
id="com.wxxr.management.admin.console.log.ui.LogEditor">
</editor>
<editor
name="地图"
icon="icons/map_view.gif"
class="com.wxxr.management.admin.console.map.MapEditor"
id="com.wxxr.management.admin.console.map.MapEditor">
</editor>
</extension>
<extension
point="org.eclipse.ui.views">
<category
id="com.wxxr.management.admin.console.monitor.view"
name="%views.category.name"/>
<view
id="com.wxxr.management.admin.console.navigator.ui.StationExploreView"
name="工作站"
icon="icons/eclipse.gif"
class="com.wxxr.management.admin.console.navigator.ui.StationExploreView"
category="com.wxxr.management.admin.console.monitor.view"/>
<view
name="事件细节"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.monitor.view"
class="com.wxxr.management.admin.console.monitor.eventview.EventDetailView"
id="com.wxxr.management.admin.console.monitor.eventview.EventDetailView" />
<view
name="事件统计"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.monitor.view"
class="com.wxxr.management.admin.console.monitor.view.SystemEventStatisticsView"
id="com.wxxr.management.admin.console.monitor.view.SystemEventStatisticsView" />
<view
name="紧急事件处理"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.monitor.view"
class="com.wxxr.management.admin.console.emergency.ui.EmergencyEventReceiverView"
id="com.wxxr.management.admin.console.emergency.ui.EmergencyEventReceiverView" />
<category
id="com.wxxr.management.admin.console.jmx.view"
name="%views.category.name"/>
<view
name="JMX Connections"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.jmx.view"
class="com.wxxr.management.admin.console.jmx.ui.JMXExploreView"
id="com.wxxr.management.admin.console.jmx.ui.JMXExploreView" />
<view
name="JMX Attributes View"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.jmx.view"
class="com.wxxr.management.admin.console.jmx.ui.AttributesView"
id="com.wxxr.management.admin.console.jmx.ui.AttributesView" />
<view
name="JMX Operations View"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.jmx.view"
class="com.wxxr.management.admin.console.jmx.ui.OperationsView"
id="com.wxxr.management.admin.console.jmx.ui.OperationsView" />
<view
name="JMX MBean View"
icon="icons/eclipse.gif"
category="com.wxxr.management.admin.console.jmx.view"
class="com.wxxr.management.admin.console.jmx.ui.MBeanView"
id="com.wxxr.management.admin.console.jmx.ui.MBeanView" />
</extension>
<extension
id="AdminConsole"
point="org.eclipse.core.runtime.products">
<product
application="com.wxxr.management.admin.console.AdminConsole"
name="AdminConsole"/>
</extension>
</plugin>
2、
META-INF\MANIFEST.MF文件
注意:(1)这里require-bundle定义了项目依赖的插件。
(2)Bundle-ClassPath定义了引用的第三方库,别忘了把AdminConolse项目自己console.jar加进去,否则连自己项目里的类都会找不到。
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: com.wxxr.management.admin.console; singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: com.wxxr.management.admin.console.AdminConsolePlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.gef,
org.eclipse.ui.forms,
org.eclipse.ui.console
Eclipse-AutoStart: true
Bundle-Vendor: %providerName
Bundle-ClassPath: console.jar,
lib/commons-codec-1.3.jar,
lib/jboss.jar,
lib/jbossall-client.jar,
lib/jboss-jmx.jar,
lib/jboss-system.jar,
lib/log4j-1.2.8.jar,
lib/wxxr-common-1.0-b1.jar,
lib/wxxr-common-jboss-1.0-b1.jar,
lib/wxxr-db-persistence-1.0-b1.jar,
lib/wxxr-jboss-controller-1.0-b1.jar,
lib/wxxr-jboss-workstation-1.0-b1.jar,
lib/wxxr-remoting-1.0-b1.jar,
lib/wxxr-security-1.0-b1.jar,
lib/xerces-2.6.2.jar,
lib/xmlParserAPIs-2.2.1.jar,
lib/xmlrpc-2.0.jar
3、build.properties文件。
这个文件主要是用Eclipse导出包的时候用。
source.console.jar = src/
output.console.jar = bin/
bin.includes = plugin.xml,\
*.jar,\
console.jar, \
plugin.properties
pluginName = Admin Console Plug-in
providerName = WXXR.com.cn
perspectiveName = Admin Console
configurePerspectiveName= Configure
jmxPerspectiveName= JMX Console
jars.extra.classpath = lib/commons-codec-1.3.jar,\
lib/jboss.jar,\
lib/jbossall-client.jar,\
lib/jboss-jmx.jar,\
lib/jboss-system.jar,\
lib/log4j-1.2.8.jar,\
lib/wxxr-common-1.0-b1.jar,\
lib/wxxr-common-jboss-1.0-b1.jar,\
lib/wxxr-db-persistence-1.0-b1.jar,\
lib/wxxr-jboss-controller-1.0-b1.jar,\
lib/wxxr-jboss-workstation-1.0-b1.jar,\
lib/wxxr-security-1.0-b1.jar,\
lib/wxxr-remoting-1.0-b1.jar,\
lib/xerces-2.6.2.jar,\
lib/xmlParserAPIs-2.2.1.jar,\
lib/xmlrpc-2.0.jar
4、plugin.properties,这个放一些上面几个文件用到的变量。
pluginName= WXXR Admin Console
providerName= wxxr.com.cn
productName= WXXR SMS Operation Platform
appName= WXXR Admin Console
perspectives.browser.name= WXXR Admin Console
views.category.name= WXXR Admin Console
views.browser.name= Browser
views.history.name= History
views.stationexplore.name= Stations
views.tasklist.name= Task List
views.loglist.name= Workstation Monitor
monitor.message.detail=Monitor Message Detail
monitor.message.statistics=????
swtAppName= AdminConsole
aboutText= WXXR Admin Console \n\n\
(c) Copyright WXXR Ltd. and others 2003, 2004. All rights reserved.\n\
Visit
http://www.wxxr.com.cn 二、图形方式 有时直接编辑plugin.xml等文件容易出错(全角空格什么的),那么可以用图形编辑方式来,不过最后结果还是反映到plugin.xml等文件中的。我把plugin.xml打开,然后一个项一个项的把图截下来,以供大家参考。