用Java制作动画效果

用Java画动画很简单,让一个线程自己定时调用自己即可,记得要设置一个退出(结束)条件。

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Animation {
    final static int DELAY = 500;

    public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        final Text text = new Text(shell, SWT.BORDER);
        text.setText("0");
        new Runnable() {
            public void run() {
                if (shell.isDisposed())
                    return;
                text.setText("" + (Integer.parseInt(text.getText()) + 1));
                Display.getDefault().timerExec(DELAY, this);
            }
        }.run();

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
}

运行结果:

file

可以看到窗口中显示的数字不停增长。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/03/30/694268.html

使用Java JNI的步骤

  1. 写Java类,其中定义了native方法
public class WitWrapper {

    static {
        System.loadLibrary("witengine");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        new WitWrapper().run();
    }

    private void run() {
        solve("C:\\temp\\witlib\\problem.txt");
    }

    public native static int solve(String filename);
}
  1. 在命令行下用javah生成.h文件,内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class XXX_WitWrapper */

#ifndef _Included_XXX_witwrapper_WitWrapper
#define _Included_XXX_witwrapper_WitWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     XXX_WitWrapper
 * Method:    solve
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_XXX_WitWrapper_solve
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif 
  1. 复制.h文件到一个vc++6.0的dll工程里,用vs2005得到的dll会依赖msvcr80d.dll等其他dll,不建议。把$jdk_dir$/include里的jni.h和$jdk_dir$/include/win32里的jni_md.h也添加到这个工程里。

  2. 按.h文件实现.c文件对应的方法,如下例,注意jstring类型要转换成char *类型,否则即使英文也会有乱码:

/**************************************************************************** 
 *
 * Sample WIT API Program.
 * Runs implosion on the Diner problem.
 *
 ****************************************************************************/
#include <stdlib.h>
#include "wit.h"
#include "jni.h"

/****************************************************************************/
/* Main Program                                                             */
/****************************************************************************/
JNIEXPORT jint JNICALL Java_XXX_WitWrapper_solve
  (JNIEnv * env, jclass jc, jstring file)
{
  WitRun * theWitRun;
  const char *str = (*env)->GetStringUTFChars(env, file, 0);//把jstring转换为char *,否则会有错
  printf(str);

   /* Initialize WIT */
   witNewRun( &theWitRun );
   witInitialize ( theWitRun );

   witReadData (theWitRun, str);
   /*************************************************************************
    *
    * Finished entering data
    *
    ************************************************************************/

   witOptImplode( theWitRun );
   witWriteExecSched( theWitRun, "execsched.txt", WitBSV );
   witWriteShipSched( theWitRun, "shipsched.txt", WitBSV );

   witDeleteRun( theWitRun );

   exit (0);

} /* main */
  1. 编译生成.dll文件,把它和其他依赖的文件放在path环境变量包含的一个目录下,在java里就可以调用了。注意调用这个dll的java类名(包括所在包)不能改,否则会出现UnsatisfiedLinkException,如果一定要改名,只能重新生成一遍dll了。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/03/30/693889.html

用JFreeChart画仪表盘

JFreeChart画仪表盘(Speedo Meter Chart)的例子:

DefaultValueDataset data = new DefaultValueDataset(32.0);
MeterPlot plot = new MeterPlot(data);
plot.setDialShape(DialShape.CHORD);
plot.setDialBackgroundPaint(Color.WHITE);
plot.setRange(new Range(0, 120));
plot.setDialOutlinePaint(Color.GRAY);
plot.setNeedlePaint(Color.BLACK);
plot.setTickLabelsVisible(true);
plot.setTickLabelPaint(Color.BLACK);
plot.setTickPaint(Color.GRAY);
plot.setTickLabelFormat(NumberFormat.getNumberInstance());
plot.setTickSize(10);
plot.setValuePaint(Color.BLACK);
plot.addInterval(new MeterInterval("Low", new Range(0, 70), null, null,new Color(128, 255, 128,90) ));
plot.addInterval(new MeterInterval("Normal", new Range(70, 100), null, null, new Color(255, 255, 128,90)));
plot.addInterval(new MeterInterval("High", new Range(100, 120), null, null, new Color(255, 128, 128,90)));

