IBM x346服务器两个问题和解决

服务器型号IBM x346,使用随机提供的Server安装光盘配置并安装Windows 2003 Server英文标准版。

问题1:安装了5G物理内存,在Win2003 server里只能认出3.36G。

解决方法:在c:\boot.ini里加/PAE参数可以认到4G内存,但Win2003 server standard版最多支持4G内存,要想完全解决需要advanced server。

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Standard" /fastdetect /NoExecute=OptOut /PAE

问题2:在RAID界面可以看到硬盘为146G,但在Win2003 server里只看到一个48.8G的c盘。

解决方法:在Control Panel->Administrative Tools->Computer Management里选Disk Management,应该可以看到剩余未被划分的空间,创建为新的逻辑分区并格式化即可。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/11/28/575550.html

EMF里EReference的containment和container属性

EReference的containment属性如果为true,表示目标EClass是被源EClass包含的,这是一种十分强的关系,例如汽车和车轮的关系。在ecore里,不允许包含关系形成圈,也就是说如果A包含B,B就不能再直接或间接的包含A;另外,如果作为容器的对象结束了自己的生命周期,被它包含的对象也将结束自己的生命周期。

如果一个EReference有作为EOpposite的EReference,并且后者的containment属性为true,则这个EReference的container属性为true。换句话说,一个EReference的container属性表示它指向的EClass是否为包含者。

public boolean isContainer()
{
  EReference theOpposite = getEOpposite();
  return theOpposite != null && theOpposite.isContainment();
}

最后,container属性是derived属性,所以在ecore编辑器里我们无法直接编辑一个EReference的这个属性。

参考资料

http://dev.eclipse.org/newslists/news.eclipse.tools.emf/msg01448.html

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/11/20/566556.html

[Eclipse]RCP程序的启动进度条

在RCP应用的.product文件里指定Add a progress bar和进度条的尺寸以后,进度条很可能并未如你设想中出现在Splash图片上,解决的方法如下:

1、在.product文件同一目录里创建customization.ini文件,包含这样的文本内容:

org.eclipse.ui/SHOW_PROGRESS_ON_STARTUP=true

2、在plugin.xml里的org.eclipse.core.runtime.products扩展点下的对应product下添加属性preferenceCustomization,值为customization.ini;这个扩展点一般是在编辑.product文件后导出RCP时自动生成的。

3、为让所有的修改生效,可能需要以-clean方式启动你的RCP程序。

4、进度条的位置和大小也可直接在plugin.xml里指定,同样是对应product下的属性,分别为startupProgressRect和startupMessageRect,属性值例如10,290,200,16,前两个数字是位置,后两个是尺寸。

file

BTW,在3.3版本的Eclipse里可能会免去在customization.ini文件里做设置的步骤。

补充(2009.8.20):控制perspective切换按钮位置用org.eclipse.ui/DOCK_PERSPECTIVE_BAR = topRight

参考资料

http://www.eclipsezone.com/eclipse/forums/m92055175.html
http://eclipsezone.com/eclipse/forums/m92053781.html

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/10/31/545974.html

GMF常见问题和解决

本文记录在使用GMF开发图形化桌面应用的过程中,遇到的若干问题和解决方法。

1、问题:连接线旁边没有文字标签和箭头

文字标签:在gmfmap里的Connection Mappping下增加Label Mapping元素;箭头:在gmfgraph里为Polyline Connection指定一个Polyline Decorator作为source/target decoration,要为这个Decorator创建一些Template Point来决定箭头的形状,例如指定(-1,-1), (0,0), (-1,1)。

2、让一个图形可以在另一个图形里随意改变位置

在gmfgen里把作为容器的那个图形的Gen Compartment里把Listlayout属性改为false。

3、隐藏图形标签文字前的小图标

在gmfgen里把相应的Gen Node Label元素的Element Icon属性改为false(但重新生成gmfgen时这个属性会被覆盖)

4、让标签里同时显示和编辑多个属性

在gmfmap里把相应的Label Mapping元素的View Pattern属性改为类似“属性1:{0},属性2:{1}”的形式。

5、问题:跨Compartment进行连线操作时会创建两条连线

