package com.yoursway.ide.worksheet.internal.controller;
import java.util.LinkedList;
import java.util.Queue;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.events.VerifyEvent;
import com.yoursway.ide.worksheet.WorksheetShortcuts;
import com.yoursway.ide.worksheet.executors.OutputListener;
import com.yoursway.ide.worksheet.executors.WorksheetCommandExecutor;
import com.yoursway.ide.worksheet.internal.view.ResultInset;
import com.yoursway.ide.worksheet.internal.view.WorksheetView;
import com.yoursway.ide.worksheet.internal.view.WorksheetViewCallback;
import com.yoursway.ide.worksheet.internal.view.WorksheetViewFactory;
import com.yoursway.utils.annotations.SynchronizedWithMonitorOfThis;
import com.yoursway.utils.annotations.UseFromAnyThread;
import com.yoursway.utils.annotations.UseFromUIThread;
public class WorksheetController implements OutputListener, WorksheetViewCallback {
private final WorksheetView view;
private final WorksheetCommandExecutor executor;
private final Queue<Execution> executions = new LinkedList<Execution>(); //? sync
private ResultInset outputInset = null;
private final WorksheetShortcuts shortcuts;
public WorksheetController(WorksheetViewFactory viewFactory, WorksheetCommandExecutor executor,
WorksheetShortcuts shortcuts) {
if (executor == null)
throw new NullPointerException("executor is null");
if (shortcuts == null)
throw new NullPointerException("shortcuts is null");
view = viewFactory.createView(this);
this.executor = executor;
this.shortcuts = shortcuts;
if (view == null)
throw new NullPointerException("view created by viewFactory is null");
executor.addOutputListener(this);
}
public void verifyKey(VerifyEvent e) {
if (e.doit == false)
return;
boolean handled = true;
if (shortcuts.isExecHotkey(e))
executeSelectedCommands();
else if (shortcuts.isRemoveInsetsHotkey(e))
removeAllInsets();
else if (shortcuts.isShowTextHotkey(e))
showSelectedText();
else
handled = false;
e.doit = !handled;
}
private void showSelectedText() {
view.showSelectedText();
}
private void removeAllInsets() {
view.removeAllInsets();
}
private void executeSelectedCommands() {
for (Command command : view.selectedCommands())
executeCommand(command);
if (!view.multilineSelection())
if (view.inLastLine())
view.makeNewLineAtEnd();
else
view.lineDown();
}
public void modifyText(ExtendedModifyEvent e) {
int start = e.start;
int end = e.start + (e.length > 0 ? e.length - 1 : 0);
//> check backspaces which doesn't change the line
if (e.length == 1 && view.isNewLineChar(e.start)) //> check line breaking
return;
view.makeInsetsObsolete(start, end);
}
@UseFromUIThread
private void executeCommand(Command command) {
executions.add(new Execution(command, executor));
if (executions.size() == 1)
outputInset = executions.peek().start();
}
@UseFromAnyThread
@SynchronizedWithMonitorOfThis
public synchronized void outputted(String text, boolean error) {
outputInset.append(text, error);
}
@UseFromAnyThread
@SynchronizedWithMonitorOfThis
public synchronized void completed() {
executions.poll();
outputInset = null;
Execution execution = executions.peek();
if (execution != null)
outputInset = execution.start();
}
}