//创建chart,最后一个参数决定是否显示图例
final JFreeChart chart = new JFreeChart("Meter Chart", JFreeChart.DEFAULT_TITLE_FONT, plot, false);

//放到SWT的Composite里,以前介绍过这个方法
Composite drawarea = new Composite(tabFolder, SWT.EMBEDDED);
drawarea.setLayout(new FillLayout());
Frame canvasFrame = SWT_AWT.new_Frame(drawarea);
java.awt.Canvas canvas = new java.awt.Canvas() {
    public void paint(Graphics g) {
        super.paint(g);
        if (chart != null)
            chart.draw((Graphics2D) g, getBounds());
    }
};
TabItem tab = new TabItem(tabFolder, SWT.NONE);
tab.setControl(drawarea);
tab.setText("Meter");
canvasFrame.add(canvas);

运行效果:

file

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/03/13/673303.html

为GMF应用程序设置背景图片

要为GMF应用程序的画布设置背景图片,可以覆盖XXXDiagramEditor的configureGraphicalViewer()方法,加入如下代码即可。不过加入背景图片后,网格线无法显示,有可能是图层顺序的问题。

/**
 * @generated NOT
 */
protected void configureGraphicalViewer() {
    super.configureGraphicalViewer();

    //////Background Layer//////////////////
    Layer backgroundLayer = new Layer() {
        @Override
        protected void paintFigure(Graphics graphics) {
            super.paintFigure(graphics);
            graphics.drawImage(NetworkDiagramEditorPlugin.getInstance().getBundledImage("images/worldmap_no_text.gif"), 0,
                    0);
        }
    };
    backgroundLayer.setSize(4990, 2484);
    ////////////////////////////////////////

    DiagramRootEditPart root = (DiagramRootEditPart) getDiagramGraphicalViewer().getRootEditPart();
    LayeredPane printableLayers = (LayeredPane) root.getLayer(LayerConstants.PRINTABLE_LAYERS);
    FreeformLayer extLabelsLayer = new FreeformLayer();
    extLabelsLayer.setLayoutManager(new DelegatingLayout());
    printableLayers.addLayerAfter(extLabelsLayer, NetworkEditPartFactory.EXTERNAL_NODE_LABELS_LAYER,
            LayerConstants.PRIMARY_LAYER);

    //////Insert Background Layer///////////
    printableLayers.addLayerBefore(backgroundLayer, NetworkEditPartFactory.EXTERNAL_NODE_LABELS_LAYER,
            LayerConstants.PRIMARY_LAYER);
    ////////////////////////////////////////

    LayeredPane scalableLayers = (LayeredPane) root.getLayer(LayerConstants.SCALABLE_LAYERS);
    FreeformLayer scaledFeedbackLayer = new FreeformLayer();
    scaledFeedbackLayer.setEnabled(false);
    scalableLayers.addLayerAfter(scaledFeedbackLayer, LayerConstants.SCALED_FEEDBACK_LAYER,
            DiagramRootEditPart.DECORATION_UNPRINTABLE_LAYER);
}

参考资料

为图形编辑器设置背景图片

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/03/13/673273.html

Graphical Modeling Framework简介

本文已发表在2006年12月《程序员》杂志,请勿转载。

本文假设读者有Eclipse平台应用程序开发经验,了解Eclipse平台的插件机制,使用EMF和GEF开发过应用程序。在本文中,“Eclipse应用程序”等价于“Eclipse插件”。