GMF的bug,见https://bugs.eclipse.org/bugs/show_bug.cgi?id=148021,在你的XXXDiagramCanonicalEditPolicy里覆盖方法:

protected boolean shouldHandleNotificationEvent(Notification event) {
    return false;
}

6、让Label出现在图元外面

在gmfgraph里定义这个Figure时把Label定义在外面,而非定义为Figure的子元素。

7、在gmfgraph里设置一个Figure使用GridLayout后生成的代码无法正确编译

GMF的bug,见https://bugs.eclipse.org/bugs/show_bug.cgi?id=133279

8、改变Figure的缺省大小

在gmfgraph里为Figure增加Preferred Size子元素;若想让图形尺寸小于40x40象素,要覆盖XXXEditPart里的createNodePlate()方法。在GMF2.0里,使用DefaultSizeFacet,见http://dev.eclipse.org/newslists/news.eclipse.modeling.gmf/msg01546.html

9、禁止用户修改图元的尺寸

在gmfgraph里将此Node的Resize Constraint属性值改为“NONE”(但size-on-drop功能仍存在,也就是用户仍然可以在创建时指定尺寸)。

10、让Compartment在容纳不下子图形时自动显示滚动箭头

在genmodel的GenDiagram元素里改Units属性为“himetric”(经测试对GMF1.0不起作用),见https://bugs.eclipse.org/bugs/show_bug.cgi?id=140789

11、为画布Canvas指定Layout

GMF1.0不支持,需要手工改代码,见https://bugs.eclipse.org/bugs/show_bug.cgi?id=139951

12、Border Item

Border Item是指只能紧贴其他图元运动的图形,GMF1.0可通过打patch实现这个功能,见https://bugs.eclipse.org/bugs/show_bug.cgi?id=124826;GMF2.0开始支持。

13、规定连接线的约束,例如规定source和target不能是同一对象

在gmfmap里定义,在Link Mapping元素下定义Link Constraint元素,缺省使用OCL,见教程http://wiki.eclipse.org/index.php/GMF_Tutorial_Part_2#Link_Constraints;不论使用OCL或是Java,在XXXBaseItemSemanticEditPolicy里会生成LinkConstraint类,在生成command前检查是否满足这些constraint。

14、Audit

定义的constraint出现在com.your.diagram项目的plugin.xml里,作为constraintProvider扩展;为了让这些constraint生效,要在gmfgen的Gen Diagram元素里设定Validate Enabled/Decorator属性值为true,并将优先级(Validation Provider Priority, Validation Decorator Provider Priority)设定为medium(非lowest)才会在Diagram菜单里出现Validate命令。

若是在gmfmap里选择使用Java验证,则在gmfmap里指定的是一个Java方法名,生成代码后,应在XXXValidationProvider类里应实现这个方法。

15、GMF里从EditPart得到Semantic Model

因为GMF里EditPart#getModel()方法得到的是Notation Model里的对象,如Node或Edge,所以可以使用这样的方法得到真正的业务对象:((org.eclipse.gmf.runtime.notation.View) EditPart.getModel()).getElement()或ViewUtil.resolveSemanticElement(view)

16、问题:从gmfgen生成代码时产生java.lang.ClassCastException: org.eclipse.jdt.internal.core.jdom.DOMMethod

删除原先生成的代码中无法编译的类,重新生成。

17、在gmfgraph里定义Polyline的图形

在Rectangle上画Polyline,注意是固定大小的

18、问题:每次重新生成代码后,在plugin.xml里的修改会丢失

GMF1.0里生成代码时不能保留plugin.xml里的任何修改,从GMF2.0开始用户可以在plugin.xml里标记不要覆盖的区域

19、问题:Outline树视图里的节点没有图标

在plugin.xml里找到org.eclipse.gmf.runtime.emf.type.core.elementTypes扩展点,在下面相应的元素里指定icon属性,见http://dev.eclipse.org/newslists/news.eclipse.modeling.gmf/msg00341.html,但我在GMF1.0里测试不起作用,何况每次生成代码时这个文件都会被覆盖。

20、问题:提示java.lang.IllegalStateException: Cannot modify resource set without a write transaction异常

