Skip to content

Commit

Permalink
Add option to loop visible range (#254)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwbonner committed Oct 28, 2024
1 parent 4bb9ecb commit b94f45f
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 10 deletions.
2 changes: 1 addition & 1 deletion docsSite/docs/getting-started/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The navigation buttons (green) on the top manage the tabs and control playback.
- **Plus Button**: Opens a dropdown menu to create a new tab.
- **Window Button:** Creates a new pop-out window with the tab tab. This feature can be used to view data from multiple tabs simultaneously.
- **X Button:** Closes the current tab.
- **Play Button:** Start and stop real-time playback. _Right-click to change playback speed._
- **Play Button:** Start and stop real-time playback. _Right-click to change playback speed or enable looping._

## Viewer Pane

Expand Down
15 changes: 13 additions & 2 deletions src/hub/SelectionImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default class SelectionImpl implements Selection {
private playbackStartLog: number = 0;
private playbackStartReal: number = 0;
private playbackSpeed: number = 1;
private playbackLooping = false;
private liveConnected: boolean = false;
private liveTimeSupplier: (() => number) | null = null;

Expand All @@ -35,10 +36,11 @@ export default class SelectionImpl implements Selection {
[this.PLAY_BUTTON, this.PAUSE_BUTTON].forEach((button) => {
button.addEventListener("contextmenu", () => {
let rect = button.getBoundingClientRect();
window.sendMainMessage("ask-playback-speed", {
window.sendMainMessage("ask-playback-options", {
x: Math.round(rect.right),
y: Math.round(rect.top),
speed: this.playbackSpeed
speed: this.playbackSpeed,
looping: this.playbackLooping
});
});
});
Expand Down Expand Up @@ -104,6 +106,10 @@ export default class SelectionImpl implements Selection {
return Math.max(this.staticTime, window.log.getTimestampRange()[0]);
case SelectionMode.Playback:
let time = (this.now() - this.playbackStartReal) * this.playbackSpeed + this.playbackStartLog;
if (this.playbackLooping && time > this.timelineRange[1]) {
time = this.timelineRange[0];
this.setSelectedTime(time);
}
let maxTime = window.log.getTimestampRange()[1];
if (this.liveTimeSupplier !== null) {
maxTime = Math.max(maxTime, this.liveTimeSupplier());
Expand Down Expand Up @@ -302,6 +308,11 @@ export default class SelectionImpl implements Selection {
this.playbackSpeed = speed;
}

/** Updates whether playback is looping. */
setPlaybackLooping(looping: boolean) {
this.playbackLooping = looping;
}

/** Sets a new time range for an in-progress grab zoom. */
setGrabZoomRange(range: [number, number] | null) {
if (range !== null) {
Expand Down
5 changes: 3 additions & 2 deletions src/hub/hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,9 @@ async function handleMainMessage(message: NamedMessage) {
}
break;

case "set-playback-speed":
window.selection.setPlaybackSpeed(message.data);
case "set-playback-options":
window.selection.setPlaybackSpeed(message.data.speed);
window.selection.setPlaybackLooping(message.data.looping);
break;

case "toggle-sidebar":
Expand Down
25 changes: 20 additions & 5 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,21 +507,36 @@ async function handleHubMessage(window: BrowserWindow, message: NamedMessage) {
}
break;

case "ask-playback-speed":
const playbackSpeedMenu = new Menu();
case "ask-playback-options":
const playbackOptionsMenu = new Menu();
Array(0.25, 0.5, 1, 1.5, 2, 4, 8).forEach((value) => {
playbackSpeedMenu.append(
playbackOptionsMenu.append(
new MenuItem({
label: (value * 100).toString() + "%",
type: "checkbox",
checked: value === message.data.speed,
click() {
sendMessage(window, "set-playback-speed", value);
sendMessage(window, "set-playback-options", { speed: value, looping: message.data.looping });
}
})
);
});
playbackSpeedMenu.popup({
playbackOptionsMenu.append(
new MenuItem({
type: "separator"
})
);
playbackOptionsMenu.append(
new MenuItem({
label: "Loop Visible Range",
type: "checkbox",
checked: message.data.looping,
click() {
sendMessage(window, "set-playback-options", { speed: message.data.speed, looping: !message.data.looping });
}
})
);
playbackOptionsMenu.popup({
window: window,
x: message.data.x,
y: message.data.y
Expand Down
4 changes: 4 additions & 0 deletions src/satellite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ class MockSelection implements Selection {
throw new Error("Method not implemented.");
}

setPlaybackLooping(looping: boolean): void {
throw new Error("Method not implemented.");
}

setGrabZoomRange(range: [number, number] | null) {
window.sendMainMessage("call-selection-setter", { name: "setGrabZoomRange", args: [range] });
}
Expand Down
3 changes: 3 additions & 0 deletions src/shared/Selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export default interface Selection {
/** Updates the playback speed. */
setPlaybackSpeed(speed: number): void;

/** Updates whether playback is looping. */
setPlaybackLooping(looping: boolean): void;

/** Sets a new time range for an in-progress grab zoom. */
setGrabZoomRange(range: [number, number] | null): void;

Expand Down

0 comments on commit b94f45f

Please sign in to comment.