Eclipse是一个开源的平台,从一开始就被设计为允许各种功能以插件(Plug-in)的形式自由组装的结构,它凝聚了无数天才的设计,目前仅Eclipse.org下的子项目就有数十种,全世界范围内的各种插件则数以千计。随着Eclipse开源社区影响力的不断增强,国内外有越来越多的实际应用构造在Eclipse平台上,同时有更多组织和个人加入到为Eclipse贡献力量的行列中,这样的良性循环形成了以Eclipse平台为中心的巨大生态系统。

在众多插件中,一些插件存在的目标是为了简化开发人员开发其他Eclipse插件的过程,接下来要介绍的GMF就是这样一个插件。

一、GMF与EMF、GEF

开发过Eclipse插件的朋友们一定知道EMF和GEF这两个插件项目。EMF (Eclipse Modeling Framework)可以帮助我们以模型驱动的方式开发Eclipse应用程序,具体来说,它定义了一套名为Ecore的元模型(类似UML元模型,包括包、类型、属性和方法等元素),用Ecore定义的模型可以被EMF转换为运行在Eclipse平台上的Java代码,这些代码实现了一套消息通知机制,是构造一个可靠应用不可缺少的基础。

绝大多数应用程序都有一个业务模型,不论以什么方式描述,这个模型都是整个应用程序的基础。利用EMF强大而完善的建模能力,我们不仅可以更直观方便的构造业务模型,更重要的是,得益于EMF的代码生成能力,在整个应用程序的开发周期里,这个模型都能够保持最新的版本,开发人员在任何时候都能很快的了解整个业务。

虽然对开发人员来说,业务逻辑是应用程序的关键,但直接和用户打交道的还是程序的UI部分。我们经常说一幅图胜过千言万语,这句话在应用程序的UI设计里也同样适用。试想如果我们熟悉的UML类图是用文本来描述的,我们将多花费多少时间在理清类与类之间的关系上呢。GEF的出现,为我们在Eclipse平台下开发图形化的应用程序铺平了道路。

GEF(Graphical Editing Framework)框架具有标准的MVC(Model-View-Control)结构。在模型部分,GEF没有对开发人员进行任何限制,只要模型发生改变时能够通知到控制器即可。GEF里的控制器被称为EditPart,它们是应用程序的核心部分,负责将模型的改变反映到视图,并将用户在视图上所做的操作应用到模型。在视图方面,GEF使用Draw2D,一个轻量级的图形系统。有了GEF的帮助,要在Eclipse里开发出类似Visio的图形化应用程序变得简单多了。

随着Eclipse平台被更多开发人员接受,结合EMF和GEF逐渐成为了构造GEF应用程序的主要模式,也就是在EMF生成的模型基础上开发GEF应用程序,这样可以在模型部分节约不少的工作量。但也有一些问题,例如两个框架各实现了一套命令机制来操作模型等等,它们又在一定程度上削弱了结合这两种技术带来的改善程度。

GMF(Graphical Modeling Framework)让我们可以用更简单的方法实现以前要同时用EMF和GEF开发的应用程序,而结合二者所带来的的各种问题则不需要关心。同时,借助Eclipse的插件机制,GMF还提供了十分丰富的扩展性,便于开发适合特定需求的应用程序。

file

图表 1 GMF的运行机制

我们不妨拿房子做比喻来说明他们在构造Eclipse应用程序中的地位。一个完整的图形化应用程序就像一个漂亮舒适的家,用EMF构造了业务模型后就相当于买到了毛坯房,这时的房子甚至连门都不全,看起来就像EMF为我们生成的缺省编辑器,十分的简陋。所以接下来的工作就是装修,也就是让应用程序的界面更加漂亮。装修的风格因人而异,这项花费有时甚至比房子本身的价值更高,在装修过程中还有可能对房子本身做出一些修改,例如拆掉一面墙或是做一个楼梯等等,可以把GEF的部分比做对客厅的装修,因为客人来参观时对整个房子的第一印象往往来自客厅,所以在客厅上多花些精力十分有必要,GEF帮我们实现的图形化编辑器就是很大的亮点。然而,不可否认房子的主人每天最多时间是在卧室度过的,所以卧室的布置也是决定房子是否舒适的重要因素,可以把应用程序里各种视图、向导、偏好、菜单和工具条等等比作对卧室的装饰。

