Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/site/app/webroot/js/simile/timeline/scripts/detailed-painter.js
diff options
context:
space:
mode:
Diffstat (limited to 'site/app/webroot/js/simile/timeline/scripts/detailed-painter.js')
-rwxr-xr-xsite/app/webroot/js/simile/timeline/scripts/detailed-painter.js667
1 files changed, 667 insertions, 0 deletions
diff --git a/site/app/webroot/js/simile/timeline/scripts/detailed-painter.js b/site/app/webroot/js/simile/timeline/scripts/detailed-painter.js
new file mode 100755
index 0000000..8ec14a8
--- /dev/null
+++ b/site/app/webroot/js/simile/timeline/scripts/detailed-painter.js
@@ -0,0 +1,667 @@
+/*==================================================
+ * Detailed Event Painter
+ *==================================================
+ */
+
+Timeline.DetailedEventPainter = function(params) {
+ this._params = params;
+ this._onSelectListeners = [];
+
+ this._filterMatcher = null;
+ this._highlightMatcher = null;
+ this._frc = null;
+
+ this._eventIdToElmt = {};
+};
+
+Timeline.DetailedEventPainter.prototype.initialize = function(band, timeline) {
+ this._band = band;
+ this._timeline = timeline;
+
+ this._backLayer = null;
+ this._eventLayer = null;
+ this._lineLayer = null;
+ this._highlightLayer = null;
+
+ this._eventIdToElmt = null;
+};
+
+Timeline.DetailedEventPainter.prototype.addOnSelectListener = function(listener) {
+ this._onSelectListeners.push(listener);
+};
+
+Timeline.DetailedEventPainter.prototype.removeOnSelectListener = function(listener) {
+ for (var i = 0; i < this._onSelectListeners.length; i++) {
+ if (this._onSelectListeners[i] == listener) {
+ this._onSelectListeners.splice(i, 1);
+ break;
+ }
+ }
+};
+
+Timeline.DetailedEventPainter.prototype.getFilterMatcher = function() {
+ return this._filterMatcher;
+};
+
+Timeline.DetailedEventPainter.prototype.setFilterMatcher = function(filterMatcher) {
+ this._filterMatcher = filterMatcher;
+};
+
+Timeline.DetailedEventPainter.prototype.getHighlightMatcher = function() {
+ return this._highlightMatcher;
+};
+
+Timeline.DetailedEventPainter.prototype.setHighlightMatcher = function(highlightMatcher) {
+ this._highlightMatcher = highlightMatcher;
+};
+
+Timeline.DetailedEventPainter.prototype.paint = function() {
+ var eventSource = this._band.getEventSource();
+ if (eventSource == null) {
+ return;
+ }
+
+ this._eventIdToElmt = {};
+ this._prepareForPainting();
+
+ var eventTheme = this._params.theme.event;
+ var trackHeight = Math.max(eventTheme.track.height, this._frc.getLineHeight());
+ var metrics = {
+ trackOffset: Math.round(this._band.getViewWidth() / 2 - trackHeight / 2),
+ trackHeight: trackHeight,
+ trackGap: eventTheme.track.gap,
+ trackIncrement: trackHeight + eventTheme.track.gap,
+ icon: eventTheme.instant.icon,
+ iconWidth: eventTheme.instant.iconWidth,
+ iconHeight: eventTheme.instant.iconHeight,
+ labelWidth: eventTheme.label.width
+ }
+
+ var minDate = this._band.getMinDate();
+ var maxDate = this._band.getMaxDate();
+
+ var filterMatcher = (this._filterMatcher != null) ?
+ this._filterMatcher :
+ function(evt) { return true; };
+ var highlightMatcher = (this._highlightMatcher != null) ?
+ this._highlightMatcher :
+ function(evt) { return -1; };
+
+ var iterator = eventSource.getEventReverseIterator(minDate, maxDate);
+ while (iterator.hasNext()) {
+ var evt = iterator.next();
+ if (filterMatcher(evt)) {
+ this.paintEvent(evt, metrics, this._params.theme, highlightMatcher(evt));
+ }
+ }
+
+ this._highlightLayer.style.display = "block";
+ this._lineLayer.style.display = "block";
+ this._eventLayer.style.display = "block";
+};
+
+Timeline.DetailedEventPainter.prototype.softPaint = function() {
+};
+
+Timeline.DetailedEventPainter.prototype._prepareForPainting = function() {
+ var band = this._band;
+
+ if (this._backLayer == null) {
+ this._backLayer = this._band.createLayerDiv(0, "timeline-band-events");
+ this._backLayer.style.visibility = "hidden";
+
+ var eventLabelPrototype = document.createElement("span");
+ eventLabelPrototype.className = "timeline-event-label";
+ this._backLayer.appendChild(eventLabelPrototype);
+ this._frc = SimileAjax.Graphics.getFontRenderingContext(eventLabelPrototype);
+ }
+ this._frc.update();
+ this._lowerTracks = [];
+ this._upperTracks = [];
+
+ if (this._highlightLayer != null) {
+ band.removeLayerDiv(this._highlightLayer);
+ }
+ this._highlightLayer = band.createLayerDiv(105, "timeline-band-highlights");
+ this._highlightLayer.style.display = "none";
+
+ if (this._lineLayer != null) {
+ band.removeLayerDiv(this._lineLayer);
+ }
+ this._lineLayer = band.createLayerDiv(110, "timeline-band-lines");
+ this._lineLayer.style.display = "none";
+
+ if (this._eventLayer != null) {
+ band.removeLayerDiv(this._eventLayer);
+ }
+ this._eventLayer = band.createLayerDiv(110, "timeline-band-events");
+ this._eventLayer.style.display = "none";
+};
+
+Timeline.DetailedEventPainter.prototype.paintEvent = function(evt, metrics, theme, highlightIndex) {
+ if (evt.isInstant()) {
+ this.paintInstantEvent(evt, metrics, theme, highlightIndex);
+ } else {
+ this.paintDurationEvent(evt, metrics, theme, highlightIndex);
+ }
+};
+
+Timeline.DetailedEventPainter.prototype.paintInstantEvent = function(evt, metrics, theme, highlightIndex) {
+ if (evt.isImprecise()) {
+ this.paintImpreciseInstantEvent(evt, metrics, theme, highlightIndex);
+ } else {
+ this.paintPreciseInstantEvent(evt, metrics, theme, highlightIndex);
+ }
+}
+
+Timeline.DetailedEventPainter.prototype.paintDurationEvent = function(evt, metrics, theme, highlightIndex) {
+ if (evt.isImprecise()) {
+ this.paintImpreciseDurationEvent(evt, metrics, theme, highlightIndex);
+ } else {
+ this.paintPreciseDurationEvent(evt, metrics, theme, highlightIndex);
+ }
+}
+
+Timeline.DetailedEventPainter.prototype.paintPreciseInstantEvent = function(evt, metrics, theme, highlightIndex) {
+ var doc = this._timeline.getDocument();
+ var text = evt.getText();
+
+ var startDate = evt.getStart();
+ var startPixel = Math.round(this._band.dateToPixelOffset(startDate));
+ var iconRightEdge = Math.round(startPixel + metrics.iconWidth / 2);
+ var iconLeftEdge = Math.round(startPixel - metrics.iconWidth / 2);
+
+ var labelSize = this._frc.computeSize(text);
+ var iconTrack = this._findFreeTrackForSolid(iconRightEdge, startPixel);
+ var iconElmtData = this._paintEventIcon(evt, iconTrack, iconLeftEdge, metrics, theme);
+
+ var labelLeft = iconRightEdge + theme.event.label.offsetFromLine;
+ var labelTrack = iconTrack;
+
+ var iconTrackData = this._getTrackData(iconTrack);
+ if (Math.min(iconTrackData.solid, iconTrackData.text) >= labelLeft + labelSize.width) { // label on the same track, to the right of icon
+ iconTrackData.solid = iconLeftEdge;
+ iconTrackData.text = labelLeft;
+ } else { // label on a different track, below icon
+ iconTrackData.solid = iconLeftEdge;
+
+ labelLeft = startPixel + theme.event.label.offsetFromLine;
+ labelTrack = this._findFreeTrackForText(iconTrack, labelLeft + labelSize.width, function(t) { t.line = startPixel - 2; });
+ this._getTrackData(labelTrack).text = iconLeftEdge;
+
+ this._paintEventLine(evt, startPixel, iconTrack, labelTrack, metrics, theme);
+ }
+
+ var labelTop = Math.round(
+ metrics.trackOffset + labelTrack * metrics.trackIncrement +
+ metrics.trackHeight / 2 - labelSize.height / 2);
+
+ var labelElmtData = this._paintEventLabel(evt, text, labelLeft, labelTop, labelSize.width, labelSize.height, theme);
+
+ var self = this;
+ var clickHandler = function(elmt, domEvt, target) {
+ return self._onClickInstantEvent(iconElmtData.elmt, domEvt, evt);
+ };
+ SimileAjax.DOM.registerEvent(iconElmtData.elmt, "mousedown", clickHandler);
+ SimileAjax.DOM.registerEvent(labelElmtData.elmt, "mousedown", clickHandler);
+
+ this._createHighlightDiv(highlightIndex, iconElmtData, theme);
+
+ this._eventIdToElmt[evt.getID()] = iconElmtData.elmt;
+};
+
+Timeline.DetailedEventPainter.prototype.paintImpreciseInstantEvent = function(evt, metrics, theme, highlightIndex) {
+ var doc = this._timeline.getDocument();
+ var text = evt.getText();
+
+ var startDate = evt.getStart();
+ var endDate = evt.getEnd();
+ var startPixel = Math.round(this._band.dateToPixelOffset(startDate));
+ var endPixel = Math.round(this._band.dateToPixelOffset(endDate));
+
+ var iconRightEdge = Math.round(startPixel + metrics.iconWidth / 2);
+ var iconLeftEdge = Math.round(startPixel - metrics.iconWidth / 2);
+
+ var labelSize = this._frc.computeSize(text);
+ var iconTrack = this._findFreeTrackForSolid(endPixel, startPixel);
+
+ var tapeElmtData = this._paintEventTape(evt, iconTrack, startPixel, endPixel,
+ theme.event.instant.impreciseColor, theme.event.instant.impreciseOpacity, metrics, theme);
+ var iconElmtData = this._paintEventIcon(evt, iconTrack, iconLeftEdge, metrics, theme);
+
+ var iconTrackData = this._getTrackData(iconTrack);
+ iconTrackData.solid = iconLeftEdge;
+
+ var labelLeft = iconRightEdge + theme.event.label.offsetFromLine;
+ var labelRight = labelLeft + labelSize.width;
+ var labelTrack;
+ if (labelRight < endPixel) {
+ labelTrack = iconTrack;
+ } else {
+ labelLeft = startPixel + theme.event.label.offsetFromLine;
+ labelRight = labelLeft + labelSize.width;
+
+ labelTrack = this._findFreeTrackForText(iconTrack, labelRight, function(t) { t.line = startPixel - 2; });
+ this._getTrackData(labelTrack).text = iconLeftEdge;
+
+ this._paintEventLine(evt, startPixel, iconTrack, labelTrack, metrics, theme);
+ }
+ var labelTop = Math.round(
+ metrics.trackOffset + labelTrack * metrics.trackIncrement +
+ metrics.trackHeight / 2 - labelSize.height / 2);
+
+ var labelElmtData = this._paintEventLabel(evt, text, labelLeft, labelTop, labelSize.width, labelSize.height, theme);
+
+ var self = this;
+ var clickHandler = function(elmt, domEvt, target) {
+ return self._onClickInstantEvent(iconElmtData.elmt, domEvt, evt);
+ };
+ SimileAjax.DOM.registerEvent(iconElmtData.elmt, "mousedown", clickHandler);
+ SimileAjax.DOM.registerEvent(tapeElmtData.elmt, "mousedown", clickHandler);
+ SimileAjax.DOM.registerEvent(labelElmtData.elmt, "mousedown", clickHandler);
+
+ this._createHighlightDiv(highlightIndex, iconElmtData, theme);
+
+ this._eventIdToElmt[evt.getID()] = iconElmtData.elmt;
+};
+
+Timeline.DetailedEventPainter.prototype.paintPreciseDurationEvent = function(evt, metrics, theme, highlightIndex) {
+ var doc = this._timeline.getDocument();
+ var text = evt.getText();
+
+ var startDate = evt.getStart();
+ var endDate = evt.getEnd();
+ var startPixel = Math.round(this._band.dateToPixelOffset(startDate));
+ var endPixel = Math.round(this._band.dateToPixelOffset(endDate));
+
+ var labelSize = this._frc.computeSize(text);
+ var tapeTrack = this._findFreeTrackForSolid(endPixel);
+ var color = evt.getColor();
+ color = color != null ? color : theme.event.duration.color;
+
+ var tapeElmtData = this._paintEventTape(evt, tapeTrack, startPixel, endPixel, color, 100, metrics, theme);
+
+ var tapeTrackData = this._getTrackData(tapeTrack);
+ tapeTrackData.solid = startPixel;
+
+ var labelLeft = startPixel + theme.event.label.offsetFromLine;
+ var labelTrack = this._findFreeTrackForText(tapeTrack, labelLeft + labelSize.width, function(t) { t.line = startPixel - 2; });
+ this._getTrackData(labelTrack).text = startPixel - 2;
+
+ this._paintEventLine(evt, startPixel, tapeTrack, labelTrack, metrics, theme);
+
+ var labelTop = Math.round(
+ metrics.trackOffset + labelTrack * metrics.trackIncrement +
+ metrics.trackHeight / 2 - labelSize.height / 2);
+
+ var labelElmtData = this._paintEventLabel(evt, text, labelLeft, labelTop, labelSize.width, labelSize.height, theme);
+
+ var self = this;
+ var clickHandler = function(elmt, domEvt, target) {
+ return self._onClickDurationEvent(tapeElmtData.elmt, domEvt, evt);
+ };
+ SimileAjax.DOM.registerEvent(tapeElmtData.elmt, "mousedown", clickHandler);
+ SimileAjax.DOM.registerEvent(labelElmtData.elmt, "mousedown", clickHandler);
+
+ this._createHighlightDiv(highlightIndex, tapeElmtData, theme);
+
+ this._eventIdToElmt[evt.getID()] = tapeElmtData.elmt;
+};
+
+Timeline.DetailedEventPainter.prototype.paintImpreciseDurationEvent = function(evt, metrics, theme, highlightIndex) {
+ var doc = this._timeline.getDocument();
+ var text = evt.getText();
+
+ var startDate = evt.getStart();
+ var latestStartDate = evt.getLatestStart();
+ var endDate = evt.getEnd();
+ var earliestEndDate = evt.getEarliestEnd();
+
+ var startPixel = Math.round(this._band.dateToPixelOffset(startDate));
+ var latestStartPixel = Math.round(this._band.dateToPixelOffset(latestStartDate));
+ var endPixel = Math.round(this._band.dateToPixelOffset(endDate));
+ var earliestEndPixel = Math.round(this._band.dateToPixelOffset(earliestEndDate));
+
+ var labelSize = this._frc.computeSize(text);
+ var tapeTrack = this._findFreeTrackForSolid(endPixel);
+ var color = evt.getColor();
+ color = color != null ? color : theme.event.duration.color;
+
+ var impreciseTapeElmtData = this._paintEventTape(evt, tapeTrack, startPixel, endPixel,
+ theme.event.duration.impreciseColor, theme.event.duration.impreciseOpacity, metrics, theme);
+ var tapeElmtData = this._paintEventTape(evt, tapeTrack, latestStartPixel, earliestEndPixel, color, 100, metrics, theme);
+
+ var tapeTrackData = this._getTrackData(tapeTrack);
+ tapeTrackData.solid = startPixel;
+
+ var labelLeft = latestStartPixel + theme.event.label.offsetFromLine;
+ var labelTrack = this._findFreeTrackForText(tapeTrack, labelLeft + labelSize.width, function(t) { t.line = latestStartPixel - 2; });
+ this._getTrackData(labelTrack).text = latestStartPixel - 2;
+
+ this._paintEventLine(evt, latestStartPixel, tapeTrack, labelTrack, metrics, theme);
+
+ var labelTop = Math.round(
+ metrics.trackOffset + labelTrack * metrics.trackIncrement +
+ metrics.trackHeight / 2 - labelSize.height / 2);
+
+ var labelElmtData = this._paintEventLabel(evt, text, labelLeft, labelTop, labelSize.width, labelSize.height, theme);
+
+ var self = this;
+ var clickHandler = function(elmt, domEvt, target) {
+ return self._onClickDurationEvent(tapeElmtData.elmt, domEvt, evt);
+ };
+ SimileAjax.DOM.registerEvent(tapeElmtData.elmt, "mousedown", clickHandler);
+ SimileAjax.DOM.registerEvent(labelElmtData.elmt, "mousedown", clickHandler);
+
+ this._createHighlightDiv(highlightIndex, tapeElmtData, theme);
+
+ this._eventIdToElmt[evt.getID()] = tapeElmtData.elmt;
+};
+
+Timeline.DetailedEventPainter.prototype._findFreeTrackForSolid = function(solidEdge, softEdge) {
+ for (var i = 0; true; i++) {
+ if (i < this._lowerTracks.length) {
+ var t = this._lowerTracks[i];
+ if (Math.min(t.solid, t.text) > solidEdge && (!(softEdge) || t.line > softEdge)) {
+ return i;
+ }
+ } else {
+ this._lowerTracks.push({
+ solid: Number.POSITIVE_INFINITY,
+ text: Number.POSITIVE_INFINITY,
+ line: Number.POSITIVE_INFINITY
+ });
+
+ return i;
+ }
+
+ if (i < this._upperTracks.length) {
+ var t = this._upperTracks[i];
+ if (Math.min(t.solid, t.text) > solidEdge && (!(softEdge) || t.line > softEdge)) {
+ return -1 - i;
+ }
+ } else {
+ this._upperTracks.push({
+ solid: Number.POSITIVE_INFINITY,
+ text: Number.POSITIVE_INFINITY,
+ line: Number.POSITIVE_INFINITY
+ });
+
+ return -1 - i;
+ }
+ }
+};
+
+Timeline.DetailedEventPainter.prototype._findFreeTrackForText = function(fromTrack, edge, occupiedTrackVisitor) {
+ var extendUp;
+ var index;
+ var firstIndex;
+ var result;
+
+ if (fromTrack < 0) {
+ extendUp = true;
+ firstIndex = -fromTrack;
+
+ index = this._findFreeUpperTrackForText(firstIndex, edge);
+ result = -1 - index;
+ } else if (fromTrack > 0) {
+ extendUp = false;
+ firstIndex = fromTrack + 1;
+
+ index = this._findFreeLowerTrackForText(firstIndex, edge);
+ result = index;
+ } else {
+ var upIndex = this._findFreeUpperTrackForText(0, edge);
+ var downIndex = this._findFreeLowerTrackForText(1, edge);
+
+ if (downIndex - 1 <= upIndex) {
+ extendUp = false;
+ firstIndex = 1;
+ index = downIndex;
+ result = index;
+ } else {
+ extendUp = true;
+ firstIndex = 0;
+ index = upIndex;
+ result = -1 - index;
+ }
+ }
+
+ if (extendUp) {
+ if (index == this._upperTracks.length) {
+ this._upperTracks.push({
+ solid: Number.POSITIVE_INFINITY,
+ text: Number.POSITIVE_INFINITY,
+ line: Number.POSITIVE_INFINITY
+ });
+ }
+ for (var i = firstIndex; i < index; i++) {
+ occupiedTrackVisitor(this._upperTracks[i]);
+ }
+ } else {
+ if (index == this._lowerTracks.length) {
+ this._lowerTracks.push({
+ solid: Number.POSITIVE_INFINITY,
+ text: Number.POSITIVE_INFINITY,
+ line: Number.POSITIVE_INFINITY
+ });
+ }
+ for (var i = firstIndex; i < index; i++) {
+ occupiedTrackVisitor(this._lowerTracks[i]);
+ }
+ }
+ return result;
+};
+
+Timeline.DetailedEventPainter.prototype._findFreeLowerTrackForText = function(index, edge) {
+ for (; index < this._lowerTracks.length; index++) {
+ var t = this._lowerTracks[index];
+ if (Math.min(t.solid, t.text) >= edge) {
+ break;
+ }
+ }
+ return index;
+};
+
+Timeline.DetailedEventPainter.prototype._findFreeUpperTrackForText = function(index, edge) {
+ for (; index < this._upperTracks.length; index++) {
+ var t = this._upperTracks[index];
+ if (Math.min(t.solid, t.text) >= edge) {
+ break;
+ }
+ }
+ return index;
+};
+
+Timeline.DetailedEventPainter.prototype._getTrackData = function(index) {
+ return (index < 0) ? this._upperTracks[-index - 1] : this._lowerTracks[index];
+};
+
+Timeline.DetailedEventPainter.prototype._paintEventLine = function(evt, left, startTrack, endTrack, metrics, theme) {
+ var top = Math.round(metrics.trackOffset + startTrack * metrics.trackIncrement + metrics.trackHeight / 2);
+ var height = Math.round(Math.abs(endTrack - startTrack) * metrics.trackIncrement);
+
+ var lineStyle = "1px solid " + theme.event.label.lineColor;
+ var lineDiv = this._timeline.getDocument().createElement("div");
+ lineDiv.style.position = "absolute";
+ lineDiv.style.left = left + "px";
+ lineDiv.style.width = theme.event.label.offsetFromLine + "px";
+ lineDiv.style.height = height + "px";
+ if (startTrack > endTrack) {
+ lineDiv.style.top = (top - height) + "px";
+ lineDiv.style.borderTop = lineStyle;
+ } else {
+ lineDiv.style.top = top + "px";
+ lineDiv.style.borderBottom = lineStyle;
+ }
+ lineDiv.style.borderLeft = lineStyle;
+ this._lineLayer.appendChild(lineDiv);
+};
+
+Timeline.DetailedEventPainter.prototype._paintEventIcon = function(evt, iconTrack, left, metrics, theme) {
+ var icon = evt.getIcon();
+ icon = icon != null ? icon : metrics.icon;
+
+ var middle = metrics.trackOffset + iconTrack * metrics.trackIncrement + metrics.trackHeight / 2;
+ var top = Math.round(middle - metrics.iconHeight / 2);
+
+ var img = SimileAjax.Graphics.createTranslucentImage(icon);
+ var iconDiv = this._timeline.getDocument().createElement("div");
+ iconDiv.style.position = "absolute";
+ iconDiv.style.left = left + "px";
+ iconDiv.style.top = top + "px";
+ iconDiv.appendChild(img);
+ iconDiv.style.cursor = "pointer";
+ this._eventLayer.appendChild(iconDiv);
+
+ return {
+ left: left,
+ top: top,
+ width: metrics.iconWidth,
+ height: metrics.iconHeight,
+ elmt: iconDiv
+ };
+};
+
+Timeline.DetailedEventPainter.prototype._paintEventLabel = function(evt, text, left, top, width, height, theme) {
+ var doc = this._timeline.getDocument();
+
+ var labelBackgroundDiv = doc.createElement("div");
+ labelBackgroundDiv.style.position = "absolute";
+ labelBackgroundDiv.style.left = left + "px";
+ labelBackgroundDiv.style.width = width + "px";
+ labelBackgroundDiv.style.top = top + "px";
+ labelBackgroundDiv.style.height = height + "px";
+ labelBackgroundDiv.style.backgroundColor = theme.event.label.backgroundColor;
+ SimileAjax.Graphics.setOpacity(labelBackgroundDiv, theme.event.label.backgroundOpacity);
+ this._eventLayer.appendChild(labelBackgroundDiv);
+
+ var labelDiv = doc.createElement("div");
+ labelDiv.style.position = "absolute";
+ labelDiv.style.left = left + "px";
+ labelDiv.style.width = width + "px";
+ labelDiv.style.top = top + "px";
+ labelDiv.innerHTML = text;
+ labelDiv.style.cursor = "pointer";
+
+ var color = evt.getTextColor();
+ if (color == null) {
+ color = evt.getColor();
+ }
+ if (color != null) {
+ labelDiv.style.color = color;
+ }
+
+ this._eventLayer.appendChild(labelDiv);
+
+ return {
+ left: left,
+ top: top,
+ width: width,
+ height: height,
+ elmt: labelDiv
+ };
+};
+
+Timeline.DetailedEventPainter.prototype._paintEventTape = function(
+ evt, iconTrack, startPixel, endPixel, color, opacity, metrics, theme) {
+
+ var tapeWidth = endPixel - startPixel;
+ var tapeHeight = theme.event.tape.height;
+ var middle = metrics.trackOffset + iconTrack * metrics.trackIncrement + metrics.trackHeight / 2;
+ var top = Math.round(middle - tapeHeight / 2);
+
+ var tapeDiv = this._timeline.getDocument().createElement("div");
+ tapeDiv.style.position = "absolute";
+ tapeDiv.style.left = startPixel + "px";
+ tapeDiv.style.width = tapeWidth + "px";
+ tapeDiv.style.top = top + "px";
+ tapeDiv.style.height = tapeHeight + "px";
+ tapeDiv.style.backgroundColor = color;
+ tapeDiv.style.overflow = "hidden";
+ tapeDiv.style.cursor = "pointer";
+ SimileAjax.Graphics.setOpacity(tapeDiv, opacity);
+
+ this._eventLayer.appendChild(tapeDiv);
+
+ return {
+ left: startPixel,
+ top: top,
+ width: tapeWidth,
+ height: tapeHeight,
+ elmt: tapeDiv
+ };
+}
+
+Timeline.DetailedEventPainter.prototype._createHighlightDiv = function(highlightIndex, dimensions, theme) {
+ if (highlightIndex >= 0) {
+ var doc = this._timeline.getDocument();
+ var eventTheme = theme.event;
+
+ var color = eventTheme.highlightColors[Math.min(highlightIndex, eventTheme.highlightColors.length - 1)];
+
+ var div = doc.createElement("div");
+ div.style.position = "absolute";
+ div.style.overflow = "hidden";
+ div.style.left = (dimensions.left - 2) + "px";
+ div.style.width = (dimensions.width + 4) + "px";
+ div.style.top = (dimensions.top - 2) + "px";
+ div.style.height = (dimensions.height + 4) + "px";
+ div.style.background = color;
+
+ this._highlightLayer.appendChild(div);
+ }
+};
+
+Timeline.DetailedEventPainter.prototype._onClickInstantEvent = function(icon, domEvt, evt) {
+ var c = SimileAjax.DOM.getPageCoordinates(icon);
+ this._showBubble(
+ c.left + Math.ceil(icon.offsetWidth / 2),
+ c.top + Math.ceil(icon.offsetHeight / 2),
+ evt
+ );
+ this._fireOnSelect(evt.getID());
+
+ domEvt.cancelBubble = true;
+ SimileAjax.DOM.cancelEvent(domEvt);
+ return false;
+};
+
+Timeline.DetailedEventPainter.prototype._onClickDurationEvent = function(target, domEvt, evt) {
+ if ("pageX" in domEvt) {
+ var x = domEvt.pageX;
+ var y = domEvt.pageY;
+ } else {
+ var c = SimileAjax.DOM.getPageCoordinates(target);
+ var x = domEvt.offsetX + c.left;
+ var y = domEvt.offsetY + c.top;
+ }
+ this._showBubble(x, y, evt);
+ this._fireOnSelect(evt.getID());
+
+ domEvt.cancelBubble = true;
+ SimileAjax.DOM.cancelEvent(domEvt);
+ return false;
+};
+
+Timeline.DetailedEventPainter.prototype.showBubble = function(evt) {
+ var elmt = this._eventIdToElmt[evt.getID()];
+ if (elmt) {
+ var c = SimileAjax.DOM.getPageCoordinates(elmt);
+ this._showBubble(c.left + elmt.offsetWidth / 2, c.top + elmt.offsetHeight / 2, evt);
+ }
+};
+
+Timeline.DetailedEventPainter.prototype._showBubble = function(x, y, evt) {
+ var div = document.createElement("div");
+ evt.fillInfoBubble(div, this._params.theme, this._band.getLabeller());
+
+ SimileAjax.WindowManager.cancelPopups();
+ SimileAjax.Graphics.createBubbleForContentAndPoint(div, x, y, this._params.theme.event.bubble.width);
+};
+
+Timeline.DetailedEventPainter.prototype._fireOnSelect = function(eventID) {
+ for (var i = 0; i < this._onSelectListeners.length; i++) {
+ this._onSelectListeners[i](eventID);
+ }
+};