/*******************************************************************************
* Copyright (c) 2009-2012 CWI
* 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:
*
* * Various members of the Software Analysis and Transformation Group - CWI
* * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI
*******************************************************************************/
package org.rascalmpl.eclipse.views;
import static org.rascalmpl.eclipse.IRascalResources.ID_RASCAL_TUTOR_VIEW_PART;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.WorkbenchJob;
import org.rascalmpl.eclipse.Activator;
import org.rascalmpl.eclipse.nature.ProjectEvaluatorFactory;
import org.rascalmpl.eclipse.nature.RascalMonitor;
import org.rascalmpl.eclipse.nature.WarningsToErrorLog;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.tutor.RascalTutor;
public class Tutor extends ViewPart {
public static final String ID = ID_RASCAL_TUTOR_VIEW_PART;
private Browser browser;
private volatile String mainLocation;
private RascalTutor tutor;
private Object lock = new Object();
private ExecutorService backgroundTasks;
public Tutor() {
backgroundTasks = Executors.newSingleThreadExecutor();
}
public void gotoPage(final String page) {
if (mainLocation == null) {
// lets wait in the background for the tutor being loaded, we know it will at some point..
backgroundTasks.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10);
gotoPage(page);
} catch (InterruptedException e) {
}
}
});
}
else {
new WorkbenchJob("Loading concept page") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (mainLocation == null) {
// this shouldn't happen but lets just be sure
gotoPage(page);
}
else {
browser.setUrl(mainLocation + page);
}
return Status.OK_STATUS;
}
}.schedule();
}
}
@Override
public void createPartControl(Composite parent) {
browser = new Browser(parent, SWT.NONE);
browser.setText("<html><body>The Rascal tutor is now loading: <progress max=\"100\"></progress></body></html>");
new StarterJob().schedule();
}
@Override
public void setFocus() {
browser.setFocus();
}
@Override
public void dispose() {
stop();
}
private void stop() {
if (tutor != null) {
try {
tutor.stop();
tutor = null;
} catch (Exception e) {
Activator.log("could not stop tutor", e);
}
}
}
private class StarterJob extends Job {
public StarterJob() {
super("Starting tutor");
}
@Override
protected IStatus run(IProgressMonitor monitor) {
synchronized (lock) {
try {
if (tutor != null) {
tutor.stop();
}
if (tutor == null) {
monitor.beginTask("Loading Tutor server", 2);
tutor = new RascalTutor();
// to make sure we can find classes used in the Eclipse libraries.
Evaluator eval = tutor.getRascalEvaluator();
eval.addClassLoader(ProjectEvaluatorFactory.class.getClassLoader());
// This is to make parser generation work (a JDK classpath has to be constructed)
ProjectEvaluatorFactory.configureClassPath(Activator.getInstance().getBundle(), eval);
// if we go into edit mode and have some extra checks
if (tutor.isEditMode()) {
IProject exampleProject = ResourcesPlugin.getWorkspace().getRoot().getProject("example-project");
if (exampleProject == null || !exampleProject.exists() || !exampleProject.isOpen()) {
throw new RuntimeException("Tutor will not start before you make sure example-project is open in your workspace. You can find it nested in the rascal project to import.");
}
}
tutor.start(new RascalMonitor(monitor, new WarningsToErrorLog()));
}
monitor.worked(1);
new WorkbenchJob("Loading tutor start page") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
mainLocation = tutor.getServer().toString();
browser.setUrl(mainLocation);
return Status.OK_STATUS;
}
}.schedule();
}
catch (Throwable e) {
Activator.getInstance().logException("Could not start tutor server", e);
}
}
return Status.OK_STATUS;
}
}
}