至于GMF呢,用它构造图形化应用程序,就像买了一套“精装修”的现房,按开发商的承诺您是可以立即入住的,不仅墙壁喷涂了,地板铺好了,就连整套家具和家电也预备齐全。然而开发商给所有人的装修都是差不多的,顶多提供几套可选方案,不可能完全满足你的全部个性化需求。同样,用GMF生成的程序虽然比EMF生成的好看很多,但还有不少工作是需要自己动手的。

下面,为了能让大家对GMF能为我们做什么有一个直观的印象,我们简单演示一下如何用GMF开发一个流程编辑器。

二、用GMF实现图形化流程编辑器

GMF是以EMF为建模基础的,理所当然业务模型也是一个ecore模型。开始一个GMF项目的第一步就是新建一个空白的EMF项目,在项目里定义我们的业务模型,这个ecore模型里,我们定义一个流程(Process)需要的各种元素。为了节约篇幅,这里的流程模型元素十分简单,只包括开始节点(Beginning)、结束节点(Ending)、流程(Process)、活动(Activity)、条件(Condition)和关系连接(Relationship)这几种类型。其中,Process是根节点,即一个流程文件里只包含一个Process元素。Process下包含多个Activity、多个Condition和多个Relationship,但只包含一个Beginning和一个Ending。

每个流程元素都具有一个字符串类型的名字属性,我们为Activity添加一个优先级(priority)属性用来表示活动的紧急程度,这个属性是枚举类型,具有High、Normal和Low这三个值,在ecore里定义枚举类型是十分方便的;再为Condition添加一个字符串类型的表达式(expression)属性。

file

图表 2 流程编辑器的ecore模型

现在从ecore模型生成genmodel模型(菜单File -> New -> EMF Model),并生成全部代码(在genmodel模型根节点的右键菜单里选Generate All命令),这个genmodel模型将被后面需要定义的一些模型引用,模型和.edit部分的代码是GMF图形项目编译的前提条件,所以这一步是必要的。

到现在为止的这些步骤和构造普通的EMF应用程序并没有什么不同,不要着急,下面要做的事情就进入GMF的领域了。

现在我们来定义图形模型(Graph Model)、工具模型(Tooling Model)和映射模型(Mapping Model)这三个模型,然后利用它们生成名为GMF生成模型的模型(GMFGen Model,相当于EMF里的Gen Model),最后由生成代码。为了把将要建立的几个GMF模型与已经定义好的EMF模型分开,我们可以新建一个Eclipse项目存放它们,以便在需要时更快的找到想要的模型。

首先来定义图形模型,顾名思义,在这个模型里我们要定义出流程编辑器里每种元素的外观,例如,用圆圈表示开始和结束节点,用方块表示Activity,用菱形表示Condition等等。GMF提供了名为“GMFGraph Simple Model”的向导可以从刚才定义好的ecore文件得到一个缺省的图形模型,我们只要在向导里指定ecore文件所在的位置即可。

接下来定义工具模型,这个模型指定流程编辑器的调色板(Palette)里都可以有哪些工具,你还可以在这个模型里对这些工具进行分组。同样,使用“GMFTool Simple Model”向导可以很快的得到这个模型。

然后是映射模型,这个模型的作用是把ecore模型、图形模型和工具模型联系起来,这样每个业务元素就可以对应到一个外观和一个工具,并且ecore模型里各元素之间的包含、引用关系也可以通过这个模型映射到图元的包含或连线方式。GMF提供的“Guide GMFMap Creation”向导可以帮助我们建立这个模型的一部分内容,其余部分还是需要在编辑器里手动添加或修改。尽管现在这几个模型的编辑界面还显得十分简陋,但在下一个版本(2.0)的GMF里将会提供更多新的GUI以帮助编辑这几个模型,例如提供可视化的模型编辑器。

