S-JIS[2013-03-15] 変更履歴

Eclipse GEF DirectEdit

Eclipseプラグイン開発GEFの図形の直接編集について。


概要

エディター上の図形をクリックして、図形内の文字列を直接編集することが出来る。


図形を直接編集する為に、DirectEditPolicyとDirectEditManagerを用意する必要がある。

対象図形のEditPart:

import org.eclipse.draw2d.Label;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
public class MyEditPart extends AbstractModelEditPart implements NodeEditPart {
〜
	@Override
	protected void createEditPolicies() {
〜
		installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new MyModelDirectEditPolicy());
	}
	@Override
	public void performRequest(Request request) {
		if (request.getType() == RequestConstants.REQ_DIRECT_EDIT) {
			performDirectEdit();
		}
	}

	private void performDirectEdit() {
		MyFigure figure = (MyFigure)getFigure();
		Label label = figure.getMyValueLabel();
		MyModelDirectEditManager manager = new MyModelDirectEditManager(this, label);
		manager.show();
	}

DirectEditPolicyを指定することで、図形をクリックしたときにREQ_DIRECT_EDITのリクエストが来るようになる。
そこでDirectEditManagerで編集用のTextを用意する。編集用のTextのサイズや初期文字列を決める為に、Figureに表示しているLabelを使う。


DirectEditPolicyで、Textに入力された文字列をモデルへ移送するコマンドを用意する。

MyModelDirectEditPolicy.java

import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.DirectEditPolicy;
import org.eclipse.gef.requests.DirectEditRequest;
public class MyModelDirectEditPolicy extends DirectEditPolicy {
	@Override
	protected Command getDirectEditCommand(DirectEditRequest request) {
		MyModel model = (MyModel) getHost().getModel();
		String value = (String) request.getCellEditor().getValue();
		MyModelDirectEditCommand command = new MyModelDirectEditCommand(model, value);
		return command;
	}
	@Override
	protected void showCurrentEditValue(DirectEditRequest request) {
		MyFigure figure = (MyFigure) getHostFigure();
		String value = (String) request.getCellEditor().getValue();
		figure.setMyValue(value);
	}
}

MyModelDirectEditCommand.java

import org.eclipse.gef.commands.Command;
public class MyModelDirectEditCommand extends Command {
	private MyModel model;
	private String value, old_value;
	public MyModelDirectEditCommand(MyModel model, String value) {
		this.model = model;
		this.value = value;
	}
	@Override
	public void execute() {
		old_value = model.getMyValue();
		model.setMyValue(value);
	}
	@Override
	public void undo() {
		model.setMyValue(old_value);
	}
}

MyModelDirectEditManager.java

import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.tools.CellEditorLocator;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Text;
public class MyModelDirectEditManager extends DirectEditManager {
	public MyModelDirectEditManager(GraphicalEditPart source, Label label) {
		super(source, TextCellEditor.class, new Locator(label), label);
	}
	@Override
	protected void initCellEditor() {
		Label label = (Label) getDirectEditFeature();
		String initialLabelText = label.getText();
		getCellEditor().setValue(initialLabelText);
	}
	public static class Locator implements CellEditorLocator {
		private Label label;

		public Locator(Label label) {
			this.label = label;
		}

		@Override
		public void relocate(CellEditor celleditor) {
			Text text = (Text) celleditor.getControl();
			Point pref = text.computeSize(SWT.DEFAULT, SWT.DEFAULT);
			Rectangle rect = label.getTextBounds().getCopy();
			label.translateToAbsolute(rect);
			text.setBounds(rect.x - 1, rect.y - 1, pref.x + 1, pref.y + 1);
		}
	}
}

F2キーによる編集

F2キーを押したときに直接編集を始めるようにする方法。

GraphicalEditorクラス:

import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;

import org.eclipse.gef.ui.actions.DirectEditAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;

import org.eclipse.jface.action.IAction;
import org.eclipse.swt.SWT;
public class MyEditor extends GraphicalEditorWithFlyoutPalette {
〜
	@Override
	protected void configureGraphicalViewer() {
〜
		ActionRegistry registry = getActionRegistry();

		KeyHandler handler = new GraphicalViewerKeyHandler(viewer);
		viewer.setKeyHandler(handler);
		handler.put(KeyStroke.getPressed(SWT.F2, 0), registry.getAction(GEFActionConstants.DIRECT_EDIT));
	}

KeyHandlerを用意し、F2キーを押したときのアクションを指定する。
そのアクションは、createActions()で定義しておく。

	@SuppressWarnings("unchecked")
	@Override
	protected void createActions() {
		super.createActions();
		ActionRegistry registry = getActionRegistry();

		IAction action = new DirectEditAction(this);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());
	}

vainoloさんのサイトによるとKeyHandlerだけ定義すれば良さそうに見えるが、どこかでDirectEditActionをActionRegistryに登録しておく必要があるようだ。
また、図形の様に、選択したオブジェクトに対して直接編集を行いたい場合は、selectionActionsにActionのIDを登録しておく必要があるらしい。
(selectionActionsは、選択された図形に対するアクションを登録しておくもの。デフォルトではDeleteActionが登録されている。
 図形を選択する度に、選択した図形がselectionActionsに登録されたアクションに設定される)


GEFへ戻る / Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま