[Tynstep-svn] r98 - in trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline: . components events exceptions helpers

ChrisBurrell at crosswire.org ChrisBurrell at crosswire.org
Sat Mar 6 12:45:11 MST 2010


Author: ChrisBurrell
Date: 2010-03-06 12:45:10 -0700 (Sat, 06 Mar 2010)
New Revision: 98

Modified:
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java
   trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java
Log:
checkstyle + small refactoring

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -14,26 +14,26 @@
  */
 public class TapeTrack extends Widget {
 	/**
-	 * Element on the DOM that is the track
-	 */
-	private Element track;
-
-	/**
 	 * The following variable defines the earliest spot at which an event can be
 	 * painted
 	 */
 	private int earliestPaintOpportunity;
 
 	/**
+	 * Determines whether the Tape Track is part of the DOM yet
+	 */
+	private boolean isRendered;
+
+	/**
 	 * The following spot defines the latest spot at which an event needs to be
 	 * finished if it is to be painted on this track
 	 */
 	private int latestPaintOpportunity;
 
 	/**
-	 * Determines whether the Tape Track is part of the DOM yet
+	 * Element on the DOM that is the track
 	 */
-	private boolean isRendered;
+	private final Element track;
 
 	/**
 	 * The default constructor initialises in memory a tape track. This includes
@@ -52,29 +52,13 @@
 	}
 
 	/**
-	 * The events need to be added in order, otherwise the time taping will not
-	 * be efficient Returns whether an event of width width can be painted at
-	 * position pixel
-	 * 
-	 * @param pixel
-	 *            pixel position at which to be painted
-	 * @param width
-	 *            width of the event
-	 * @return
-	 */
-	public boolean canPaintAt(int pixel, int width) {
-		return pixel > latestPaintOpportunity || (pixel + width + 1) < earliestPaintOpportunity;
-	}
-
-	/**
 	 * Checks and then adds an event to the timetrack Logically it is still
 	 * added to the band, but it is painted on the timetrack
 	 * 
-	 * @param event
-	 *            even to be painted
+	 * @param event even to be painted
 	 * @return whether the event has been painted
 	 */
-	public boolean addEvent(TimeEvent event) {
+	public boolean addEvent(final TimeEvent event) {
 		if (canPaintAt(event.getLeftPixelPosition(), event.getTotalWidth())) {
 			// Log.debug(event.getDescription() +
 			// " can be painted on timetrack");
@@ -83,7 +67,8 @@
 			// now update the available bands
 			// Log.debug("Old latest and earliest times were: " +
 			// latestPaintOpportunity + "," + earliestPaintOpportunity);
-			latestPaintOpportunity = Math.max(latestPaintOpportunity, event.getLeftPixelPosition() + event.getTotalWidth());
+			latestPaintOpportunity = Math.max(latestPaintOpportunity, event.getLeftPixelPosition()
+					+ event.getTotalWidth());
 			earliestPaintOpportunity = Math.min(earliestPaintOpportunity, event.getLeftPixelPosition());
 			// Log.debug("New latest and earliest times were: " +
 			// latestPaintOpportunity + "," + earliestPaintOpportunity);
@@ -93,15 +78,16 @@
 	}
 
 	/**
-	 * paints the timetrack on to the timeband
+	 * The events need to be added in order, otherwise the time taping will not
+	 * be efficient Returns whether an event of width width can be painted at
+	 * position pixel
 	 * 
-	 * @param band
+	 * @param pixel pixel position at which to be painted
+	 * @param width width of the event
+	 * @return true if the event can be painted
 	 */
-	public void paint(final Timeband band) {
-		if (!isRendered) {
-			band.getBandDiv().appendChild(track);
-			isRendered = true;
-		}
+	public boolean canPaintAt(final int pixel, final int width) {
+		return pixel > latestPaintOpportunity || (pixel + width + 1) < earliestPaintOpportunity;
 	}
 
 	/**
@@ -110,4 +96,16 @@
 	public Element getTrack() {
 		return track;
 	}
+
+	/**
+	 * paints the timetrack on to the timeband
+	 * 
+	 * @param band the band to be painteds
+	 */
+	public void paint(final Timeband band) {
+		if (!isRendered) {
+			band.getBandDiv().appendChild(track);
+			isRendered = true;
+		}
+	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -7,62 +7,62 @@
 import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimelineConstants;
 import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.TimeConversionUtil;
 
+/**
+ * A time event, to be positioned on the screen
+ * 
+ * @author CJBurrell
+ * 
+ */
 public class TimeEvent {
 
 	/**
-	 * the date of the event, and if a duration, the start date
-	 * 
+	 * events can move from one timeband to another
 	 */
-	private Long minDate;
+	private final Timeband currentTimeband;
 
 	/**
-	 * the end date of a duration event
-	 */
-	private Long maxDate;
-
-	/**
 	 * description of the event
 	 */
 	private String description;
 
-	/**
-	 * id of the event
-	 */
-	private int id;
+	private int durationWidth;
 
-	/**
-	 * Show event text
-	 */
-	private boolean showText;
+	private Element eventDiv;
 
 	/**
 	 * default to a standard event or duration we will drive this from the
 	 * database
 	 */
 	private String eventType;
-	private Element eventDiv;
+
 	private Element icon;
+	/**
+	 * id of the event
+	 */
+	private int id;
+	private boolean isRendered = false;
 	private Element label;
 	private int leftPixelPosition;
-	private int totalWidth;
+	/**
+	 * the end date of a duration event
+	 */
+	private Long maxDate;
 
-	private int durationWidth;
-
 	/**
-	 * events can move from one timeband to another
+	 * the date of the event, and if a duration, the start date
+	 * 
 	 */
-	private Timeband currentTimeband;
+	private Long minDate;
 
-	private boolean isRendered = false;
-
 	/**
-	 * @return the isRendered
+	 * Show event text
 	 */
-	public boolean isRendered() {
-		return isRendered;
-	}
+	private boolean showText;
 
-	public TimeEvent(final int id, final String description, final Long minDate, final Long maxDate, final Timeband tb) {
+	private int totalWidth;
+
+	public TimeEvent(final int id, final String description, final Long minDate, final Long maxDate,
+			final Timeband tb) {
 		this.id = id;
 		this.description = description;
 		this.minDate = minDate;
@@ -72,96 +72,51 @@
 		setupEventSpecificOptions();
 	}
 
-	/**
-	 * Sets up properties and fields that depend on the type of event
-	 */
-	private void setupEventSpecificOptions() {
-		this.leftPixelPosition = (int) TimeConversionUtil.timeToPixel(minDate.longValue(), currentTimeband);
-		if (maxDate == null) {
-			// then it's a point in time
-			eventType = TimelineConstants.POINT_IN_TIME_EVENT;
-		} else {
-			eventType = TimelineConstants.DURATION;
-			durationWidth = Math.max(TimelineConstants.EVENT_MIN_WIDTH, TimeConversionUtil.timeToPixel(maxDate.longValue(), currentTimeband)
-					- leftPixelPosition);
+	@Override
+	public boolean equals(final Object obj) {
+		if (obj == null || !(obj instanceof TimeEvent)) {
+			return false;
 		}
+
+		final TimeEvent e = (TimeEvent) obj;
+		return e.getId() == getId();
 	}
 
 	/**
-	 * Creates all the elements/styles/etc.
+	 * @return the description
 	 */
-	private void setupDivProperties() {
-		eventDiv = DOM.createDiv();
-		icon = DOM.createDiv();
-		label = DOM.createDiv();
-		El gxtEvent = new El(eventDiv);
-		El gxtLabel = new El(label);
-
-		// setup div hierarchy
-		eventDiv.appendChild(icon);
-		eventDiv.appendChild(label);
-
-		// setup CSS properties
-		eventDiv.setClassName(TimelineConstants.EVENT);
-
-		// setup positioning
-		gxtEvent.setLeft(leftPixelPosition);
-
-		// setup values
-		label.setInnerText(description);
-
-		// specific properties
-		if (maxDate != null) {
-			setupDurationProperties();
-		} else {
-			setupPointInTimeProperties();
-		}
-
-		// all css is setup, take measurement of label element:
-
-		TextMetrics ruler = TextMetrics.get();
-		ruler.bind(new El(label));
-		int labelWidth = ruler.getWidth(description);
-		gxtLabel.setWidth(labelWidth);
-
-		// set up width: if event, then labelWidth, otherwise
-		// max(duration,label)
-		totalWidth = maxDate == null ? labelWidth : Math.max(durationWidth, labelWidth);
-		gxtEvent.setWidth(totalWidth);
+	public String getDescription() {
+		return description;
 	}
 
 	/**
-	 * Sets up point in time properties
+	 * returns the event div that is shown on the screen
+	 * 
+	 * @return the eventDiv
 	 */
-	private void setupPointInTimeProperties() {
-		El gxtLabel = new El(label);
-		gxtLabel.setStyleName(TimelineConstants.POINT_IN_TIME_LABEL, true);
+	public Element getEventDiv() {
+		return eventDiv;
 	}
 
 	/**
-	 * Sets up duration properties
+	 * @return the eventType
 	 */
-	private void setupDurationProperties() {
-		El gxtIcon = new El(icon);
-		El gxtLabel = new El(label);
-		gxtIcon.setWidth((int) durationWidth);
-		gxtIcon.setStyleName(eventType, true);
-		gxtLabel.setStyleName(TimelineConstants.DURATION_LABEL, true);
+	public String getEventType() {
+		return eventType;
 	}
 
 	/**
-	 * @return the minDate
+	 * @return the id
 	 */
-	public long getMinDate() {
-		return minDate;
+	public int getId() {
+		return id;
 	}
 
 	/**
-	 * @param minDate
-	 *            the minDate to set
+	 * @return the leftPixelPosition
 	 */
-	public void setMinDate(long minDate) {
-		this.minDate = minDate;
+	public int getLeftPixelPosition() {
+		return leftPixelPosition;
 	}
 
 	/**
@@ -172,63 +127,28 @@
 	}
 
 	/**
-	 * @param maxDate
-	 *            the maxDate to set
+	 * @return the minDate
 	 */
-	public void setMaxDate(long maxDate) {
-		this.maxDate = maxDate;
+	public long getMinDate() {
+		return minDate;
 	}
 
 	/**
-	 * @return the description
+	 * @return the totalWidth
 	 */
-	public String getDescription() {
-		return description;
+	public int getTotalWidth() {
+		return totalWidth;
 	}
 
-	/**
-	 * @param description
-	 *            the description to set
-	 */
-	public void setDescription(String description) {
-		this.description = description;
-	}
-
-	/**
-	 * @return the id
-	 */
-	public int getId() {
-		return id;
-	}
-
-	/**
-	 * @param id
-	 *            the id to set
-	 */
-	public void setId(final int id) {
-		this.id = id;
-	}
-
 	public boolean isDuration() {
 		return maxDate == null;
 	}
 
-	@Override
-	public boolean equals(Object obj) {
-		if (obj == null || !(obj instanceof TimeEvent)) {
-			return false;
-		}
-
-		TimeEvent e = (TimeEvent) obj;
-		return e.getId() == getId();
-	}
-
 	/**
-	 * @param showText
-	 *            the showText to set
+	 * @return the isRendered
 	 */
-	public void setShowText(boolean showText) {
-		this.showText = showText;
+	public boolean isRendered() {
+		return isRendered;
 	}
 
 	/**
@@ -241,7 +161,7 @@
 	/**
 	 * the main responsible culprit for painting events on the timeband
 	 */
-	public synchronized void paint(TapeTrack track) {
+	public synchronized void paint(final TapeTrack track) {
 		// all we do is attach it to the parent if need be.
 		if (!isRendered) {
 			setupDivProperties();
@@ -250,74 +170,153 @@
 		}
 	}
 
+	public void reset() {
+		isRendered = false;
+
+		// also recalculate the times and dates of the events (perhaps this is
+		// not always necessary)
+		setupEventSpecificOptions(); // a few extra bits in there, but nothing
+		// that takes time
+	}
+
 	/**
-	 * @return the eventType
+	 * @param description the description to set
 	 */
-	public String getEventType() {
-		return eventType;
+	public void setDescription(final String description) {
+		this.description = description;
 	}
 
 	/**
-	 * @param eventType
-	 *            the eventType to set
+	 * @param eventType the eventType to set
 	 */
-	public void setEventType(String eventType) {
+	public void setEventType(final String eventType) {
 		this.eventType = eventType;
 	}
 
 	/**
-	 * @param minDate
-	 *            the minDate to set
+	 * @param id the id to set
 	 */
-	public void setMinDate(Long minDate) {
-		this.minDate = minDate;
+	public void setId(final int id) {
+		this.id = id;
 	}
 
 	/**
-	 * @param maxDate
-	 *            the maxDate to set
+	 * @param leftPixelPosition the leftPixelPosition to set
 	 */
-	public void setMaxDate(Long maxDate) {
+	public void setLeftPixelPosition(final int leftPixelPosition) {
+		this.leftPixelPosition = leftPixelPosition;
+	}
+
+	/**
+	 * @param maxDate the maxDate to set
+	 */
+	public void setMaxDate(final long maxDate) {
 		this.maxDate = maxDate;
 	}
 
 	/**
-	 * @return the leftPixelPosition
+	 * @param maxDate the maxDate to set
 	 */
-	public int getLeftPixelPosition() {
-		return leftPixelPosition;
+	public void setMaxDate(final Long maxDate) {
+		this.maxDate = maxDate;
 	}
 
 	/**
-	 * @param leftPixelPosition
-	 *            the leftPixelPosition to set
+	 * @param minDate the minDate to set
 	 */
-	public void setLeftPixelPosition(int leftPixelPosition) {
-		this.leftPixelPosition = leftPixelPosition;
+	public void setMinDate(final long minDate) {
+		this.minDate = minDate;
 	}
 
 	/**
-	 * @return the totalWidth
+	 * @param minDate the minDate to set
 	 */
-	public int getTotalWidth() {
-		return totalWidth;
+	public void setMinDate(final Long minDate) {
+		this.minDate = minDate;
 	}
 
-	public void reset() {
-		isRendered = false;
+	/**
+	 * @param showText the showText to set
+	 */
+	public void setShowText(final boolean showText) {
+		this.showText = showText;
+	}
 
-		// also recalculate the times and dates of the events (perhaps this is
-		// not always necessary)
-		setupEventSpecificOptions(); // a few extra bits in there, but nothing
-										// that takes time
+	/**
+	 * Creates all the elements/styles/etc.
+	 */
+	private void setupDivProperties() {
+		eventDiv = DOM.createDiv();
+		icon = DOM.createDiv();
+		label = DOM.createDiv();
+		final El gxtEvent = new El(eventDiv);
+		final El gxtLabel = new El(label);
+
+		// setup div hierarchy
+		eventDiv.appendChild(icon);
+		eventDiv.appendChild(label);
+
+		// setup CSS properties
+		eventDiv.setClassName(TimelineConstants.EVENT);
+
+		// setup positioning
+		gxtEvent.setLeft(leftPixelPosition);
+
+		// setup values
+		label.setInnerText(description);
+
+		// specific properties
+		if (maxDate != null) {
+			setupDurationProperties();
+		} else {
+			setupPointInTimeProperties();
+		}
+
+		// all css is setup, take measurement of label element:
+
+		final TextMetrics ruler = TextMetrics.get();
+		ruler.bind(new El(label));
+		final int labelWidth = ruler.getWidth(description);
+		gxtLabel.setWidth(labelWidth);
+
+		// set up width: if event, then labelWidth, otherwise
+		// max(duration,label)
+		totalWidth = maxDate == null ? labelWidth : Math.max(durationWidth, labelWidth);
+		gxtEvent.setWidth(totalWidth);
 	}
 
 	/**
-	 * returns the event div that is shown on the screen
-	 * 
-	 * @return the eventDiv
+	 * Sets up duration properties
 	 */
-	public Element getEventDiv() {
-		return eventDiv;
+	private void setupDurationProperties() {
+		final El gxtIcon = new El(icon);
+		final El gxtLabel = new El(label);
+		gxtIcon.setWidth(durationWidth);
+		gxtIcon.setStyleName(eventType, true);
+		gxtLabel.setStyleName(TimelineConstants.DURATION_LABEL, true);
 	}
+
+	/**
+	 * Sets up properties and fields that depend on the type of event
+	 */
+	private void setupEventSpecificOptions() {
+		this.leftPixelPosition = TimeConversionUtil.timeToPixel(minDate.longValue(), currentTimeband);
+		if (maxDate == null) {
+			// then it's a point in time
+			eventType = TimelineConstants.POINT_IN_TIME_EVENT;
+		} else {
+			eventType = TimelineConstants.DURATION;
+			durationWidth = Math.max(TimelineConstants.EVENT_MIN_WIDTH, TimeConversionUtil.timeToPixel(
+					maxDate.longValue(), currentTimeband)
+					- leftPixelPosition);
+		}
+	}
+
+	/**
+	 * Sets up point in time properties
+	 */
+	private void setupPointInTimeProperties() {
+		final El gxtLabel = new El(label);
+		gxtLabel.setStyleName(TimelineConstants.POINT_IN_TIME_LABEL, true);
+	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -9,10 +9,10 @@
 import com.tyndalehouse.step.web.shared.timeline.Unit;
 
 public class TimeScale {
+	private final Timeband band;
 	private boolean isRendered = false;
-	private final Timeband band;
+	private final HashMap<Integer, Element> paintedTimescaleBands;
 	private Element scaleBand;
-	private HashMap<Integer, Element> paintedTimescaleBands;
 
 	/**
 	 * A timescale is attached to a timeband
@@ -38,7 +38,7 @@
 			scaleBand = DOM.createDiv();
 			paintedTimescaleBands.clear(); // reset in case we're in a zoom
 
-			El gxtScaleBand = new El(scaleBand);
+			final El gxtScaleBand = new El(scaleBand);
 			band.getBandDiv().appendChild(scaleBand);
 			gxtScaleBand.setStyleName("step-scale-band", true);
 			isRendered = true;
@@ -48,36 +48,32 @@
 		paintVisibleScale();
 	}
 
-	private void paintVisibleScale() {
-		long visibleLeft = band.getMinVisibleDate();
-		long visibleRight = band.getMaxVisibleDate();
+	/**
+	 * The easy way is to get rid of everything and repaint The slightly more
+	 * clever way is to actually repaint the existing dom elements. It uses more
+	 * memory though, however, we can try both eventually if need be.
+	 */
+	public void repaint() {
+		// remove oneself first
+		reset();
+		paint();
+	}
 
-		Unit unit = band.getUnit();
-
-		// We do not want to generate all the time scale segments,
-		// the number of visible segments is number of time 'unit' is in the
-		// visible section
-		long numberOfVisibleSegments = (visibleRight - visibleLeft) / unit.getMilliseconds();
-
-		// first visible segment is going to be located at
-		long firstVisibleSegmentPixel = TimeConversionUtil.timeToPixel(visibleLeft - (visibleLeft % unit.getMilliseconds()), band);
-
-		// TODO: uncomment all the debug statements and change global logging
-		// level to info
-		// Log.debug("Drawing segments for timeband" + band.getId());
-		drawSegments(firstVisibleSegmentPixel, numberOfVisibleSegments);
+	public void reset() {
+		isRendered = false;
 	}
 
-	private synchronized void drawSegments(final long firstVisibleSegmentPixel, final long numberOfVisibleSegments) {
-		El gxtScaleBand = new El(scaleBand);
-		int pixelsPerUnit = band.getPixelsPerUnit();
+	private synchronized void drawSegments(final long firstVisibleSegmentPixel,
+			final long numberOfVisibleSegments) {
+		final El gxtScaleBand = new El(scaleBand);
+		final int pixelsPerUnit = band.getPixelsPerUnit();
 		int relativeLeft = (int) firstVisibleSegmentPixel;
 		// Log.debug("Drawing segments");
 		for (long ii = 0; ii < numberOfVisibleSegments + 1; ii++) {
 			// check segment not already drawn...
-			Integer key = new Integer(relativeLeft);
-			Integer keyMinus1 = new Integer(relativeLeft - 1);
-			Integer keyPlus1 = new Integer(relativeLeft + 1);
+			final Integer key = new Integer(relativeLeft);
+			final Integer keyMinus1 = new Integer(relativeLeft - 1);
+			final Integer keyPlus1 = new Integer(relativeLeft + 1);
 
 			// due to rounding errors, we need to check 1 below key and 1 above
 			// too
@@ -86,8 +82,8 @@
 			// then rely on intervals. Saves computations for storage.
 			if (!paintedTimescaleBands.containsKey(key) && !paintedTimescaleBands.containsKey(keyPlus1)
 					&& !paintedTimescaleBands.containsKey(keyMinus1)) {
-				Element un = DOM.createDiv();
-				El gxtUn = new El(un);
+				final Element un = DOM.createDiv();
+				final El gxtUn = new El(un);
 				gxtUn.setWidth(pixelsPerUnit);
 
 				un.setInnerText(TimeConversionUtil.formatPixelToTime(relativeLeft, band));
@@ -107,18 +103,24 @@
 		}
 	}
 
-	public void reset() {
-		isRendered = false;
-	}
+	private void paintVisibleScale() {
+		final long visibleLeft = band.getMinVisibleDate();
+		final long visibleRight = band.getMaxVisibleDate();
 
-	/**
-	 * The easy way is to get rid of everything and repaint The slightly more
-	 * clever way is to actually repaint the existing dom elements. It uses more
-	 * memory though, however, we can try both eventually if need be.
-	 */
-	public void repaint() {
-		// remove oneself first
-		reset();
-		paint();
+		final Unit unit = band.getUnit();
+
+		// We do not want to generate all the time scale segments,
+		// the number of visible segments is number of time 'unit' is in the
+		// visible section
+		final long numberOfVisibleSegments = (visibleRight - visibleLeft) / unit.getMilliseconds();
+
+		// first visible segment is going to be located at
+		final long firstVisibleSegmentPixel = TimeConversionUtil.timeToPixel(visibleLeft
+				- (visibleLeft % unit.getMilliseconds()), band);
+
+		// TODO: uncomment all the debug statements and change global logging
+		// level to info
+		// Log.debug("Drawing segments for timeband" + band.getId());
+		drawSegments(firstVisibleSegmentPixel, numberOfVisibleSegments);
 	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -29,89 +29,91 @@
  */
 public class Timeband extends Widget {
 	/**
-	 * Id of the timeband
+	 * The DOM element containing all timeband elements
 	 */
-	private int id;
+	private Element bandDiv;
 
 	/**
-	 * Min date that the timeband is expected to paint
+	 * The current date that is shown
 	 */
-	private long minDate;
+	private long currentDate;
 
 	/**
-	 * Max date that the timeband is expected to paint
+	 * The current pixel on the timeband representing the current date (above)
 	 */
-	private long maxDate;
+	private long currentDateX = 0;
 
 	/**
-	 * this contains all the events on the time band
+	 * when this is set to true, then we can use the request window object to
+	 * determine whether or not we are showing all the events we are able to If
+	 * events can be deleted or moved to other timebands, it becomes difficult
+	 * to work out what the request window should be.
 	 */
-	private TreeMap<Integer, TimeEvent> events;
+	private boolean deletionsDisabled = true;
 
 	/**
-	 * Determines the unit of the timeband and how to convert from/to
-	 * time/pixels
+	 * The timeband description
 	 */
-	private Unit unit;
+	private String description;
 
 	/**
-	 * The DOM element containing all timeband elements
+	 * this contains all the events on the time band
 	 */
-	private Element bandDiv;
+	private final TreeMap<Integer, TimeEvent> events;
 
 	/**
-	 * The timeband container which contains the bandDiv
+	 * Id of the timeband
 	 */
-	private Element timebandContainer;
+	private int id;
 
 	/**
-	 * Number of pixels to be shown per unit
+	 * This indicates whether the band has been painted and is showing
 	 */
-	private int pixelsPerUnit;
+	private boolean isRendered = false;
 
 	/**
-	 * this is the parent widget Timeline object
+	 * whether the user is interested in this timeband or not
 	 */
-	private final Timeline parent;
+	private boolean isUserInterested;
 
 	/**
-	 * The current date that is shown
+	 * Max date that the timeband is expected to paint
 	 */
-	private long currentDate;
+	private long maxDate;
 
 	/**
-	 * The current pixel on the timeband representing the current date (above)
+	 * Min date that the timeband is expected to paint
 	 */
-	private long currentDateX = 0;
+	private long minDate;
 
 	/**
-	 * Whether or not to show the scale band
+	 * The last recorded mouse position on the mouse down event
 	 */
-	private boolean showScale = true;
+	private int mouseDownScrollLeft;
 
 	/**
-	 * The last recorded mouse position on the mouse down event
+	 * original unit as set up before it was rendered for the first time This is
+	 * used so that we can revert back to the original, recommended unit at
+	 * point in time
 	 */
-	private int mouseDownScrollLeft;
+	private Unit originalUnit = null;
 
+	// TODO:Derive this from a properties file? somehow? or database?
 	/**
-	 * This indicates whether the band has been painted and is showing
+	 * this describes how much of a unit needs to be visible before calling back
+	 * to the server
 	 */
-	private boolean isRendered = false;
+	private double outstandingUnitFactor = TimelineConstants.MINIMUM_UNIT_PORTION_BEFORE_SERVER_CALL;
 
 	/**
-	 * This is the timescale visible on the timeband drawing lines across the
-	 * timebands for each unit
+	 * this is the parent widget Timeline object
 	 */
-	private TimeScale timescale;
+	private final Timeline parent;
 
 	/**
-	 * when this is set to true, then we can use the request window object to
-	 * determine whether or not we are showing all the events we are able to If
-	 * events can be deleted or moved to other timebands, it becomes difficult
-	 * to work out what the request window should be.
+	 * Number of pixels to be shown per unit
 	 */
-	private boolean deletionsDisabled = true;
+	private int pixelsPerUnit;
 
 	/**
 	 * Each timeband is given a request window. This object is responsible of
@@ -120,47 +122,53 @@
 	 */
 	private TimebandRequestWindow requestWindow = null;
 
-	// TODO:Derive this from a properties file? somehow? or database?
 	/**
-	 * this describes how much of a unit needs to be visible before calling back
-	 * to the server
+	 * Whether or not to show the scale band
 	 */
-	private double outstandingUnitFactor = 0.5;
+	private boolean showScale = true;
 
 	/**
-	 * This determines how much of a zoom is applied. For example a factor of
-	 * 0.25 changes the scale of 50 pixels per decade to (1 + 0.25) * 50 = 75
-	 * pixels
+	 * The list of tape tracks on this timeband.
 	 */
-	private double zoomFactor = 0.25;
+	private final List<TapeTrack> tapeTracks;
 
 	/**
-	 * The timeband description
+	 * The timeband container which contains the bandDiv
 	 */
-	private String description;
+	private final Element timebandContainer;
 
 	/**
-	 * The list of tape tracks on this timeband.
+	 * label of the timeband
 	 */
-	private List<TapeTrack> tapeTracks;
-
 	private Element timebandLabel;
 
-	private Unit originalUnit = null;
+	/**
+	 * This is the timescale visible on the timeband drawing lines across the
+	 * timebands for each unit
+	 */
+	private TimeScale timescale;
 
-	private boolean isUserInterested;
+	/**
+	 * Determines the unit of the timeband and how to convert from/to
+	 * time/pixels
+	 */
+	private Unit unit;
 
 	/**
+	 * This determines how much of a zoom is applied. For example a factor of
+	 * 0.25 changes the scale of 50 pixels per decade to (1 + 0.25) * 50 = 75
+	 * pixels
+	 */
+	private double zoomFactor = TimelineConstants.ZOOM_FACTOR;
+
+	/**
 	 * To create a new timeband on the timeline
 	 * 
-	 * @param parent
-	 *            the timeline on which it is to be created
-	 * @param id
-	 *            the id of the timeband
-	 * @param description
-	 *            its description
+	 * @param parent the timeline on which it is to be created
+	 * @param id the id of the timeband
+	 * @param description its description
 	 */
-	public Timeband(final Timeline parent, final int id, String description) {
+	public Timeband(final Timeline parent, final int id, final String description) {
 		this.parent = parent;
 		this.id = id;
 		this.description = description;
@@ -178,16 +186,20 @@
 
 	/**
 	 * Adds an event to the timeband, and therefore on to a random timetack. The
-	 * first available spot to minimize the space required.
+	 * first available spot to minimize the space required. In particular this
+	 * delegates to addEventToTapeTrack after checking the event is not already
+	 * in our list of events
 	 * 
-	 * @param event
+	 * @param event event to be added
 	 */
-	public void addEvent(TimeEvent event) {
+	public void addEvent(final TimeEvent event) {
 		// need to check the event isn't already in our list:
 		if (!events.containsKey(event.getId())) {
 			events.put(event.getId(), event);
 			addEventToTapeTrack(event);
 
+			// TODO: analyse this, but it is likely that it is not possible
+			// that the bit in the middle is redundant
 			if (isEventInVisibleSection(event)) {
 				Log.debug("Adding event to hidden band: " + event.getDescription());
 				addEventToTapeTrack(event);
@@ -196,267 +208,134 @@
 		}
 	}
 
-	public void addEventToTapeTrack(TimeEvent event) {
-		int startIndex = showScale ? 1 : 0; // leaving room for the scale band
-
-		// if event is added already, then exit
-		if (event.isRendered()) {
-			return;
+	/**
+	 * This method is used to tell the Timeband that it now has all events
+	 * within the section: (x1,x2). We can then use this to ensure subsequent
+	 * requests don't request the same thing from the server, hence reducing
+	 * load between the server and the client and also reducing the load on the
+	 * server
+	 * 
+	 * @param minDateRequested the minimum date that was requested and retrieved
+	 *            from the back-end
+	 * @param maxDateRequested the maximum date that was requested and retrieved
+	 *            from the back-end
+	 */
+	public void adjustRequestedView(final long minDateRequested, final long maxDateRequested) {
+		if (requestWindow == null) {
+			requestWindow = new TimebandRequestWindow(minDateRequested, maxDateRequested);
+		} else {
+			requestWindow.adjustRange(minDateRequested, maxDateRequested);
 		}
-
-		while (startIndex < tapeTracks.size()) {
-			// Log.debug("Trying to add " + event.getDescription() +
-			// " to track " + startIndex);
-			// try and add event to track
-			if (tapeTracks.get(startIndex).addEvent(event)) {
-				return;
-			}
-			startIndex++;
-		}
-
-		// Log.debug("Going to create a new tape track");
-
-		// check that the event was added, otherwise add timetrack
-		if (startIndex >= tapeTracks.size()) {
-			// did not manage to add it to tracks. therefore, let's add another
-			// one:
-			TapeTrack t = addNewTapeTrack();
-			t.addEvent(event);
-		}
 	}
 
-	private TapeTrack addNewTapeTrack() {
-		TapeTrack t = new TapeTrack();
-		tapeTracks.add(t);
-		t.paint(this);
-		return t;
-	}
-
 	/**
-	 * Removes an event from the band
+	 * when a mousedown event has been captured, update the position at which
+	 * the mouse was
 	 * 
-	 * @param id
-	 *            the id of the event to be removed.
-	 * @throws CannotDeleteEventException
-	 *             An event cannot be removed from a timeband.
+	 * @param e the mousedown event
 	 */
-	public void removeEvent(final int id) throws CannotDeleteEventException {
-		if (deletionsDisabled) {
-			throw new CannotDeleteEventException("The event you are trying to delete (" + id + ") is on band set on" + "deletionsDisabled = true");
-		}
-
-		events.remove(id);
-		// TODO: refresh the timeline dom
+	public void captureScrollLeft(final MouseDownEvent e) {
+		this.mouseDownScrollLeft = timebandContainer.getScrollLeft();
 	}
 
-	public TimeEvent getSingleEvent(final String eventId) {
-		return events.get(eventId);
+	/**
+	 * @return the bandDiv
+	 */
+	public Element getBandDiv() {
+		return bandDiv;
 	}
 
-	public long getMinVisibleDate() {
-		return TimeConversionUtil.pixelToTime(timebandContainer.getScrollLeft(), this);
+	/**
+	 * @return the currentDate
+	 */
+	public long getCurrentDate() {
+		return currentDate;
 	}
 
-	public long getMaxVisibleDate() {
-		int realClientWidth = timebandContainer.getClientWidth();
-		// if this is not rendered properly yet, then we have no width:
-		if (realClientWidth == 0) {
-			// use the timeline width, perhaps we can take the parent width
-			// instead...
-			// this is important as it it could that the timline doesn't take
-			// the full width
-			realClientWidth = Window.getClientWidth();
-		}
-
-		return TimeConversionUtil.pixelToTime(timebandContainer.getScrollLeft() + realClientWidth, this);
+	/**
+	 * @return the currentDateX
+	 */
+	public long getCurrentDateX() {
+		return currentDateX;
 	}
 
 	/**
-	 * Repaints the timeband
-	 * 
-	 * @param top
+	 * @return the description
 	 */
-	protected void paint() {
-		// Log.debug("Request to paint band id:" + getId() + " Current date: " +
-		// getCurrentDate() + " Desc:" + getDescription());
-		if (!isRendered) {
-			addBandToUI();
-			isRendered = true;
-		}
-
-		// show scale band?
-		if (showScale) {
-			// check if default time track has been added and add if not
-			if (tapeTracks.size() == 0) {
-				addNewTapeTrack();
-			}
-
-			if (timescale == null) {
-				timescale = new TimeScale(this);
-			}
-			timescale.paint();
-		}
-
-		drawEvents();
-
-		if (isUserInterested) {
-			// after adding events, call the resizing function.
-			// It decides whether or not the band needs resizing, so no overhead
-			resizeBand();
-		} else {
-			hideFromUser();
-		}
+	public String getDescription() {
+		return description;
 	}
 
 	/**
-	 * Draws event onto the band
+	 * @return the events
 	 */
-	private void drawEvents() {
-		// get the events to paint themselves (they will decide whether or not
-		// to
-		// paint if they are already showing...
-		for (TimeEvent te : events.values()) {
-			addEventToTapeTrack(te);
-		}
+	public TreeMap<Integer, TimeEvent> getEvents() {
+		return events;
 	}
 
 	/**
-	 * Resizes bands dependant on how many bands are present.
+	 * @return the id
 	 */
-	public void resizeBand() {
-		if (isUserInterested) {
-			// resize the timeband to take account of the number of timetracks
-			new El(timebandContainer).setHeight(tapeTracks.size() * TimelineConstants.TAPE_TRACK_HEIGHT);
-		}
+	public int getId() {
+		return id;
 	}
 
 	/**
-	 * adds the band to the DOM
+	 * @return the maxDate
 	 */
-	protected void addBandToUI() {
-		El el = new El(timebandContainer);
-		El gxtBandDiv = new El(bandDiv);
-
-		// set display options, ie. auto hide
-		// if (autoHide && !hasVisibleEvents()) {
-		// el.setDisplayed(false);
-		// }
-
-		parent.getTimelineContainer().appendChild(timebandContainer);
-		timebandContainer.appendChild(bandDiv);
-		addLabelToBand();
-
-		el.setStyleName("step-timeband-container");
-		gxtBandDiv.setHeight("100%");
-		gxtBandDiv.setTop(0);
+	public long getMaxDate() {
+		return maxDate;
 	}
 
-	private void addLabelToBand() {
-		timebandLabel = DOM.createDiv();
-		El gxtTimebandLabel = new El(timebandLabel);
-		gxtTimebandLabel.setStyleName("step-timeband-label", true);
-		gxtTimebandLabel.setLeft(getElement().getScrollLeft());
-		timebandLabel.setInnerText(description + "(" + id + ")");
-		timebandContainer.appendChild(timebandLabel);
-
-	}
-
 	/**
-	 * Tells the caller whether the event is in the visible section of the div
-	 * on the browser.
+	 * returns the current maximum visible date on the band
 	 * 
-	 * @param event
-	 *            the event to be tested
-	 * @return true if the event is in the visible section
+	 * @return the maximum date visible on the band
 	 */
-	private boolean isEventInVisibleSection(TimeEvent event) {
-		Long eventMinDate = event.getMinDate();
-		Long eventMaxDate = event.getMaxDate(); // eventMaxDate can be null
-		long minVisibleDate = getMinVisibleDate();
-		long maxVisibleDate = getMaxVisibleDate();
-
-		// output compare option:
-		// DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy G");
-
-		// Log.debug("Comparing ev(" +
-		// dtf.format(new Date(eventMinDate)) + "," +
-		// dtf.format(new Date(eventMaxDate)) + ") " +
-		// "to band(" +
-		// dtf.format(new Date(minVisibleDate)) + "," +
-		// dtf.format(new Date(maxVisibleDate)) + ")");
-
-		if ((eventMinDate >= minVisibleDate && eventMinDate <= maxVisibleDate)
-				|| (eventMaxDate != null && eventMaxDate >= minVisibleDate && eventMaxDate <= maxVisibleDate)
-				|| (eventMaxDate != null && eventMinDate <= minVisibleDate && eventMaxDate >= maxVisibleDate)) {
-			return true;
+	public long getMaxVisibleDate() {
+		int realClientWidth = timebandContainer.getClientWidth();
+		// if this is not rendered properly yet, then we have no width:
+		if (realClientWidth == 0) {
+			// use the timeline width, perhaps we can take the parent width
+			// instead...
+			// this is important as it it could that the timline doesn't take
+			// the full width
+			realClientWidth = Window.getClientWidth();
 		}
 
-		return false;
+		return TimeConversionUtil.pixelToTime(timebandContainer.getScrollLeft() + realClientWidth, this);
 	}
 
-//	/**
-//	 * Checks whether any of the already attached events are in the visible
-//	 * section
-//	 * 
-//	 * @return
-//	 */
-//	private boolean hasVisibleEvents() {
-//		// first check count of events, this is because perhaps we are
-//		// initialising
-//		// and we don't have anything else to go on...
-//		if (events.size() == 0) {
-//			return false;
-//		}
-//
-//		// check each event to see if they are in the visible section
-//		for (TimeEvent event : events.values()) {
-//			if (isEventInVisibleSection(event)) {
-//				return true;
-//			}
-//		}
-//		return false;
-//	}
-
-	public void captureScrollLeft(MouseDownEvent e) {
-		this.mouseDownScrollLeft = timebandContainer.getScrollLeft();
+	/**
+	 * @return the minDate, in pixels
+	 */
+	public long getMinDate() {
+		return minDate;
 	}
 
-	public void setScrollLeft(int previousClientX, int newClientX, Unit defaultUnit, int defaultPixelsPerUnit) {
-		// we scroll, but we calculate the unit/scale factor first
-		// say default is 1 Year
-		// this one is 10 years
-		// unit Factor = 0.1 so we scroll 10 times less pixels
-		double unitFactor = (double) defaultUnit.getMilliseconds() / (double) unit.getMilliseconds();
-
-		// now say instead unit factor is 1, ie. the same unit, but different
-		// number of pixels
-		// default is 50 pixels per year, this one is 25 pixels a year
-		// so we want to scroll half
-		double pixelFactor = (double) pixelsPerUnit / (double) defaultPixelsPerUnit;
-		this.timebandContainer.setScrollLeft((int) (mouseDownScrollLeft + ((previousClientX - newClientX) * (unitFactor * pixelFactor))));
-		displayTimebandLabel();
+	/**
+	 * returns the current minimum visible date on the band
+	 * 
+	 * @return the minimum date visible on the band
+	 */
+	public long getMinVisibleDate() {
+		return TimeConversionUtil.pixelToTime(timebandContainer.getScrollLeft(), this);
 	}
 
 	/**
-	 * This method is used to tell the Timeband that it now has all events
-	 * within the section: (x1,x2). We can then use this to ensure subsequent
-	 * requests don't request the same thing from the server, hence reducing
-	 * load between the server and the client and also reducing the load on the
-	 * server
+	 * Could this be optimized by organising the events in time order, and on
+	 * scroll recording which events have popped off?
 	 * 
-	 * @param minDateRequested
-	 *            the minimum date that was requested and retrieved from the
-	 *            back-end
-	 * @param maxDate2
-	 *            the maximum date that was requested and retrieved from the
-	 *            back-end
+	 * @return the number of visible events in the band
 	 */
-	public void adjustRequestedView(long minDateRequested, long maxDateRequested) {
-		if (requestWindow == null) {
-			requestWindow = new TimebandRequestWindow(minDateRequested, maxDateRequested);
-		} else {
-			requestWindow.adjustRange(minDateRequested, maxDateRequested);
+	public int getNumberOfVisibleEvents() {
+		int count = 0;
+		for (final TimeEvent te : events.values()) {
+			if (isEventInVisibleSection(te)) {
+				count++;
+			}
 		}
+		return count;
 	}
 
 	/**
@@ -464,14 +343,14 @@
 	 * TODO: this somewhere else.
 	 * 
 	 * @return the visible section of the timeband
-	 * @throws IncapableOfCalculatingRequestWindowException
-	 *             thrown if we are not in a position to calculate what the
-	 *             remaining section is.
+	 * @throws IncapableOfCalculatingRequestWindowException thrown if we are not
+	 *             in a position to calculate what the remaining section is.
 	 */
-	public TimeBandVisibleDate getOustandingTimebandPeriod() throws IncapableOfCalculatingRequestWindowException {
-		long minVisibleDate = getMinVisibleDate();
-		long maxVisibleDate = getMaxVisibleDate();
-		long minimumDifference = (long) (unit.getMilliseconds() * outstandingUnitFactor);
+	public TimeBandVisibleDate getOustandingTimebandPeriod()
+			throws IncapableOfCalculatingRequestWindowException {
+		final long minVisibleDate = getMinVisibleDate();
+		final long maxVisibleDate = getMaxVisibleDate();
+		final long minimumDifference = (long) (unit.getMilliseconds() * outstandingUnitFactor);
 
 		// the new requested bit depends on our request window
 		if (requestWindow == null) {
@@ -481,10 +360,10 @@
 			// worth)!
 			// -------|--------$------|-----$--------------------
 			// mvd mrd Mvd Mrd
-			long minReceivedDate = requestWindow.getMinDate();
-			long maxReceivedDate = requestWindow.getMaxDate();
-			boolean shiftedLeft = minVisibleDate < minReceivedDate;
-			boolean shiftedRight = maxVisibleDate > maxReceivedDate;
+			final long minReceivedDate = requestWindow.getMinDate();
+			final long maxReceivedDate = requestWindow.getMaxDate();
+			final boolean shiftedLeft = minVisibleDate < minReceivedDate;
+			final boolean shiftedRight = maxVisibleDate > maxReceivedDate;
 
 			if (!shiftedLeft && !shiftedRight) {
 				return TimeBandVisibleDate.getNoRequest();
@@ -529,67 +408,59 @@
 					}
 				}
 			} else {
-				throw new IncapableOfCalculatingRequestWindowException(minVisibleDate, maxVisibleDate, minReceivedDate, maxReceivedDate);
+				throw new IncapableOfCalculatingRequestWindowException(minVisibleDate, maxVisibleDate,
+						minReceivedDate, maxReceivedDate);
 			}
 		}
 	}
 
 	/**
-	 * The way zooming works is that we recalculate the positions of all events
-	 * on the timeline
+	 * @return the outstandingUnitFactor
 	 */
-	public void zoomOut() {
-		// first change the zoom factor, then repaint events, and the timescale
-		// lets just assume a default zoom factor for now
-		// TODO: zoom in factor to be parameterised
-		zoom(1 - zoomFactor);
-
+	public double getOutstandingUnitFactor() {
+		return outstandingUnitFactor;
 	}
 
 	/**
-	 * Zooms in
+	 * @return the pixelsPerUnit
 	 */
-	public void zoomIn() {
-		zoom(1 + zoomFactor);
+	public int getPixelsPerUnit() {
+		return pixelsPerUnit;
 	}
 
 	/**
-	 * Zooms out given a ratio
+	 * returns a single event contained on the timeband
 	 * 
-	 * @param zoomRatio
-	 *            the given ratio to zoom in and out
+	 * @param eventId event id of the event
+	 * @return the TimeEvent
 	 */
-	private void zoom(double zoomRatio) {
-		// TODO: somehow start with those events in the window (although for
-		// zoomout, won't make a different
-		// first change the scale
-		pixelsPerUnit *= zoomRatio;
-		adjustUnit();
-		redrawBand();
+	public TimeEvent getSingleEvent(final String eventId) {
+		return events.get(eventId);
 	}
 
 	/**
-	 * Gets the band to scroll to the current date
+	 * current number of tape tracks on the band. Also remember that one tape
+	 * track is allocated at the top of the timeband to allow for dates to be
+	 * displayed
+	 * 
+	 * @return the numbers of tracks on the band
 	 */
-	public void scrollToCurrentDate() {
-		Log.debug("Client width /2 : " + (timebandContainer.getClientWidth() / 2));
-		new El(timebandContainer).setScrollLeft((int) currentDateX - (timebandContainer.getClientWidth() / 2));
-		displayTimebandLabel();
+	public int getSizeTapeTracks() {
+		return tapeTracks.size();
 	}
 
 	/**
-	 * Displays the timeband label on the timeband, with the description of it
+	 * @return the unit
 	 */
-	private void displayTimebandLabel() {
-		new El(timebandLabel).setLeft(getElement().getScrollLeft());
+	public Unit getUnit() {
+		return unit;
 	}
 
 	/**
-	 * Resets the timeband and redraws it
+	 * @return the zoomFactor
 	 */
-	public void redrawEmptyBand() {
-		events.clear();
-		redrawBand();
+	public double getZoomFactor() {
+		return zoomFactor;
 	}
 
 	/**
@@ -602,6 +473,36 @@
 	}
 
 	/**
+	 * @return the deletionsDisabled
+	 */
+	public boolean isDeletionsDisabled() {
+		return deletionsDisabled;
+	}
+
+	/**
+	 * indicates whether the band has been rendered or not
+	 * 
+	 * @return true if the band has been rendered
+	 */
+	public boolean isRendered() {
+		return isRendered;
+	}
+
+	/**
+	 * @return the showScale
+	 */
+	public boolean isShowScale() {
+		return showScale;
+	}
+
+	/**
+	 * @return the isUserInterested
+	 */
+	public boolean isUserInterested() {
+		return isUserInterested;
+	}
+
+	/**
 	 * Does not delete the events but redraws everything else.
 	 */
 	public void redrawBand() {
@@ -619,189 +520,291 @@
 	}
 
 	/**
-	 * Resets the rendered status on all events
+	 * Resets the timeband and redraws it
 	 */
-	private void resetAllEvents() {
-		for (TimeEvent te : events.values()) {
-			te.reset();
+	public void redrawEmptyBand() {
+		events.clear();
+		redrawBand();
+	}
+
+	/**
+	 * true if the band is targetted from user input
+	 * 
+	 * @param isUserInterested identifies whether a user is interested in the
+	 *            band
+	 */
+	public void registerUserInterest(final boolean isUserInterested) {
+		this.isUserInterested = isUserInterested;
+	}
+
+	/**
+	 * Removes an event from the band
+	 * 
+	 * @param id the id of the event to be removed.
+	 * @throws CannotDeleteEventException An event cannot be removed from a
+	 *             timeband.
+	 */
+	public void removeEvent(final int id) throws CannotDeleteEventException {
+		if (deletionsDisabled) {
+			throw new CannotDeleteEventException("The event you are trying to delete (" + id
+					+ ") is on band set on" + "deletionsDisabled = true");
 		}
+
+		events.remove(id);
+		// TODO: refresh the timeline dom
 	}
 
 	/**
-	 * @return the showScale
+	 * resets the band to use the original unit
 	 */
-	public boolean isShowScale() {
-		return showScale;
+	public void resetOriginalUnit() {
+		setUnit(originalUnit);
 	}
 
 	/**
-	 * @param showScale
-	 *            the showScale to set
+	 * Resizes bands dependant on how many bands are present.
 	 */
-	public void setShowScale(boolean showScale) {
-		this.showScale = showScale;
+	public void resizeBand() {
+		if (isUserInterested) {
+			// resize the timeband to take account of the number of timetracks
+			new El(timebandContainer).setHeight(tapeTracks.size() * TimelineConstants.TAPE_TRACK_HEIGHT);
+		}
 	}
 
 	/**
-	 * @return the bandDiv
+	 * Gets the band to scroll to the current date
 	 */
-	public Element getBandDiv() {
-		return bandDiv;
+	public void scrollToCurrentDate() {
+		Log.debug("Client width /2 : " + (timebandContainer.getClientWidth() / 2));
+		new El(timebandContainer)
+				.setScrollLeft((int) currentDateX - (timebandContainer.getClientWidth() / 2));
+		displayTimebandLabel();
 	}
 
 	/**
-	 * @param bandDiv
-	 *            the bandDiv to set
+	 * @param bandDiv the bandDiv to set
 	 */
 	public final void setBandDiv(final Element bandDiv) {
 		this.bandDiv = bandDiv;
 	}
 
 	/**
-	 * @return the pixelsPerUnit
+	 * resetting the current date...
+	 * 
+	 * @param currentDate the date on which the timeband is rooted
 	 */
-	public int getPixelsPerUnit() {
-		return pixelsPerUnit;
+	public void setCurrentDate(final long currentDate) {
+		this.currentDate = currentDate;
+
+		// if we're changing the date, then everything on the band is going to
+		// be wrong, so
+		// get rid of it...
+
 	}
 
 	/**
-	 * @param pixelsPerUnit
-	 *            the pixelsPerUnit to set
+	 * @param currentDateX the currentDateX to set
 	 */
-	public void setPixelsPerUnit(int pixelsPerUnit) {
-		this.pixelsPerUnit = pixelsPerUnit;
+	public void setCurrentDateX(final long currentDateX) {
+		this.currentDateX = currentDateX;
 	}
 
 	/**
-	 * @return the id
+	 * @param deletionsDisabled the deletionsDisabled to set
 	 */
-	public int getId() {
-		return id;
+	public void setDeletionsDisabled(final boolean deletionsDisabled) {
+		this.deletionsDisabled = deletionsDisabled;
 	}
 
 	/**
-	 * @param id
-	 *            the id to set
+	 * @param description the description to set
 	 */
-	public void setId(int id) {
-		this.id = id;
+	public void setDescription(final String description) {
+		this.description = description;
 	}
 
 	/**
-	 * @return the minDate
+	 * @param id the id to set
 	 */
-	public long getMinDate() {
-		return minDate;
+	public void setId(final int id) {
+		this.id = id;
 	}
 
 	/**
-	 * @param minDate
-	 *            the minDate to set
+	 * @param maxDate the maxDate to set
 	 */
-	public void setMinDate(long minDate) {
-		this.minDate = minDate;
+	public void setMaxDate(final long maxDate) {
+		this.maxDate = maxDate;
 	}
 
 	/**
-	 * @return the maxDate
+	 * @param minDate the minDate to set
 	 */
-	public long getMaxDate() {
-		return maxDate;
+	public void setMinDate(final long minDate) {
+		this.minDate = minDate;
 	}
 
 	/**
-	 * @return the unit
+	 * Usuall, the first call ever to set the unit of the timeband. The original
+	 * unit gets cached in the originalUnit field For other uses, use @see
+	 * {@link Timeband.setUnit} If not set, then it gets set. Otherwise a
+	 * warning if produced
+	 * 
+	 * @param unit unit to be associated with the timeband
 	 */
-	public Unit getUnit() {
-		return unit;
+	public void setOriginalUnit(final Unit unit) {
+		if (originalUnit == null) {
+			originalUnit = unit;
+		} else {
+			Log.warn("Original unit is already set. Please use resetOriginalUnit instead");
+		}
+		resetOriginalUnit();
 	}
 
 	/**
-	 * @param unit
-	 *            the unit to set
+	 * @param outstandingUnitFactor the outstandingUnitFactor to set
 	 */
-	public void setUnit(Unit unit) {
-		this.unit = unit;
+	public void setOutstandingUnitFactor(final double outstandingUnitFactor) {
+		this.outstandingUnitFactor = outstandingUnitFactor;
 	}
 
 	/**
-	 * @param maxDate
-	 *            the maxDate to set
+	 * @param pixelsPerUnit the pixelsPerUnit to set
 	 */
-	public void setMaxDate(long maxDate) {
-		this.maxDate = maxDate;
+	public void setPixelsPerUnit(final int pixelsPerUnit) {
+		this.pixelsPerUnit = pixelsPerUnit;
 	}
 
 	/**
-	 * @return the events
+	 * sets the new position of the window, when the user is moving it
+	 * 
+	 * @param previousClientX the previousPosition on the x axis
+	 * @param newClientX the new position where it should be moved
+	 * @param defaultUnit the default unit which should be used to calculate the
+	 *            time difference
+	 * @param defaultPixelsPerUnit the default number of pixels per unit
 	 */
-	public TreeMap<Integer, TimeEvent> getEvents() {
-		return events;
-	}
+	public void setScrollLeft(final int previousClientX, final int newClientX, final Unit defaultUnit,
+			final int defaultPixelsPerUnit) {
+		// we scroll, but we calculate the unit/scale factor first
+		// say default is 1 Year
+		// this one is 10 years
+		// unit Factor = 0.1 so we scroll 10 times less pixels
+		final double unitFactor = (double) defaultUnit.getMilliseconds() / (double) unit.getMilliseconds();
 
-	public void setCurrentDate(long currentDate) {
-		this.currentDate = currentDate;
-
-		// if we're changing the date, then everything on the band is going to
-		// be wrong, so
-		// get rid of it...
-
+		// now say instead unit factor is 1, ie. the same unit, but different
+		// number of pixels
+		// default is 50 pixels per year, this one is 25 pixels a year
+		// so we want to scroll half
+		final double pixelFactor = (double) pixelsPerUnit / (double) defaultPixelsPerUnit;
+		final double xAxisDiff = (previousClientX - newClientX) * (unitFactor * pixelFactor);
+		final int newScrollLeft = (int) (mouseDownScrollLeft + xAxisDiff);
+		this.timebandContainer.setScrollLeft(newScrollLeft);
+		displayTimebandLabel();
 	}
 
 	/**
-	 * @return the currentDateX
+	 * @param showScale the showScale to set
 	 */
-	public long getCurrentDateX() {
-		return currentDateX;
+	public void setShowScale(final boolean showScale) {
+		this.showScale = showScale;
 	}
 
 	/**
-	 * @param currentDateX
-	 *            the currentDateX to set
+	 * @param unit the unit to set
 	 */
-	public void setCurrentDateX(long currentDateX) {
-		this.currentDateX = currentDateX;
+	public void setUnit(final Unit unit) {
+		this.unit = unit;
 	}
 
 	/**
-	 * @return the currentDate
+	 * @param zoomFactor the zoomFactor to set
 	 */
-	public long getCurrentDate() {
-		return currentDate;
+	public void setZoomFactor(final double zoomFactor) {
+		this.zoomFactor = zoomFactor;
 	}
 
 	/**
-	 * @return the deletionsDisabled
+	 * Zooms in
 	 */
-	public boolean isDeletionsDisabled() {
-		return deletionsDisabled;
+	public void zoomIn() {
+		zoom(1 + zoomFactor);
 	}
 
 	/**
-	 * @param deletionsDisabled
-	 *            the deletionsDisabled to set
+	 * The way zooming works is that we recalculate the positions of all events
+	 * on the timeline
 	 */
-	public void setDeletionsDisabled(boolean deletionsDisabled) {
-		this.deletionsDisabled = deletionsDisabled;
+	public void zoomOut() {
+		// first change the zoom factor, then repaint events, and the timescale
+		// lets just assume a default zoom factor for now
+		// TODO: zoom in factor to be parameterised
+		zoom(1 - zoomFactor);
+
 	}
 
 	/**
-	 * @param outstandingUnitFactor
-	 *            the outstandingUnitFactor to set
+	 * Adds an event to the tape track. This ensures that the event has not
+	 * already been rendered If so, then it is present somewhere, perhaps not on
+	 * this band though. Then, iterates through the tape tracks trying to add
+	 * the event (i.e. asking each track whether there is space for the icon and
+	 * the text to be added)
+	 * 
+	 * @param event event to be added to the tape track
 	 */
-	public void setOutstandingUnitFactor(double outstandingUnitFactor) {
-		this.outstandingUnitFactor = outstandingUnitFactor;
+	private void addEventToTapeTrack(final TimeEvent event) {
+		int startIndex = showScale ? 1 : 0; // leaving room for the scale band
+
+		// if event is added already, then exit
+		if (event.isRendered()) {
+			return;
+		}
+
+		while (startIndex < tapeTracks.size()) {
+			// Log.debug("Trying to add " + event.getDescription() +
+			// " to track " + startIndex);
+			// try and add event to track
+			if (tapeTracks.get(startIndex).addEvent(event)) {
+				return;
+			}
+			startIndex++;
+		}
+
+		// Log.debug("Going to create a new tape track");
+
+		// check that the event was added, otherwise add timetrack
+		if (startIndex >= tapeTracks.size()) {
+			// did not manage to add it to tracks. therefore, let's add another
+			// one:
+			final TapeTrack t = addNewTapeTrack();
+			t.addEvent(event);
+		}
 	}
 
 	/**
-	 * @return the outstandingUnitFactor
+	 * Adds the timeband label to the band
 	 */
-	public double getOutstandingUnitFactor() {
-		return outstandingUnitFactor;
+	private void addLabelToBand() {
+		timebandLabel = DOM.createDiv();
+		final El gxtTimebandLabel = new El(timebandLabel);
+		gxtTimebandLabel.setStyleName("step-timeband-label", true);
+		gxtTimebandLabel.setLeft(getElement().getScrollLeft());
+		timebandLabel.setInnerText(description + "(" + id + ")");
+		timebandContainer.appendChild(timebandLabel);
+
 	}
 
-	public boolean isRendered() {
-		return isRendered;
+	/**
+	 * adds a new tape track to the timeband. The TapeTrack gets rendered at the
+	 * same time
+	 * 
+	 * @return the TapeTrack that was added
+	 */
+	private TapeTrack addNewTapeTrack() {
+		final TapeTrack t = new TapeTrack();
+		tapeTracks.add(t);
+		t.paint(this);
+		return t;
 	}
 
 	/**
@@ -814,82 +817,135 @@
 	}
 
 	/**
-	 * @return the zoomFactor
+	 * Displays the timeband label on the timeband, with the description of it
 	 */
-	public double getZoomFactor() {
-		return zoomFactor;
+	private void displayTimebandLabel() {
+		new El(timebandLabel).setLeft(getElement().getScrollLeft());
 	}
 
 	/**
-	 * @return the description
+	 * Draws event onto the band
 	 */
-	public String getDescription() {
-		return description;
+	private void drawEvents() {
+		// get the events to paint themselves (they will decide whether or not
+		// to
+		// paint if they are already showing...
+		for (final TimeEvent te : events.values()) {
+			addEventToTapeTrack(te);
+		}
 	}
 
 	/**
-	 * @param description
-	 *            the description to set
+	 * Tells the caller whether the event is in the visible section of the div
+	 * on the browser.
+	 * 
+	 * @param event the event to be tested
+	 * @return true if the event is in the visible section
 	 */
-	public void setDescription(String description) {
-		this.description = description;
-	}
+	private boolean isEventInVisibleSection(final TimeEvent event) {
+		final Long eventMinDate = event.getMinDate();
+		final Long eventMaxDate = event.getMaxDate(); // eventMaxDate can be
+		// null
+		final long minVisibleDate = getMinVisibleDate();
+		final long maxVisibleDate = getMaxVisibleDate();
 
-	/**
-	 * @param zoomFactor
-	 *            the zoomFactor to set
-	 */
-	public void setZoomFactor(double zoomFactor) {
-		this.zoomFactor = zoomFactor;
-	}
+		// output compare option:
+		// DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy G");
 
-	public int getSizeTapeTracks() {
-		return tapeTracks.size();
-	}
+		// Log.debug("Comparing ev(" +
+		// dtf.format(new Date(eventMinDate)) + "," +
+		// dtf.format(new Date(eventMaxDate)) + ") " +
+		// "to band(" +
+		// dtf.format(new Date(minVisibleDate)) + "," +
+		// dtf.format(new Date(maxVisibleDate)) + ")");
 
-	public void resetOriginalUnit() {
-		setUnit(originalUnit);
+		if ((eventMinDate >= minVisibleDate && eventMinDate <= maxVisibleDate)
+				|| (eventMaxDate != null && eventMaxDate >= minVisibleDate && eventMaxDate <= maxVisibleDate)
+				|| (eventMaxDate != null && eventMinDate <= minVisibleDate && eventMaxDate >= maxVisibleDate)) {
+			return true;
+		}
+
+		return false;
 	}
 
-	public void setOriginalUnit(Unit unit) {
-		if (originalUnit == null) {
-			originalUnit = unit;
-		} else {
-			Log.warn("Original unit is already set. Please use resetOriginalUnit instead");
+	/**
+	 * Resets the rendered status on all events
+	 */
+	private void resetAllEvents() {
+		for (final TimeEvent te : events.values()) {
+			te.reset();
 		}
-		resetOriginalUnit();
 	}
 
 	/**
-	 * @return the isUserInterested
+	 * Zooms out given a ratio
+	 * 
+	 * @param zoomRatio the given ratio to zoom in and out
 	 */
-	public boolean isUserInterested() {
-		return isUserInterested;
+	private void zoom(final double zoomRatio) {
+		// TODO: somehow start with those events in the window (although for
+		// zoomout, won't make a different
+		// first change the scale
+		pixelsPerUnit *= zoomRatio;
+		adjustUnit();
+		redrawBand();
 	}
 
 	/**
-	 * true if the band is targetted from user input
-	 * 
-	 * @param isKeyBand
-	 *            a key band that the user wants to see
+	 * adds the band to the DOM
 	 */
-	public void registerUserInterest(boolean isUserInterested) {
-		this.isUserInterested = isUserInterested;
+	protected void addBandToUI() {
+		final El el = new El(timebandContainer);
+		final El gxtBandDiv = new El(bandDiv);
+
+		// set display options, ie. auto hide
+		// if (autoHide && !hasVisibleEvents()) {
+		// el.setDisplayed(false);
+		// }
+
+		parent.getTimelineContainer().appendChild(timebandContainer);
+		timebandContainer.appendChild(bandDiv);
+		addLabelToBand();
+
+		el.setStyleName("step-timeband-container");
+		gxtBandDiv.setHeight("100%");
+		gxtBandDiv.setTop(0);
 	}
 
 	/**
-	 * Could this be optimized by organising the events in time order, and on
-	 * scroll recording which events have popped off?
+	 * Repaints the timeband
 	 * 
-	 * @return
+	 * @param top
 	 */
-	public int getNumberOfVisibleEvents() {
-		int count = 0;
-		for (TimeEvent te : events.values()) {
-			if (isEventInVisibleSection(te)) {
-				count++;
+	protected void paint() {
+		// Log.debug("Request to paint band id:" + getId() + " Current date: " +
+		// getCurrentDate() + " Desc:" + getDescription());
+		if (!isRendered) {
+			addBandToUI();
+			isRendered = true;
+		}
+
+		// show scale band?
+		if (showScale) {
+			// check if default time track has been added and add if not
+			if (tapeTracks.size() == 0) {
+				addNewTapeTrack();
 			}
+
+			if (timescale == null) {
+				timescale = new TimeScale(this);
+			}
+			timescale.paint();
 		}
-		return count;
+
+		drawEvents();
+
+		if (isUserInterested) {
+			// after adding events, call the resizing function.
+			// It decides whether or not the band needs resizing, so no overhead
+			resizeBand();
+		} else {
+			hideFromUser();
+		}
 	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -47,19 +47,26 @@
  * 
  */
 public class Timeline extends Widget {
-	private List<Timeband> timebands;
-	private boolean isHorizontal;
-	private int width;
-	private int height;
-	private Element timelineContainer;
-	private Element timelineDiv;
-	private boolean downStatus;
-	private int clientX;
+	private native static void disableSelection(Element e) /*-{
+		e.ondrag = function() { return false; };
+		e.onselectstart = function() { return false; };
+		e.style.MozUserSelect = "none";
+	}-*/;
 
+	private int clientX;
+	private boolean downStatus;
 	private final EventBus eventBus;
+	private int height;
+	private boolean isHorizontal;
 	private boolean isRendered = false;
+	private final List<Timeband> timebands;
 
-	public Timeline(EventBus eventBus) {
+	private final Element timelineContainer;
+	private final Element timelineDiv;
+
+	private int width;
+
+	public Timeline(final EventBus eventBus) {
 		this.eventBus = eventBus;
 		timebands = new ArrayList<Timeband>();
 
@@ -75,80 +82,88 @@
 		disableSelection(getElement());
 	}
 
-	// TODO: investigate pushing the handlers in to the handler!!!
-	private void addEventHandlers(EventBus eventBus) {
-		TimelineMouseHandler tmh = new TimelineMouseHandler(this);
-		addDomHandler(tmh, MouseMoveEvent.getType());
-		addDomHandler(tmh, MouseUpEvent.getType());
-		addDomHandler(tmh, MouseDownEvent.getType());
-		addDomHandler(tmh, MouseOutEvent.getType());
-		addDomHandler(tmh, MouseOverEvent.getType());
+	public synchronized void addBand(final Timeband band) {
+		timebands.add(band);
+		band.paint();
+	}
 
-		eventBus.addHandler(UserInterestInBandEvent.TYPE, new UserInterestInBandEventHandler() {
+	/**
+	 * Both on load and on scroll we are doing an awful lot of looping to
+	 * repaint just in case TODO: change this perhaps with a stack of repainting
+	 * needed to ensure that we only repaint those timebands that think they
+	 * need repainting. for example, we don't need to be repainting the whole
+	 * band for one event etc.
+	 */
+	public void fireTimelineScrollEvent() {
+		final TimelineScrollEvent tse = new TimelineScrollEvent();
 
-			@Override
-			public void onUserInterestedInBand(UserInterestInBandEvent userInterestInBandEvent) {
-				try {
-					Timeband band = getBand(userInterestInBandEvent.getBandId());
-					band.registerUserInterest(userInterestInBandEvent.isOfInterest());
-					band.paint();
-				} catch (TimeBandNotFoundException e) {
-					Log.warn("The user request a band that no longer exists.");
-				}
+		// calculate only those bits that need requesting! but at the same time
+		// we don't need to wait for the server to redraw timebands
+		for (final Timeband tb : timebands) {
+			try {
+				tb.paint(); // the timeband is rendered, and there are no new
+				// events,
+				// so apart from looping through the events which are already
+				// rendered
+				// we are only repainting the timescale
+
+				final TimeBandVisibleDate tvd = tb.getOustandingTimebandPeriod();
+				Log.debug("firing scroll " + tb.getDescription() + " " + tvd.getMinDate() + ","
+						+ tvd.getMaxDate());
+				tse.addTimebandVisibleDate(tvd);
+			} catch (final IncapableOfCalculatingRequestWindowException e) {
+				Log.error("Incapable of calculating request window", e);
 			}
-		});
+		}
 
-		// TODO: add window handler
+		// check we have something to fire
+		if (tse.getTimebandVisibleDates().size() != 0) {
+			eventBus.fireEvent(tse);
+		} else {
+			// this is fired after the scroll has got the events,
+			// but in this case we're not event firing
+			// the event, so should update the stats, since the visible view has
+			// changed
+			eventBus.fireEvent(new TimebandListUpdateRequiredEvent(getCurrentBandStats()));
+		}
+	}
 
+	public Timeband getBand(final int bandId) throws TimeBandNotFoundException {
+		// do a linear search - we're not going to have lots of timebands
+		for (final Timeband t : timebands) {
+			if (t.getId() == bandId) {
+				return t;
+			}
+		}
+
+		throw new TimeBandNotFoundException("Timeband " + bandId + " was not found.");
 	}
 
-	private native static void disableSelection(Element e) /*-{
-		e.ondrag = function() { return false; };
-		e.onselectstart = function() { return false; };
-		e.style.MozUserSelect = "none";
-	}-*/;
+	public int getBandCount() {
+		return timebands.size();
+	}
 
-	public void handle(MouseOutEvent event) {
-		downStatus = false;
+	public List<Timeband> getBands() {
+		return timebands;
 	}
 
-	/**
-	 * An awful lot of events are going to fired and captured and discarded and
-	 * one wonders if this is really the best way to do it
-	 * 
-	 * @param me
-	 */
-	public void handleMouseOverTimeEvent(MouseEvent e) {
-		EventTarget et = e.getNativeEvent().getEventTarget();
-		Element targetElement = et.cast();
+	public List<CurrentBandStats> getCurrentBandStats() {
+		final List<CurrentBandStats> stats = new ArrayList<CurrentBandStats>();
+		for (final Timeband band : timebands) {
 
-		// find out if moved over event:
-		// Log.debug("Scanning " + timebands.size() + " timebands");
-		for (Timeband band : timebands) {
-			// Log.debug("Scanning " + band.getEvents().size());
-			for (TimeEvent te : band.getEvents().values()) {
-				if (te.getEventDiv().isOrHasChild(targetElement)) {
-					// Log.debug("Found event:" + te.getId() + " " +
-					// te.getDescription());
-					TimeEventDescriptor.show(this, te, e);
-					return;
-				}
-			}
+			final CurrentBandStats bandStats = new CurrentBandStats(band.getId(), band.getDescription(), band
+					.getEvents().size(), band.getNumberOfVisibleEvents(), band.isUserInterested());
+			stats.add(bandStats);
 		}
 
-		// if no events found, then hide description:
-		TimeEventDescriptor.hide(this);
+		return stats;
 	}
 
-	public void handle(MouseOverEvent e) {
-		handleMouseOverTimeEvent(e);
-	}
+	public Timeband getFiredBand(final MouseMoveEvent e) throws UnknownFiredElement {
+		final EventTarget et = e.getNativeEvent().getEventTarget();
+		final Element targetElement = et.cast();
 
-	public Timeband getFiredBand(MouseMoveEvent e) throws UnknownFiredElement {
-		EventTarget et = e.getNativeEvent().getEventTarget();
-		Element targetElement = et.cast();
-
-		for (Timeband b : timebands) {
+		for (final Timeband b : timebands) {
 			if (b.getBandDiv().isOrHasChild(targetElement)) {
 				return b;
 			}
@@ -157,18 +172,56 @@
 		throw new UnknownFiredElement();
 	}
 
-	public void handle(MouseMoveEvent e) {
+	/**
+	 * @return the height
+	 */
+	public int getHeight() {
+		return height;
+	}
+
+	/**
+	 * @return the timelineContainer
+	 */
+	public Element getTimelineContainer() {
+		return timelineContainer;
+	}
+
+	/**
+	 * @return the width
+	 */
+	public int getWidth() {
+		return width;
+	}
+
+	public void handle(final MouseDownEvent e) {
+		downStatus = true;
+		clientX = e.getClientX();
+
+		// capture scrollLeft on every timeband
+		for (final Timeband tb : timebands) {
+			tb.captureScrollLeft(e);
+		}
+
+		// Log.debug("ClientX " + clientX);
+
+		// change cursor to hand grab
+		new El(timelineDiv).setStyleName("step-grab", true);
+
+		// cursor: hand; /* ? */ TODO
+	}
+
+	public void handle(final MouseMoveEvent e) {
 		if (timebands.size() != 0) {
 			Timeband firedBand;
 			try {
 				firedBand = getFiredBand(e);
-			} catch (UnknownFiredElement e1) {
+			} catch (final UnknownFiredElement e1) {
 				Log.debug("Unknown element was fired");
 				firedBand = timebands.get(0);
 			}
 
-			Unit unit = firedBand.getUnit();
-			int pixelsPerUnit = firedBand.getPixelsPerUnit();
+			final Unit unit = firedBand.getUnit();
+			final int pixelsPerUnit = firedBand.getPixelsPerUnit();
 
 			if (downStatus) {
 				// mouse is down so move the scroll bars on each timeband
@@ -179,7 +232,7 @@
 				// to
 				// allow service layer to update
 				// the events shown if necessary on each timeband
-				for (Timeband tb : timebands) {
+				for (final Timeband tb : timebands) {
 					tb.setScrollLeft(clientX, e.getClientX(), unit, pixelsPerUnit);
 					// Log.debug("About to scroll: " + (clientX -
 					// e.getClientX()));
@@ -197,66 +250,52 @@
 		// ignore if no timebands, as it is not fully rendered
 	}
 
-	/**
-	 * Both on load and on scroll we are doing an awful lot of looping to
-	 * repaint just in case TODO: change this perhaps with a stack of repainting
-	 * needed to ensure that we only repaint those timebands that think they
-	 * need repainting. for example, we don't need to be repainting the whole
-	 * band for one event etc.
-	 */
-	public void fireTimelineScrollEvent() {
-		TimelineScrollEvent tse = new TimelineScrollEvent();
+	public void handle(final MouseOutEvent event) {
+		downStatus = false;
+	}
 
-		// calculate only those bits that need requesting! but at the same time
-		// we don't need to wait for the server to redraw timebands
-		for (Timeband tb : timebands) {
-			try {
-				tb.paint(); // the timeband is rendered, and there are no new
-							// events,
-				// so apart from looping through the events which are already
-				// rendered
-				// we are only repainting the timescale
-
-				TimeBandVisibleDate tvd = tb.getOustandingTimebandPeriod();
-				Log.debug("firing scroll " + tb.getDescription() + " " + tvd.getMinDate() + "," + tvd.getMaxDate());
-				tse.addTimebandVisibleDate(tvd);
-			} catch (IncapableOfCalculatingRequestWindowException e) {
-				Log.error("Incapable of calculating request window", e);
-			}
-		}
-
-		// check we have something to fire
-		if (tse.getTimebandVisibleDates().size() != 0) {
-			eventBus.fireEvent(tse);
-		} else {
-			// this is fired after the scroll has got the events,
-			// but in this case we're not event firing
-			// the event, so should update the stats, since the visible view has
-			// changed
-			eventBus.fireEvent(new TimebandListUpdateRequiredEvent(getCurrentBandStats()));
-		}
+	public void handle(final MouseOverEvent e) {
+		handleMouseOverTimeEvent(e);
 	}
 
-	public void handle(MouseUpEvent e) {
+	public void handle(final MouseUpEvent e) {
 		downStatus = false;
 		new El(timelineDiv).setStyleName("step-letgo", true);
 	}
 
-	public void handle(MouseDownEvent e) {
-		downStatus = true;
-		clientX = e.getClientX();
+	/**
+	 * An awful lot of events are going to fired and captured and discarded and
+	 * one wonders if this is really the best way to do it
+	 * 
+	 * @param me
+	 */
+	public void handleMouseOverTimeEvent(final MouseEvent e) {
+		final EventTarget et = e.getNativeEvent().getEventTarget();
+		final Element targetElement = et.cast();
 
-		// capture scrollLeft on every timeband
-		for (Timeband tb : timebands) {
-			tb.captureScrollLeft(e);
+		// find out if moved over event:
+		// Log.debug("Scanning " + timebands.size() + " timebands");
+		for (final Timeband band : timebands) {
+			// Log.debug("Scanning " + band.getEvents().size());
+			for (final TimeEvent te : band.getEvents().values()) {
+				if (te.getEventDiv().isOrHasChild(targetElement)) {
+					// Log.debug("Found event:" + te.getId() + " " +
+					// te.getDescription());
+					TimeEventDescriptor.show(this, te, e);
+					return;
+				}
+			}
 		}
 
-		// Log.debug("ClientX " + clientX);
+		// if no events found, then hide description:
+		TimeEventDescriptor.hide(this);
+	}
 
-		// change cursor to hand grab
-		new El(timelineDiv).setStyleName("step-grab", true);
-
-		// cursor: hand; /* ? */ TODO
+	/**
+	 * @return the isHorizontal
+	 */
+	public boolean isHorizontal() {
+		return isHorizontal;
 	}
 
 	/**
@@ -267,7 +306,7 @@
 			timelineDiv.appendChild(timelineContainer);
 
 			int relativeTop = 0;
-			for (Timeband tb : timebands) {
+			for (final Timeband tb : timebands) {
 				tb.paint();
 				relativeTop += tb.getSizeTapeTracks() * TimelineConstants.TAPE_TRACK_HEIGHT;
 			}
@@ -279,87 +318,56 @@
 		}
 	}
 
-	public synchronized void addBand(Timeband band) {
-		timebands.add(band);
-		band.paint();
-	}
-
-	public void removeBand(String bandId) {
+	public void removeBand(final String bandId) {
 		timebands.remove(bandId);
 	}
 
-	public Timeband getBand(final int bandId) throws TimeBandNotFoundException {
-		// do a linear search - we're not going to have lots of timebands
-		for (Timeband t : timebands) {
-			if (t.getId() == bandId) {
-				return t;
-			}
-		}
+	public void repaint(final Long originDate, final Unit unit, final int timebandId) {
+		// remove all the timebands from the timeline widget
+		// TODO: HERE all we want to do is set the corect timeband with that
+		// unit, not all of them, right?
+		// what if we have several timebands in the origin, is that possible?
+		// events on different timebands with the same scripture references
 
-		throw new TimeBandNotFoundException("Timeband " + bandId + " was not found.");
-	}
+		// TODO: set other timbands back to their original scales
 
-	/**
-	 * @param isHorizontal
-	 *            the isHorizontal to set
-	 */
-	public void setHorizontal(boolean isHorizontal) {
-		this.isHorizontal = isHorizontal;
-	}
+		for (final Timeband band : timebands) {
+			setUserInterestOnBand(band, timebandId, unit);
+			band.setCurrentDate(originDate);
+			band.setCurrentDateX(TimelineConstants.TIMELINE_WIDTH + timelineDiv.getClientWidth() / 2);
+			band.scrollToCurrentDate();
+			band.redrawEmptyBand();
+		}
 
-	/**
-	 * @return the isHorizontal
-	 */
-	public boolean isHorizontal() {
-		return isHorizontal;
+		fireTimelineScrollEvent();
 	}
 
 	/**
-	 * @param width
-	 *            the width to set
+	 * @param height the height to set
 	 */
-	public void setWidth(int width) {
-		this.width = width;
-	}
-
-	/**
-	 * @return the width
-	 */
-	public int getWidth() {
-		return width;
-	}
-
-	/**
-	 * @param height
-	 *            the height to set
-	 */
-	public void setHeight(int height) {
+	public void setHeight(final int height) {
 		this.height = height;
 	}
 
 	/**
-	 * @return the height
+	 * @param isHorizontal the isHorizontal to set
 	 */
-	public int getHeight() {
-		return height;
+	public void setHorizontal(final boolean isHorizontal) {
+		this.isHorizontal = isHorizontal;
 	}
 
-	public int getBandCount() {
-		return timebands.size();
-	}
-
 	/**
-	 * @return the timelineContainer
+	 * @param width the width to set
 	 */
-	public Element getTimelineContainer() {
-		return timelineContainer;
+	public void setWidth(final int width) {
+		this.width = width;
 	}
 
 	/**
 	 * Zooming is done on a band level, so delegate to timebands
 	 */
 	public void zoomIn() {
-		for (Timeband tb : timebands) {
+		for (final Timeband tb : timebands) {
 			tb.zoomIn();
 		}
 	}
@@ -368,43 +376,47 @@
 	 * Zooming is done on a band level, so delegate to timebands
 	 */
 	public void zoomOut() {
-		for (Timeband tb : timebands) {
+		for (final Timeband tb : timebands) {
 			tb.zoomOut();
 		}
 	}
 
-	public void repaint(final Long originDate, final Unit unit, final int timebandId) {
-		// remove all the timebands from the timeline widget
-		// TODO: HERE all we want to do is set the corect timeband with that
-		// unit, not all of them, right?
-		// what if we have several timebands in the origin, is that possible?
-		// events on different timebands with the same scripture references
+	// TODO: investigate pushing the handlers in to the handler!!!
+	private void addEventHandlers(final EventBus eventBus) {
+		final TimelineMouseHandler tmh = new TimelineMouseHandler(this);
+		addDomHandler(tmh, MouseMoveEvent.getType());
+		addDomHandler(tmh, MouseUpEvent.getType());
+		addDomHandler(tmh, MouseDownEvent.getType());
+		addDomHandler(tmh, MouseOutEvent.getType());
+		addDomHandler(tmh, MouseOverEvent.getType());
 
-		// TODO: set other timbands back to their original scales
+		eventBus.addHandler(UserInterestInBandEvent.TYPE, new UserInterestInBandEventHandler() {
 
-		for (Timeband band : timebands) {
-			setUserInterestOnBand(band, timebandId, unit);
-			band.setCurrentDate(originDate);
-			band.setCurrentDateX(TimelineConstants.TIMELINE_WIDTH + timelineDiv.getClientWidth() / 2);
-			band.scrollToCurrentDate();
-			band.redrawEmptyBand();
-		}
+			@Override
+			public void onUserInterestedInBand(final UserInterestInBandEvent userInterestInBandEvent) {
+				try {
+					final Timeband band = getBand(userInterestInBandEvent.getBandId());
+					band.registerUserInterest(userInterestInBandEvent.isOfInterest());
+					band.paint();
+				} catch (final TimeBandNotFoundException e) {
+					Log.warn("The user request a band that no longer exists.");
+				}
+			}
+		});
 
-		fireTimelineScrollEvent();
+		// TODO: add window handler
+
 	}
 
 	/**
 	 * if the band corresponds to the correct timeband id, then set unit,
 	 * otherwise revert back to the original state...
 	 * 
-	 * @param band
-	 *            band
-	 * @param timebandId
-	 *            timebandId
-	 * @param unit
-	 *            unit
+	 * @param band band
+	 * @param timebandId timebandId
+	 * @param unit unit
 	 */
-	private void setUserInterestOnBand(Timeband band, int timebandId, Unit unit) {
+	private void setUserInterestOnBand(final Timeband band, final int timebandId, final Unit unit) {
 		if (band.getId() == timebandId) {
 			band.setUnit(unit);
 			band.registerUserInterest(true);
@@ -414,20 +426,4 @@
 		}
 	}
 
-	public List<Timeband> getBands() {
-		return timebands;
-	}
-
-	public List<CurrentBandStats> getCurrentBandStats() {
-		List<CurrentBandStats> stats = new ArrayList<CurrentBandStats>();
-		for (Timeband band : timebands) {
-
-			CurrentBandStats bandStats = new CurrentBandStats(band.getId(), band.getDescription(), band.getEvents().size(), band
-					.getNumberOfVisibleEvents(), band.isUserInterested());
-			stats.add(bandStats);
-		}
-
-		return stats;
-	}
-
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -10,9 +10,20 @@
  * 
  */
 public class TimebandRequestWindow {
-	private long minDate;
+	/** max date requested so far */
 	private long maxDate;
 
+	/** min date requested so far */
+	private long minDate;
+
+	/**
+	 * timeband request window, when created takes the intial window (min, max)
+	 * 
+	 * @param initialMin initial minimum, usually the left most visible pixel of
+	 *            the timeband
+	 * @param initialMax initial maximum, usually the right most visible pixel
+	 *            of the timeband
+	 */
 	public TimebandRequestWindow(final long initialMin, final long initialMax) {
 		minDate = initialMin;
 		maxDate = initialMax;
@@ -21,10 +32,10 @@
 	/**
 	 * Enlarges the minimum window on the left hand-side
 	 * 
-	 * @param minDateRequested
-	 *            the new minDate that the band has received
+	 * @param minDateRequested the new minDate that the band has received
+	 * @param maxDateRequested the new maxDate that the band has received
 	 */
-	public void adjustRange(long minDateRequested, long maxDateRequested) {
+	public void adjustRange(final long minDateRequested, final long maxDateRequested) {
 		// Log.debug("Adjusting minimum of received/requested window");
 
 		// adjust minimum: as long as the minimum is before, but the max within
@@ -42,32 +53,30 @@
 	}
 
 	/**
-	 * @return the minDate
+	 * @return the maxDate
 	 */
-	public long getMinDate() {
-		return minDate;
+	public long getMaxDate() {
+		return maxDate;
 	}
 
 	/**
-	 * @param minDate
-	 *            the minDate to set
+	 * @return the minDate
 	 */
-	public void setMinDate(long minDate) {
-		this.minDate = minDate;
+	public long getMinDate() {
+		return minDate;
 	}
 
 	/**
-	 * @return the maxDate
+	 * @param maxDate the maxDate to set
 	 */
-	public long getMaxDate() {
-		return maxDate;
+	public void setMaxDate(final long maxDate) {
+		this.maxDate = maxDate;
 	}
 
 	/**
-	 * @param maxDate
-	 *            the maxDate to set
+	 * @param minDate the minDate to set
 	 */
-	public void setMaxDate(long maxDate) {
-		this.maxDate = maxDate;
+	public void setMinDate(final long minDate) {
+		this.minDate = minDate;
 	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -25,10 +25,15 @@
 	 */
 	public static final int EVENT_MIN_WIDTH = 2;
 	/**
+	 * this describes how much of a unit needs to be visible before calling back
+	 * to the server
+	 */
+	public static final double MINIMUM_UNIT_PORTION_BEFORE_SERVER_CALL = 0.5;
+
+	/**
 	 * css of a point in time event
 	 */
 	public static final String POINT_IN_TIME_EVENT = "step-timeline-pointInTime";
-
 	/**
 	 * css for the label of a point in time event label
 	 */
@@ -37,6 +42,7 @@
 	 * space between the icon and the text
 	 */
 	public static final int POINT_IN_TIME_WIDTH_SPACE = 15;
+
 	/**
 	 * space between the popup and the mouse
 	 */
@@ -55,6 +61,13 @@
 	public static final int TIMELINE_WIDTH = 32000;
 
 	/**
+	 * The initial zoom factor. This determines how much of a zoom is applied.
+	 * For example a factor of 0.25 changes the scale of 50 pixels per decade to
+	 * (1 + 0.25) * 50 = 75 pixels
+	 */
+	public static final double ZOOM_FACTOR = 0.25;
+
+	/**
 	 * prevent intialisation
 	 */
 	private TimelineConstants() {

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -12,36 +12,52 @@
 import com.google.gwt.event.dom.client.MouseUpHandler;
 import com.tyndalehouse.step.web.client.toolkit.timeline.Timeline;
 
-public class TimelineMouseHandler implements MouseMoveHandler, MouseUpHandler, MouseDownHandler, MouseOutHandler, MouseOverHandler {
+/**
+ * timeline mouse handler to re-delegate events to the timeline component this
+ * is used mainly for the scrolling functionality on the timeline
+ * 
+ * @author CJBurrell
+ * 
+ */
+public class TimelineMouseHandler implements MouseMoveHandler, MouseUpHandler, MouseDownHandler,
+		MouseOutHandler, MouseOverHandler {
+	/**
+	 * The timeline component
+	 */
 	private final Timeline timeline;
 
-	public TimelineMouseHandler(Timeline timeline) {
+	/**
+	 * constructor takes the timeline component
+	 * 
+	 * @param timeline the timeline component.
+	 */
+	public TimelineMouseHandler(final Timeline timeline) {
 		this.timeline = timeline;
 	}
 
 	@Override
-	public void onMouseUp(MouseUpEvent event) {
+	public void onMouseDown(final MouseDownEvent event) {
 		timeline.handle(event);
 	}
 
 	@Override
-	public void onMouseDown(MouseDownEvent event) {
+	public void onMouseMove(final MouseMoveEvent event) {
 		timeline.handle(event);
 	}
 
 	@Override
-	public void onMouseOut(MouseOutEvent event) {
+	public void onMouseOut(final MouseOutEvent event) {
 		timeline.handle(event);
 	}
 
 	@Override
-	public void onMouseMove(MouseMoveEvent event) {
+	public void onMouseOver(final MouseOverEvent event) {
 		timeline.handle(event);
+
 	}
 
 	@Override
-	public void onMouseOver(MouseOverEvent event) {
+	public void onMouseUp(final MouseUpEvent event) {
 		timeline.handle(event);
-
 	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -19,17 +19,14 @@
 	/**
 	 * The client is unable to calculate which bit to request from the server
 	 * 
-	 * @param minVisibleDate
-	 *            the minimum visible date from the client
-	 * @param maxVisibleDate
-	 *            the maximum visible date from the client
-	 * @param minReceivedDate
-	 *            the minimum date the client has ever seen
-	 * @param maxReceivedDate
-	 *            the maximum date the client has ever seen
+	 * @param minVisibleDate the minimum visible date from the client
+	 * @param maxVisibleDate the maximum visible date from the client
+	 * @param minReceivedDate the minimum date the client has ever seen
+	 * @param maxReceivedDate the maximum date the client has ever seen
 	 */
-	public IncapableOfCalculatingRequestWindowException(long minVisibleDate, long maxVisibleDate, long minReceivedDate, long maxReceivedDate) {
-		super("Unable to calculate request window for: " + minReceivedDate + " / " + maxReceivedDate + ". Visible section is: " + minVisibleDate
-				+ " / " + maxVisibleDate);
+	public IncapableOfCalculatingRequestWindowException(final long minVisibleDate, final long maxVisibleDate,
+			final long minReceivedDate, final long maxReceivedDate) {
+		super("Unable to calculate request window for: " + minReceivedDate + " / " + maxReceivedDate
+				+ ". Visible section is: " + minVisibleDate + " / " + maxVisibleDate);
 	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -9,17 +9,17 @@
 public class TimeBandNotFoundException extends Exception {
 
 	/**
+	 * serial id
+	 */
+	private static final long serialVersionUID = 6234571991235670035L;
+
+	/**
 	 * Constructor specifying the error message
 	 * 
-	 * @param message
+	 * @param message message indicating which band was not found
 	 */
 	public TimeBandNotFoundException(final String message) {
 		super(message);
 	}
 
-	/**
-	 * serial id
-	 */
-	private static final long serialVersionUID = 6234571991235670035L;
-
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -1,9 +1,16 @@
 package com.tyndalehouse.step.web.client.toolkit.timeline.exceptions;
 
+/**
+ * Thrown if an DOM element contained in the timeline is fired but it is not
+ * recognised by the timeline element
+ * 
+ * @author CJBurrell
+ * 
+ */
 public class UnknownFiredElement extends Exception {
 
 	/**
-	 * 
+	 * serial id
 	 */
 	private static final long serialVersionUID = -726869406002130223L;
 

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -1,23 +1,48 @@
 package com.tyndalehouse.step.web.client.toolkit.timeline.helpers;
 
+/**
+ * Contains the current statistics of how many events are present on a
+ * particular timeband This bean is band specific
+ * 
+ * @author CJBurrell
+ * 
+ */
 public class CurrentBandStats {
+	/**
+	 * description of the band to be displayed on the screen
+	 */
+	private final String bandDescription;
+
+	/**
+	 * timeband id
+	 */
 	private final int bandId;
+
+	/**
+	 * ticked or not, whether the user is interested in this
+	 */
+	private final boolean isUserInterested;
+
+	/**
+	 * number of elements on the timeband
+	 */
 	private final int numElements;
+
+	/**
+	 * number of elements currently visible
+	 */
 	private final int numVisibleElements;
-	private final String bandDescription;
-	private final boolean isUserInterested;
 
 	/**
 	 * 
-	 * @param bandId
-	 *            the id of the band
-	 * @param numElements
-	 *            the number of events on the band
-	 * @param numVisibleElements
-	 *            the number of visible events in the frame viewed on the scren
+	 * @param bandId the id of the band
+	 * @param numElements the number of events on the band
+	 * @param numVisibleElements the number of visible events in the frame
+	 * @param bandDescription description to be displayed on the view
+	 * @param isUserInterested whether the user is interested in the band
 	 */
-	public CurrentBandStats(final int bandId, final String bandDescription, int numElements, final int numVisibleElements,
-			final boolean isUserInterested) {
+	public CurrentBandStats(final int bandId, final String bandDescription, final int numElements,
+			final int numVisibleElements, final boolean isUserInterested) {
 		this.bandId = bandId;
 		this.bandDescription = bandDescription;
 		this.numElements = numElements;
@@ -26,13 +51,6 @@
 	}
 
 	/**
-	 * @return the isUserInterested
-	 */
-	public boolean isUserInterested() {
-		return isUserInterested;
-	}
-
-	/**
 	 * @return the bandDescription
 	 */
 	public String getBandDescription() {
@@ -59,4 +77,11 @@
 	public int getNumVisibleElements() {
 		return numVisibleElements;
 	}
+
+	/**
+	 * @return the isUserInterested
+	 */
+	public boolean isUserInterested() {
+		return isUserInterested;
+	}
 }

Modified: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java	2010-03-06 18:04:47 UTC (rev 97)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java	2010-03-06 19:45:10 UTC (rev 98)
@@ -6,72 +6,87 @@
 import com.tyndalehouse.step.web.client.toolkit.timeline.Timeband;
 import com.tyndalehouse.step.web.shared.timeline.Unit;
 
-public class TimeConversionUtil {
+/**
+ * Util class to convert time to date and vice versa
+ * 
+ * @author CJBurrell
+ * 
+ */
+public final class TimeConversionUtil {
 	/**
+	 * converts a pixel position to its date using the format associated to the
+	 * unit of the timeband
+	 * 
+	 * @param pixelPosition pixel position to be converted
+	 * @param timeband current timeband (this contains the current viewing
+	 *            location, and unit
+	 * @return the date as a formatted string
+	 */
+	public static String formatPixelToTime(final long pixelPosition, final Timeband timeband) {
+		return formatTime(pixelToTime(pixelPosition, timeband), timeband);
+	}
+
+	/**
+	 * formats the given time using the unit described in the timeband
+	 * 
+	 * @param timeband the timeband containing the current view, unit, etc.
+	 * @param eventDate date to be formatted
+	 * @return the string representation of the date
+	 */
+	public static String formatTime(final long eventDate, final Timeband timeband) {
+		final Date date = new Date(eventDate);
+		final String formatForBand = timeband.getUnit().getFormat();
+		final DateTimeFormat format = DateTimeFormat.getFormat(formatForBand);
+		return format.format(date);
+	}
+
+	/**
 	 * This takes a pixel position and returns the equivalent time
 	 * 
-	 * @param pixelPosition
-	 *            the pixel position that we are trying to convert
-	 * @param currentDateX
-	 *            the pixel position of the origin
-	 * @param currentDate
-	 *            the time that the origin is set to
-	 * @param unit
-	 *            the size of a unit
-	 * @param pixelsPerUnit
-	 *            the number of pixels per unit
+	 * @param pixelPosition the pixel position that we are trying to convert
+	 * @param timeband the timeband which contains the relevant information
+	 *            (current view, unit) to calculate the time from the pixel
+	 *            position
 	 * @return the time of pixelPosition
 	 */
-	public static long pixelToTime(long pixelPosition, Timeband timeband) {
-		long currentDateX = timeband.getCurrentDateX();
-		long currentDate = timeband.getCurrentDate();
-		Unit unit = timeband.getUnit();
-		long pixelsPerUnit = timeband.getPixelsPerUnit();
+	public static long pixelToTime(final long pixelPosition, final Timeband timeband) {
+		final long currentDateX = timeband.getCurrentDateX();
+		final long currentDate = timeband.getCurrentDate();
+		final Unit unit = timeband.getUnit();
+		final long pixelsPerUnit = timeband.getPixelsPerUnit();
 
-		long differenceWithOrigin = pixelPosition - currentDateX;
-		long date = currentDate + (differenceWithOrigin * unit.getMilliseconds() / pixelsPerUnit);
+		final long differenceWithOrigin = pixelPosition - currentDateX;
+		final long date = currentDate + (differenceWithOrigin * unit.getMilliseconds() / pixelsPerUnit);
 		return date;
 	}
 
 	/**
 	 * A date is always calculated within a time band.
 	 * 
-	 * @param eventDate
-	 *            the date to be converted
-	 * @param timeband
-	 * @return
+	 * @param eventDate the date to be converted
+	 * @param currentTimeband reference timeband (including current view, unit,
+	 *            etc).
+	 * @return the pixel position on the timeband for the passed in time
 	 */
-	public static int timeToPixel(final long eventDate, Timeband currentTimeband) {
+	public static int timeToPixel(final long eventDate, final Timeband currentTimeband) {
 		// here's what we start from
-		long millisecondPerUnit = currentTimeband.getUnit().getMilliseconds();
-		long pixelsPerUnit = currentTimeband.getPixelsPerUnit();
-		long currentOriginDate = currentTimeband.getCurrentDate();
-		long currentOriginXPixel = currentTimeband.getCurrentDateX();
+		final long millisecondPerUnit = currentTimeband.getUnit().getMilliseconds();
+		final long pixelsPerUnit = currentTimeband.getPixelsPerUnit();
+		final long currentOriginDate = currentTimeband.getCurrentDate();
+		final long currentOriginXPixel = currentTimeband.getCurrentDateX();
 
 		// what's one pixel in milliseconds?
-		double onePixelInMs = (double) millisecondPerUnit / pixelsPerUnit;
+		final double onePixelInMs = (double) millisecondPerUnit / pixelsPerUnit;
 
 		// calculate difference with current position on timeband
-		long differenceWithEvent = eventDate - currentOriginDate;
-		long pixelValueOnBand = currentOriginXPixel + (long) (differenceWithEvent / onePixelInMs);
+		final long differenceWithEvent = eventDate - currentOriginDate;
+		final long pixelValueOnBand = currentOriginXPixel + (long) (differenceWithEvent / onePixelInMs);
 		return (int) pixelValueOnBand;
 	}
 
-	public static String formatPixelToTime(final long pixelPosition, final Timeband timeband) {
-		return formatTime(pixelToTime(pixelPosition, timeband), timeband);
-	}
-
 	/**
-	 * formats the given time using the unit described in the timeband
-	 * 
-	 * @param eventDate
-	 *            date to be formatted
-	 * @return the string representation of the date
+	 * making the constructor invisible to outsiders
 	 */
-	public static String formatTime(final long eventDate, final Timeband timeband) {
-		Date date = new Date(eventDate);
-		String formatForBand = timeband.getUnit().getFormat();
-		DateTimeFormat format = DateTimeFormat.getFormat(formatForBand);
-		return format.format(date);
+	private TimeConversionUtil() {
 	}
 }




More information about the Tynstep-svn mailing list