有了映射模型,我们可以像在EMF里从ecore模型生成genmodel模型那样生成一个gmfgen模型了。生成步骤很简单,只要在Package Explorer里的gmfmap文件上点右键,选择“Create generator model”命令即可。生成以后,我们还可以对gmfgen模型进行微调,因为其中有些信息是在前三个模型里都没有包含的,大部分时候我们只需要根据需要修改其中的少数几个就够了。常用的一个是可以修改Gen Compartment的List layout属性来控制子图形是否可以在父图形里随意拖动。

最后,在gmfgen文件上点右键,选择“Generate diagram code”命令,GMF就会为我们生成完整的图形编辑器代码了。这些代码会存放在名为your.package.diagram的新工程里,这个工程依赖EMF帮你生成的两个工程,所以前面要先生成EMF的工程,否则这个工程无法正确编译。怎么样,这个界面和EMF生成的编辑器比起来够不够“精装修”的标准:

file

图表 3-1 GMF生成的流程编辑器

file

图表 3-2 EMF缺省编辑器

当然,这个编辑器的外观可能还不能让你满意,比如除了连接线外所有的图元都是用矩形表示的,未免过于单调,而且每个图元上只显示了有限的文字信息。下面我们介绍一下如何通过修改GMF的几个模型来定制流程编辑器。

首先,要改变各个图形元素的缺省外观,在缺省情况下,GMF建模向导里都将节点元素映射为矩形(Rectangle),连接元素映射为折线(Polyline),当然这些都可以在gmfgraph里修改,例如我们可以让开始和结束节点显示为圆点,让条件节点显示为菱形,将活动节点填充为蓝色,同时可以为连接线的目标端增加箭头图形来表示连接的方向,这样一来,熟悉UML的用户就更容易理解流程图的含义了。

从上面不难看出,gmfgraph模型的作用是定义图形表现的方式,GMF映射模型负责关联业务模型、gmfgraph模型和gmftool模型。任何在gmfgraph里定义的元素如果没有映射到业务模型也是没有意义的,相对来讲gmfmap模型是这三个模型中最复杂的一个,因为几乎每个元素都至少有三个属性需要定义。通过修改gmfmap模型,我们可以规定图形编辑器里,各图形元素的包含关系。在流程编辑器里,可以通过添加一个标签映射(Label Mapping)元素让活动节点里显示优先级属性。

file

图表 4 定制后的流程编辑器界面

需要注意的是,在每次修改任意一个模型文件后,都要重新生成gmfgen文件,这样重新生成的代码才能反映最近的更新。

三、GMF Runtime介绍

前面已经说过,GMF的Runtime部分是GMF的核心,不依赖GMF帮助生成代码,你也完全可以利用Runtime提供的功能写出漂亮的图形编辑器应用程序,但前提是你对GMF Runtime有充分的了解。

关于GMF Runtime提供了哪些实用功能,在Eclipse.org上有一篇文章“Introducing the GMF Runtime”已经介绍得很详细了,其中主要包括可展开折叠的compartment,Direct-Editing时的快速协助(Quick Assistant)、Pop-up工具条、连接手柄、通用工具项(如备注、文本、各种形状等等)、通用菜单命令和工具条(如颜色、字体、选择、排列、缩放,等等)、动态展示的缩放和自动布局功能、通用属性页、打印和打印预览支持、多种图片格式输出、系统剪贴板支持,等等。

GMF的Runtime相当于对GEF进行了一层包装,如果不想利用GMF生成代码的能力,只使用GMF Runtime也可以开发基于GMF的应用程序。与GEF相比,GMF Runtime充分利用了Eclipse的扩展功能,它提供了十分丰富的扩展点,不仅开发起来很方便(因为各个功能都通过定义的扩展点划分清楚了),同时还便于以后对应用程序的扩展。GMF提供的Logic例子就没有使用代码生成,而是直接写成的,你对GMF Runtime的使用方法如果不清楚,这个例子是很好的参考。

