/*******************************************************************************
* Copyright (c) 2006-2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* IBM Research
*******************************************************************************/
package com.ibm.research.tours.runtime;
import java.util.Timer;
import java.util.TimerTask;
import org.eclipse.core.resources.IFile;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Display;
import com.ibm.research.tours.ITour;
import com.ibm.research.tours.ITourElement;
import com.ibm.research.tours.ToursPlugin;
public class TourRunner implements ITourControlListener, IRuntimeContext
{
private TourHarness fTourHarness;
private TourNotesViewer fViewer;
private TourControl fTourController;
private int fIndex;
private ITour fTour;
private ITourElement[] fElements;
private Timer fTimer;
private long startTime = 0;
public TourRunner(ITour tour, TourHarness harness, TourNotesViewer viewer)
{
fTour = tour;
fViewer = viewer;
fTourHarness = harness;
// Cache the elements to prevent changes screwing up the running tour
fElements = tour.getElements();
// Index begins at -1, the first element will be 0
fIndex = -1;
}
public TourControl getTourControl()
{
return fTourController;
}
public void init()
{
fTourController = new TourControl(fTourHarness.getTabFolder());
fTourController.init();
fTourController.addTourControlListener(this);
if(fTour.getTitle().trim().length() > 0)
fTourController.getTabItem().setText(fTour.getTitle());
else
fTourController.getTabItem().setText("Untitled");
fTourController.getElementLabel().setText("Click next to start");
int width = fTourController.getElementLabel().computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
// Approximate the size of the element label based on the longest element label and image
// This will prevent cropping of text and images which looks dumb
for(ITourElement element : fElements)
{
fTourController.getElementLabel().setImage(element.getImage());
fTourController.getElementLabel().setText(element.getShortText());
int newWidth = fTourController.getElementLabel().computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
if(newWidth > width)
width = newWidth;
}
fTourController.getElementLabel().setImage(null);
fTourController.getElementLabel().setText("Click next to start");
GridData data = (GridData)fTourController.getElementLabel().getLayoutData();
data.widthHint = width;
fTourController.getElementLabel().setLayoutData(data);
updateCounter();
updateToolBar();
fTourHarness.changed();
// pack/layout and open
//fTourController.open();
}
public void next()
{
if(fTimer == null)
{
fTimer = new Timer();
startTime = System.currentTimeMillis();
fTimer.schedule(new TimerTask()
{
@Override
public void run()
{
final long elapsedTime = System.currentTimeMillis() - startTime;
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
if(!fTourController.getTimeLabel().isDisposed())
fTourController.getTimeLabel().setText(toFormattedTime(elapsedTime));
}
});
}
},0,500);
}
stopCurrentElement();
saveNoteChanges(); // this must be called BEFORE index is updated
// Jump to the next index
fIndex = fIndex + 1;
updateElement();
updateCounter();
updateToolBar();
runCurrentElement();
}
private void stopCurrentElement()
{
if(fIndex >= 0 && fIndex < fElements.length)
// Stop the executing element
fElements[fIndex].stop();
}
private void runCurrentElement()
{
if(fIndex >= 0 && fIndex < fElements.length)
{
// Start the element
fElements[fIndex].start();
// Perfrom the transition i.e. do whatever it does
fElements[fIndex].transition();
}
}
public void previous()
{
stopCurrentElement();
saveNoteChanges(); // this must be called BEFORE index is updated
// Jump back to the previous index
fIndex = fIndex - 1;
updateElement();
updateCounter();
updateToolBar();
runCurrentElement();
}
public void stop()
{
if(fTimer!=null)
fTimer.cancel();
stopCurrentElement();
saveNoteChanges(); // this must be called BEFORE index is updated
fTourController.dispose();
// This tells the harness that a tab was added or removed so that it
// can tell when to dispose of itself
fTourHarness.changed();
}
private void updateCounter()
{
fTourController.getCounterLabel().setText(getCurrentElementLabel()+"/"+getNumberOfElementsLabel());
}
private void updateElement()
{
fTourController.getElementLabel().setText(fElements[fIndex].getShortText());
fTourController.getElementLabel().setImage(fElements[fIndex].getImage());
fViewer.getStyledText().setText(fElements[fIndex].getNotes());
if ( fElements[fIndex].getNotes()!=null && !fElements[fIndex].getNotes().trim().equals("") )
fViewer.setGripBackground(Display.getDefault().getSystemColor(SWT.COLOR_YELLOW));
else
fViewer.setGripBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
}
private void updateToolBar()
{
if(fIndex <= 0)
fTourController.getPrevious().setEnabled(false);
else
fTourController.getPrevious().setEnabled(true);
if(fIndex >= fElements.length - 1)
fTourController.getNext().setEnabled(false);
else
fTourController.getNext().setEnabled(true);
}
private String getCurrentElementLabel()
{
return Integer.toString(fIndex + 1);
}
private String getNumberOfElementsLabel()
{
return Integer.toString(fElements.length);
}
private String toFormattedTime(long elapsedTime)
{
long seconds = elapsedTime/1000;
long minutes = seconds/60;
long remainder = seconds %60;
String minuteString = Long.toString(minutes);
if(minutes<10)
minuteString = "0" + minuteString;
String secondString = Long.toString(remainder);
if(remainder<10)
secondString = "0" + secondString;
return minuteString + ":" + secondString;
}
// must call before index is changed
private void saveNoteChanges()
{
if ( fIndex<0 || fIndex>=fElements.length )
return;
String viewerNoteText = fViewer.getStyledText().getText(),
noteText = fElements[fIndex].getNotes();
if ( noteText!=null && viewerNoteText!=null && !noteText.trim().equals(viewerNoteText.trim()) )
{
fElements[fIndex].setNotes(viewerNoteText);
IFile file = fTour.getFile();
if ( file!=null )
{
try {
fTour.write(file);
} catch (Exception e) {
ToursPlugin.log("error while trying to save updated note at index=" + fIndex + " in tour=" + fTour.getTitle() + " text=" + viewerNoteText, e);
}
}
}
}
}