在GMF里修改Model要通过在TransactionalEditingDomain里执行命令完成,GMF提供的RecordingCommand是不错的选择,它为我们提供了Undo支持,我们只要实现执行部分的代码就可以了,下面是一个例子:

TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(myElement);
domain.getCommandStack().execute(new RecordingCommand(domain) {
    @Override
    protected void doExecute() {
        //Do anything
    }
});

若是在EditPolicy里需要返回一个Command,用下面的代码:

AbstractTransactionalCommand command = new AbstractTransactionalCommand(TransactionUtil
        .getEditingDomain(myElement), "Command Name", Collections.EMPTY_LIST) {
    @Override
    protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info)
            throws ExecutionException {
        //Any modification to the model
        return CommandResult.newOKCommandResult();
    }
};

21、问题:创建图元时提示异常“java.lang.IllegalArgumentException: Figure must be a child”

Workaround:注释掉产生异常的setRatio()方法里的全部内容。

22、问题:在AbstractBorderItemEditPart子类的getPrimaryDragEditPolicy()方法里提示ClassCastException异常

在gmfgraph里检查作为BorderItem的那个Node的Resize Constraint属性是否改过,若为缺省的NSEW则对应的editpart不会生成这个方法,对BorderItem(即Affixed Node Side属性不为NONE的Node)来说这个属性虽然设置为NSEW也无法改变大小。相关链接:https://bugs.eclipse.org/bugs/show_bug.cgi?id=155698

23、如何禁用PopupBar和ConnectionHandler功能(鼠标停止在图形上时出现的连线符号)

在需要禁用该功能的EditPart的createDefaultEditPolicies()方法的最后加下面的语句:

//禁用PopupBar
removeEditPolicy(EditPolicyRoles.POPUPBAR_ROLE);
//禁用ConnectionHandler
removeEditPolicy(EditPolicyRoles.CONNECTION_HANDLES_ROLE);

24、使用ConnectionHandler连接到canvas上已存在的图形或创建新的图形

覆盖XXXModelingAssistantProvider里的几个get方法,要连接到已存在的图形覆盖getRelTypesOnSourceAndTarget()方法,创建新的作为源的图形覆盖getRelTypesOnSource()和getTypesForTarget()方法,创建新的作为目标的图形应覆盖getRelTypesOnTarget()和getTypesForSource()方法。具体代码可参考LogicModelingAssistantProvider里的实现。

25、给画布加背景图

http://www.cnblogs.com/bjzhanghao/archive/2007/03/13/673273.html

BTW, 以上所有问题只针对GMF1.0,GMF2.0的gmfmap模型和gmfgen模型与前一版本有所不同,一些问题可能也在GMF2.0里不存在了。

26、使用Label作为一个editpart的figure

在.gmfgraph里不用创建Node,只用Diagram Label即可;在.gmfmap里,Node Mapping的Diagram Node属性指定为这个Diagram Label,下面的Feature Label Mapping的Diagram Label属性也是这个Diagram Label。在parent使用ListLayout的时候这个方法比较有用。GMF的mindmap例子里的ThreadItem就是这样一个例子。

27、若类A包含B和C,且C继承B,则试图让A的图形同时包含B和C会造成运行时异常,异常信息是无法创建C的View,可能是GMF目前版本的bug。解决办法是建立抽象类D,让B和C都继承D,并且让A包含D。(update 2007/7/23: 有一点像这个bug,异常信息差不多)

update(2008/10/09): 今天再次遇到了这个问题,复制异常信息如下以便查找:

org.eclipse.core.commands.ExecutionException: While executing the operation, an exception occurred
    at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:519)
...
Caused by: org.eclipse.core.runtime.AssertionFailedException: null argument:failed to create a view
    at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:86)
    at org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand.doExecuteWithResult(CreateCommand.java:99)

28、用渐变色填充非矩形图形

覆盖图形的fillShape()方法,利用swt的Path,但draw2d的graphics对它的支持似乎不好。http://dev.eclipse.org/newslists/news.eclipse.tools.gef/msg13928.html

29、(这条实际是关于EMF的,anyway)为TableViewer增加Drag and Drop支持

非常简单,见下面的代码(tv是TreeViewer的一个实例)

int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() };
tv.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(tv));
tv.addDropSupport(dndOperations, transfers, new EditingDomainViewerDropAdapter(editingDomain, tv));

30、从EObject得到TransactionalEditingDomain

TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(eobject);

31、让Label换行

.gmfgraph里无法指定Label是否换行,要修改生成的代码:

fFigureXXXFigure = new WrapLabel();
fFigureXXXFigure.setTextWrap(true);//add this line
fFigureXXXFigure.setText("<>");

另外可以在.gmfgraph里指定需要的布局以便让换行Label更好的显示。给Label设置Margin Border会有问题(Label被推向右侧),可以给Parent图形设置Margin Border,或建一个RectangleFigure来实现设置文字边距的需求。

32、定制Project Exploerer里显示的内容

修改.gmfgen里Gen Navigator节点下面的元素,见http://wiki.eclipse.org/index.php/GMF_Tutorial_Part_4#Project_Navigator

33、可缩放的多边形

在.gmfgraph里定义为Scalable Polygon,和普通Polygon一样要定义template points,每个点的坐标绝对值不是关键,但它们之间的位置关系要保证。我发现绝对值定义得大一些时,得到的结果会更精确。下面是一个可缩放菱形的定义:

<descriptors name="ConditionFigure">
  <actualFigure xsi:type="gmfgraph:ScalablePolygon" name="MyDiamondFigure">
    <template x="200" y="0"/>
    <template x="0" y="200"/>
    <template x="200" y="400"/>
    <template x="400" y="200"/>
    <template x="200" y="0"/>
  </actualFigure>
</descriptors>

34、生成的RCP应用里,保存操作后经常提示“the file has been modifying on the file system...”信息。

GMF太“聪明”了,每次save后都要记录文件修改的timestamp,一旦发现不符则认为有其他程序修改了这个文件。要让RCP应用不检查当前编辑的文件是否被其他程序修改,可覆盖XXXDocumentProvider的isSynchronized()方法,让它直接“return super.isSynchronized(element);”。(但要小心,这有可能造成用户的修改无法被保存的情况。)

35、生成的GMF应用程序里,打印功能是禁用状态。

打开.gmfgen文件,修改Gen Plugin的"Printing Enabled"属性为true,再重新生成代码。这样除了 Print变为可用外,GMF还会生成一个XXXContributionItemProvider类在主菜单上添加Print Preview选项。 http://dev.eclipse.org/newslists/news.eclipse.modeling.gmf/msg02207.html

36、(实际是Eclipse OCL问题)脱离Eclipse环境使用OCL时,报异常java.lang.NoClassDefFoundError: lpg/lpgjavaruntime/RuleAction

Eclipse OCL依赖lpg库(LALR parser generator,使用EPL协议),在RCP里使用OCL需要把net.sourceforge.lpg.lpgjavaruntime这个插件加在dependencies列表里。参考链接

37、(还是OCL问题)Eclipse OCL实现里,OCL语句里各集合类型与ecore里集合类型的映射:

Collection Type isUnique isOrdered
Bag N N
Sequence N Y
Set Y N
OrderedSet Y Y

所以,如果一个EList在ecore里定义为Unique且Ordered(即缺省定义)时,在OCL里应该用OrderedSet类型,例如:XXX->allInstances()->asOrderedSet()或OrderedSet{object1, object2},等等。

38、在画布上创建一个元素(包括连接)后根据当前模型状态自动设置某属性值:

(GMF允许通过多种语言如ocl、regexp和java来实现初始值的设置,这里以java为例)在xxx.gmfmap文件里,找到这个元素对应的Mapping节点(如Node Mapping或Link Mapping),点右键新建一个Feature Seq Initializer元素,在这个元素上点右键再新建一个Feature Value Spec元素,设置后者的Feature为想要设置的类型,语言选java,在Body属性里输入一个方法名,例如“initialMyFeature”。重新生成.gmfgen和代码,GMF会在名为ElementInitializers.java的文件里生成initialMyFeature()这个空壳方法,实现它即可。

39、新建向导结束后,生成一个非空的模型文件。(Customize新创建的模型文件)

修改XXXDiagramEditorUtil#createInitialModel()方法。

40、在partition diagram里,从shortcut到一个正常节点间的连线在关闭editor后再次打开时丢失(2008.1.4)

原因不明,暂时的解决方法是注释掉XXXCanonicalEditPolicy#refreshConnections()方法里的deleteViews(existingLinks.iterator()),其中XXX代表link元素的父元素,例如Diagram。

Update: 上面的方法有严重问题,会造成Initialize Diagram时丢失全部连接。新探索出来的解决方法如下,覆盖XXXCanonicalEditPolicy#sholdDeleteView()方法:

/**
* @generated NOT
*/
protected boolean shouldDeleteView(View view) {
    if(view instanceof Edge){
        Edge edge = (Edge)view;
        View sourceView = edge.getSource();
        View targetView = edge.getTarget();
        if(sourceView.getEAnnotation("Shortcut")!=null 
                || targetView.getEAnnotation("Shortcut")!=null){
            return false;
        }
    }
    return true;
}

41、删除右键菜单里不需要的菜单项

在plugin.xml里声明contributionItemProviders扩展点,在popupContribution下指定如下元素:

<popupPredefinedItem id="autoSizeAction"remove="true"/>

一些GMF Runtime定义的ID:deleteFromModelAction, navigateGroup, fileMenu, toolbarArrangeAllAction, addGeoShapesGroup, addGeoShapes2Group

详见org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds

42、在单独的编辑窗口里编辑子图(Diagram Partitioning)

http://wiki.eclipse.org/Diagram_Partitioning

43、在单独的项目(非GMF生成的xxx.diagram项目)里扩展DiagramEditor能识别的adapter类型:

在单独项目的Activator的start()方法里用类似下面的代码,这样就不需要直接修改生成的XXXDiagramEditor#getAdapter()方法了(因为我们希望把定制的内容尽量放在生成的项目以外):

//Register adapters for ERM reports and charts
Platform.getAdapterManager().registerAdapters(new IAdapterFactory() {

    /**
     * @see org.eclipse.core.runtime.IAdapterFactory
     */
    public Object getAdapter(Object adaptableObject, Class adapterType) {
        ErmDiagramEditor editor = (ErmDiagramEditor) adaptableObject;
        Process process = (Process) editor.getDiagram().getElement();
        if (adapterType == IRiskImportancePage.class) {
            return new RiskImportancePage(process);
        } else if (adapterType == IRiskDrillDownPage.class) {
            return new RiskDrillDownPage(process);
        }

        return null;
    }

    /**
     * @see org.eclipse.core.runtime.IAdapterFactory
     */
    public Class[] getAdapterList() {
        return new Class[] { IRiskImportancePage.class, IRiskDrillDownPage.class };
    }

}, ErmDiagramEditor.class);
  1. 允许创建shortcut

在.gmfgen的Gen Diagram元素的属性“Shortcuts Provided”和"Contains Shortcuts To"里设置相应的model名字,然后重新生成代码,这样画布的右键菜单里将出现“Create Shortcut...”菜单项。参考http://wiki.eclipse.org/GMF_Tutorial_Part_2#Shortcuts

  1. 提示“Cannot activate read/write transaction in read-only transaction context”

在editpolicy的getXXXCommand()里不能直接对模型进行操作,否则将提示上面的异常,应该返回一个ICommandProxy(yourCommand) ,其中yourCommand一般继承自AbstractTransactionalCommand。参考http://dev.eclipse.org/mhonarc/newsLists/news.eclipse.modeling.gmf/msg04366.html

  1. (实际是OCL问题)在ocl语句里增加预定义的变量,当变量是集合类型时,如何setType:
OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl;
ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);

//Customize this OCL environment
Variable appContextVar = ExpressionsFactory.eINSTANCE.createVariable();
appContextVar.setName("customers");
EClassifier type = TypeUtil.resolveSequenceType(ocl.getEnvironment(), EcorePackage.Literals.ORDERED_SET_TYPE);
appContextVar.setType(type);
ocl.getEnvironment().addElement(appContextVar.getName(), appContextVar, true);

