在绘制方法中使用GC绘制可编辑的文本区域

时间:2015-08-11 11:45:54

标签: java canvas eclipse-plugin swt eclipse-rcp

我正在开发一个eclipse插件,我在其中创建自己的自定义属性。我有一个扩展AbstractTextPropertyEditor的类,并覆盖了这个类的paint方法。

我想通过写入值手动编辑属性表中的属性。我为此扩展了AbstractPropertyTextEditor类的窗口构建器。

package com.verifone.ide.eclipse.edt.editors.layout.properties;

import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.wb.internal.core.model.property.Property;
import org.eclipse.wb.internal.core.model.property.editor.AbstractTextPropertyEditor;
import org.eclipse.wb.internal.core.model.property.editor.presentation.ButtonPropertyEditorPresentation;
import org.eclipse.wb.internal.core.model.property.editor.presentation.PropertyEditorPresentation;
import org.eclipse.wb.internal.core.model.property.table.PropertyTable;
import org.eclipse.wb.internal.core.utils.ui.DrawUtils;

import tk.eclipse.plugin.htmleditor.HTMLPlugin;

import com.android.ide.common.rendering.api.ResourceValue;
import com.android.resources.ResourceType;
import com.google.common.collect.Maps;
import com.verifone.ide.eclipse.edt.editors.SimpleGraphicalEditor;

