??xml version="1.0" encoding="utf-8" standalone="yes"?> 所以的工具都安装或解压之后Q在swt源代码目录下扑ֈbuild.batQ在:X86 label部分做如下配|,其中配置的目录视你的安装而定Q?br />
如果你和我一L用的是Sun的JDKQ且版本?.5?.6Q还M改一下和build.bat同目录的make_win32.mak文g?/p>
替换 ?/p>
一旦配|完成后Q就可以在命令行中运?build.bat x86 来build swt了,如果你的buildq程中出错,使用build x86 clean删除垃圾文gQ然后再查明原因。如果没有错误的话,目录下会生成5个dll文gQ分别是swt-awt-win32-XXXX.dll, swt-gdip-win32-XXXX.dll, swt-wgl-win32-XXXX.dll, swt-win32-XXXX.dll, swt-xulrunner-win32-XXXX.dllQ其中XXXX是视你的Eclipse版本而定?br />
改动之后Q?br />
改动的目的就是在pȝ菜单里面加了一个菜单项 "Bang"Q点d会出?#8220;Hello world” 对话框?br />
对应语言注释 /* a lot of words */ 或文档注?/** more words */
其中 *因ؓ是regular expression的meta wordQ需要{义?br />Eclipse中的查找是不能设|单行或者多行的Q即DOT . 不包?\r \nQ所以\s代替Q?表示非贪婪,即碰到注释结?*/ 要停?br />
我的邮箱是: lifesting%gmail.com (replace % with @), msn id is step.in%hotmail.com
我想要做的一个东西就是以模型Z心的开发方式,它被“隐藏”在Eclipse里面。比如日常我们做的企业开发大部分是以业务层BO为核心,然后向下延臛_储,向上有service/service control/page control/page之类Q那么通过一套可~程模板Q即Template DSL)+代码生成器就可以生成惌的各个层的代码了Q其本质上是一个UML囑Ş建模工具Q上面绑定模板,模板的编写提供类似JDT(提供在Eclipse~写/调试Java代码的插仉)的高?U错Q重构等Q代码生成过E可以被q行或者单步调试?br />
MDA在EclipseC的推动下Q日渐成熟,以EMF metamodel描述的UML2_强大Q在技术完全可行,德国的oawQ法国的acceleo都有成熟的应用?br />
我做q个的想法就是帮E序员摆q重琐的比如javabean, html, configuration{?br />
商业模式是使用免费+收费专业培训支持?br />
有同仁在搞MDAcM的开发么Q欢q提出宝贉|见?br />
如果你是一个多层JavaEE的开发者,每天被spring, hibernate, jdbc, structs/jsf/xxx, html折磨Q最希望共帮你解决那些问题呢Q谢谢?/strong>
Update: Just do itQ先d试一把,做一个版本出来,谢谢x?br />
Ubuntu真是个好东西Q耗的资源,囑ŞpȝE_Q对开发h员及其友好,真的很强大?br />
-I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/pixman-1
-lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
static void destroy(GtkWidget*, gpointer);
static gboolean delete_event(GtkWidget*, GdkEvent*, gpointer);
int main(int argc, char *argv[]) {
GtkWidget *window, *label;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW (window), "Hello World!");
gtk_container_set_border_width(GTK_CONTAINER (window), 10);
gtk_widget_set_size_request(window, 200, 100);
/* Connect the main window to the destroy and delete-event signals. */
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(delete_event), NULL);
/* Create a new GtkLabel widget that is selectable. */
label = gtk_label_new("Hello World");
gtk_label_set_selectable(GTK_LABEL (label), TRUE);
/* Add the label as a child widget of the window. */
gtk_container_add(GTK_CONTAINER (window), label);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
/* Stop the GTK+ main loop function when the window is destroyed. */
static void destroy(GtkWidget *window, gpointer data) {
gtk_main_quit();
}
/* Return FALSE to destroy the widget. By returning TRUE, you can cancel
* a delete-event. This can be used to confirm quitting the application. */
static gboolean delete_event(GtkWidget *window, GdkEvent *event, gpointer data) {
return FALSE;
}
(以上代码来自图书 Foundation of GTK+ development)
然后q行Q正怼昑ּ如下Q?br />
关于Job不说了,无所不在Q我要讲的是job的一些属性?br />
1 lJob加上ActionQ当用户在Jobq行的时候点LQ可昄更具体的job描述或者对job本nq行操作?br />
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("My job is working", 100);
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {} // ignore
monitor.worked(1);
}
monitor.done();
return new Status(IStatus.OK, Activator.PLUGIN_ID, "ok, job finished!");
}
};
job.setProperty(IProgressConstants.ACTION_PROPERTY, new Action() {
@Override
public void run() {
MessageDialog.openInformation(new Shell(), "Job Status", "Some partial results processed can be displayed here");
}
});
job.schedule();
效果图:
2 在Progress View里面保留记录
效果图:
3 防止error dialog打断你的操作。process view里面q行的job如果q回的status是errorQ那么默认它会弹Z个error dialog警告job有错误,如果jobq行的同时你在干别的Q这可能会打断你的某个操?Eclispe的dialog都是modal??br />
把job的返回状态改为error?br />
error dialog:
加上属性屏蔽error dialog:
4 lJob加一个图标:
效果如下Q?br />
看得出来它是在JDT UI里面定义的,l合了jdt text editor template ?Java开头的category 和custom editor template如SWT开头的category。对于我来说QSWT/Draw2d/Plugin的大量重复性代码就可以通过q个来完成了。将模板的代码插入到~辑器有两种ҎQ一U是直接拖拽到编辑器中,另一U是输入写入?execute"Q按Contxt Assist快捷?一般ؓCtrl+Space)?br />
除此之外QTemplates Viewq可以维护template比如add/remove。Template的gXML字串存放?metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.jdt.ui.prefs文g的org.eclipse.jdt.ui.text.custom_templates?br />
起初我以为Template View好像q没有提供什么NB功能Q在Window->Preferences->Java->-Editor->Templates可以做同L事情Q但E微看了一下代码,发现我错了:
Templates View是PageBookViewQ意味着它跟Properties View/Outline View一P可以Ҏ不同的Editor来显CZ同的PageQ比如上图JDT是JavaTemplatesPageQ如果编写一个DSL Editor需要用到Templates ViewQ承AbstractTemplatesPageQ然后在Editor的getAapter()q回pageQ看Java EditorCZQ?br />
public class CompilationUnitEditor extends JavaEditor implements IJavaReconcilingListener {
public Object getAdapter(Class required) {
if (SmartBackspaceManager.class.equals(required)) {
if (getSourceViewer() instanceof JavaSourceViewer) {
return ((JavaSourceViewer) getSourceViewer()).getBackspaceManager();
}
}
if (ITemplatesPage.class.equals(required)) {
if (fTemplatesPage == null)
fTemplatesPage= createTemplatesPage();
return fTemplatesPage;
}
return super.getAdapter(required);
protected JavaTemplatesPage createTemplatesPage() {
return new JavaTemplatesPage(this);
}
}
当然Q大部分Z需要写editorQ我们可以在自己的插仉通过使用扩展Ҏorg.eclipse.ui.editors.templates扩展JDT TemplateQ比如我在GEF目里面加入了GEF TemplateQ这L写讨厌的EditPart/EditPolicy/Command可以少些好多代码?br />
W一张图片看到的swt template是在上图所C的default-swttemplates.xml里面定义好了的?br />
最后想告诉q大Eclipse爱好者的是QEclipse SDK写的代码真工_果然是协作的l晶Q整一个代码宝库,Ҏ不用?strong>代码大全?)?
即在GMF? DiagramAction也是取得是鼠标点击paste时的位置Q而不是之前右键单d现contxt menu的位|。这?strong>“定点”关键是在选择paste之前右键单击的位|已l被C了,q且对context menu中所有对位置敏感的action都有效,比如merge, duplicate{?br />
下面分三步完成:
1 定义一个接口,为所有位|敏感action提供位置信息
void setLocation(int x,int y);
}
2 注册一个listener到GEF editor的context menuQ提供位|记忆,q个是关键?/strong>
private LivingEditor editor;
private IMenuListener listener = new IMenuListener(){
@Override
public void menuAboutToShow(IMenuManager manager) {
Control canvas = getViewer().getControl();
Point cursor_location = canvas.getDisplay().getCursorLocation();
Point relative_canvas = canvas.toControl(cursor_location);
setItemLocation(manager,relative_canvas);
}
private void setItemLocation(IMenuManager manager, Point relative_canvas) {
IContributionItem[] items = manager.getItems();
for (int i =0; i < items.length; i++)
{
IContributionItem item = items[i];
if (item instanceof ActionContributionItem)
{
IAction host_action = ((ActionContributionItem)item).getAction();
if (host_action instanceof ILocationWare)
((ILocationWare)host_action).setLocation(relative_canvas.x, relative_canvas.y);
}
else if (item instanceof IMenuManager)
{
setItemLocation((IMenuManager)item, relative_canvas);
}
}
}
};
public LivingContextMenu(LivingEditor lv) {
super((GraphicalViewer)lv.getAdapter(GraphicalViewer.class));
editor = lv;
addMenuListener(listener);
}
.
.
.
@Override
public void dispose() {
removeMenuListener(listener);
super.dispose();
}
}
3 对位|敏感的action实现ILocationWare接口Q比如paste?/strong>
private Point location = new Point(10,10);
private boolean contextTrigged=false;
public PasteAction(LivingEditor part) {
super(part);
}
@Override
public void run() {
//some operations depend on location
}
@Override
public void setLocation(int x, int y) {
location.setLocation(x, y);
contextTrigged = true;
}
@Override
protected void init() {
super.init();
setId(ActionFactory.PASTE.getId());
ISharedImages workbench_images = PlatformUI.getWorkbench().getSharedImages();
setImageDescriptor(workbench_images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
setDisabledImageDescriptor(workbench_images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED));
}
}
q种解决同样适用于GMF的DiagramAction?DiagramAction也是Action的子c?
1 定义一个HackedGroupEditPart:
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.internal.ui.palette.editparts.GroupEditPart;
import org.eclipse.gef.palette.PaletteContainer;
import org.eclipse.jface.action.Separator;
public class HackedGroupEditPart extends GroupEditPart {
public HackedGroupEditPart(PaletteContainer group) {
super(group);
}
@Override
protected void refreshVisuals() {
super.refreshVisuals();
Insets insets = getContentPane().getBorder().getInsets(getContentPane());
getContentPane().setBorder(new MarginBorder(insets){
@Override
public void paint(IFigure figure, Graphics graphics, Insets insets) {
Rectangle r = getPaintRectangle(figure, insets);
r.height--;
graphics.setForegroundColor(ColorConstants.buttonDarker);
graphics.drawLine(r.x, r.bottom(), r.right(), r.bottom());
}
});
}
}
2 使用q个加了Ҏ的GroupEditPartQ在~辑器定义里面重?createPaletteViewerProvider ҎQ如下:
.
.
@Override
protected PaletteViewerProvider createPaletteViewerProvider() {
return new PaletteViewerProvider(getEditDomain())
{
@Override
public PaletteViewer createPaletteViewer(Composite parent) {
//add border for GroupEditPart
final PaletteEditPartFactory pepf = new PaletteEditPartFactory()
{
@Override
protected EditPart createGroupEditPart(
EditPart parentEditPart, Object model) {
return new HackedGroupEditPart((PaletteContainer)model);
}
};
PaletteViewer pViewer = new PaletteViewer(){
{
setEditPartFactory(pepf);
}
};
pViewer.createControl(parent);
configurePaletteViewer(pViewer);
hookPaletteViewer(pViewer);
return pViewer;
}
};
}
}
我的Palette定义Q用了三个PaletteGroupQ但不改一下根本看不出?strong>group之间的分?/strong>Q?br />
public static PaletteRoot provide(LivingEditor livingEditor) {
PaletteRoot root = new PaletteRoot();
createStandardTool(root);
createConnectionTool(root);
createModelTool(root);
return root;
}
private static void createModelTool(PaletteRoot root) {
PaletteGroup model_group = new PaletteGroup("model");
CombinedTemplateCreationEntry person_entry = new CombinedTemplateCreationEntry("Person",
"Create a person",
new SimpleFactory(Person.class),
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icon/person16.png"),
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icon/person24.png")
);
model_group.add(person_entry);
CombinedTemplateCreationEntry dog_entry = new CombinedTemplateCreationEntry("Dog",
"Create a dog",
new SimpleFactory(Dog.class),
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icon/dog16.gif"),
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icon/dog24.gif"));
model_group.add(dog_entry);
root.add(model_group);
}
private static void createConnectionTool(PaletteRoot root) {
ConnectionCreationToolEntry relation = new ConnectionCreationToolEntry("relation",
"relation between person and dog",
new SimpleFactory(Relation.class),
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icon/connection16.gif"),
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icon/connection24.gif")
);
PaletteGroup conn_group = new PaletteGroup("relations");
conn_group.add(relation);
root.add(conn_group);
}
private static void createStandardTool(PaletteRoot root) {
PaletteGroup std = new PaletteGroup("Standard");
SelectionToolEntry selection = new SelectionToolEntry();
std.add(selection);
root.add(std);
}
可以看一下修改后的对比:
不过q种Ҏ使用了internal APIQ不适应版本更新Q只适合救急。我已经报告了这?strong>误会Q?.5应该不会有了?br />
如果你也有这个困扎ͼp试吧?br />
q些效果让RCP下的SWT来跟q_相关Q但矛盾的是SWT要跨q_Q提供的API只能是一个^衡?许补充Q更多特性依赖我们对SWTq行扩展。比较常见的是对SWT Win32 APIq行扩展Q因为Windows的图形特性太丰富了,不用白不用啊?br />
下面׃SWT win32 x86来演CZ下这个扩展过E。扩展很单,是在swt的窗口上加一个自定义pȝ菜单Q最l效果如下图Q?br />
首先要有SWT JNI源代码,在Eclipse plug-in目录下找到org.eclipse.swt.win32.win32.x86.source_3.X.X.vXXX.jar(xx为版本号)Q解压羃到c:\build\swt-jniQ解完后在会发现有一堆h和c文gQ其中比较重要的是os, gdip, xpcom,wgl,awtQ用途分别如下:
了解swt源代码之后,接下来ؓbuild swt做准备?br />
:X86
2
3IF x.%DEV_TOOLS%==x. set DEV_TOOLS=c:\PROGRA~1
4call %DEV_TOOLS%\MICROS~2\vc98\bin\vcvars32.bat
5IF x.%MSSDK%==x. set MSSDK=%DEV_TOOLS%\MICROS~3
6call %MSSDK%\setenv /XP32 /RETAIL
7IF x.%OUTPUT_DIR%==x. set OUTPUT_DIR=..\out
8IF x.%JAVA_HOME%==x. set JAVA_HOME=%DEV_TOOLS%\Java\jdk1.6.0_06
9IF x.%XULRUNNER_SDK%==x. set XULRUNNER_SDK=C:\gecko-sdk
10set XULRUNNER_MAKE=make_xulrunner
11IF x.%1==x.x86 shift
12GOTO MAKE
要实现我们想要的效果Q还需针对SWT的消息处理程?WndProc) 扩展一下OSQ那是在就在主H口建立q程中候往pȝ菜单里面加一自定义项。在Win32中,H口建立的消息ؓWM_CREATE(gؓ1)。ؓ单v见,q里只是覆盖了SWT的默认消息处理程序,它通过os.c中的 OS_NATIVE(DefWindowProcW)Ҏ来实现的(?8以后的版本api都是unicodeQ所以只覆盖W版本)
改动之前Q?/p>
#ifndef NO_DefWindowProcW
2JNIEXPORT jint JNICALL OS_NATIVE(DefWindowProcW)
3 (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3)
4{
5 jint rc = 0;
6 OS_NATIVE_ENTER(env, that, DefWindowProcW_FUNC);
7 rc = (jint)DefWindowProcW((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
8 OS_NATIVE_EXIT(env, that, DefWindowProcW_FUNC);
9 return rc;
10}
11#endif
#ifndef NO_DefWindowProcW
2
3#define ID_CUSTOM_MENU 32888
4
5const wchar_t* wcTitle=L"Hello";
6const wchar_t* wcContent=L"World";
7const wchar_t* wcName = L"Bang";
8
9LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
10{
11 int wmId, wmEvent;
12 HMENU hSysMenu;
13 switch (message)
14 {
15 case WM_CREATE:
16 hSysMenu = GetSystemMenu(hWnd,FALSE);
17 InsertMenuW(hSysMenu,1,MF_BYPOSITION | MF_STRING,ID_CUSTOM_MENU,wcName);
18 break;
19 case WM_DESTROY:
20 PostQuitMessage(0);
21 break;
22 case WM_SYSCOMMAND:
23 wmId = LOWORD(wParam);
24 if (wmId==ID_CUSTOM_MENU)
25 MessageBoxW(hWnd,wcTitle,wcContent,MB_OK);
26 else
27 return DefWindowProcW(hWnd, message, wParam, lParam);
28 break;
29 default:
30 return DefWindowProcW(hWnd, message, wParam, lParam);
31 }
32 return 0;
33}
34
35JNIEXPORT jint JNICALL OS_NATIVE(DefWindowProcW)
36 (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3)
37{
38 jint rc = 0;
39 OS_NATIVE_ENTER(env, that, DefWindowProcW_FUNC);
40 rc = (jint)MyWndProc((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
41 OS_NATIVE_EXIT(env, that, DefWindowProcW_FUNC);
42 return rc;
43}
44
45#endif
重新在swt源目录下q行build x86Q生成的swt是扩展以后的版本?br />
现在我们来测试一下效果,写一个如下所C的HelloWorld1.javaQ放到swt源目录下Q先q行javac HelloWorld1.javaQ再q行java HelloWorld1。不用担心classpath与library pathQbuild之后它们默认都在当前目录下?/p>
import org.eclipse.swt.widgets.*;
public class HelloWorld1 {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new HelloWorld1 ().open (display);
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
public Shell open (Display display) {
Shell shell = new Shell (display);
shell.open ();
return shell;
}
}
在窗口标题栏单击右键Q点d现的Bang菜单会有如下效果图:
q个例子虽然单,但大致描qC扩展swt的过E,更复杂的扩展{待YOU来实玎ͼ
首先看一D代码:
2 public class Simple {
3 public static void main(String[] args) {
4 int max = 10;
5 for(int i = 0; i < max ; i++)
6 {
7 simpleAction(i);
8 }
9 }
10
11 private static void simpleAction(int i) {
12 int tmp = i;
13 if (i == 5)
14 throw new NullPointerException("5 is invalid number!");
15 System.out.println("Number "+tmp+" reached!");
16 }
17 }
18
q段代码非常单,是打印10个数字,但中间一个出了异常,假设我们忘记Eclipse的Exception BreakPoint(在复杂的场合Q不一定抛Exception)Q于是看到控制台除了异常信息之后Q我们可在第7行和W?2行设|断点,看调用i到底发生了什么?br />
启动调试后一切正常,除了你必F8 4ơ,因ؓ0-4正常Q但也在断点处,很烦人。有没有可能ȀzL点一ơ呢Q当然可以?br />
从控制台看到5 is invalid numberQ那么这ơ调试只针对5Q我们可以简单的讄一下:
W一步:
W二步在出现的对话框内,选中Enable ConditionQ接着输入我们的condition: i==5
OKQ再调试启动SimpleQ发现断ҎzL在i=5的时候,我们可以F6一步一步看到底发生了什么?br />
q种条g调试在用复杂的框架的时候极其有用,举个例子Q?br />
GMF的AbstractActionHandler有N多子c,你必ȝ接或间接的承它Q同时用它的APIQ在它的API很复杂而我q在探烦的情况下Q出错在所隑օQ出错后在AbstractActionHandler的某个API里设|了一断点Q但你只惛_心自己写的子c?/span>Q否?/span>?/span>按F8过1分钟Q那么我们可以在上面的condition text里面输入Q?br />
this.getClass().getName().equals("foo.bar.MyDiagramAction")
可以省掉很多麻烦?br />
当然condition可以写的很复杂,可以针对断点的context写Q意Java代码?br />
!ENTRY org.eclipse.osgi 4 0 2008-05-30 12:54:33.671
!MESSAGE Application error
!STACK 1
java.lang.RuntimeException: Application "org.eclipse.ui.ide.workbench" could not be found in the registry. The applications available are: org.eclipse.jdt.core.JavaCodeFormatter, org.eclipse.update.core.standaloneUpdate, org.eclipse.update.core.siteOptimizer, org.eclipse.equinox.app.error.
at org.eclipse.equinox.internal.app.EclipseAppContainer.startDefaultApp(EclipseAppContainer.java:242)
at org.eclipse.equinox.internal.app.EclipseAppContainer.start(EclipseAppContainer.java:98)
at org.eclipse.equinox.internal.app.Activator.addingService(Activator.java:112)
at org.osgi.util.tracker.ServiceTracker$Tracked.trackAdding(ServiceTracker.java:1064)
at org.osgi.util.tracker.ServiceTracker$Tracked.trackInitialServices(ServiceTracker.java:926)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:330)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:274)
at org.eclipse.equinox.internal.app.Activator.start(Activator.java:54)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$2.run(BundleContextImpl.java:999)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:993)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:974)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:346)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:260)
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:400)
at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:111)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:417)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:189)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findLocalClass(BundleLoader.java:340)
at org.eclipse.osgi.framework.internal.core.SingleSourcePackage.loadClass(SingleSourcePackage.java:37)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClassInternal(BundleLoader.java:405)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:369)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:357)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:83)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at org.eclipse.core.internal.runtime.PlatformActivator.startAppContainer(PlatformActivator.java:47)
at org.eclipse.core.internal.runtime.PlatformActivator.start(PlatformActivator.java:32)
....
U色字体表示workbenchq个applicationq没有加载到RCP runtime中来QPlugin registry里面没有注册信息Q在3.2?extension org.eclipse.ui.ide.workbench是申明在插gorg.eclipse.ui.ide中的Q通过Plugin Registry SearchQ发现在3.3中,q个extension declaration被挪到插件org.eclipse.ui.ide.application中了Q于?strong>在项目的product配置中加入org.eclipse.ui.ide.applicationq个插g依赖Q然后选中q个插gQ点?Add Required Plug-ins"Q再clear, 启动Q运行正常?br />
从这个o人恼火的改动来看QEclipse在逐渐向它的两个趋势之一靠拢Q即成ؓ产品开发^?RCP)?另外一个是向OSGi标准看齐)
二进制包下蝲 Q?span style="color: #ff0000">因ؓblogjava不许上传jar文gQ请下蝲后将zip后缀改ؓjar后缀然后拯到eclipse/plugins目录)
一般在使用Eclipseq程中会有两U跟文g~码(charset)有关的情况让我们不愉快?br />
1 导入一个项目?/strong>
假设你的同事做好了一个项目,Z更好的支持国际化Q里面的jsp面都采用UTF-8Q然后发l你Q你导入到Eclipse的workspace中,一般情况下Q在Eclipse中,q些jsp都变成了GBK~码Q你双击打开Q一堆ؕ码。假设你知道原因Q稍微如下设|一下可以解决问题:
(? 讄文g~码)
但是Q这个项目可能包?000个jsp文gQ且你还可能反反复复到q个问题Q真是一个体力活?br />
2 改变一个项目文件的~码
q种情况发生比较,但发生了是一个大N。比如公司有两个团队Q一个开发的目jsp采用UTF-8~码Q另外一个采用GBK~码。一D|间之后,需要整合两个项目,jsp面只能采用一U编码,UTF-8/GBK或其它。有l验的h知道q是一?strong>拯/讄~码/_脓的过E:
2.1 某个jsp的内容全部拷贝下来?br />
2.2 如图1所C将~码讄为统一~码如UTF-8?br />
2.3 把设|过~码的jsp文g清空Q然后粘贴?br />
好像解决问题很完,但是Eclipse没有宏,如果文g很多Q比?000个,是一个恐怖的d?br />
因ؓq两个问题老是反复的困扰着我的同事Q相信也困扰了不Java开发者,Eclipse转码插g很好很方便的解决了这个问题,它基于Eclipse 3.3开发,所以编译环境最好采用Eclipse 3.3?br />
下面是用步?br />
step1. 插件com.lifesting.tool.encoding_1.0.0.jar拯到eclipse/plugins目录下,重启Eclipse?br />
step2. 选择某个目Q右键选择propertiesQ然后点击Convert Settingq行转码规则讄Q如下图Q?br />
下蝲eclipse 3.2 binary下蝲后改后缀zip为jarQ然后放到eclipse/plugins目录
eclipse内置一个properties editor但是只支持latin-1~码Q调用native2ascii太麻烦,sourceforge上有一个很强大的properties editorQ日本h搞得Q肯定支持中文了Q但是版本太老,3.1Q还有很多没有什么多大用处的swing, jbuild支持{,我稍微改了一下,做了一个最化的编辑器?br />
严正xQ?strong>此Y件属于研I性质Q版权属于原作者:http://propedit.sourceforge.jp/index_en.html
效果Q?br />
下蝲后将工程导入到workspace中,export成plugin卛_?br />