import {SimulationController} from "../simulationcontroller"; import {Util} from "../../util"; import * as $ from "jquery"; export class TimelineController { private simulationController: SimulationController; private startLabel: JQuery; private endLabel: JQuery; private playButton: JQuery; private loadingIcon: JQuery; private cacheSection: JQuery; private timeMarker: JQuery; private timeline: JQuery; private timeUnitFraction: number; private timeMarkerWidth: number; private timelineWidth: number; constructor(simulationController: SimulationController) { this.simulationController = simulationController; this.startLabel = $(".timeline-container .labels .start-time-label"); this.endLabel = $(".timeline-container .labels .end-time-label"); this.playButton = $(".timeline-container .play-btn"); this.loadingIcon = this.playButton.find("img"); this.cacheSection = $(".timeline-container .timeline .cache-section"); this.timeMarker = $(".timeline-container .timeline .time-marker"); this.timeline = $(".timeline-container .timeline"); this.timeMarkerWidth = this.timeMarker.width(); this.timelineWidth = this.timeline.width(); } public togglePlayback(): void { if (this.simulationController.stateCache.cacheBlock) { this.simulationController.playing = false; return; } this.simulationController.playing = !this.simulationController.playing; this.setButtonIcon(); } public setupListeners(): void { this.playButton.on("click", () => { this.togglePlayback(); }); $(".timeline-container .timeline").on("click", (event: JQueryEventObject) => { const parentOffset = $(event.target).closest(".timeline").offset(); const clickX = event.pageX - parentOffset.left; let newTick = Math.round(clickX / (this.timelineWidth * this.timeUnitFraction)); if (newTick > this.simulationController.stateCache.lastCachedTick) { newTick = this.simulationController.stateCache.lastCachedTick; } this.simulationController.currentTick = newTick; this.simulationController.checkCurrentSimulationSection(); this.simulationController.update(); }); } public setButtonIcon(): void { if (this.simulationController.playing && !this.playButton.hasClass("glyphicon-pause")) { this.playButton.removeClass("glyphicon-play").addClass("glyphicon-pause"); } else if (!this.simulationController.playing && !this.playButton.hasClass("glyphicon-play")) { this.playButton.removeClass("glyphicon-pause").addClass("glyphicon-play"); } } public update(): void { this.timeUnitFraction = 1 / (this.simulationController.lastSimulatedTick + 1); this.timelineWidth = $(".timeline-container .timeline").width(); this.updateTimeLabels(); this.cacheSection.css("width", this.calculateTickPosition(this.simulationController.stateCache.lastCachedTick)); this.timeMarker.css("left", this.calculateTickPosition(this.simulationController.currentTick)); this.updateTaskIndicators(); this.updateSectionMarkers(); if (this.simulationController.stateCache.cacheBlock) { this.playButton.removeClass("glyphicon-pause").removeClass("glyphicon-play"); this.loadingIcon.show(); } else { this.loadingIcon.hide(); this.setButtonIcon(); } } private updateTimeLabels(): void { this.startLabel.text(Util.convertSecondsToFormattedTime(this.simulationController.currentTick)); this.endLabel.text(Util.convertSecondsToFormattedTime(this.simulationController.lastSimulatedTick)); } private updateSectionMarkers(): void { $(".section-marker").remove(); this.simulationController.sections.forEach((simulationSection: ISection) => { if (simulationSection.startTick === 0) { return; } this.timeline.append( $('