[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