上一篇文章我们知道了Eclipse弹出菜单的基本用法。其实Eclipse的弹出菜单可以用来做很多文章,简单一点的根据文件类别,我们可以进行不同的文件操作,比如Ant的build.xml我们可以用来build,Java文件我们可以用Java Editor打开,这些基于文件类型的操作我们都可以很容易的实现。但是还有一种情况,如果文件类型一样,我们想进行不同的操作,该怎么实现呢?实际上这样的应用很多,比如同样是Java文件,含有main方法的Java文件有Run和Debug的选项,其它的都没有。还有现在的框架都是基于XML文件进行配置的,如果一个项目使用了多个框架,我们怎么根据不同的XML文件进行框架的区分呢?答案就是enablement的test。
<!ELEMENT
test
EMPTY>
<!ATTLIST test
property CDATA #REQUIRED
args CDATA #IMPLIED
value CDATA #IMPLIED>
This element is used to evaluate the property state of the object in focus. The set of testable properties can be extended using the propery tester extension point. The test expression returns EvaluationResult.NOT_LOADED if teh property tester doing the actual testing isn't loaded yet.
-
property - the name of an object's property to test.
-
args - additional arguments passed to the property tester. Multiple arguments are seperated by commas. Each individual argument is converted into a Java base type using the same rules as defined for the value attribute of the test expression.
-
value - the expected value of the property. Can be omitted if the property is a boolean property. The test expression is supposed to return EvaluationResult.TRUE if the property matches the value and EvaluationResult.FALSE otherwise. The value attribute is converted into a Java base type using the following rules:
-
the string "true" is converted into Boolean.TRUE
-
the string "false" is converted into Boolean.FALSE
-
if the string contains a dot then the interpreter tries to convert the value into a Float object. If this fails the string is treated as a java.lang.String
-
if the string only consists of numbers then the interpreter converts the value in an Integer object.
-
in all other cases the string is treated as a java.lang.String
-
the conversion of the string into a Boolean, Float, or Integer can be suppressed by surrounding the string with single quotes. For example, the attribute value="'true'" is converted into the string "true"
比如我们要让含有main方法的Java文件它的右键弹出菜单包含一个额外的选项“This is main class”,需要编写如下的Plugin.xml:
<
plugin
>
<
extension
point
="org.eclipse.ui.popupMenus"
>
<
objectContribution
id
="Advanced.PopupMenus"
objectClass
="java.lang.Object"
>
<
action
id
="Advanced.PopupMenus.Action"
label
="AdvancedPopupMenus"
style
="pulldown"
menubarPath
="additions"
class
="advancedpopupmenus.popup.actions.AdvancedPopupMenusAction"
enablesFor
="+"
>
</
action
>
<
enablement
>
<
test
property
="advancedpopupmenus.popup.visable"
/>
</
enablement
>
</
objectContribution
>
</
extension
>
<
extension
point
="org.eclipse.core.expressions.propertyTesters"
>
<
propertyTester
namespace
="advancedpopupmenus.popup"
properties
="visable"
type
="java.lang.Object"
class
="advancedpopupmenus.popup.actions.VisablePropertyTester"
id
="advancedpopupmenus.popup.propertyTesters.visable"
>
</
propertyTester
>
</
extension
>
</
plugin
>
我们需要检测在当前情况下是否需要显示这个菜单项,使用扩展点
org.eclipse.core.expressions.propertyTesters
:
<!ELEMENT propertyTester EMPTY>
<!ATTLIST propertyTester
id CDATA #REQUIRED
type CDATA #REQUIRED
namespace CDATA #REQUIRED
properties CDATA #REQUIRED
class CDATA #REQUIRED>
id - unique identifier for the property tester
type - the type to be extended by this property tester
namespace - a unique id determining the name space the properties are added to
properties - a comma separated list of properties provided by this property tester
class - the name of the class that implements the testing methods. The class must be public and extend org.eclipse.core.expressions.PropertyTester with a public 0-argument constructor.
这里只须注意
propertyTester的namespace和properties正好对应test的property。
至于检测的逻辑我们在advancedpopupmenus.popup.actions.VisablePropertyTester中实现,这个类必须继承自org.eclipse.core.expressions.PropertyTester。
package
advancedpopupmenus.popup.actions;
import
org.eclipse.core.expressions.PropertyTester;
import
org.eclipse.jdt.core.IMethod;
import
org.eclipse.jdt.core.IType;
import
org.eclipse.jdt.core.JavaModelException;
import
org.eclipse.jdt.internal.core.CompilationUnit;
public
class
VisablePropertyTester
extends
PropertyTester
{
public
boolean
test( Object receiver, String property, Object[] args,
Object expectedValue )
{
if
(
!
( receiver
instanceof
CompilationUnit ) )
return
false
;
CompilationUnit unit
=
(CompilationUnit) receiver;
try
{
IType[] types
=
unit.getTypes( );
if
( types
==
null
)
return
false
;
for
(
int
i
=
0
; i
<
types.length; i
++
)
{
IMethod[] methods
=
types[i].getMethods( );
if
( methods
==
null
)
return
false
;
for
(
int
j
=
0
; j
<
methods.length; j
++
)
{
if
( methods[j].isMainMethod( ) )
return
true
;
}
}
}
catch
( JavaModelException e )
{
e.printStackTrace( );
}
return
false
;
}
}
我们只要判断接受的Java文件中是否含有main方法,如果有,则返回True,没有则返回False。
如果我们是要接受一个Web开发的配置文件,我们可以这样写:
<
plugin
>
<
extension
point
="org.eclipse.ui.popupMenus"
>
<
objectContribution
id
="Advanced.PopupMenus"
objectClass
="org.eclipse.core.resources.IFile"
nameFilter
="*.xml"
>
<
action
id
="Advanced.PopupMenus.Action"
label
="This is web xml"
style
="pulldown"
menubarPath
="additions"
class
="advancedpopupmenus.popup.actions.AdvancedPopupMenusAction"
enablesFor
="+"
>
</
action
>
<
enablement
>
<
test
property
="advancedpopupmenus.popup.visable"
/>
</
enablement
>
</
objectContribution
>
</
extension
>
<
extension
point
="org.eclipse.core.expressions.propertyTesters"
>
<
propertyTester
namespace
="advancedpopupmenus.popup"
properties
="visable"
type
="org.eclipse.core.resources.IFile"
class
="advancedpopupmenus.popup.actions.VisablePropertyTester"
id
="advancedpopupmenus.popup.propertyTesters.visable"
>
</
propertyTester
>
</
extension
>
</
plugin
>
注意和上一个例子不同的地方,objectClass,nameFileter和type(在上一个例子中,我们也可以使用objectClass="org.eclipse.core.resources.IFile" nameFilter
="*.java"
),相应的我们的VisablePropertyTester类也要做一些改动:
package
advancedpopupmenus.popup.actions;
import
javax.xml.parsers.DocumentBuilder;
import
javax.xml.parsers.DocumentBuilderFactory;
import
org.eclipse.core.expressions.PropertyTester;
import
org.eclipse.core.resources.IFile;
import
org.w3c.dom.Document;
import
org.w3c.dom.DocumentType;
public
class
VisablePropertyTester
extends
PropertyTester
{
public
boolean
test( Object receiver, String property, Object[] args,
Object expectedValue )
{
if
(
!
( receiver
instanceof
IFile ) )
return
false
;
IFile xml
=
(IFile) receiver;
try
{
DocumentBuilderFactory dbf
=
DocumentBuilderFactory.newInstance( );
DocumentBuilder db
=
dbf.newDocumentBuilder( );
Document doc
=
db.parse( xml.getContents( ) );
DocumentType type
=
doc.getDoctype( );
if
(type.getSystemId( ).equalsIgnoreCase(
"
http://java.sun.com/j2ee/dtds/web-app_2_2.dtd
"
))
return
true
;
}
catch
( Exception e )
{
e.printStackTrace( );
}
return
false
;
}
}
这样根据不同的xml SystemID,我们就能够知道到底这是哪一种框架的配置文件了。