﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-很久很久以前-随笔分类-Eclipse</title><link>http://www.blogjava.net/pandawang/category/6832.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 17 May 2007 15:40:59 GMT</lastBuildDate><pubDate>Thu, 17 May 2007 15:40:59 GMT</pubDate><ttl>60</ttl><item><title>JFace的作为Java Application使用</title><link>http://www.blogjava.net/pandawang/archive/2007/05/17/118079.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 17 May 2007 06:33:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2007/05/17/118079.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/118079.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2007/05/17/118079.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/118079.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/118079.html</trackback:ping><description><![CDATA[JFace的单独使用很久都没有做过，基本上都是在开发elcipse插件时用JFace。今天使用JFace作为Java Application时遇到了
<tt>Exception in thread "main" java.lang.NoClassDefFoundError:
org/eclipse/core/runtime/IStatus</tt>
错误，虽然已经添加了org.eclipse.jface,org.eclipse.core.runtime,org.eclipse.osgi包，但仍然出错，后来发现org.eclipse.core.runtime.IStatus是在org.eclipse.equonix.common包中，添加后发现 ，还需要添加org.eclipse.core.command包，再添加后搞定。<br><img src ="http://www.blogjava.net/pandawang/aggbug/118079.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2007-05-17 14:33 <a href="http://www.blogjava.net/pandawang/archive/2007/05/17/118079.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SWT中的模式和非模式船体（modal or non-modal）</title><link>http://www.blogjava.net/pandawang/archive/2007/05/17/118075.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 17 May 2007 06:27:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2007/05/17/118075.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/118075.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2007/05/17/118075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/118075.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/118075.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 以前实现SWT中的模式和非模式窗体（modal or non-modal window
)是通过在子窗体中是否截取父窗体的消息循环来实现的，现在发现这样好像不行了，但可以通过指定子窗体的样式（style）来制定子窗体是否是模式窗体。<br>Shell child = new Shell(shell,SWT.SHELL_TRIM|SWT.APPLICATION_MODAL);
<br>上面的语句指定了子窗体child为模式窗体。在上面的style中指定SWT.SHELL_TRIM
是为了显示窗体的三个默认按钮（最大，最小和关闭），也可以用SWT.DIALOG_TRIM，不过此时为对话框样式，只有一个默认按钮（关闭）。默认的Shell是非模式窗体，并且是有默认系统按钮的，即样式为：SWT.SHELL_TRIM|SWT.MODELESS。<br>顺便说一下，在JFace的Dialog中使用模式对话框只要简单的设置该对话框setBlockOnOpen(true)即可。<strong><a name="exdialog"></a> <img src ="http://www.blogjava.net/pandawang/aggbug/118075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2007-05-17 14:27 <a href="http://www.blogjava.net/pandawang/archive/2007/05/17/118075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse的新功能——tabbed property 的使用</title><link>http://www.blogjava.net/pandawang/archive/2006/09/17/70163.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 17 Sep 2006 14:24:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/09/17/70163.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/70163.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/09/17/70163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/70163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/70163.html</trackback:ping><description><![CDATA[
		<p>       Tabbed Property是eclipse3.2中新加入一个view,可以使属性编辑器的功能近乎无限的扩大。这里说明一些Tabbed Property的使用方法。Tabbed Property中分成三个部分，Contributer,Tabs,Sections,一个Contributor包含若干个Tabs，一个Tabs又可以包含若干个sections。下面我们来分别进行描述。<br />      1。Contributor 这需要扩展<font face="Courier New">org.eclipse.ui.views.properties.tabbed.PropertyContributor扩展点，定义时，最重要的是定义contributId，这个id必须是全局唯一的，这样在加载属性页时，才能找到这个我们定义的属性页，一般地，我们都将对应于这个属性页的workbenchpart的id作为本contributor的id，这样我们在代码中可以不硬编码本id字符串，而使用getSite（）.getId（）就可以得到这个id了（当然，这样定义id不是必须的）。一个property view可以被多个workbench part共享，但 一个workbench part只能有一个property view，这个workbench part需要实现ITabbedPropertySheetPageContributor 接口，这个接口只有一个方法，要求返回本part对应的tabbed property Contributor id，一般只要return getSite（）.getId（）；<br />   contributor有如下几个attribute：<br />   1）typeMapper，这个类需要实现org.eclipse.ui.views.properties.tabbed.ITypeMapper，主要是实现类型的映射，因为我们选择的元素并不一定是实现IPropertySource的元素（即能够给property view提供内容的元素），比如在GEF中，我们选择的finger实际上是选择了对应的EditPart，而实际上实现了IPropertySource一般的是model部分的元素，所以这时候我们要将Editpart映射到对应的model元素。<br />   2）labelProvider，需要一个实现org.eclipse.jface.viewers.ILabelProvider的类，主要是在各个tabs的最上面显示文字和图片。<br />   3）propertyCategory，用于聚合多个tabs，注意至少要定义一个category，来聚合tabs，否则，可能会显示property失败。</font></p>
		<p>
				<font face="Courier New">   2。Tabs，这个需要扩展org.eclipse.ui.views.properties.tabbed.propertyTabs扩展点，其中contributorId就是与之相关联的Contributor的id，然后我们可以定义多个tab，这些tab的属性如下：<br />   1）label，用于显示在property view的tab bar上的字<br />   2）category，填入的就是在Contributor扩展点中定义的那些category，用于聚合tabs<br />   3）id，本tab的唯一标识<br />   4）afterTab，用于tab之间的排序，如果这是第一个tab，则没有afterTab，afterTab指的是在本tab之前的那个tab，并且afterTab描述的是在同一个category中的tabs，不同category之间的顺序是按照在contributor中定义category的顺序来定义的。<br />   5）indented，如果为ture，则各个tabs是有缩进的<br />   6）image，本tab的图片<br /><br />   3。section ，需要扩展 org.eclipse.ui.views.properties.tabbed.PropertySections扩展点，它的contributionId就是本section所在的Contribution的id，针对每个tab，我们可以定义多个section，每个section的attribut描述如下：<br />   1）id，本secation的唯一标识<br />   2）tab，本section所属tab的标识<br />   3）class，实现了org.eclipse.ui.views.properties.tabbed.AbstractPropertySection抽象类的类，用于描述这个section的控件和布局。<br />   4）aftersection和上面的aftertab差不多，描述的是同一个tab中的section的顺序，注意afterserction描述的是本section之前的section的id<br />   5）filter：一个实现org.eclipse.jface.viewers.IFilter接口的过滤器，对选中元素进行过滤。<br />   6）enableFor：一个用于只是选择数目的值，必须要符合这个舒服才能使能这个section。如果不符合，则这个section就被过滤了，如果省略本值，则section的使能器就不会工作了。这是一个自然数，比如，当enableFor＝1时，仅仅只有一个元素被选择的时候，本section才会被使能。<br /><br />some notes：<br />    上面说过实现ITabbedPropertySheetPageContributor接口的workbench part除了要实现getContributeId方法外，还需要重载getAdapter方法，因为eclipse的默认加载的property veiw时原来的那个view，为了使tabbed property view能够加载，我们就需要重载getAdapter方法，返回一个TabbedPropertySheetPage对象。<br /><br />    在实现section class的时候需要注意，createcontrol时首先应该先创建一个composite，一般是 Composite composite = getWidgetFactory().createFlatFormComposite(parent); 然后各个控件在这个composite上创建。</font>
				<font face="Courier New">
				</font>
		</p>
		<p>
				<br />
		</p>
<img src ="http://www.blogjava.net/pandawang/aggbug/70163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-09-17 22:24 <a href="http://www.blogjava.net/pandawang/archive/2006/09/17/70163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse下java动态编译时com.sun.tools.javac.Main类加载问题的解决</title><link>http://www.blogjava.net/pandawang/archive/2006/08/20/64639.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 20 Aug 2006 09:28:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/08/20/64639.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/64639.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/08/20/64639.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/64639.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/64639.html</trackback:ping><description><![CDATA[
		<table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td align="left" width="100%">
										<table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td style="PADDING-LEFT: 5px; LINE-HEIGHT: 25px" align="left" colspan="2">
																		<h3>理解Java ClassLoader机制 </h3>
																</td>
														</tr>
														<tr>
																<td style="PADDING-LEFT: 5px; LINE-HEIGHT: 25px" align="left">
																		<h4>Java ClassLoader </h4>
																</td>
																<td align="right">2006-5-23 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
						<div>java.lang.NoClassDefFoundError: com/sun/tools/javac/Main<br />最近在使用java的动态编译的时候出现的问题,主要是由于在使用类com.sun.tool.javac.Main时,总是出现NoClassDefFoundError的错误,后来找到如下的文章,分析,可能是由于对于包tools.jar的加载问题,虽然我在classpath中声明了这个包,但在eclipse环境下,始终都还是出现运行时异常,对于编译时正确,运行时异常的情况,eclipse一般都是由于其自身的加载机制造成的.在eclipse下,对于一般的java工程,只要设置了系统的classpath,在其中添加了tools.jar包,即可;对于plugin工程,我是将tools.jar包,直接拷贝到本工程下,并在property中引用,而且在META-INF/MANIFEST.MF文件中的Runtime页的classpath中添加了这个tool.jar包,这样在运行时就没有异常了,可以正常编译了.</div>
						<tr height="100%">
								<td colspan="2">
										<span id="post1" style="FONT-SIZE: 12px; COLOR: #000000">当JVM（Java虚拟机）启动时，会形成由三个类加载器组成的初始类加载器层次结构：<br /><br />       bootstrap classloader<br />                |<br />       extension classloader<br />                |<br />       system classloader<br /><br />bootstrap classloader －引导（也称为原始）类加载器，它负责加载Java的核心类。在Sun的JVM中，在执行java的命令中使用-Xbootclasspath选项或使用- D选项指定sun.boot.class.path系统属性值可以指定附加的类。这个加载器的是非常特殊的，它实际上不是 java.lang.ClassLoader的子类，而是由JVM自身实现的。大家可以通过执行以下代码来获得bootstrap classloader加载了那些核心类库：<br />   URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();<br />   for (int i = 0; i &lt; urls.length; i++) {<br />     System.out.println(urls.toExternalform());<br />   }<br />在我的计算机上的结果为：<br />文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/dom.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/sax.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xalan-2.3.1.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xercesImpl-2.0.0.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xml-apis.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xsltc.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/rt.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/i18n.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/sunrsasign.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/jsse.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/jce.jar<br />文件:/C:/j2sdk1.4.1_01/jre/lib/charsets.jar<br />文件:/C:/j2sdk1.4.1_01/jre/classes<br />这时大家知道了为什么我们不需要在系统属性CLASSPATH中指定这些类库了吧，因为JVM在启动的时候就自动加载它们了。<br /><br />extension classloader －扩展类加载器，它负责加载JRE的扩展目录（JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的）中JAR的类包。这为引入除Java核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个JRE中启动的JVM都是通用的，所以放入这个目录的 JAR类包对所有的JVM和system classloader都是可见的。在这个实例上调用方法getParent()总是返回空值null，因为引导加载器bootstrap classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码时：<br />   System.out.println(System.getProperty("java.ext.dirs"));<br />   ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();<br />   System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());<br />结果为：<br />C:\j2sdk1.4.1_01\jre\lib\ext<br />the parent of extension classloader : null<br />extension classloader是system classloader的parent，而bootstrap classloader是extension classloader的parent，但它不是一个实际的classloader，所以为null。<br /><br />system classloader －系统（也称为应用）类加载器，它负责在JVM被启动时，加载来自在命令java中的-classpath或者java.class.path系统属性或者 CLASSPATH操作系统属性所指定的JAR类包和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()找到该类加载器。如果没有特别指定，则用户自定义的任何类加载器都将该类加载器作为它的父加载器。执行以下代码即可获得：<br />   System.out.println(System.getProperty("java.class.path"));<br />输出结果则为用户在系统属性里面设置的CLASSPATH。<br />classloader 加载类用的是全盘负责委托机制。所谓全盘负责，即是当一个classloader加载一个Class的时候，这个Class所依赖的和引用的所有 Class也由这个classloader负责载入，除非是显式的使用另外一个classloader载入；委托机制则是先让parent（父）类加载器 (而不是super，它与parent classloader类不是继承关系)寻找，只有在parent找不到的时候才从自己的类路径中去寻找。此外类加载还采用了cache机制，也就是如果 cache中保存了这个Class就直接返回它，如果没有才从文件中读取和转换成Class，并存入cache，这就是为什么我们修改了Class但是必须重新启动JVM才能生效的原因。<br /><br /><br />每个ClassLoader加载Class的过程是：<br />1.检测此Class是否载入过（即在cache中是否有此Class），如果有到8,如果没有到2<br />2.如果parent classloader不存在（没有parent，那parent一定是bootstrap classloader了），到4<br />3.请求parent classloader载入，如果成功到8，不成功到5<br />4.请求jvm从bootstrap classloader中载入，如果成功到8<br />5.寻找Class文件（从与此classloader相关的类路径中寻找）。如果找不到则到7.<br />6.从文件中载入Class，到8.<br />7.抛出ClassNotFoundException.<br />8.返回Class.<br /><br />其中5.6步我们可以通过覆盖ClassLoader的findClass方法来实现自己的载入策略。甚至覆盖loadClass方法来实现自己的载入过程。<br /><br />类加载器的顺序是：<br />先是bootstrap classloader，然后是extension classloader，最后才是system classloader。大家会发现加载的Class越是重要的越在靠前面。这样做的原因是出于安全性的考虑，试想如果system classloader“亲自”加载了一个具有破坏性的“java.lang.System”类的后果吧。这种委托机制保证了用户即使具有一个这样的类，也把它加入到了类路径中，但是它永远不会被载入，因为这个类总是由bootstrap classloader来加载的。大家可以执行一下以下的代码：<br />   System.out.println(System.class.getClassLoader());<br />将会看到结果是null，这就表明java.lang.System是由bootstrap classloader加载的，因为bootstrap classloader不是一个真正的ClassLoader实例，而是由JVM实现的，正如前面已经说过的。<br /><br />下面就让我们来看看JVM是如何来为我们来建立类加载器的结构的：<br />sun.misc.Launcher，顾名思义，当你执行java命令的时候，JVM会先使用bootstrap classloader载入并初始化一个Launcher，执行下来代码：<br />  System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());<br />结果为：<br />  the Launcher's classloader is null (因为是用bootstrap classloader加载,所以class loader为null)<br />Launcher 会根据系统和命令设定初始化好class loader结构，JVM就用它来获得extension classloader和system classloader,并载入所有的需要载入的Class，最后执行java命令指定的带有静态的main方法的Class。extension classloader实际上是sun.misc.Launcher$ExtClassLoader类的一个实例，system classloader实际上是sun.misc.Launcher$AppClassLoader类的一个实例。并且都是 java.net.URLClassLoader的子类。<br /><br />让我们来看看Launcher初试化的过程的部分代码。<br /><br />Launcher的部分代码：<br />public class Launcher  {<br />   public Launcher() {<br />       ExtClassLoader extclassloader;<br />       try {<br />           //初始化extension classloader<br />           extclassloader = ExtClassLoader.getExtClassLoader();<br />       } catch(IOException ioexception) {<br />           throw new InternalError("Could not create extension class loader");<br />       }<br />       try {<br />           //初始化system classloader，parent是extension classloader<br />           loader = AppClassLoader.getAppClassLoader(extclassloader);<br />       } catch(IOException ioexception1) {<br />           throw new InternalError("Could not create application class loader");<br />       }<br />       //将system classloader设置成当前线程的context classloader（将在后面加以介绍）<br />       Thread.currentThread().setContextClassLoader(loader);<br />       ......<br />   }<br />   public ClassLoader getClassLoader() {<br />       //返回system classloader<br />       return loader;<br />   }<br />}<br /><br />extension classloader的部分代码：<br />static class Launcher$ExtClassLoader extends URLClassLoader {<br /><br />   public static Launcher$ExtClassLoader getExtClassLoader()<br />       throws IOException<br />   {<br />       File afile[] = getExtDirs();<br />       return (Launcher$ExtClassLoader)AccessController.doPrivileged(new Launcher$1(afile));<br />   }<br />  private static File[] getExtDirs() {<br />       //获得系统属性“java.ext.dirs”<br />       String s = System.getProperty("java.ext.dirs");<br />       File afile[];<br />       if(s != null) {<br />           StringTokenizer stringtokenizer = new StringTokenizer(s, File.pathSeparator);<br />           int i = stringtokenizer.countTokens();<br />           afile = new File;<br />           for(int j = 0; j &lt; i; j++)<br />               afile[j] = new File(stringtokenizer.nextToken());<br /><br />       } else {<br />           afile = new File[0];<br />       }<br />       return afile;<br />   }<br />}<br /><br />system classloader的部分代码：<br />static class Launcher$AppClassLoader extends URLClassLoader<br />{<br /><br />   public static ClassLoader getAppClassLoader(ClassLoader classloader)<br />       throws IOException<br />   {<br />       //获得系统属性“java.class.path”<br />       String s = System.getProperty("java.class.path");<br />       File afile[] = s != null ? Launcher.access$200(s) : new File[0];<br />       return (Launcher$AppClassLoader)AccessController.doPrivileged(new Launcher$2(s, afile, classloader));<br />   }<br />}<br /><br />看了源代码大家就清楚了吧，extension classloader是使用系统属性“java.ext.dirs”设置类搜索路径的，并且没有parent。system classloader是使用系统属性“java.class.path”设置类搜索路径的，并且有一个parent classloader。Launcher初始化extension classloader，system classloader，并将system classloader设置成为context classloader，但是仅仅返回system classloader给JVM。<br /><br />　　这里怎么又出来一个context classloader呢？它有什么用呢？我们在建立一个线程Thread的时候，可以为这个线程通过setContextClassLoader方法来指定一个合适的classloader作为这个线程的context classloader，当此线程运行的时候，我们可以通过getContextClassLoader方法来获得此context classloader，就可以用它来载入我们所需要的Class。默认的是system classloader。利用这个特性，我们可以“打破”classloader委托机制了，父classloader可以获得当前线程的context classloader，而这个context classloader可以是它的子classloader或者其他的classloader，那么父classloader就可以从其获得所需的 Class，这就打破了只能向父classloader请求的限制了。这个机制可以满足当我们的classpath是在运行时才确定,并由定制的 classloader加载的时候,由system classloader(即在jvm classpath中)加载的class可以通过context classloader获得定制的classloader并加载入特定的class(通常是抽象类和接口,定制的classloader中是其实现),例如web应用中的servlet就是用这种机制加载的.<br /><br /><br />好了，现在我们了解了classloader的结构和工作原理，那么我们如何实现在运行时的动态载入和更新呢？只要我们能够动态改变类搜索路径和清除classloader的cache中已经载入的Class就行了，有两个方案，一是我们继承一个classloader，覆盖loadclass方法，动态的寻找Class文件并使用defineClass方法来；另一个则非常简单实用，只要重新使用一个新的类搜索路径来new一个classloader就行了，这样即更新了类搜索路径以便来载入新的Class，也重新生成了一个空白的cache(当然,类搜索路径不一定必须更改)。噢，太好了，我们几乎不用做什么工作，java.netURLClassLoader正是一个符合我们要求的classloader！我们可以直接使用或者继承它就可以了！<br /><br />这是j2se1.4 API的doc中URLClassLoader的两个构造器的描述：<br />URLClassLoader(URL[] urls)<br />         Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader.<br />URLClassLoader(URL[] urls, ClassLoader parent)<br />         Constructs a new URLClassLoader for the given URLs.<br />其中URL[] urls就是我们要设置的类搜索路径，parent就是这个classloader的parent classloader，默认的是system classloader。<br /><br /><br />好，现在我们能够动态的载入Class了，这样我们就可以利用newInstance方法来获得一个Object。但我们如何将此Object造型呢？可以将此Object造型成它本身的Class吗？<br /><br />首先让我们来分析一下java源文件的编译，运行吧！javac命令是调用“JAVA_HOME/lib/tools.jar”中的“com.sun.tools.javac.Main”的compile方法来编译：<br /><br />   public static int compile(String as[]);<br /><br />   public static int compile(String as[], PrintWriter printwriter);<br /><br />返回0表示编译成功，字符串数组as则是我们用javac命令编译时的参数，以空格划分。例如：<br />javac -classpath c:\foo\bar.jar;. -d c:\ c:\Some.java<br />则字符串数组as为{"-classpath","c:\\foo\\bar.jar;.","-d","c:\\","c:\\Some.java"}，如果带有PrintWriter参数，则会把编译信息出到这个指定的printWriter中。默认的输出是System.err。<br /><br />其中 Main是由JVM使用Launcher初始化的system classloader载入的，根据全盘负责原则，编译器在解析这个java源文件时所发现的它所依赖和引用的所有Class也将由system classloader载入，如果system classloader不能载入某个Class时，编译器将抛出一个“cannot resolve symbol”错误。<br /><br />所以首先编译就通不过，也就是编译器无法编译一个引用了不在CLASSPATH中的未知Class的java源文件，而由于拼写错误或者没有把所需类库放到CLASSPATH中，大家一定经常看到这个“cannot resolve symbol”这个编译错误吧！<br /><br />其次，就是我们把这个Class放到编译路径中，成功的进行了编译，然后在运行的时候不把它放入到CLASSPATH中而利用我们自己的 classloader来动态载入这个Class，这时候也会出现“java.lang.NoClassDefFoundError”的违例，为什么呢？<br /><br />我们再来分析一下，首先调用这个造型语句的可执行的Class一定是由JVM使用Launcher初始化的system classloader载入的，根据全盘负责原则，当我们进行造型的时候，JVM也会使用system classloader来尝试载入这个Class来对实例进行造型，自然在system classloader寻找不到这个Class时就会抛出“java.lang.NoClassDefFoundError”的违例。<br /><br />OK，现在让我们来总结一下，java文件的编译和Class的载入执行，都是使用Launcher初始化的system classloader作为类载入器的，我们无法动态的改变system classloader，更无法让JVM使用我们自己的classloader来替换system classloader，根据全盘负责原则，就限制了编译和运行时，我们无法直接显式的使用一个system classloader寻找不到的Class，即我们只能使用Java核心类库，扩展类库和CLASSPATH中的类库中的Class。<br /><br />还不死心！再尝试一下这种情况，我们把这个Class也放入到CLASSPATH中，让system classloader能够识别和载入。然后我们通过自己的classloader来从指定的class文件中载入这个Class（不能够委托 parent载入，因为这样会被system classloader从CLASSPATH中将其载入），然后实例化一个Object，并造型成这个Class，这样JVM也识别这个Class（因为 system classloader能够定位和载入这个Class从CLASSPATH中），载入的也不是CLASSPATH中的这个Class，而是从 CLASSPATH外动态载入的，这样总行了吧！十分不幸的是，这时会出现“java.lang.ClassCastException”违例。<br /><br />为什么呢？我们也来分析一下，不错，我们虽然从CLASSPATH外使用我们自己的classloader动态载入了这个Class，但将它的实例造型的时候是JVM会使用system classloader来再次载入这个Class，并尝试将使用我们的自己的classloader载入的Class的一个实例造型为system classloader载入的这个Class（另外的一个）。大家发现什么问题了吗？也就是我们尝试将从一个classloader载入的Class的一个实例造型为另外一个classloader载入的Class，虽然这两个Class的名字一样，甚至是从同一个class文件中载入。但不幸的是JVM 却认为这个两个Class是不同的，即JVM认为不同的classloader载入的相同的名字的Class（即使是从同一个class文件中载入的）是不同的！这样做的原因我想大概也是主要出于安全性考虑，这样就保证所有的核心Java类都是system classloader载入的，我们无法用自己的classloader载入的相同名字的Class的实例来替换它们的实例。<br /><br />看到这里，聪明的读者一定想到了该如何动态载入我们的Class，实例化，造型并调用了吧！<br /><br />那就是利用面向对象的基本特性之一的多形性。我们把我们动态载入的Class的实例造型成它的一个system classloader所能识别的父类就行了！这是为什么呢？我们还是要再来分析一次。当我们用我们自己的classloader来动态载入这我们只要把这个Class的时候，发现它有一个父类Class，在载入它之前JVM先会载入这个父类Class，这个父类Class是system classloader所能识别的，根据委托机制，它将由system classloader载入，然后我们的classloader再载入这个Class，创建一个实例，造型为这个父类Class，注意了，造型成这个父类 Class的时候（也就是上溯）是面向对象的java语言所允许的并且JVM也支持的，JVM就使用system classloader再次载入这个父类Class，然后将此实例造型为这个父类Class。大家可以从这个过程发现这个父类Class都是由 system classloader载入的，也就是同一个class loader载入的同一个Class，所以造型的时候不会出现任何异常。而根据多形性，调用这个父类的方法时，真正执行的是这个Class（非父类 Class）的覆盖了父类方法的方法。这些方法中也可以引用system classloader不能识别的Class，因为根据全盘负责原则，只要载入这个Class的classloader即我们自己定义的 classloader能够定位和载入这些Class就行了。<br /><br />这样我们就可以事先定义好一组接口或者基类并放入CLASSPATH中，然后在执行的时候动态的载入实现或者继承了这些接口或基类的子类。还不明白吗？让我们来想一想Servlet吧，web application server能够载入任何继承了Servlet的Class并正确的执行它们，不管它实际的Class是什么，就是都把它们实例化成为一个Servlet Class，然后执行Servlet的init，doPost，doGet和destroy等方法的,而不管这个Servlet是从web- inf/lib和web-inf/classes下由system classloader的子classloader(即定制的classloader)动态载入。说了这么多希望大家都明白了。在applet,ejb等容器中,都是采用了这种机制.<br /><br />对于以上各种情况，希望大家实际编写一些example来实验一下。<br /><br />最后我再说点别的， classloader虽然称为类加载器，但并不意味着只能用来加载Class，我们还可以利用它也获得图片，音频文件等资源的URL，当然，这些资源必须在CLASSPATH中的jar类库中或目录下。我们来看API的doc中关于ClassLoader的两个寻找资源和Class的方法描述吧：<br />　　　　　　　　public URL getResource(String name)<br />　　　　　　　　用指定的名字来查找资源，一个资源是一些能够被class代码访问的在某种程度上依赖于代码位置的数据（图片，音频，文本等等）。<br />               一个资源的名字是以'/'号分隔确定资源的路径名的。<br />               这个方法将先请求parent classloader搜索资源，如果没有parent，则会在内置在虚拟机中的classloader（即bootstrap classloader）的路径中搜索。如果失败，这个方法将调用findResource(String)来寻找资源。<br />　　　　　　　　public static URL getSystemResource(String name)<br />               从用来载入类的搜索路径中查找一个指定名字的资源。这个方法使用system class loader来定位资源。即相当于ClassLoader.getSystemClassLoader().getResource(name)。<br /><br />例如：<br />   System.out.println(ClassLoader.getSystemResource("java/lang/String.class"));<br />的结果为：<br />   jar:文件:/C:/j2sdk1.4.1_01/jre/lib/rt.jar!/java/lang/String.class<br />表明String.class文件在rt.jar的java/lang目录中。<br />因此我们可以将图片等资源随同Class一同打包到jar类库中（当然，也可单独打包这些资源）并添加它们到class loader的搜索路径中，我们就可以无需关心这些资源的具体位置，让class loader来帮我们寻找了！<br /></span>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/pandawang/aggbug/64639.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-08-20 17:28 <a href="http://www.blogjava.net/pandawang/archive/2006/08/20/64639.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于RCP的GEF编辑器中RetargetAction的注册问题</title><link>http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sat, 19 Aug 2006 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/64532.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/64532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/64532.html</trackback:ping><description><![CDATA[最近做的gef编辑器在删除时遇到了一些问题,就是不能通过delete键删除,到处搜集资料,解决了,<br />首先需要在相应rcp工程中的ActionBarAdviser类中注册相应的Action,比如对应于deleteAction,我在方法org.eclipse.ui.application.ActionBarAdvisor#makeAction(IWorkbenchWindow)中注册deleteAction,如下:<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_56_144_Open_Image" onclick="this.style.display='none'; Codehighlighter1_56_144_Open_Text.style.display='none'; Codehighlighter1_56_144_Closed_Image.style.display='inline'; Codehighlighter1_56_144_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_56_144_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_56_144_Closed_Text.style.display='none'; Codehighlighter1_56_144_Open_Image.style.display='inline'; Codehighlighter1_56_144_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> makeAction(</span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> IWorkbenchWindow window)</span><span id="Codehighlighter1_56_144_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_56_144_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    IAction delAction </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ActionFactory.DELETE.create(window);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    register(delAction);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><br />只是这么设置还是不能删除相应的图形元素,需要在相应的编辑器中重载init方法,添加如下的代码<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_80_378_Open_Image" onclick="this.style.display='none'; Codehighlighter1_80_378_Open_Text.style.display='none'; Codehighlighter1_80_378_Closed_Image.style.display='inline'; Codehighlighter1_80_378_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_80_378_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_80_378_Closed_Text.style.display='none'; Codehighlighter1_80_378_Open_Image.style.display='inline'; Codehighlighter1_80_378_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> init(IEditorSite site, IEditorInput input) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> PartInitException </span><span id="Codehighlighter1_80_378_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_80_378_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> TODO Auto-generated method stub</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">super</span><span style="COLOR: #000000">.init(site, input);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    ActionRegistry registry </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> getActionRegistry();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    IActionBars bar </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> site.getActionBars();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    String id </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ActionFactory.DELETE.getId();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    bar.setGlobalActionHandler(id,registry.getAction(id));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    bar.updateActionBars();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br />在这里仔细研究会发现,在第一段代码中实际上时创建了一个action,这是一个RetargetAction,而在super.init()方法会调用一个createAction方法,这里创建的是gef默认的redoAction undoAction selectionAction deleteAction saveAction.需要注意的是RetargetAction是一种可以跟踪当前活动的部分,由于retargetAction含有一个id,如果这个活动部分提供的handler的id和retargetAction的id相同,那么相应的对retargetAction的调用就转嫁成对当前这个活动部分的handle的调用,(当然如果根本就没有handle,那么这个action会disable).所以,我们可以看出来,这个retargetAction会在gef编辑器激活后调用gef的deleteAction.<img src ="http://www.blogjava.net/pandawang/aggbug/64532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-08-19 17:35 <a href="http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载][备份][Java|Eclipse|GEF]Figure是如何定位和设置大小？ </title><link>http://www.blogjava.net/pandawang/archive/2006/08/14/63424.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Mon, 14 Aug 2006 03:18:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/08/14/63424.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/63424.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/08/14/63424.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/63424.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/63424.html</trackback:ping><description><![CDATA[
		<h3 class="post-title">
				<a href="http://www.approc.com/">http://www.approc.com/</a>
		</h3>
		<h3 class="post-title">[Java|Eclipse|GEF]Figure是如何定位和设置大小？ </h3>
		<div class="post-body">
				<div>
						<div style="CLEAR: both">
						</div>有两种会创建图元：<br />1、打开图形文件时，先会创建所有的model，这样图元的定位和设置大小是依据图元model的size和location属性，通过图元EditPart.refreshVisuals()来设置的<br />2、通过拖放托盘里面的图标来建立的图元，会先设置model的size，然后通过model对应的figure.setPreferredSize()来设置了，而location则是通过鼠标的位置来确定的</div>
		</div>