相比起EMF来,GMF项目成立的时间要晚很多,如果想让现有的GEF应用程序使用GMF Runtime带来的新功能,最简单的方法就是在原先代码的基础之上进行修改,而不是从头开始以生成代码的方式进行开发。

和EMF类似,GMF也有代码生成的功能。除了上面提到的情况以外,最好利用GMF的代码生成功能先得到应用程序的框架,再在此基础之上进行开发。

在GEF或EMF+GEF构造的应用程序里,一个让人头疼的问题就是在业务模型里不得不包含一些与图形有关的信息,例如每个元素在编辑器里的位置、大小、颜色、字体等等,这可能让本来清晰的业务模型变得难以理解。GMF通过引入记号模型(Notation Model)解决了这个问题。在GMF里,EditPart不再与业务模型直接相连,而是连接到记号模型(GMF的EditPart#getModel()方法得到的是记号模型),由记号模型维护到业务模型的引用。这个记号模型是GMF预先定义好的,它把图形抽象为画布、节点和连接三大类元素,开发人员只要知道GMF的这个设计就可以了,而不需要在业务模型里做任何特殊操作。GMF在持久化一个业务模型实例的时候(即用户保存图形编辑器时),缺省会得到两个文件,一个是业务模型的持久化信息,另一个是记号模型的持久化信息,后者依赖前者的内容。当然,用户也可以在gmfgen里设定参数让GMF只生成一个文件包含这两者的全部信息,但就失去了业务与图形分离的好处。

前面说过,GMF应用程序里的很多功能都是通过扩展点实现的,GMF里这些扩展点被称为服务(Services),用户通过在插件里实现这些服务可以改变图形编辑器的行为。这些服务包括控制控制调色板(Palette)上有哪些工具,业务模型与EditPart的对应关系,EditPart上的EditPolicy等等。实现GMF服务的方法和实现其他Eclipse平台扩展点的方法是一样的,用户要实现的接口名称一般以Provider结尾,例如EditPartProvider、ViewProvider和PaletteProvider,等等。

四、总结

GMF不仅在名称上集合了EMF和GEF这两个框架,它同时拥有EMF的代码生成能力和GEF的图形编辑能力。以往对EMF程序的定制主要通过修改代码实现,在GMF里,我们更多通过实现各种扩展点来改变应用程序的外观和行为,当然,必要的时候修改代码也是不可避免的。

另外,GMF还利用了EMFT项目里的不少成果,例如EMFT Transaction、EMFT Workspace和EMFT OCL等等,EMFT项目是对EMF项目的有益补充,它们让GMF应用程序更加健壮,更好的和Eclipse平台集成以及更好的用户体验,但也在一定程度上增加了GMF本身的入门门槛。

本文发出时,GMF 1.0版本已经相对比较稳定,而GMF 2.0也有了Milestone2版本。如果是做实际项目推荐选择1.0版本,因为虽然这两个版本的模型略有区别,但2.0正式版按计划要在2007年四月前后才能发出,这中间API很可能还会有多次修改。GMF 2.0的建模用户界面更友好一些,至于Runtime增加的新功能我们拭目以待。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/01/16/621545.html

将SWT包装成Eclipse Plugin需要修改的地方

把一个SWT程序包装到Eclipse里作为Plugin运行很容易,但有以下几点需要注意:

1、Eclipse的PDE Tools->Convert Projects to Plug-in Projects可生成Plugin工程需要的文件,注意原来在classpath里对swt.jar的引用应改为manifest.mf文件里对 org.eclipse.ui的依赖。

2、相对路径文件的使用,在SWT里用ClassLoader.getResourceAsStream()等方法引用的文件放在Plugin里会找不到,应改为

FileLocator.toFileURL(Platform.getBundle("plugin.id").getEntry("/images")).getFile();

或与其等效的方式。

3、对本地方法需要的静态链接库dll文件的引用,如果SWT程序是在启动参数里指定的,在Plugin里需要修改,可在系统环境变量里加到Path里。

4、SWT程序的入口类一般会被Editor或View等Plugin元素代替,要注意原来在入口类里初始化的变量也要改到Plugin里,特别是静态变量,正确初始化以防止NullPointerException。

5、必要的话,利用JFace等Plugin特性改写原来的SWT对话框、树、表格等元素,可使UI更具Plugin风格。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/01/11/617449.html

[Eclipse]在程序里隐藏但利用Resource Navigator

有些时候需要在应用程序里隐藏Resource Navigator,用程序控制而非双击鼠标打开编辑器。一个方法是让程序在目标workspace里创建一个project和需要的文件,用户不知道它们的存在:

IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject(".my");
if (!project.exists()) {
    try {
        project.create(null);
    } catch (CoreException e1) {
        e1.printStackTrace();
    }
}
if(!project.isOpen()){
    try {
        project.open(null);
    } catch (CoreException e1) {
        e1.printStackTrace();
    }
}
IFile file = project.getFile("default.my");
if (!file.exists()) {
    InputStream is = this.getClass().getResourceAsStream("/data/blank.my");
    try {
        file.create(is, false, null);
    } catch (CoreException e1) {
        e1.printStackTrace();
    }
}
FileEditorInput input = new FileEditorInput(file);
openEditor(input, MyEditor.EDITOR_ID);//IWorkbenchPage#openEditor()

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/01/11/617260.html

Eclipse里几个常用视图的ID

Eclipse提供的几个常用公共视图的ID,在定义perspective时可能会用到,如下:

//Resource Navigator
public final static String VIEW_ID_NAVIGATOR = "org.eclipse.ui.views.ResourceNavigator";

//Properties
public final static String VIEW_ID_PROPERTIES = "org.eclipse.ui.views.PropertySheet";

//Outline
public final static String VIEW_ID_OUTLINE = "org.eclipse.ui.views.ContentOutline";

Update(2007/4/9): Eclipse提供的IPageLayout接口里已经包含了这些ID,直接使用更方便,例如IPageLayout.ID_OUTLINE

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/01/10/616998.html

关于WSRP服务的异步调用

Portal可以将不同的Web应用聚合在同一页面,而Web Services for Remote Portlets (WSRP)规范允许Portal聚合远程Portal Server提供的Portlet,在这种关系下,远程Portal被称为Producer,本地Portal被称为Consumer,最终用户只访问Consumer,并不需要了解Producer的存在。WSRP和普通Web Services比起来更容易使用,因为界面部分已经由Producer提供了,我们只要在Consumer里做一些设置而不是编写JSP代码。

听起来不错,但为此我们也许要付出些代价,其中我想最突出的是性能问题。因为Consumer在向最终用户返回聚合后的页面前,必须等待所有Portlet包括远程Portlet返回结果,这样,只要有一个Portlet响应时间较长,整个页面就变得很慢。在使用WSRP时,用户到Consumer一般是远程访问,而Consumer到Producer也是远程的,这必然带来额外的时间开销。

一个可能的解决方法是在Consumer里异步显示每个Portlet(或仅异步显示那些远程Portlet),AJAX技术听起来是一个不错的选择,lao_lee的这篇文章里曾提到他们有过类似的想法:

05年时我们曾经的一个idea是,把每一个portlet封装为一个web service服务点, (WSRP已经可以作到这一点), 然后改进聚合器,让聚合器首先把页面的框架和js返回,然后每一个portlet通过AJAX请求异步拿到自己的内容. 这里涉及到一个关键问题是URL改写.

我想除了URL改写以外还有些问题必须处理。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/12/27/605510.html

改变GMF应用程序画布的布局

在GMF帮我们生成的应用程序里,画布(Canvas)的布局缺省是使用XYLayout的,这种布局适合UML类图、流程图等应用,但并不适合序列图或表格这类应用。而且目前GMF的.gmfgraph模型里没有提供为整个Canvas设置布局的地方,因此只能通过修改代码的方式实现。因为GMF Runtime是基于GEF的,即GMF生成的代码本质上也是一个GEF应用程序,所以根据以往编写GEF应用程序的经验,不难找到需要修改的地方。

首先要修改作为画布的那个EditPart(下称yourCanvasEditPart),这个类是从gmf的DiagramEditPart继承过来的,看一下后者的createDefaultEditPolicies()方法就会发现它的LAYOUT_ROLE的EditPolicy是gmf的XYLayoutEditPolicy:

installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy());