try {
    OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
    helper.setContext(SpmsPackage.Literals.SP_SERVICE_PLAN);
    OCLExpression<EClassifier> exp = helper.createQuery(metric.getFormula());//Seems this call is time costly
    Query<EClassifier, EClass, EObject> query = ocl.createQuery(exp);
    query.getEvaluationEnvironment().add(appContextVar.getName(),
            SpmsResourceManager.getInstance().getCustomerModel().getCustomers());
    Object object = query.evaluate(servicePlan);
    System.out.println(object);
    if (object instanceof Number) {
        result = ((Number) object).doubleValue();
    }
} catch (ParserException e) {
    e.printStackTrace();
}
ocl.dispose();

47、创建一个新的Diagram实例

GMF生成代码时同时生成了工具类XXXDiagramEditorUtil,调用XXXDiagramEditorUtil.createDiagram()即可创建新的Diagram实例。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/10/26/541262.html

[Eclipse]让多个Viewer对应一个属性视图

为了让用户在WorkbenchPart(如IEditorPart)的Viewer(如TableViewer)里选择一个对象时,属性视图里能显示这个元素的属性,一般会将这个Viewer设置为该WorkbenchPart的site的selectionProvider:

editPart.getSite().setSelectionProvider(theViewer);

但如果是一个WorkbenchPart里有多个Viewer的情况呢?我们可以实现为当用户在任意一个Viewer里选择了一个对象后,属性视图里显示这个对象的属性。为此,根据黄老大的提示,需要写一个CompositeSelectionProvider,它实现ISelectionChangedListener以监听每个Viewer的选择事件,同时它要实现ISelectionProvider,因为我们要把它设置为该site的selectionProvider:

class CompositeSelectionProvider implements ISelectionProvider, ISelectionChangedListener {
    ISelection selection;

    List listeners = new ArrayList();

    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        listeners.add(listener);
    }

    public ISelection getSelection() {
        return selection;
    }

    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        listeners.remove(listener);
    }

    public void setSelection(ISelection selection) {
        this.selection = selection;
        final SelectionChangedEvent e = new SelectionChangedEvent(this, selection);
        Object[] listenersArray = listeners.toArray();

        for (int i = 0; i < listenersArray.length; i++) {
            final ISelectionChangedListener l = (ISelectionChangedListener) listenersArray[i];
            Platform.run(new SafeRunnable() {
                public void run() {
                    l.selectionChanged(e);
                }
            });
        }
    }

    /*****************************************************************
    ************** ISelectionChangedListener implementation **********
    ******************************************************************/
    public void selectionChanged(SelectionChangedEvent event) {
        setSelection(event.getSelection());

    }

}

在WorkbenchPart#createPartControl()方法里让这个CompositeSelectionProvider监听每个viewer的选择事件,并把它设置为site的selectionProvider,代码如下:

//The composite selectionProvider instance
CompositeSelectionProvider compositeSelectionProvider=new CompositeSelectionProvider();

public void createPartControl(Composite parent) {
    ...
    viewer1.addSelectionChangedListener(compositeSelectionProvider);
    viewer2.addSelectionChangedListener(compositeSelectionProvider);
    ...
    getSite().setSelectionProvider(compositeSelectionProvider);
}

 注:在这篇教程里也有类似的解决方法,见“Multiple Selection Providers Within a Part”一节。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/10/23/537205.html

[Eclipse]让输出的Plug-in文件名里包含当前时间

在MANIFEST.MF里指定的Bundle-Version时一般是1.0.0的形式,这样输出的Plug-in文件会是com.my.plugin_1.0.0.jar

其实还可以用qualifier关键字让Eclipse在输出这个Plug-in时在文件名里增加输出时的时间,精确到分。例如指定Bundle-Version为1.0.0.qualifier,则输出的文件名就是com.my.plugin_1.0.0.200609131335.jar,这个技巧在开发测试时比较有用,从文件名就能分辨Plug-in的新旧。

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

给GMF应用程序添加自定义Action

假设GMF为你生成的项目名称为com.example.diagram,现在要在右键菜单里增加一个自定义命令,并关联在名为Activity的模型元素上,即只有在Activity类型的元素上点右键,弹出菜单里才有这个自定义命令。此命令的功能是简单的把该Activity的Name属性改为Modified Activity。实现的步骤如下:

1、如果之前没有创建过,则创建一个名为com.example.diagram.custom的plugin项目(以下简称为custom项目),新建这个项目的目的是把自己的定制与GMF生成的代码分开;

2、在custom项目里实现org.eclipse.ui.popupMenus扩展点,这样会在右键菜单里多出一个"Change"菜单项,下面有"Name"命令;

<extension
         point="org.eclipse.ui.popupMenus">
  <objectContribution
        adaptable="false"
        id="com.example.custom.objectContribution.ActivityEditPart"
        objectClass="com.example.diagram.edit.parts.ActivityEditPart">
     <menu
           id="BMAChange"
           label="&Change"
           path="additions">
        <separator name="group1"/>
     </menu>
     <action
           class="com.example.diagram.popup.ChangeActivityNameAction"
           enablesFor="1"
           id="com.example.diagram.popup.ChangeActivityNameAction"
           label="&Name"
           menubarPath="BMAChange/group1"/>
  </objectContribution>
</extension>

3、实现上一步里定义的Action类ChangeActivityNameAction,这个类不仅要实现IObjectActionDelegate(popupMenus扩展点的要求),还要继承自AbstractActionDelegate这个类(GMF的要求)。我们要做的是实现doRun()方法,首先取得当前选中的editpart,然后创建一个SetRequest实例,它包含了改变属性操作的所有信息,包括目标对象、属性的名字和新属性值。因为GMF里editpart的getModel()方法不是业务模型里的元素了,而是View对象,要再调用View#getElement()才能得到业务模型里的元素,所以代码里我们利用ViewUtil#resolveSemanticElement()方法直接得到Activity对象。另外,GMF使用了EMFT的Transaction项目来操作模型,所以editpart.getEditingDomain()方法得到的会是一个TransactionalEditingDomain类型。

有了request,我们用它作为构造参数创建一个SetValueCommand(),这是一个GMF命令(实现org.eclipse.gmf.runtime.common.core.command.ICommand),用来改变属性值。最后要执行这个命令,我们知道command是要用CommandStack来执行的,这样才能undo/redo,但editpart.getDiagramEditDomain().getDiagramCommandStack()得到的CommandStack只能执行GEF的命令(org.eclipse.gef.commands.Command),所以要把我们的command用ICommandProxy()包装一下,这样就没问题了。

public class ChangeActivityNameAction extends AbstractActionDelegate 
                implements IObjectActionDelegate {

    protected void doRun(IProgressMonitor progressMonitor) {

        // Get the selected edit part
        IStructuredSelection structuredSelection = getStructuredSelection();
        Object selection = structuredSelection.getFirstElement();
        IGraphicalEditPart editpart = (IGraphicalEditPart) selection;

        // Create a command to modify its property
        SetRequest request = new SetRequest(
                editpart.getEditingDomain(),
                ViewUtil.resolveSemanticElement((View) editpart.getModel()),//The semantic model 
                BmaPackage.Literals.ACTIVITY__NAME,//Name feature of activity
                "Modified Activity");//New name value
        SetValueCommand command = new SetValueCommand(request);

        //Do the work
        editpart.getDiagramEditDomain().getDiagramCommandStack().execute(new ICommandProxy(command));

    }
}

Update: 可以用IGraphicalEditPart#resolveSemanticElement()直接取得editpart对应的EObject,IGraphicalEditPart#getNotationView()是得到View对象,和getModel()作用一样。

运行效果如下,选择修改名字命令后,Activity1的名字改为Modified Activity,并且可以undo/redo:

file

参考资料

GMF提供的Logic例子中CreateLogicElementActionDelegate.java文件
GMF Tips,Change Names Of Newly Created Elements小节
GMF Tutorial Part 3

Update(2007/07/17): GMF更推荐使用IOperationHistory来修改模型,例如在Action的doRun()方法里像下面这样写:

AbstractTransactionalCommand command = new AbstractTransactionalCommand(
        editingDomain,
        "Modifying the model", Collections.EMPTY_LIST) { 
    protected CommandResult doExecuteWithResult(
            IProgressMonitor monitor, IAdaptable info)
            throws ExecutionException {
        //在这里修改模型
        return CommandResult.newOKCommandResult();
    }
};
try {
    OperationHistoryFactory.getOperationHistory().execute(command,
            new SubProgressMonitor(progressMonitor, 1), null);
} catch (ExecutionException e) {
    MindmapDiagramEditorPlugin.getInstance().logError(
            "Unable to create model and diagram", e); //$NON-NLS-1$
}

因为在GMF新闻组里提到过(原文链接):

in a GMF application, you should probably never execute commands in a CommandStack, because it will not be worth the effort of coordinating the IUndoContexts applied to these commands and your GMF AbstractTransactionalCommands to ensure that the Undo/Redo menus make sense.

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/09/06/496394.html

关于Draw2D里的Layout

就像在swt里我们使用layout来控制各个控件的摆放位置一样,在Draw2D里最好也把这个工作交给LayoutManager来做。除非是在自己实现的Layout里,一般程序里自己不要轻易使用setBounds()setLocation()setSize()这些方法控制图形的位置和大小,而应该在为每个图形设置了适当的LayoutManager后,通过setConstraint()setPreferredSize()等方法告诉layoutmanager如何布局。

在需要的时候,父图形的布局管理器负责修改每个子图形的位置和大小,但计算每个子图形大小的工作可能是交给子图形自己的LayoutManager来做的,计算的方法一般是在这个LayoutManager的getPreferredSize()方法里体现。

例如当父图形使用XYLayout,子图形使用ToolbarLayout时,假设在子图形里又增加了子子图形(子图形里的子图形),add()方法会导致revalidate()的调用,这时父图形的xylayout将检查子图形是否具有constraint,如果有并且有至少一个方向为-1,则利用子图形上的ToolbarLayout计算出子图形新的尺寸,这个尺寸是和子图形里包含的子子图形的数目有关的(ToolbarLayout会把每个子图形的宽/高度加起来,加上其中间隔的空间,再考虑图形的边框,返回得到的尺寸)。

XYLayout对layout(IFigure)方法的实现:

public void layout(IFigure parent) {
    Iterator children = parent.getChildren().iterator();
    Point offset = getOrigin(parent);
    IFigure f;
    while (children.hasNext()) {
        f = (IFigure)children.next();
        Rectangle bounds = (Rectangle)getConstraint(f);//因此必须为子图形指定constraint
        if (bounds == null) continue;

        if (bounds.width == -1 || bounds.height == -1) {
            Dimension preferredSize = f.getPreferredSize(bounds.width, bounds.height);
            bounds = bounds.getCopy();
            if (bounds.width == -1)
                bounds.width = preferredSize.width;
            if (bounds.height == -1)
                bounds.height = preferredSize.height;
        }
        bounds = bounds.getTranslated(offset);
        f.setBounds(bounds);
    }
}

Draw2D里Figure类的setPreferredSize(Dimension)setSize(Dimension)的区别是,setSize()方法不会调用revalidate()方法导致重新layout,而只是调用repaint()对所涉及到的“脏”区域进行重绘(repaint)。setPreferredSize()方法可以约等于setSize()方法+revalidate()方法,因为在Figure对getPreferredSize(int,int)的实现里,若该figure没有任何layoutmanager,则返回当前size:

public Dimension getPreferredSize(int wHint, int hHint) {
    if (prefSize != null)
        return prefSize;
    if (getLayoutManager() != null) {
        Dimension d = getLayoutManager().getPreferredSize(this, wHint, hHint);
        if (d != null)
            return d;
    }
    return getSize();
}

只要看一下ToolbarLayout.java就会知道,ToolbarLayout对constraint是不感兴趣的,调用它的getConstraint()永远返回null值,所以我们不必对放在使用ToolbarLayout的图形的子图形设置constraint。因此,假如我们的问题是,有图形A包含B,B包含C,要实现B(使用ToolbarLayout)尺寸随C数目多少而自动改变该如何做呢?这要看A使用何种LayoutManager,如果是ToolbarLayout则不用做特殊的设置,如果是XYLayout则要用A.getLayoutManager().setConstraint(B,new Rectangle(x,y,-1,-1))这样的语句为A设置constraint,对图形C则用setPreferredSize()指定实际大小。

一个Layout的例子,点此下载,截图如下。

file

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/09/05/495747.html