<img src ="http://www.blogjava.net/pandawang/aggbug/63424.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-08-14 11:18 <a href="http://www.blogjava.net/pandawang/archive/2006/08/14/63424.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载][备份][Java|Eclipse]用NLS的方式访问资源文件 </title><link>http://www.blogjava.net/pandawang/archive/2006/08/14/63423.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Mon, 14 Aug 2006 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/08/14/63423.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/63423.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/08/14/63423.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/63423.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/63423.html</trackback:ping><description><![CDATA[
		<div style="CLEAR: both">
		</div>
		<a href="http://www.approc.com/">http://www.approc.com/</a>
		<br />现在在3.1里面访问资源文件变得比较简单了，用户可以通过继承osgi.util.NLS，典型例子：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_35_302_Open_Image" onclick="this.style.display='none'; Codehighlighter1_35_302_Open_Text.style.display='none'; Codehighlighter1_35_302_Closed_Image.style.display='inline'; Codehighlighter1_35_302_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_35_302_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_35_302_Closed_Text.style.display='none'; Codehighlighter1_35_302_Open_Image.style.display='inline'; Codehighlighter1_35_302_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> MsgBoundle </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> NLS</span><span id="Codehighlighter1_35_302_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_35_302_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> String BOUNDLE_NAME <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                       </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">resource.msg</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> String mo_1;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> String mo_2;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_205_300_Open_Image" onclick="this.style.display='none'; Codehighlighter1_205_300_Open_Text.style.display='none'; Codehighlighter1_205_300_Closed_Image.style.display='inline'; Codehighlighter1_205_300_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_205_300_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_205_300_Closed_Text.style.display='none'; Codehighlighter1_205_300_Open_Image.style.display='inline'; Codehighlighter1_205_300_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">static</span><span id="Codehighlighter1_205_300_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_205_300_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         NLS.initializeMessage(BOUNDLE_NAME,<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                       MsgBoundle.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />      }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br /><br />好啦，现在就可以建立资源文件了，文件应该建在哪里呢？跟踪代码发现，这个由BOUNDLE_NAME决定，在MessageResourceBoundle.buildVariants()中，会将BOUNDLE_NAME中的“."替换成"/"，然后再根据地区设定组合几种不同的资源文件名称，比如我的就是:<br /><br />1、resource/msg_zh_CN.properties<br />2、resource/msg_zh.properties<br />3、resource/msg.properties<br />注意：这三个文件是有顺序的哦<br /><br />然后通过EclipseClassLoader.getResource()来<a onclick="return false;" href="javascript:void(0);"><strong><font color="#4386ce"></font></strong></a>查找这些文件，并将文件中的值赋予给MsgBoundle对应的成员变量。<img src ="http://www.blogjava.net/pandawang/aggbug/63423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-08-14 11:16 <a href="http://www.blogjava.net/pandawang/archive/2006/08/14/63423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下引入Plugin-Project的一个问题</title><link>http://www.blogjava.net/pandawang/archive/2006/07/19/58924.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Wed, 19 Jul 2006 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/07/19/58924.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/58924.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/07/19/58924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/58924.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/58924.html</trackback:ping><description><![CDATA[在linux（ubuntu）下引入了在windows工作时建立的一个pluginProject，但是发现，在plugin.xml中require包都没有了，在3.0以后这些require都是放在MANIFEST.MF文件中的，这两个文件是同步的，即在编辑plugin.xml文件视图时会看到MANIFEST.MF文件中的require，不过在从windows引入后就看不到了，不过这是发现MANIFEST.MF和他所在的目录META-INF都变成了小写，改成大写后，再update classpath就可以了。<br /><img src ="http://www.blogjava.net/pandawang/aggbug/58924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-07-19 10:26 <a href="http://www.blogjava.net/pandawang/archive/2006/07/19/58924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF中鼠标双击事件的截获</title><link>http://www.blogjava.net/pandawang/archive/2006/06/08/51513.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 08 Jun 2006 14:21:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/06/08/51513.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/51513.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/06/08/51513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/51513.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/51513.html</trackback:ping><description><![CDATA[
		<span class="tpc_content">
				<a href="http://dev.eclipse.org/mhonarc/lists/gef-dev/msg00183.html" target="_blank">
						<font color="#663366" size="2">http://dev.eclipse.org/mhonarc/lists/gef-dev/msg00183.html</font>
				</a>
				<font size="2">
						<br />Ask:<br />How to add a double click event or Request on a figure?when double click on a figure, a dialog pop up and do some actions.for example when double click on<br />a UML class figure, a dialog pop up, user can Add a method to the class.<br />Answer:<br />This is already done in GEF. Your editpart will receive a performRequest(req) with the type RequestConstants.REQ_OPEN. <br />See SelectEditPartTRacker#performOpen() <br /><br />-randy <br />就是在figure对应的editpart中重载方法performRequest(Request req),并判断req的type是否为RequestConstants.REQ_OPEN,如果是,则处理这个双击事件.<br />这个方法是个回调方法,在SelectEditPartTRacker#performOpen() 中调用的.</font>
		</span>