GEF里同一个EditPart上要覆盖一个已有EditPolicy的方法是使用同样的Role安装新的EditPolicy,所以我们应该在yourCanvasEditPart的createDefaultEditPolicies()方法里使用LAYOUT_ROLE安装自己的EditPolicy,这里为方便使用了GEF提供的FlowLayoutEditPolicy,你若有特殊需要可实现自己的EditPolicy:

installEditPolicy(EditPolicy.LAYOUT_ROLE, new FlowLayoutEditPolicy() {

    @Override
    protected Command getCreateCommand(CreateRequest request) {
        return null;
    }

    @Override
    protected Command createMoveChildCommand(EditPart child,
            EditPart after) {
        return null;
    }

    @Override
    protected Command createAddCommand(EditPart child, EditPart after) {
        return null;
    }

    @Override
    protected boolean isHorizontal() {
        return true;
    }

});

我们知道,GEF里每个EditPart上作为LAYOUT_ROLE安装的EditPolicy应该和此EditPart对应的Figure使用的LayoutManager匹配,例如XYLayoutEditPolicy对应XYLayout,而FlowLayoutEditPolicy匹配的LayoutManager就是FlowLayout或ToolbarLayout,这两个LayoutManager最大的区别是前者允许子图形换行(列)排列,而后者只能有一行(列)。要注意一点,FlowLayoutEditPolicy与ToolbarLayout一起使用存在一点问题,原因是在FlowLayoutEditPolicy的isHorizontal()方法里认为传入的layoutmanager参数是FlowLayout,因此我们在上面代码里覆盖了isHorizontal()方法,至于返回true或false根据你的需求决定。