public class HTMLPropertyEditor extends AbstractTextPropertyEditor {

// public static final HTMLPropertyEditor INSTANCE = new
// HTMLPropertyEditor();

private PropertyTable mPropertyTable;

public HTMLPropertyEditor(PropertyTable propertyTable) {
    mPropertyTable = propertyTable;
}

private static final int SAMPLE_SIZE = 10;
private static final int SAMPLE_MARGIN = 3;

private final PropertyEditorPresentation mPresentation = new ButtonPropertyEditorPresentation() {
    @Override
    protected void onClick(PropertyTable propertyTable, Property property)
            throws Exception {
        openDialog(propertyTable, property);
    }
};

private void openDialog(PropertyTable propertyTable, Property property)
        throws Exception {
    // HTMLProperty htmlProperty = (HTMLProperty) property;
    // IAttributeInfo attributeInfo = htmlProperty.getDescriptor()
    // .getAttributeInfo();
    //
    // if (isIdProperty(property)) {
    // Object value = htmlProperty.getValue();
    // if (value != null && !value.toString().isEmpty()) {
    // SimpleGraphicalEditor editor = htmlProperty
    // .getGraphicalEditor();
    // if (editor != null) {
    // LayoutCanvas canvas = editor.getCanvasControl();
    // SelectionManager manager = canvas.getSelectionManager();
    //
    // NodeProxy primary = canvas.getNodeFactory().create(
    // htmlProperty.getNode());
    // if (primary != null) {
    // RenameResult result = manager.performRename(primary,
    // null);
    // if (result.isCanceled()) {
    // return;
    // } else if (!result.isUnavailable()) {
    // String name = result.getName();
    // String id = NEW_ID_PREFIX
    // + BaseViewRule.stripIdPrefix(name);
    // htmlProperty.setValue(id);
    // return;
    // }
    // }
    // }
    // }
    //
    // // When editing the id attribute, don't offer a resource chooser:
    // // usually
    // // you want to enter a *new* id here
    // // attributeInfo = null;
    // }
    //
    // boolean referenceAllowed = false;
    // if (attributeInfo != null) {
    // EnumSet<Format> formats = attributeInfo.getFormats();
    // ResourceType type = null;
    // List<ResourceType> types = null;
    // if (formats.contains(Format.FLAG)) {
    // String[] flagValues = attributeInfo.getFlagValues();
    // if (flagValues != null) {
    // FlagXmlPropertyDialog dialog = new FlagXmlPropertyDialog(
    // propertyTable.getShell(), "Select Flag Values",
    // false /* radio */, flagValues, htmlProperty);
    //
    // dialog.open();
    // return;
    // }
    // } else if (formats.contains(Format.ENUM)) {
    // String[] enumValues = attributeInfo.getEnumValues();
    // if (enumValues != null) {
    // FlagXmlPropertyDialog dialog = new FlagXmlPropertyDialog(
    // propertyTable.getShell(), "Select Enum Value",
    // true /* radio */, enumValues, htmlProperty);
    // dialog.open();
    // return;
    // }
    // } else {
    // for (Format format : formats) {
    // ResourceType t = format.getResourceType();
    // if (t != null) {
    // if (type != null) {
    // if (types == null) {
    // types = new ArrayList<ResourceType>();
    // types.add(type);
    // }
    // types.add(t);
    // }
    // type = t;
    // } else if (format == Format.REFERENCE) {
    // referenceAllowed = true;
    // }
    // }
    // }
    // if (types != null || referenceAllowed) {
    // // Multiple resource types (such as string *and* boolean):
    // // just use a reference chooser
    // SimpleGraphicalEditor graphicalEditor = htmlProperty
    // .getGraphicalEditor();
    // if (graphicalEditor != null) {
    // LayoutEditorDelegate delegate = graphicalEditor
    // .getEditorDelegate();
    // IProject project = delegate.getParentEditor().getProject();
    // if (project != null) {
    // // get the resource repository for this project and the
    // // system
    // resources.ResourceRepository projectRepository = ResourceManager
    // .getInstance().getProjectResources(project);
    // Shell shell = AdtPlugin.getShell();
    // ReferenceChooserDialog dlg = new ReferenceChooserDialog(
    // project, projectRepository, shell);
    // dlg.setPreviewHelper(new ResourcePreviewHelper(dlg,
    // graphicalEditor));
    //
    // String currentValue = (String) property.getValue();
    // dlg.setCurrentResource(currentValue);
    //
    // if (dlg.open() == Window.OK) {
    // String resource = dlg.getCurrentResource();
    // if (resource != null) {
    // // Returns null for cancel, "" for clear and
    // // otherwise a new value
    // if (resource.length() > 0) {
    // property.setValue(resource);
    // } else {
    // property.setValue(null);
    // }
    // }
    // }
    //
    // return;
    // }
    // }
    // } else if (type != null) {
    // // Single resource type: use a resource chooser
    // SimpleGraphicalEditor graphicalEditor = htmlProperty
    // .getGraphicalEditor();
    // if (graphicalEditor != null) {
    // String currentValue = (String) property.getValue();
    // // TODO: Add validator factory?
    // String resource = ResourceChooser
    // .chooseResource(graphicalEditor, type,
    // currentValue, null /* validator */);
    // // Returns null for cancel, "" for clear and otherwise a new
    // // value
    // if (resource != null) {
    // if (resource.length() > 0) {
    // property.setValue(resource);
    // } else {
    // property.setValue(null);
    // }
    // }
    // }
    //
    // return;
    // }
    // }
    //
    // // Fallback: Just use a plain string editor
    // StringXmlPropertyDialog dialog = new StringXmlPropertyDialog(
    // propertyTable.getShell(), property);
    // dialog.open();
    // if (dialog.open() == Window.OK) {
    // TODO: Do I need to activate?
    // }
}

public PropertyEditorPresentation getPresentation() {
    return mPresentation;
};

//
// @Override
// public boolean activate(PropertyTable propertyTable, Property property,
// Point location) throws Exception {
// boolean isActive = super.activate(propertyTable, property, location);
// Utils.getInstance().printMsg("isActivate: " + isActive);
// return isActive;
// }

@Override
public String getText(Property property) throws Exception {
    Object value = property.getValue();
    if (value instanceof String) {
        return (String) value;
    }
    return null;
}

@Override
protected String getEditorText(Property property) throws Exception {
    return getText(property);
}

@Override
public void paint(Property property, GC gc, int x, int y, int width,
        int height) throws Exception {

    String text = getText(property);

    if (text != null) {
        ResourceValue resValue = null;
        String resolvedText = null;

        // TODO: Use the constants for @, ?, @android: etc
        if (text.startsWith("@") || text.startsWith("?")) { //$NON-NLS-1$ //$NON-NLS-2$
            // // Yes, try to resolve it in order to show better info
            HTMLProperty htmlProperty = (HTMLProperty) property;
            SimpleGraphicalEditor graphicalEditor = htmlProperty
                    .getGraphicalEditor();
            if (graphicalEditor != null) {
                // ResourceResolver resolver =
                // graphicalEditor.getResourceResolver();
                // boolean isFramework = text.startsWith(ANDROID_PREFIX)
                // || text.startsWith(ANDROID_THEME_PREFIX);
                // boolean isFramework = true;
                // resValue = resolver.findResValue(text, isFramework);
                // while (resValue != null && resValue.getValue() != null) {
                // String value = resValue.getValue();
                // if (value.startsWith(PREFIX_RESOURCE_REF)
                // || value.startsWith(PREFIX_THEME_REF)) {
                // // TODO: do I have to strip off the @ too?
                // isFramework = isFramework
                // || value.startsWith(ANDROID_PREFIX)
                // || value.startsWith(ANDROID_THEME_PREFIX);
                // ResourceValue v = resolver.findResValue(text,
                // isFramework);
                // if (v != null && !value.equals(v.getValue())) {
                // resValue = v;
                // } else {
                // break;
                // }
                // } else {
                // break;
                // }
                // }
            }
        } else if (text.startsWith("#") && text.matches("#\\p{XDigit}+")) { //$NON-NLS-1$
            resValue = new ResourceValue(ResourceType.COLOR,
                    property.getName(), text, false);
        }

        if (resValue != null && resValue.getValue() != null) {
            // String value = resValue.getValue();
            // // Decide whether it's a color, an image, a nine patch etc
            // // and decide how to render it
            //              if (value.startsWith("#") || value.endsWith(DOT_XML) //$NON-NLS-1$
            //                      && value.contains("res/color")) { //$NON-NLS-1$ // TBD: File.separator?
            // HTMLProperty htmlProperty = (HTMLProperty) property;
            // SimpleGraphicalEditor graphicalEditor = htmlProperty
            // .getGraphicalEditor();
            // if (graphicalEditor != null) {
            // ResourceResolver resolver = graphicalEditor
            // .getResourceResolver();
            // RGB rgb = ResourceHelper.resolveColor(resolver,
            // resValue);
            // if (rgb != null) {
            // Color color = new Color(gc.getDevice(), rgb);
            // // draw color sample
            // Color oldBackground = gc.getBackground();
            // Color oldForeground = gc.getForeground();
            // try {
            // int width_c = SAMPLE_SIZE;
            // int height_c = SAMPLE_SIZE;
            // int x_c = x;
            // int y_c = y + (height - height_c) / 2;
            // // update rest bounds
            // int delta = SAMPLE_SIZE + SAMPLE_MARGIN;
            // x += delta;
            // width -= delta;
            // // fill
            // gc.setBackground(color);
            // gc.fillRectangle(x_c, y_c, width_c, height_c);
            // // draw line
            // gc.setForeground(IColorConstants.gray);
            // gc.drawRectangle(x_c, y_c, width_c, height_c);
            // } finally {
            // gc.setBackground(oldBackground);
            // gc.setForeground(oldForeground);
            // }
            // color.dispose();
            // }
            // }
            // } else {
            // Image swtImage = null;
            // if (value.endsWith(DOT_XML)
            // && value.contains("res/drawable")) { // TBD:
            // // Filesep?
            // Map<String, Image> cache = getImageCache(property);
            // swtImage = cache.get(value);
            // if (swtImage == null) {
            // HTMLProperty htmlProperty = (HTMLProperty) property;
            // SimpleGraphicalEditor graphicalEditor = htmlProperty
            // .getGraphicalEditor();
            // RenderService service = RenderService
            // .create(graphicalEditor);
            // service.setOverrideRenderSize(SAMPLE_SIZE,
            // SAMPLE_SIZE);
            // BufferedImage drawable = service
            // .renderDrawable(resValue);
            // if (drawable != null) {
            // swtImage = SwtUtils.convertToSwt(
            // gc.getDevice(), drawable,
            // true /* transferAlpha */, -1);
            // cache.put(value, swtImage);
            // }
            // }
            // } else if (value.endsWith(DOT_PNG)) {
            // // TODO: 9-patch handling?
            // // if (text.endsWith(DOT_9PNG)) {
            // // // 9-patch image: How do we paint this?
            // // URL url = new File(text).toURI().toURL();
            // // NinePatch ninepatch = NinePatch.load(url, false /* ??
            // // */);
            // // BufferedImage image = ninepatch.getImage();
            // // }
            // Map<String, Image> cache = getImageCache(property);
            // swtImage = cache.get(value);
            // if (swtImage == null) {
            // File file = new File(value);
            // if (file.exists()) {
            // try {
            // BufferedImage awtImage = ImageIO.read(file);
            // if (awtImage != null
            // && awtImage.getWidth() > 0
            // && awtImage.getHeight() > 0) {
            // awtImage = ImageUtils.cropBlank(
            // awtImage, null);
            // if (awtImage != null) {
            // // Scale image
            // int imageWidth = awtImage
            // .getWidth();
            // int imageHeight = awtImage
            // .getHeight();
            // int maxWidth = 3 * height;
            //
            // if (imageWidth > maxWidth
            // || imageHeight > height) {
            // double scale = height
            // / (double) imageHeight;
            // int scaledWidth = (int) (imageWidth * scale);
            // if (scaledWidth > maxWidth) {
            // scale = maxWidth
            // / (double) imageWidth;
            // }
            // awtImage = ImageUtils.scale(
            // awtImage, scale, scale);
            // }
            // swtImage = SwtUtils
            // .convertToSwt(
            // gc.getDevice(),
            // awtImage,
            // true /* transferAlpha */,
            // -1);
            // }
            // }
            // } catch (IOException e) {
            // e.printStackTrace();
            // }
            // }
            // cache.put(value, swtImage);
            // }
            //
            // } else if (value != null) {
            // // It's a normal string: if different from the text,
            // // paint
            // // it in parentheses, e.g.
            // // @string/foo: Foo Bar (probably cropped)
            //                      if (!value.equals(text) && !value.equals("@null")) { //$NON-NLS-1$
            // resolvedText = value;
            // }
            // }
            //
            // if (swtImage != null) {
            // // Make a square the size of the height
            // ImageData imageData = swtImage.getImageData();
            // int imageWidth = imageData.width;
            // int imageHeight = imageData.height;
            // if (imageWidth > 0 && imageHeight > 0) {
            // gc.drawImage(swtImage, x, y + (height - imageHeight) / 2);
            // int delta = imageWidth + SAMPLE_MARGIN;
            // x += delta;
            // width -= delta;
            // }
            // }
            // }
        }

        DrawUtils.drawStringCV(gc, text, x, y, width, height);

        if (resolvedText != null && resolvedText.length() > 0) {
            Point size = gc.stringExtent(text);
            x += size.x;
            width -= size.x;

            x += SAMPLE_MARGIN;
            width -= SAMPLE_MARGIN;

            if (width > 0) {
                Color oldForeground = gc.getForeground();
                try {
                    gc.setForeground(PropertyTable.COLOR_PROPERTY_FG_DEFAULT);
                    DrawUtils.drawStringCV(gc, '(' + resolvedText + ')', x,
                            y, width, height);
                } finally {
                    gc.setForeground(oldForeground);
                }
            }
        }
    }
}

int i = 0;

private static boolean isIdProperty(Property property) {
    // HTMLProperty xmlProperty = (HTMLProperty) property;
    // return
    // xmlProperty.getDescriptor().getHTMLLocalName().equals(ATTR_ID);
    return false;
}

@Override
protected boolean setEditorText(Property property, String text)
        throws Exception {
    Object oldValue = property.getValue();
    String old = oldValue != null ? oldValue.toString() : null;

    property.setValue(text);

    return true;
}

/** Qualified name for the per-project persistent property include-map */
private final static QualifiedName CACHE_NAME = new QualifiedName(
        HTMLPlugin.PLUGIN_ID, "property-images");//$NON-NLS-1$

private static Map<String, Image> getImageCache(Property property) {
    HTMLProperty htmlProperty = (HTMLProperty) property;
    SimpleGraphicalEditor graphicalEditor = htmlProperty
            .getGraphicalEditor();
    IProject project = graphicalEditor.getProject();
    try {
        Map<String, Image> cache = (Map<String, Image>) project
                .getSessionProperty(CACHE_NAME);
        if (cache == null) {
            cache = Maps.newHashMap();
            project.setSessionProperty(CACHE_NAME, cache);
        }

        return cache;
    } catch (CoreException e) {
        e.printStackTrace();
        return Maps.newHashMap();
    }
}
}

显示属性的值,但是,我无法编辑此表的属性。

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

这是错误的做法。 paint()是一种渲染方法,不能更改窗口小部件树 - 否则,整个窗口小部件树的绘制将以奇怪的方式打破。最有可能的是,您在某个时间点会得到ConcurrentModificationException

正确的解决方案是创建org.eclipse.ui.part.EditorPart并在createPartControl()内创建文本编辑器小部件,并将其附加到父小部件。这将确保在必要时呈现编辑器,正确处理事件以及大量其他事情。