/*******************************************************************************
* Copyright (c) 2016 itemis AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Matthias Wienand (itemis AG) - initial API and implementation
*
*******************************************************************************/
package org.eclipse.gef.mvc.fx.handlers;
import java.util.Collections;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.gef.mvc.fx.models.SelectionModel;
import org.eclipse.gef.mvc.fx.operations.ChangeSelectionOperation;
import org.eclipse.gef.mvc.fx.operations.DeselectOperation;
import org.eclipse.gef.mvc.fx.operations.ITransactionalOperation;
import org.eclipse.gef.mvc.fx.operations.SelectOperation;
import org.eclipse.gef.mvc.fx.parts.IContentPart;
import org.eclipse.gef.mvc.fx.parts.IRootPart;
import org.eclipse.gef.mvc.fx.parts.IVisualPart;
import org.eclipse.gef.mvc.fx.viewer.IViewer;
import javafx.scene.Node;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
/**
* The {@link SelectFocusedOnTypeHandler} implements (de-)selecting a focused
* part via the keyboard.
*
* @author mwienand
*
*/
public class SelectFocusedOnTypeHandler extends AbstractHandler
implements IOnStrokeHandler {
@Override
public void abortPress() {
}
@Override
public void finalRelease(KeyEvent event) {
}
@Override
public void initialPress(KeyEvent event) {
// only react to events fired directly at our host
if (isRegistered(event.getTarget())
&& !isRegisteredForHost(event.getTarget())) {
return;
}
// only react to the SPACE key
if (!isSelect(event)) {
return;
}
IVisualPart<? extends Node> host = getHost();
IViewer viewer = host.getRoot().getViewer();
SelectionModel selectionModel = viewer.getAdapter(SelectionModel.class);
ITransactionalOperation op = null;
if (host instanceof IRootPart) {
// clear the selection if on the root part/background
op = new DeselectOperation(viewer,
selectionModel.getSelectionUnmodifiable());
} else if (host instanceof IContentPart) {
IContentPart<? extends Node> contentPart = (IContentPart<? extends Node>) host;
// depending on modifier, append or set the selection
if (event.isControlDown()) {
// append selection
if (selectionModel.isSelected(contentPart)) {
op = new DeselectOperation(viewer,
Collections.singletonList(contentPart));
} else {
op = new SelectOperation(viewer,
Collections.singletonList(contentPart));
}
} else {
// set selection
op = new ChangeSelectionOperation(viewer,
Collections.singletonList(contentPart));
}
}
// execute on stack
if (op != null) {
try {
viewer.getDomain().execute(op, new NullProgressMonitor());
} catch (ExecutionException e) {
throw new IllegalStateException(e);
}
}
}
/**
* Returns <code>true</code> if the given {@link KeyEvent} should trigger
* selection. Otherwise returns <code>false</code>. Per default returns
* <code>true</code> if <code><Space></code> is pressed.
*
* @param event
* The {@link KeyEvent} in question.
* @return <code>true</code> if the given {@link KeyEvent} should trigger
* zooming, otherwise <code>false</code>.
*/
protected boolean isSelect(KeyEvent event) {
return KeyCode.SPACE.equals(event.getCode());
}
@Override
public void press(KeyEvent event) {
}
@Override
public void release(KeyEvent event) {
}
}