GMF之Shapes实例Part4:为结点Node设置右击菜单并更换图片

柔情痞子 提交于 2019-12-10 17:39:17

在上一篇文章中,我们实现了为结点设置图片,但是我们还不能修改结点的图片,所有相同类型结点的图片是一样的。

本例首先给结点添加右击菜单,然后实现修改结点图片的功能。

1、修改ReserveShape1EditPart.java的部分代码,把descriptor、originalImage、OrgImageData声明处的static都去掉,否则修改一个结点之后,同类型的其他结点也会改变。

/**
 * @generated NOT
 */
private ImageDescriptor descriptor = ShapesDiagramEditorPlugin
        .findImageDescriptor("icons/custom/ReserveShapeFigure.jpg");
private Image originalImage = descriptor.createImage();
private ImageData OrgImageData = originalImage.getImageData();

2、在ReserveShape1EditPart类中添加方法如下:

/**
 * @generated NOT
 */
public void setImageData(String imagePath) {
    descriptor = ShapesDiagramEditorPlugin.findImageDescriptor(imagePath);
    originalImage = descriptor.createImage();
    OrgImageData = originalImage.getImageData();
}

3、在工程org.eclipse.myTest.shapes.diagram下新建一个包org.eclipse.myTest.shapes.diagram.edit.actions,用于存放我们自己的Action。在这个包中新建一个类SetImageAction,内容如下:

package org.eclipse.myTest.shapes.diagram.edit.actions;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.transaction.RunnableWithResult;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIStatusCodes;
import org.eclipse.gmf.runtime.diagram.ui.requests.ChangePropertyValueRequest;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.core.util.PackageUtil;
import org.eclipse.myTest.shapes.diagram.edit.parts.ReserveShape1EditPart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;

public class SetImageAction extends DiagramAction {
    private static String actionid = "org.eclipse.myTest.shapes.diagram.edit.actions.SetImageAction";
    private static String actionText = "设置显示图片...";
    // id of the property this action will change
    private String propertyId = null;

    // name of the property this action will change
    private String propertyName = null;
    private EditPartViewer viewer = null;

    public SetImageAction(IWorkbenchPart workbenchPart, EditPartViewer viewer) {
        super(workbenchPart);
        this.viewer = viewer;
    }

    public SetImageAction(IWorkbenchPage workbenchPage, String propertyId,
            String propertyName) {
        super(workbenchPage);
        Assert.isNotNull(propertyId);
        Assert.isNotNull(propertyName);
        setPropertyId(propertyId);
        setPropertyName(propertyName);

    }

    public String getPropertyId() {
        return propertyId;
    }

    public void setPropertyId(String propertyId) {
        this.propertyId = propertyId;
    }

    public String getPropertyName() {
        return propertyName;
    }

    public void setPropertyName(String propertyName) {
        this.propertyName = propertyName;
    }

    @Override
    protected Request createTargetRequest() {
        return new ChangePropertyValueRequest(getPropertyName(),
                getPropertyId());
    }

    protected void updateTargetRequest() {
        ChangePropertyValueRequest request = (ChangePropertyValueRequest) getTargetRequest();
        request.setValue(getNewPropertyValue());
    }

    public void init() {
        super.init();
        setId(actionid);
        setText(actionText);
        setToolTipText(actionText);
        ISharedImages workbenchImages = PlatformUI.getWorkbench()
                .getSharedImages();
        setHoverImageDescriptor(workbenchImages
                .getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
        setImageDescriptor(workbenchImages
                .getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
        setDisabledImageDescriptor(workbenchImages
                .getImageDescriptor(ISharedImages.IMG_OBJ_FILE));

    }

    protected String getCommandLabel() {
        return actionText;
    }

    protected Object getNewPropertyValue() {

        String newImgPath = "icon/test.gif";
        return newImgPath;
    }

    @SuppressWarnings("rawtypes")
    protected Object getOperationSetPropertyValue(String id) {
        List set = getOperationSet();
        if (!set.isEmpty()) {
            IGraphicalEditPart primaryEditPart = (IGraphicalEditPart) set
                    .get(set.size() - 1);
            return getPropertyValue(primaryEditPart, id);
        }
        return null;
    }

    @SuppressWarnings({ "rawtypes", "restriction" })
    protected Object getPropertyValue(final IGraphicalEditPart editPart,
            final String thePropertyId) {

        try {
            return editPart.getEditingDomain().runExclusive(
                    new RunnableWithResult.Impl() {

                        @SuppressWarnings("unchecked")
                        public void run() {
                            setResult(getStructuralFeatureValue(editPart,
                                    thePropertyId));
                        }
                    });
        } catch (InterruptedException e) {
            Trace.catching(DiagramUIPlugin.getInstance(),
                    DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
                    "getPropertyValue", e); //$NON-NLS-1$
            Log.error(DiagramUIPlugin.getInstance(),
                    DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
                    "getPropertyValue", e); //$NON-NLS-1$
        }
        return null;
    }

    protected boolean isSelectionListener() {
        return true;
    }

    protected boolean digIntoGroups() {
        return false;
    }

    private Object getStructuralFeatureValue(IGraphicalEditPart editpart,
            final String thePropertyId) {
        ENamedElement element = PackageUtil.getElement(thePropertyId);
        if (element instanceof EStructuralFeature) {
            if (digIntoGroups() && editpart instanceof GroupEditPart) {
                editpart = (IGraphicalEditPart) editpart.getChildren().get(0);
            }
            return editpart
                    .getStructuralFeatureValue((EStructuralFeature) element);
        }
        return null;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected List getTargetEditParts(EditPart editpart) {
        if (digIntoGroups() && editpart instanceof GroupEditPart) {
            List targetEPs = new ArrayList();
            for (Iterator iterator = ((GroupEditPart) editpart)
                    .getShapeChildren().iterator(); iterator.hasNext();) {
                EditPart childEP = (EditPart) iterator.next();
                targetEPs.addAll(super.getTargetEditParts(childEP));
            }
            return targetEPs;
        }
        return super.getTargetEditParts(editpart);
    }

    protected boolean calculateEnabled() {
        EditPart editPart = viewer.getFocusEditPart();// 得到当前选中的EditPart
        if (editPart instanceof ReserveShape1EditPart) {
            Command command = getCommand();
            return command != null && command.canExecute();
        }

        return false;
    }

    @SuppressWarnings("rawtypes")
    protected Command getCommand(Request request) {
        List operationSet = getOperationSet();
        if (operationSet.isEmpty()) {
            return UnexecutableCommand.INSTANCE;
        }
        Iterator editParts = operationSet.iterator();
        CompositeTransactionalCommand command = new CompositeTransactionalCommand(
                getEditingDomain(), getCommandLabel());
        while (editParts.hasNext()) {
            EditPart editPart = (EditPart) editParts.next();
            Command curCommand = editPart.getCommand(request);
            if (curCommand != null) {
                command.compose(new CommandProxy(curCommand));
            }
        }
        if (command.isEmpty() || command.size() != operationSet.size()) {
            return UnexecutableCommand.INSTANCE;
        }
        return new ICommandProxy(command);
    }

    protected TransactionalEditingDomain getEditingDomain() {

        // try adapting the workbench part
        IWorkbenchPart part = getWorkbenchPart();

        if (part != null) {
            IEditingDomainProvider edProvider = (IEditingDomainProvider) part
                    .getAdapter(IEditingDomainProvider.class);

            if (edProvider != null) {
                EditingDomain domain = edProvider.getEditingDomain();

                if (domain instanceof TransactionalEditingDomain) {
                    return (TransactionalEditingDomain) domain;
                }
            }
        }
        return null;
    }

}

4、将上一步新建的Action添加到右击菜单。在DiagramEditorContextMenuProvider类中修改buildContextMenu()方法。

首先,为这个类添加成员变量:

/**
 * @generated NOT
 */
private SetImageAction setImageAction;

然后,修改DiagramEditorContextMenuProvider()方法,在这个方法最后添加如下代码:

setImageAction = new SetImageAction(part, viewer);
setImageAction.init();

在dispose()方法的super.dispose();语句之前添加代码:

if (setImageAction != null) {
    setImageAction.dispose();
    setImageAction = null;
}

最后,修改buildContextMenu()方法如下:

/**
 * @generated NOT
 */
//这里用来定义右击菜单
public void buildContextMenu(final IMenuManager menu) {
    getViewer().flush();
    try {
        TransactionUtil.getEditingDomain(
                (EObject) getViewer().getContents().getModel()).runExclusive(new Runnable() {
                    public void run() {
                        menu.removeAll();
                        menu.add(setImageAction);
                        menu.add(deleteAction);
                    }
                });
    } catch (Exception e) {
        org.eclipse.myTest.shapes.diagram.part.ShapesDiagramEditorPlugin
                .getInstance().logError("Error building context menu", e);
    }
}

这个时候如果运行程序,在一个ReserveShape1EditPart的结点上右击,菜单项会显示“设置显示图片...”这一项。

5、在包org.eclipse.myTest.shapes.diagram.edit.actions下新建类FileOption,用于后面拷贝图片到指定目录:

package org.eclipse.myTest.shapes.diagram.edit.actions;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOption {
    // 复制文件
    public static void copyFile(String sourceFilePath, String targetFilePath)
            throws IOException {
        File sourceFile = new File(sourceFilePath);
        File targetFile = new File(targetFilePath);
        FileInputStream input = new FileInputStream(sourceFile);
        BufferedInputStream inBuff = new BufferedInputStream(input);
        FileOutputStream output = new FileOutputStream(targetFile);
        BufferedOutputStream outBuff = new BufferedOutputStream(output);
        byte[] b = new byte[1024 * 5];
        int len;
        while ((len = inBuff.read(b)) != -1) {
            outBuff.write(b, 0, len);
        }
        outBuff.flush();
        inBuff.close();
        outBuff.close();
        output.close();
        input.close();
    }
}

6、在包org.eclipse.myTest.shapes.diagram.edit.actions下新建类GetPath,用于获得当前工程目录:

package org.eclipse.myTest.shapes.diagram.edit.actions;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;

public class GetPath {

    public static String getPathFromClass(Class cls) throws IOException {
        String path = null;
        if (cls == null) {
            throw new NullPointerException();
        }
        URL url = getClassLocationURL(cls);
        if (url != null) {
            path = url.getPath();
            if ("jar".equalsIgnoreCase(url.getProtocol())) {
                try {
                    path = new URL(path).getPath();
                } catch (MalformedURLException e) {
                }
                int location = path.indexOf("!/");
                if (location != -1) {
                    path = path.substring(0, location);
                }
            }
            File file = new File(path);
            path = file.getCanonicalPath();
        }
        return path;
    }

    private static URL getClassLocationURL(final Class cls) {
        if (cls == null)
            throw new IllegalArgumentException("null input: cls");
        URL result = null;
        final String clsAsResource = cls.getName().replace('.', '/')
                .concat(".class");
        final ProtectionDomain pd = cls.getProtectionDomain();
        if (pd != null) {
            final CodeSource cs = pd.getCodeSource();
            if (cs != null)
                result = cs.getLocation();
            if (result != null) {
                if ("file".equals(result.getProtocol())) {
                    try {
                        if (result.toExternalForm().endsWith(".jar")
                                || result.toExternalForm().endsWith(".zip"))
                            result = new URL("jar:"
                                    .concat(result.toExternalForm())
                                    .concat("!/").concat(clsAsResource));
                        else if (new File(result.getFile()).isDirectory())
                            result = new URL(result, clsAsResource);
                    } catch (MalformedURLException ignore) {
                    }
                }
            }
        }
        if (result == null) {
            final ClassLoader clsLoader = cls.getClassLoader();
            result = clsLoader != null ? clsLoader.getResource(clsAsResource)
                    : ClassLoader.getSystemResource(clsAsResource);
        }
        return result;
    }
}

7、在org.eclipse.myTest.shapes.diagram.edit.commands下新建一个SetImageCommand,其内容如下:

package org.eclipse.myTest.shapes.diagram.edit.commands;

import java.io.IOException;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.myTest.shapes.diagram.edit.actions.FileOption;
import org.eclipse.myTest.shapes.diagram.edit.actions.GetPath;
import org.eclipse.myTest.shapes.diagram.edit.parts.ReserveShape1EditPart;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.PlatformUI;

public class SetImageCommand extends Command {
    private EditPart sourceEditPart = null;

    public SetImageCommand(EditPart sourceEditPart) {
        this.sourceEditPart = sourceEditPart;
    }

    public void execute() {
        FileDialog fileDlg = new FileDialog(PlatformUI.getWorkbench()
                .getDisplay().getActiveShell());
        String sourceFile = fileDlg.open();
        String packageName = this.getClass().getResource("").getPath();
        packageName = packageName.replace("/", "\\");
        String projectPath = null;
        try {
            String packageFullName = GetPath.getPathFromClass(this.getClass());
            projectPath = packageFullName.substring(0,
                    packageFullName.indexOf(packageName) + 1);
        } catch (IOException e1) {
            projectPath = null;
            e1.printStackTrace();
        }
        if (projectPath == null)
            return;
        String targetFile = projectPath + "icons\\custom\\" + "test.jpg";
        try {
            FileOption.copyFile(sourceFile, targetFile);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (!sourceFile.isEmpty()) {
            ReserveShape1EditPart contrl = (ReserveShape1EditPart) sourceEditPart;
            contrl.setImageData("icons/custom/test.jpg");
            contrl.getPrimaryShape().repaint();

        }

    }
}

8、在org.eclipse.myTest.shapes.diagram.edit.policies下新建SetImagePolicy:

package org.eclipse.myTest.shapes.diagram.edit.policies;

import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.PropertyHandlerEditPolicy;
import org.eclipse.myTest.shapes.diagram.edit.commands.SetImageCommand;

public class SetImagePolicy extends PropertyHandlerEditPolicy {

    public Command getCommand(Request request) {
        Command cmd = null;
        if ("property_change".equals(request.getType())) {
            cmd = new SetImageCommand(getHost());
            return cmd;
        }
        return null;
    }
}
9、将这一Policy安装到ReserveShape1EditPart。在ReserveShape1EditPart类的createDefaultEditPolicies()方法中添加代码:
installEditPolicy(EditPolicyRoles.PROPERTY_HANDLER_ROLE, new SetImagePolicy());

10、运行一下试试:

不过现在所做的更改还不能保存,关闭程序后再运行,图片还是原来的。大概下一篇文章会写点关于保存的吧。

本例源代码:http://www.oschina.net/code/snippet_164134_6144

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!