现在,为了匹配修改后使用的FlowLayoutEditPolicy,我们要覆盖yourCanvasEditPart的createFigure()方法,在父类DiagramEditPart里这个方法返回的Figure使用的是FreeFormLayout,我们现在需要的是ToolbarLayout,所以:

protected IFigure createFigure() {
    Figure f = new FreeformLayer();
    ToolbarLayout layout = new ToolbarLayout();
    layout.setVertical(false);
    layout.setSpacing(10);
    layout.setStretchMinorAxis(true);
    f.setLayoutManager(layout);
    f.setBorder(new MarginBorder(15));
    return f;
}

经过这样两处修改后,你的编辑器应该已经像下图所示这样了(可能还有些细节代码需要处理一下):

file

GMF在GEF基础上做了很多包装,例如添加了SemanticEditPolicy、CanonicalEditPolicy等等新的EditPolicy,以及相关的很多Command和EditPart,它们为GMF应用程序提供了新的功能,虽然掌握GMF Runtime的API需要花些时间,但这允许我们在不进行大规模编写代码的情况下获得符合需求的图形化编辑器,建议先提前了解一下。

Update(2007/07/17): 在GMF 2.0里,可以通过设置xxx.gmfgen文件里Figure Viewmap的"Layout Type"属性为"TOOLBAR_LAYOUT"达到同样目的。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/12/25/603074.html