<img src ="http://www.blogjava.net/pandawang/aggbug/51513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-06-08 22:21 <a href="http://www.blogjava.net/pandawang/archive/2006/06/08/51513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF中容器图形的坐标问题</title><link>http://www.blogjava.net/pandawang/archive/2006/05/15/46203.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Mon, 15 May 2006 06:04:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/05/15/46203.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/46203.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/05/15/46203.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/46203.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/46203.html</trackback:ping><description><![CDATA[在GEF中一个容器图形,其中可以盛放其他图形,但我在实现是总是在坐标计算上出问题,就是其子图形的坐标并不是相对于此容器的坐标,而是画布的坐标,后来参考了Logical的例子,发现它在org.eclipse.gef.examples.logicdesigner.figures.CircuitFigure类中重载了useLocalCoordinates方法,返回了true(默认是false),在我的容器图形(继承于org.eclipse.draw2d.Figure)也重载这个函数,子图形的坐标问题就解决了.<img src ="http://www.blogjava.net/pandawang/aggbug/46203.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-05-15 14:04 <a href="http://www.blogjava.net/pandawang/archive/2006/05/15/46203.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse中获得插件绝对路径的方法</title><link>http://www.blogjava.net/pandawang/archive/2006/05/01/44313.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Mon, 01 May 2006 14:45:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/05/01/44313.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/44313.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/05/01/44313.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/44313.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/44313.html</trackback:ping><description><![CDATA[获得插件的绝对路径:<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_1_42_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1_42_Open_Text.style.display='none'; Codehighlighter1_1_42_Closed_Image.style.display='inline'; Codehighlighter1_1_42_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_1_42_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1_42_Closed_Text.style.display='none'; Codehighlighter1_1_42_Open_Image.style.display='inline'; Codehighlighter1_1_42_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #000000">    </span><span id="Codehighlighter1_1_42_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/** */</span><span id="Codehighlighter1_1_42_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />     * 得到插件的绝对路径<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />     * <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />     * </span><span style="COLOR: #808080">@return</span><span style="COLOR: #008000"> 路径<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />     </span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_76_343_Open_Image" onclick="this.style.display='none'; Codehighlighter1_76_343_Open_Text.style.display='none'; Codehighlighter1_76_343_Closed_Image.style.display='inline'; Codehighlighter1_76_343_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_76_343_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_76_343_Closed_Text.style.display='none'; Codehighlighter1_76_343_Open_Image.style.display='inline'; Codehighlighter1_76_343_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> String getPath() </span><span id="Codehighlighter1_76_343_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_76_343_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        String path;<br /><img id="Codehighlighter1_99_259_Open_Image" onclick="this.style.display='none'; Codehighlighter1_99_259_Open_Text.style.display='none'; Codehighlighter1_99_259_Closed_Image.style.display='inline'; Codehighlighter1_99_259_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_99_259_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_99_259_Closed_Text.style.display='none'; Codehighlighter1_99_259_Open_Image.style.display='inline'; Codehighlighter1_99_259_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id="Codehighlighter1_99_259_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_99_259_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            path </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> FileLocator.toFileURL(<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                    Platform.getBundle(pluginId).getEntry(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">)).getPath();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            path </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> path.substring(path.indexOf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">) </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">, path.length());<br /><img id="Codehighlighter1_283_325_Open_Image" onclick="this.style.display='none'; Codehighlighter1_283_325_Open_Text.style.display='none'; Codehighlighter1_283_325_Closed_Image.style.display='inline'; Codehighlighter1_283_325_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_283_325_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_283_325_Closed_Text.style.display='none'; Codehighlighter1_283_325_Open_Image.style.display='inline'; Codehighlighter1_283_325_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (IOException e) </span><span id="Codehighlighter1_283_325_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_283_325_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            path </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            e.printStackTrace();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> path;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div>其中FileLocator#toFileURL是在3.2中添加的,代替了原来的Platform#asLocalURL,并且对于FileLocator#toFileURL,if the plugin was a jar, it will extract the file into a temporary location<br /><img src ="http://www.blogjava.net/pandawang/aggbug/44313.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-05-01 22:45 <a href="http://www.blogjava.net/pandawang/archive/2006/05/01/44313.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF学习小记三</title><link>http://www.blogjava.net/pandawang/archive/2006/04/09/40091.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 09 Apr 2006 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/04/09/40091.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/40091.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/04/09/40091.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/40091.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/40091.html</trackback:ping><description><![CDATA[上文提到的GEF工作过程中还有一些不太详细的地方，这里做些补充。<br />再GEF中UI的操作交互都是通过构建Request，并调用EditPart中的API来完成相应的操作，这些API可以分为四类：<br />1。  <strong><font face="Courier New">EditPart getTargetEditPart(Request)<br />   boolean understandsRequest(Request)<br /></font></strong>再我们进行交互操作时，首先要确定激活的是那个EditPart，经常是一个当前被选中的viewer和通过单击选择的EditPart的复合体。这个被选择的部件通过询问每个被选择的EditPart是否处理这个request（通过understandsRequest方法）。那个在鼠标单击确定的EditPart是通过viewer的帮助和getTargetEditPart方法来找到的。并不是所有的交互都有target。<br />2。<br /><strong><font face="Courier New">void showSourceFeedback(Request)<br />void eraseSourceFeedback(Request)<br />void showTargetFeedback(Request)<br />void eraseTargetFeedback(Request)</font></strong><br />在我们的交互操作特别是托拽图形时，就需要EditPart来回显（Feedback），托拽源被认为是起作用的那个editpart，目的部件被认为是鼠标的目的地。showXXXFeedback可能是在鼠标移到目的地，但未作用于目的part时调用，eraseXXXFeedback则可能是在鼠标作用于目的part后调用的。<br />3。<strong><font face="Courier New">Command getCommand(Request)</font></strong><br />这个方法用于获得可执行的命令列表，命令可以对模型进行操作，Editpart通过request询问Editpolicy来获得相应的command列表。同时command也可以判断这个交互操作是否时可能的。如果没有command或者command不能执行，则ui会指出这个操作是不能执行的（鼠标变成禁止操作的样子）。如果一个editpart返回null作为command则它不会阻止这个交互操作，除非没有一个command被提供。为了指示某个操作是不能执行的则EditPart需要返回一个不能执行的command。<br />4。<strong><font face="Courier New">void performRequest(Request)</font></strong><br />还有一种API，它让EditPart去do something，可能是一些并不会立即就改变model的改变，比如打开对话框或者激活直接编辑模式。<br /><br />        EditPart并不直接进行编辑，它将操作委托给EditPolicy，每个EditPolicy专著于一种编辑任务或者一组相关的操作。当上面的API被调用后（除了performRequest方法），EditPart便委托给它的EditPolicy来处理这个request。对于不同的方法，EditPart可能是在第一个能处理request的policy处就停止调用了或者每个policy都有机会执行这个request。GEF提供了几个默认的policy，不过还是需要实现其中的一些特定方法。<br /><br />         这里再废话一点，在注册相应的EditPolicy时，需要指定Role，这是一个字符串，用来标示这个EditPolicy，相同的Role对应的EditPolicy会被替换，例如子类可以通过Role这个Key来覆盖其父类所安装的EditPolicy。EditPolicy（Role）分成两种类型，一种是图形的，一种是非图形的，上文中有提到，这里详细的描述一下：<br /><strong>Non-Graphical Roles:</strong><br />1) <strong>COMPONENT_ROLE</strong>: 一个Component存在于一个parent中，并且可以从parent中删除。更为一般的，它可以使任何只涉及到这个EditPart，而与View无关的东西。(More generally, it is anything that involves only this EditPart.) <br />2) <strong>CONNECTION_ROLE</strong> 这是ConnectionEditParts应该有的一个基本角色。Connections同Components有一点不同，删除Connections时通常还需要其从其source和target节点中删除，而不是从其parent中删除。 <br />3) <strong>CONTAINER_ROLE</strong> 大部分拥有children的EditParts都应该具有这个角色。一个Container会涉及到adds/orphans以及creates/deletes等操作。 <br />4) <strong>NODE_ROLE</strong> 如果一个EditParts用户Connection，则其应该具有这个角色，它可以用来创建，删除，重新连接一个Connection。 <br /><strong>Graphical Roles:</strong><br />1) <strong>PRIMARY_DRAG_ROLE:</strong> 用来允许用户拖动这个EditPart。用户可以通过点击这个EditPart然后拖动，或者点击这个EditPart所创建的一个Handle来进行拖动。 <br />2) <strong>LAYOUT_ROLE</strong>: Layout角色用来放在一个Container的EditPart上，这个EditPart拥有一个graphical layout。如果这个layout有constraints，则它需要通过计算来得到这个constraints。 <br />3) <strong>GRAPHICAL_NODE_ROLE</strong>: A node supports connections to terminals. When creating and manipulating connections, EditPolicies with this role might analyze a Request's data to perform "hit testing" on the graphical view and determine the semantics of the connection. 用于支持连接到重点的node，当创建、操作连接时，包含这个Role的Editpolicy会分析request的数据，来在图形view上做“hit testing”，并且判断这个connection的语义。<br />4) <strong>CONNECTION_ENDPOINTS_ROLE:</strong> 这个Role允许用户拖动一个ConnectionEditPart的端点。 <br />5) <strong>CONNECTION_BENDPOINTS_ROLE</strong>: 这个Role允许用户能够在一个Connection中间拖动和创建bendpoints。 <br />6) <strong>SELECTION_FEEDBACK_ROLE</strong>: 这个角色只是用来显示feedback。当鼠标进入或者在一个EditPart上暂停时，Selection Tool会发送两个类型的request给EditPart。安装了这个角色的EditPart能够在此时接受这些请求来改变view的样子，或者弹出tip，label等。 <br />7) <strong>TREE_CONTAINER_ROLE</strong>: SWT Tree的Layout Role。 本地SWT Tree的Layout Role的等价物。这个EditPolicy应该在树上显示反馈并计算索引，就像在file explorer里拖拽一样。<br />over。<br /><br /><img src ="http://www.blogjava.net/pandawang/aggbug/40091.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-04-09 14:38 <a href="http://www.blogjava.net/pandawang/archive/2006/04/09/40091.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF学习小记二</title><link>http://www.blogjava.net/pandawang/archive/2006/04/09/40078.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 09 Apr 2006 04:33:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/04/09/40078.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/40078.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/04/09/40078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/40078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/40078.html</trackback:ping><description><![CDATA[        GEF中的起到关键作用的是EditPart，而EditPart中起到关键作用的是EditPolicy，现在来描述一下GEF是如何创建一个图形并显示显示出来的。<br />        首先通过单击调色板，会调用一个实现org.eclipse.gef.requests.CreationFactory接口的工厂类，这个是我们在注册相应的ToolEntry时声明的，通过传入的参数这个工厂类就知道应该创建一个什么类型的model元素。（注意，这时候因为我们只是纯创建了一个模型元素，对于它的父元素，位置信息等等都还不清楚，所以一般我们在设置模型元素的构造函数时需要有个无参数的构造方法（或者有默认参数的构造函数）。）<br />        当单击画布上的某个位置后，相应的信息比如 模型的父元素，位置信息等等都已经可以确定，将这些信息以及新创建的模型元素本身包装成request传给相应的EditPart（就是鼠标单击处所在的图形元素对应的EditPart）。<br />        这个EditPart会将这个request传给相应的EditPolicy（至于怎么传递，还不清楚，估计是这样的，EditPart会传给注册在其上的所有EditPolicy，而每个EditPolicy都有个getCommand方法，通过request的type交给相应的getXXXCommand方法。查看了一下源代码，发现在AbastractEditPart中有个getCommand方法正是将每个EditPolicy中的getCommand方法都调用了一遍）。<br />       然后EditPolicy处理相应的request，具体的就是调用getXXXCommad方法得到处理相应request的Command，Command是可以改变模型。上面提到的这种EditPolicy属于NonGraphical类型，GEF中还包括了一种称为Graphical类型的EditPolicy，这种EditPolicy不对模型进行处理，只是用来修改图形显示（似乎这种说法不正确，它可以更改视图元素的位置，在业务模型和视图模型统一的情况下，这种图形EditPolicy也会更改模型）；而NonGraphical的EditPolicy则是不清楚图形元素的，但它可以对模型进行更改，因此这种EditPolicy在不同view之间是可以通用的。<br />       当模型发生改变后，注册再其上的EditPart将会得到相应的通知，此时，通过通知中的property信息，EditPart会refreshVisual或者refreshChildren，从而使视图发生改变。<img src ="http://www.blogjava.net/pandawang/aggbug/40078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-04-09 12:33 <a href="http://www.blogjava.net/pandawang/archive/2006/04/09/40078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gef学习小记一</title><link>http://www.blogjava.net/pandawang/archive/2006/02/23/32212.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 23 Feb 2006 14:40:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/02/23/32212.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/32212.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/02/23/32212.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/32212.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/32212.html</trackback:ping><description><![CDATA[Draw2D学习<BR>Draw2D is a lightweight system.轻量级系统，指这个绘图系统全部建立在一个重量级的控件上。对于Draw2D他是建立在SWT的Canvas上的。<BR>Draw2D的几个部分<BR>1.figures<BR>主要功能：<BR>&nbsp;&nbsp; 1。给一个figure注册和去注册监听器。这个figure会通知在这个figure中的鼠标时间给监听器。<BR>&nbsp;&nbsp; 2。结构化的事件。比如figure层次的结构化变化，figure的移动和大小调整。<BR>&nbsp;&nbsp; 3。当光标从figure上移过时，光标的改变和显示。<BR>&nbsp;&nbsp; 4。在figure的层次中操作figure的位置，包括添加移除访问子节点，或者访问他们的父节点。<BR>&nbsp;&nbsp; 5。存取：figure的layout manager；figure的size和location；还有tooltips。<BR>&nbsp;&nbsp; 6。设置获得焦点。<BR>&nbsp;&nbsp; 7。设置figure的透明度和可视性。<BR>&nbsp;&nbsp; 8。进行坐标变换，figure的交叠和碰撞检测。<BR>&nbsp;&nbsp; 9。绘制。<BR>&nbsp;&nbsp; 10。确认。<BR>figure有很多subclass，提供了很多附加的功能。比如<BR>&nbsp; 1。shape，它包含了非矩形的figure，可以知道如何填充，并提供了对边界的宽和类型的配置，并提供了异或的绘制方法。比如有椭圆，几何线，多边形，矩形，圆角矩形和三角形。<BR>&nbsp; 2。widget，draw2d包含的figure允许你创建轻量级（lightweight）的部件（widget），从而在你的draw2d应用程序中需要输入控制时提供支持。这包含大量的按钮，选择框和文本图形，标签。<BR>&nbsp; 3。layer and pane，这些使用来作为子类的容器，他们提供了缩放，滚动和讲figure放置在不同layer上的能力。<BR>图形上下文(the graphics context)<BR>&nbsp; 当一个figuer需要被绘制的时候轻量系统会调用fiuger的一个paint方法。每一个figure都会得到一个graphical context，他是Graphics的一个实例。作为参数传给paint方法。这个绘图上下文支持图形操作包括绘制，填充图形绘制它的文字。它也提供了图形的状态，这些可以影响图形操作。这些状态包括当前字体，背景前景颜色等等。<BR>2.LightweightSystem<BR>LightweightSystem时draw2d的核心。它提供了SWT Canvas控件和在其上建立的draw2d系统之间的映射。包含三个方面：<BR>&nbsp; 1。the root figure.这个是LightweightSystem$RootFigure类的一个实例。这个是用户的root figure的父类。它继承了一些基于SWT Canvas的图形环境，比如字体，前景背景颜色。<BR>&nbsp; 2。the event dispatcher:SWTEventDispatcher类将SWT事件传给Draw2D的root figure中相应的部件。<BR>&nbsp; 3。the update manager.它负责绘制并更新Draw2dfigure。当一个绘制请求从下层的SWTcanvas传来时，LightWeightSystem将会调用updatemanager中的performUpdate方法。update manager将会维护一个非法的或者需要重画的figure的worklist。upate manager会设法尽量连续的它的work list，这样可以尽量的提高效率。默认的update manager：DaferredUpdateManager允许通过再Display上的用户线程来使工作队列异步的更新。<BR>对于一个figure的生存周期中，绘制(painting)和确认(validating)是主要的处理过程。draw2d会要求一个figure，调用绘制方法来递归的绘制自己。paint()方法会调用多个绘制方法：<BR>&nbsp; 1。paintFigure()：figure递归的绘制自己<BR>&nbsp; 2。paintclientarea(): figure递归的绘制子图<BR>&nbsp; 3。paintborder():figure绘制边界。<BR>&nbsp;当一个figure的size或者location需要重新计算时，将会调用确认。<BR>&nbsp; 1。validate()：要求figure的layout manager去重新布局它的子图<BR>&nbsp; 2。revalidate():调用invalidate；添加一个图形和它的祖先去更新update manager的invalid list。<BR><img src ="http://www.blogjava.net/pandawang/aggbug/32212.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-02-23 22:40 <a href="http://www.blogjava.net/pandawang/archive/2006/02/23/32212.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EMF学习小记二</title><link>http://www.blogjava.net/pandawang/archive/2006/02/19/31541.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 19 Feb 2006 12:46:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/02/19/31541.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/31541.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/02/19/31541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/31541.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/31541.html</trackback:ping><description><![CDATA[<P><BR>现在来讨论一下emf所生成的几个plugin。一般通过ecore模型可以生成三个插件分别是emf模型，emf.edit和emf.editor。<BR>让我们现在看模型插件<BR>&nbsp;&nbsp;&nbsp; 对于所有的EPackage，都会生成两个或三个java package，本别是base package(*)，implemention package(*.impl),tool package(*.util)。其中，第三个包是可选的，这取决于生成属性的设置，默认是生成。包名(*)也是在生成属性中设置的。<BR>&nbsp;&nbsp;&nbsp; 对于所有EClass，在base package中生成相应的interface，而其java实现则在impl包中，如果一个EClass继承于另一个EClass，那么生成的interface和implemention都继承于相应的超类的interface和implemention。如果这个类有多个超类，那么在eSuperTypes中的第一个class将作为主超类(primary supertype)。对于这个子类的实现它将继承主超类的实现，并且实现其他超类接口中的方法。<BR>&nbsp;&nbsp;&nbsp; 对于Feature，getter和setter方法在类和接口中被定义。如果一个一个feature（成员变量）不是volatile，那么它的值会被存储在一个量值（field）中。如果一个feature是只读的，那么只生成它对应的getter方法。对于多值属性一般使用EList表示，而单值就用那个属性的类型表示。EList的类型取决于模型的约束，例如，一个non-containment reference将会使用EObjectWithInverseResolvingEList,对于一个containment reference将会使用EObjectContainmentWithInverseEList表示。<BR>&nbsp;&nbsp;&nbsp; 对于Operation，在包含类(containing class)的接口中生成一个公共方法标签，在对应的实现中生成实现骨架。<BR>&nbsp;&nbsp;&nbsp; 对于DataType，其中EEnum产生于一个继承了org.eclipse.common.util.AbstractEnumerator的实现。对于其他的EDataType，是没有接口和实现生成的，它们的实例化类就是直接使用了EAttribute的类型。<BR>再来看看edit插件：<BR>&nbsp;&nbsp;&nbsp; 对于edit插件provider package中的所有类都有相应的ItemProviders类生成。更进一步，对于整个插件有一个EMFPluginClass生成。ItemProvider类继承于org.eclipse.emf.edit.provider.ItemProviderAdaptor，用于适配模型中相应的EObject（所有emf类的基类）。当模型对象由于fireNotifyChanged()改变，ItemProvider会传送相应的通知，并过滤其他的。当你生成插件时，你可以控制哪些通知被过滤。<BR>&nbsp;&nbsp;&nbsp; ItemProvider也管理属性描述（property descriptors）对于所有的featur of the class，通过getImage和getText方法来管理类的icon和descrition。<BR>&nbsp;&nbsp;&nbsp; 对于所有的ItemProvider都有一个ItemProviderAdaptorFactory。<BR>最后时editor插件：<BR>&nbsp;&nbsp;&nbsp; 对于所有的模型都会再presentation package中生成三个类。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 一个多页编辑器，它给模型创建几个不同的jface viewer，包含一个TreeViewer，使用edit插件中的ItemProvider作为这个treeviewer的content和label的provider。这个editor还创建outline和property来显示在viewer中选中对象的属性。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 一个ActionBarContributor，它被用于对编辑器视图中选中的item所创建的context menu添加选项。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 最后是一个向导，允许你创建一个包含模型对象的一个实例的资源(resource)。</P>
<P>&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;</P><img src ="http://www.blogjava.net/pandawang/aggbug/31541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-02-19 20:46 <a href="http://www.blogjava.net/pandawang/archive/2006/02/19/31541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EMF学习笔记一</title><link>http://www.blogjava.net/pandawang/archive/2006/02/19/31472.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 19 Feb 2006 07:32:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/02/19/31472.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/31472.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/02/19/31472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/31472.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/31472.html</trackback:ping><description><![CDATA[<P>EMF中的三个部分：元数据meta-data,代码生成code generation,默认序列化default serialization.<BR>EMF is part of the Model Driver Architecture(MDA).MDA是将整个应用软件生存周期的开发管理都集中于模型上。这种模型是用元模型(meta-model)定义的。然后，使用映射，模型被用于生成software artefacts, 这就实现了整个系统。<BR>EMF所能做的：emf能够用于描述和构建模型。所实现的模型可以被用于任何java应用程序的开发。<BR>对于ecore模型我们有几点需要注意：<BR>1。在ecore文件的xmi描述中没有各个元素之间的联系，我们使用EReference来表示各个元素之间的联系。<BR>&nbsp;&nbsp; 对于两个方向上的联系，通过两个成对的EReference来表示，每个联系的类，都有一个eOpposite来保存它自己在所联系类中的名字（引用）。<BR>&nbsp;&nbsp; 对于单方向上的联系，使用一个单独的EReference，并且这个reference没有eOpposite（因为对方并没有对自己的引用）。<BR>&nbsp;&nbsp; 连接的多重性通过upperBound和lowerBound来表示。多个用-1。<BR>2。使用EPackage可以像java中的package一样用。<BR>3。两种模型，一种是业务模型，一种是视图模型。一般将两种模型放在不同的package中。两种方法将两种模型联系起来：<BR>&nbsp;&nbsp; 一是构建一个新package，构建一个多重继承的新package来将两个package联系起来。<BR>&nbsp;&nbsp; 二是将两种模型分开存储，添加从视图模型到业务模型的引用。这种方法两个模型是松耦合的。这种单方向的引用也不会破坏（污染）业务模型。注意，由于这种引用是两个package之间的，所以在移用的eType类型中需要指明包名。&nbsp;&nbsp; </P>
<P>除此之外，ecore还提供了一种递归的定义方法。就是使用eSubPackage来分别包含业务模型和视图模型，并且在这两个subPackage间建立reference（对于package来说是自己引用自己）。<BR>4。我们可以有多种方法来生成ecore模型。通过注释的java接口(annotated java interface),通过rantional rose创建模型，通过XML Schema等等。</P><img src ="http://www.blogjava.net/pandawang/aggbug/31472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-02-19 15:32 <a href="http://www.blogjava.net/pandawang/archive/2006/02/19/31472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GMF学习小记二 Step by step</title><link>http://www.blogjava.net/pandawang/archive/2006/02/15/30760.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Wed, 15 Feb 2006 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/02/15/30760.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/30760.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/02/15/30760.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/30760.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/30760.html</trackback:ping><description><![CDATA[上文已经说过了，GMF中，那些generator,definition,mapping model都是最后要合成为diagram runtime(or notation)model。<BR>以下是简单的步骤：<BR>简单的使用方法，首先应该定义ecore模型文件有很多种方法，比如用EclipseUML插件，或者使用gmf的example种的Ecore Diagram，这些图形化的类图编辑工具都可以方便的生成我们所需要的Ecore文件。这里我们使用的是EclipseUML的免费版本。是针对eclipse3.1的，不过好像3.2m1m2都可以用。<BR>生成ecore文件后 File/new/other/Eclipse Modeling Framwork/EMF Model 生成相应的genmodel文件，通过它来生成模型和.edit插件，这些都是GMF所需要的。然后再File/New/other/Example EMF Model Creation Wizards/GMFGraph Model 注意名字应该都是一样的（扩展名不同）最后的Model Object选择Canvas。在生成的gmfgraph文件中给canvas命名，canvas就相当于我们的画布。在canvas下创建一个figure gallery（图库），在这里我们保存所需要的图形。<BR>然后创建gmftool文件File/New/other/Example EMF Model Creation Wizards/GMFTool Model，可以使用File/New/other/GMF/GMFTool Simple Model来简单的构造。<BR>再创建gmfmap文件，建立模型和图形之间的映射关系。File/New/other/Example EMF Model Creation Wizards/GMFMap Model，名字应该和前面的一样，最后的Model Object选择Mapping。在生成的gmfmap文件中右键选择Load Resource，选择ecore，gmfgraph，gmftool文件。并且生成相应的映射信息，比如node mapping和canvas mapping。<BR>最后生成emf模型代码和edit代码，使用genmodel文件。<BR>使用gmfmap文件右键生成gmfgen文件，注意我们要有genmode文件才能生成gmfgen文件。<BR>最后用gmfgen生成editor插件。这时候共有三个插件 模型 edit和editor。<BR>使用时File/New/other/Example/中有个相应的diagram，一般再最上面，给一个名字，无扩展名，就打开相应的编辑器了。<img src ="http://www.blogjava.net/pandawang/aggbug/30760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-02-15 10:37 <a href="http://www.blogjava.net/pandawang/archive/2006/02/15/30760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GMF学习小记一</title><link>http://www.blogjava.net/pandawang/archive/2006/02/14/30564.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Tue, 14 Feb 2006 03:38:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/02/14/30564.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/30564.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/02/14/30564.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/30564.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/30564.html</trackback:ping><description><![CDATA[<P>GMF有可能成为一个标准的Eclipse图形模型编辑器，它分为两个部分：运行时（the runtime）和工具（tooling），工具是由一些创建和编辑符号语义模型的编辑器组成的，工具还包含了图形编辑器，并且有图形编辑器的生成器。</P>
<P>使用GMF开发一个类图形模型编辑器的步骤如下：<BR><BR>1。创建域模型，这个模型描述了通过编辑器编辑的非图形信息。<BR>2。创建图定义模型，这个模型描述了显示在图形编辑器中的图形元素。<BR>3。创建图映射模型，这个模型定义了域模型元素和图形元素之间的对应关系。<BR>4。生成图形编辑器。<BR>5。通过改进生成的代码来提高图形编辑器。<BR>介绍一点GMF的图形编辑器的特性：<BR>1。折叠<BR>2。label的直接编辑<BR>3。提示<BR>4。弹出bar<BR>5。连接柄<BR>6。通用绘图工具<BR>7。通用菜单命令<BR>8。通用工具条<BR>9。自动缩放和布局<BR>10。通用属性编辑<BR>11。打印和打印预览<BR>12。SVG和剪贴板支持<BR><BR><A href="http://www.eclipse.org/articles/Article-Introducing-GMF/article.html">http://www.eclipse.org/articles/Article-Introducing-GMF/article.html</A></P><img src ="http://www.blogjava.net/pandawang/aggbug/30564.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-02-14 11:38 <a href="http://www.blogjava.net/pandawang/archive/2006/02/14/30564.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个用RCP实现的简单的GEF程序</title><link>http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 12 Jan 2006 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/27754.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/27754.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/27754.html</trackback:ping><description><![CDATA[uo &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最近在学习GEF，本例子主要是修改了<A href="http://bjzhanghao.cnblogs.com/archive/2005/02/19/106000.html">八进制</A>的例子。在这里做一下总结。先来介绍一下gef，网上关于GEF的介绍越来越多，从另一方面也说明这个技术确实在热起来，不过GEF为了实现可扩放性和可重用性，做的很是复杂（闲话一下，最近看了一本书《Better.Faster.Lighter.Java》，没看多少，Justin Gehtland, Bruce A. Tate写的，一开始就说了，为了满足越来越多的需要，各种framework，library，language都是越来越复杂了，学习曲线也变得陡峭了，这个似乎是无法避免的，java语言也是，不信去看看jdk，1.1时才3.7MB，1.4时已经38MB了。我也一直坚信，Simply the best，呵呵）。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GEF的一些资源： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1。<A href="http://www.eclipse.org/">www.eclipse.org</A> 这个是源头啊，faq也可以看看&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2。ibm的dW 除了相关文章，这里还有本关于gef和emf的红宝书，可以<A href="http://http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/sg246302.html">免费下载</A>。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3。eclipseworld.org 这个是一个关于eclipse中文社区 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4。八进制的blog http://bjzhanghao.cnblogs.com/ 。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5。这里还有些中文教程 http://www.benisoft.com/cn/index.htm<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6。还有一些blog <A href="/hopeshared/">http://www.blogjava.net/hopeshared/</A>&nbsp; <A href="/eclipshine/">http://www.blogjava.net/eclipshine/</A>&nbsp;<A href="/reloadcn/">http://www.blogjava.net/reloadcn/</A>&nbsp;<A href="/USTCEric">http://www.blogjava.net/USTCEric</A><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 好了，现在来介绍一下GEF的实现机制，主要是我的一些理解可能还有一不对的地方，欢迎大家帮我改正。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GEF是具有标准MVC（Model-View-Control）结构的图形编辑框架，其中Model由我们自己根据业务来设计，它要能够提供某种模型改变通知的机制，用来把Model的变化告诉Control层；Control层由一些EditPart实现，EditPart是整个GEF的核心部件；而 View层，大多数情况下，使用Draw2D实现了，其作用是把Model以图形化的方式表现给使用者，当然你也可以使用其他图形包，不过gef与 Draw2D的结合还是非常紧密的，一般为了使用方便，View都是使用Draw2D实现的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关于Draw2D，八进制有一篇相应的<A href="http://http://bjzhanghao.cnblogs.com/archive/2005/02/09/103595.html">文章</A>，还有eclipse上的一篇<A href="http://www.eclipse.org/articles/Article-GEF-Draw2d/GEF-Draw2d.html">文章</A>，可以参考，这里有几点需要强调一下：<BR>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1。Draw2D提供了很多缺省图形，最常见的有三类：1、形状（Shape），如矩形、三角形、椭圆形等等；2、控件（Widget），如标签、按钮、滚动条等等；3、层（Layer），它们用来为放置于其中的图形提供缩放、滚动等功能。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2。每个图形都可以拥有一个边框（Border），Draw2D所提供的边框类型有GroupBoxBorder、TitleBarBorder、ImageBorder、 ButtonBorder，以及可以组合两种边框的CompoundBorder等等，在Draw2D里还专门有一个Insets类用来表示边框在图形中所占的位置，它包含上下左右四个整型数值。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3。一个图形可以包含很多个子图形，这些被包含的图形在显示的时候必须以某种方式被排列起来，负责这个任务的就是父图形的LayoutManager，相应的约束（Constraint）对象就在这里，比如在子图形刷新（refreshVisuals）时可以通过将其布局约束传递给其父元素来定位。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4。利用Draw2D中的Router、Anchor和Locator，可以实现多种连接样式。Router负责连接线的外观和操作方式；Anchor控制连接线端点在图形上的位置，即"锚点"的位置；Locator的作用是定位图形。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面说过了GEF是通过MVC架构实现的，下面分别介绍这三个方面：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一、模型（Model）：这个是相对比较容易理解，模型保存着业务逻辑，他是GEF这中唯一可以持久化的，并且需要提供相应的监听机制，来通知 EditPart去更新View，监听机制又可以分为分布式和集中式两种，我们可以针对域监听器进行转有通知，也可以全局广播；在这里我们认为 Command（EditPart用来更新模型的对象）也是模型的一个部分，因为它了解模型。此外，在有时候可能需要多种模型。我们对于业务模型，提供一个“视图”模型，这样便于实现和满足相应的要求，不管内部模型是怎么样的，都要实现通知机制。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二、视图。GEF提供了在EclipseWorkbench中使用Viewer，称为EditPartViewer。它的作用和jface中的 Viewer很相，不过这时候它的ContentProvider和LabelProvider是EditPart，通过setContents设置（注意在八进制代码中setContents参数为模型对象，通过分析发现，在AbstractEditPartViewer中此方法被重载，可以除了接受 org.eclipse.gef.editpart对象外可以接受Object对象，不过此时回调用EditPartFactory，通过给定的模型对象来创建相应的EditPart，个人认为这样做并不与“View与Model无直接联系”的要求相矛盾）。这个接口继承了 org.eclipse.jface.viewers.ISelectionProvider接口（这个也和jface中的viewer一样），因此使 viewer提供了监听器，这样可以将对view的操作传递到editpart。EditPartViewer会维护各个EditPart的选中状态，如果没有被选中的EditPart，则缺省选中的是作为contents的EditPart。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EditPartViewer可以适配到任何一个SWT控件，因为它要求有createControl方法，接受一个父SWT控件作为适配对象，从而将 GEF生成的Figure对象显示在这个SWT控件上，因此GEF可以使用任何图形包，不过GEF提供了对Draw2D的默认实现，比如 AbstractGraphicalEditPart类中的回调方法createFigure就要求返回一个IFigure对象。将一个GEF图形显示出来可以使用org.eclipse.ui.part.EditorPart也可以是org.eclipse.ui.part.ViewPart，如果使用 EditorPart，则需要实现继承自WorkbenchPart的createPartControl,如果是ViewPart则需要自己实现与 GEF的交互，不过Eclipse Workbench对viewpart和editorpart的支持是一样的，都是在plugin文件扩展相应的扩展点。一般来说，使用GEF对 Editorpart的模式实现是非常方便的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GEF目前提供两种视图分别是GraphicalViewer和TreeViewer，都间接继承了EditPartViewer接口，前者利用 Draw2D图形（IFigure）作为表现方式，多用于编辑区域，后者则多用于实现大纲展示，并且他们有两个具体的实现，分别是 ScrollingGraphicalViewer和TreeViewer。其中ScrollingGraphicalViewer，通过分析GEF源代码可知，是GraphicalEditor中Viewer的默认实现，我们可以通过GraphicalEditor类提供的 setGraphicalViewer(GraphicalViewer)方法重新设置其他viewer。我们在使用的时候通过 configureGraphicalViewer和initializeGraphicalViewer方法来配置GraphicalViewer。所不同的是，在configureGraphicalViewer之后initializeGraphicalViewer之前插入了一个 hookGraphicalViewer方法，其作用是同步选择和把 EditPartViewer作为SelectionProvider注册到所在的site，使其成为SelectionProvider。<BR>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此外，GEF中还提供一种成为调色板（PaletteViewer）的视图，它也是间接实现了EditPartViewer接口。因此，我也像配置GraphicalViewer一样来配置PaletteViewer，类似的使用 configurePaletteViewer和initializePaletteViewer方法，其间类似的插入了一个 hookPaletteViewer方法，用于设置相应EditDomain的PaletteViewer。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后，总结一下如何配置GraphicalView，主要是四个方面：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1。设置一个RootEditPart：RootEditPart的是使整个GEF框架运行起来的关键之一。RootEditPart并不对应于任何的模型对象，它将从setContents()方法中接收到的模型对象进行转换，并添加到整个的EditPart体系中去。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2。设置其EditPartFactory：负责从模型到EditPart的转换。一般来说一个模型对象对应于一个EditPart。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3。设置EditDomain：用来接收事件并选择恰当的事件处理函数进行处理，这个主要是为了相应view所接收到的用户的操作。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4。调用setContents()方法：为其设置要显示的内容。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 三、控制器（EditPart）。这是GEF最核心的地方了，它将model和view联系起来。程序员可以继承三种EditPart，分别是 org.eclipse.gef.editparts.<B>AbstractGraphicalEditPart</B>，org.eclipse.gef.editparts.<B>AbstractConnectionEditPart</B>（AbstractGraphicalEditPart的子类）和org.eclipse.gef.editparts.<B>AbstractTreeEditPart。</B>EditPart 的生命周期当setContents时，将模型对象输入，此对象为顶层对象，通过它可以遍历所有的模型对象。：EditPartViewer配备有 EditPartFactory，EditPartViewer通过EditPartFactory构造相应的Contents EditPart。然后EditPartViewer中的每个EditPart通过EditPartFactory构造相应的子EditPart。当用户添加新的模型的时候，包含这些模型对象的所对应的EditPart将构造相应的EditPart作出相应。视图的构造和EditPart的构造是同时进行的，每当EditPart构造并添加到它的父EditPart后相应的view也做同样的事情，比如GraphicalEditor中就有 GraphicalViewer成员变量，在此edipart创建时回调用createPartControl，在这个方法中将会创建相应的view，并将其加入到父view中。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一旦用户丢弃了某些模型对象，相应的EditPart就会被丢弃。比如用户执行了删除操作，则相应的模型对象和相应的EditPart都被删除了，但用户撤销了删除操作而重新创建的EditPart与原来的EditPart是不同的，所以EditPart是不能保存长期信息的，应该交给模型去保存，并且 EditPart也是不能被Command所引用。<BR>&nbsp;&nbsp;&nbsp; 在具体使用时，应该先定一个Contents EditPart,它的父元素为EditPartViewer的RootEditPart。RootEditPart是EditPartView的 root，它将EditPartView和它的contents（一般认为是顶层模型对象所对应的EditPart）联系起来，RootEditPart 为用户的EditPart提供一致性的上下文（context）。并且，当没有被选中的模型EditPart时，顶层对象的EditPart是默认被选中的，而RootEditPart是不能被选中的或者定位的，甚至不能与用户相交互，他也就没有对应的模型对象。GEF提供了几个默认的 RootEditPart的实现：FreeformGraphicalRootEditPart,RootTreeEditPart, ScalableRootEditPart，ScalableFreeformRootEditPart（此类继承于 FreeformGraphicalRootEditPart，增加了缩放Zoom支持，提供了ZoomManager；增加了一个LayerPane： ScalableFreeformLayeredPane。），（原来还有个GraphicalRootEditPart，已经deprecated，用 ScalableRootEditPart代替）。这里要注意的是：<BR>&nbsp;&nbsp;&nbsp; 1)对于FreeformRootEditPart（以及它的子类 ScalableFreeformRootEditPart），它的Contents EditPart应该有一个<FONT size=-1>org.eclipse.draw2d</FONT>.<B>FreeformFigure</B>对象（比如FreeformLayer或FreeformLayeredPane）作为它的Figure。例如在我们的代码里，对应的就是在 DiagramPart中的createFigure方法，它返回了一个FreeformLayer对象。<BR>&nbsp;&nbsp;&nbsp; 2) FreeformGraphicalRootEditPart的Primery Layer没有使用draw2d的LayoutManager，并且，除非contents的figure是个freeform figure，否则不能正确的调整大小。<BR>&nbsp;&nbsp;&nbsp; 3)FreefromGraphicalRootEditPart使用FreeformViewport类作为它的primary figure，这个类必须和ScrollingGraphicalViewer使用。<BR>&nbsp;&nbsp;&nbsp; 4)ScalableRootEditPart使用 Viewport作为primery figure，这个类必须和ScrollingGraphicalViewer使用。<BR>&nbsp;&nbsp;&nbsp; 5)RootTreeEditPart是TreeViewer的RootEditPart。<BR>&nbsp;&nbsp;&nbsp; Contents EditPart的图形一般是一个空面板，该面板将包含diagram的子图。<BR>&nbsp;&nbsp;&nbsp; 我们还要定义其他“视图”模型的EditPart，比如节点（node），连接（connection）。对于节点，是Graphical，可以继承 AbstractGraphicalEditPart。并且可以实现NodeEditPart接口，则可以支持源和目标的 ConnectionEditPart，使用Anchor，具体在下面有讲述。在这里，我们的代码的NodePart类中，重载了 refreshVisual方法，其中设置figure的布局约束是通过它的父元素来定位的，我不知道这是不是标准的方法，XYLayout使用的是 rectangle约束，如果长宽设为－1，表示为该图形提供理想大小。不要使用setBounds，XYLayout布局管理器可以保证对滚动条进行更新，并能将相对约束转化为绝对约束，如果长宽设置为－1，则能够将图形设置为理想的大小。此外，为了改进性能，我们可以将refreshVisual中有若干模型的分别刷新，或者设置是否需要刷新的开关。<BR>&nbsp;&nbsp;&nbsp; 对于连接，可以继承AbstractConnectionEditPart，这个抽象类已经实现了 ConnectionEditPart。和Node实现一样，通过refreshVisual方法将属性从模型映射到图形。连接也可以有约束，不过与前面的约束不尽相同。在这里，连接路由器（connection router）使用约束来是连接转向（bend）。需要注意的是，一个Connection EditPart的图形必须是一个draw2d的Connection，这样就引入了连接锚（Connection Anchor）。连接必须由连接锚（ConnectionAnchor）“锚定”在两端。因此，需要在连接EditPart或者节点EditPart中实现使用什么样的锚。缺省情况下，GEF使用节点EditPart通过实现NodeEditPart接口来提供锚。这是因为，锚的选择取决与各个节点上正在使用的图形，而连接EditPart不应了解节点上的图形，并且，当用户创建连接的时候，连接EditPart并没有创建，这时候就由节点自己显示反馈。这里需要注意的是：何时使用以及何时不使用ConnectionEditPart，当用户可以选择某些东西并可与之交互时，就需要 ConnectionEditPart。它可能与某行中的某个对象相对应，并且回自己删除；如果这是需要一个绘制直线的节点或者容器，那么只需要用图形的 paint方法绘制直线，或者组合一个图形，这个图形包含Polyline图形。连接必须要拥有源和目标。如果要创建一个连接，并且在没有源和目标存在的情况下，可以继承AbstractGraphicalEditPart，并使用连接图形，比如PolylineConnection。<BR>&nbsp;&nbsp;&nbsp; 正如前面说的，模型需要实现某种通知机制，各个EditPart要将自己做为监听者，注册在模型上，以便在模型发生改变的时候收到相应的通知。 &nbsp; 当EditPart收到相应的通知时，调用相应的处理方法，来进行一次强制的刷新，对于模型对象的增减可以调用refreshChildren方法，对于简单属性的更改可以调用refreshVisuals方法，这时，像前面提到的，可以只刷新改变的部分，以提高性能。一般，我们在Activate方法中注册监听器，在Deactivate方法中注销监听器。<BR>&nbsp;&nbsp;&nbsp; 以上完成的是从模型到视图的映射，你还需要实现的是编辑策略Edit Policies，因为EditPart并不直接对模型进行编辑，每一个EditPolicy都针对一个特定的编辑任务或者一组相关的工作。这样的实现便于在不同的EditPart间重用（reuse）编辑行为，并且这样的实现，可以动态的改变行为，比如改变layout或者routing时。在 createEditPolicies方法中，我们要insall我们的的Policies，这时候就需要roles，roles的作用就是作为关键字来标示不同的policies。policy中提供Command，每个应用程序都有个Command栈，Command的运行要通过Command栈，而不是直接调用execute方法。<BR>&nbsp;&nbsp;&nbsp; 说到这里，要注意EditPartView是视图的，一般放在一个UI插件上比如EditorPart，viewPart，甚至swt控件。EditPart是控制器，联系视图和模型。<BR>&nbsp;&nbsp;&nbsp; 在本文的最后介绍一下GEF的运行机制：EditPartView接受用户的操作，如节点的移动，增删，每个节点对应一个EditPart对象，每个 EditPart都有一组由Role区分的EditPolicies，每个EditPolicy会对应一些Command对象，Command最终会对模型进行操作。用户的操作会转化为Request分配给特定的EditPolicy，由EditPolicy创建相应的Command对模型进行操作，这些 Command会保留在EditDomain的命令堆栈中，用于实现undo，redo功能，EditDomain是专门用于维护 EditPartView，Command信息的对象，一般每个EditPart有一个EditDomain。<BR>&nbsp;&nbsp;&nbsp; 以上就是对所作的GEF部分的大概描述，可能有些地方写的比较罗嗦，有的地方写的也可能不对，希望大家指出，谢谢。下面还要对RCP部分进行一些描述。<BR><img src ="http://www.blogjava.net/pandawang/aggbug/27754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-01-12 14:35 <a href="http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>