GMF之Shapes實例Part4:爲結點Node設置右擊菜單並更換圖片

在上一篇文章中,咱們實現了爲結點設置圖片,可是咱們還不能修改結點的圖片,全部相同類型結點的圖片是同樣的。java

本例首先給結點添加右擊菜單,而後實現修改結點圖片的功能。dom

一、修改ReserveShape1EditPart.java的部分代碼,把descriptor、originalImage、OrgImageData聲明處的static都去掉,不然修改一個結點以後,同類型的其餘結點也會改變。eclipse

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

二、在ReserveShape1EditPart類中添加方法以下:ide

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

三、在工程org.eclipse.myTest.shapes.diagram下新建一個包org.eclipse.myTest.shapes.diagram.edit.actions,用於存放咱們本身的Action。在這個包中新建一個類SetImageAction,內容以下:ui

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;
    }

}

四、將上一步新建的Action添加到右擊菜單。在DiagramEditorContextMenuProvider類中修改buildContextMenu()方法。this

首先,爲這個類添加成員變量:url

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

而後,修改DiagramEditorContextMenuProvider()方法,在這個方法最後添加以下代碼:.net

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

在dispose()方法的super.dispose();語句以前添加代碼:rest

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

最後,修改buildContextMenu()方法以下:code

/**
 * @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的結點上右擊,菜單項會顯示「設置顯示圖片...」這一項。

五、在包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();
    }
}

六、在包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;
    }
}

七、在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();

        }

    }
}

八、在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;
    }
}
九、將這一Policy安裝到ReserveShape1EditPart。在ReserveShape1EditPart類的createDefaultEditPolicies()方法中添加代碼:
installEditPolicy(EditPolicyRoles.PROPERTY_HANDLER_ROLE, new SetImagePolicy());

十、運行一下試試:

不過如今所作的更改還不能保存,關閉程序後再運行,圖片仍是原來的。大概下一篇文章會寫點關於保存的吧。

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

相關文章
相關標籤/搜索