/**
* Copyright (c) 2009, 2010 Mark Feber, MulgaSoft
*
* 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
*/
package com.mulgasoft.emacsplus.commands;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IExecutionListener;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.texteditor.ITextEditor;
import com.mulgasoft.emacsplus.Beeper;
/**
* Determine if the command overruns the buffer boundaries, and beep if so.
* One of the many pieces that aids the kdb macro execution semantics
*
* @author Mark Feber - initial API and implementation
*/
public class EmacsOverrunHandler extends EmacsMovementHandler {
/**
* Check for attempt cursor movement beyond buffer boundaries and beep if detected
*
* @see com.mulgasoft.emacsplus.commands.EmacsMovementHandler#moveWithMark(ITextEditor,
* ITextSelection, String, String)
*/
@Override
protected boolean moveWithMark(ITextEditor editor, ITextSelection currentSelection, String withoutSelect,
String withSelect) throws BadLocationException {
int beforeOff = getCursorOffset(editor, currentSelection);
boolean result = false;
try {
addCheckCommand(editor);
result = super.moveWithMark(editor, currentSelection, withoutSelect, withSelect);
if (beforeOff == getCursorOffset(editor)) {
// Some movement commands simply change/remove the selection on first invocation
ITextSelection sel = (ITextSelection) editor.getSelectionProvider().getSelection();
if (currentSelection.getLength() == sel.getLength()) {
// assume we're locked in place by buffer boundaries
// so we can avoid full check on things like previous-line, etc.
beep();
}
}
} finally {
Beeper.setBeepon(true); // always restore
removeCheckCommand(editor);
}
return result;
}
// The class is not visible, so just add some hackery
private final static String ASSIST_HANDLER = "org.eclipse.jface.text.contentassist"; //$NON-NLS-1$
private void addCheckCommand(ITextEditor editor) {
((ICommandService) editor.getSite().getService(ICommandService.class)).addExecutionListener(cae);
}
private void removeCheckCommand(ITextEditor editor) {
((ICommandService) editor.getSite().getService(ICommandService.class)).removeExecutionListener(cae);
}
/**
* Listener to determine when we're in a content assist context and disable beeping on cursor
* movement (as we're not moving inside the editor, but the popup)
*/
// TODO: perhaps there's a better way?
private static IExecutionListener cae = new IExecutionListener() {
public void notHandled(String commandId, NotHandledException exception) {
}
public void postExecuteFailure(String commandId, ExecutionException exception) {
}
public void postExecuteSuccess(String commandId, Object returnValue) {
}
public void preExecute(String commandId, ExecutionEvent event) {
IHandler handler = event.getCommand().getHandler();
// The handler class is not visible
if (handler != null && handler.getClass().getName().startsWith(ASSIST_HANDLER)) {
Beeper.setBeepon(false); // disable beep if in content assist
}
}
};
}