Skip to content

Commit

Permalink
feat: add play keyboard handler
Browse files Browse the repository at this point in the history
Fixes #259

Add key commands for play/stop, increase/decrease speed and
changing direction.
  • Loading branch information
oscarlorentzon committed Dec 1, 2017
1 parent 08f1f38 commit c446227
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 16 deletions.
1 change: 1 addition & 0 deletions spec/helper/PlayServiceMockCreator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class PlayServiceMockCreator extends MockCreatorBase<PlayService> {

this._mockProperty(mock, "direction$", new Subject<EdgeDirection>());
this._mockProperty(mock, "playing$", new Subject<boolean>());
this._mockProperty(mock, "speed$", new Subject<boolean>());

return mock;
}
Expand Down
1 change: 1 addition & 0 deletions src/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export {DirectionDOMCalculator} from "./component/direction/DirectionDOMCalculat
export {DirectionDOMRenderer} from "./component/direction/DirectionDOMRenderer";
export {ImageComponent} from "./component/ImageComponent";
export {KeyboardComponent} from "./component/keyboard/KeyboardComponent";
export {KeyPlayHandler} from "./component/keyboard/KeyPlayHandler";
export {KeyZoomHandler} from "./component/keyboard/KeyZoomHandler";
export {KeySequenceNavigationHandler} from "./component/keyboard/KeySequenceNavigationHandler";
export {KeySpatialNavigationHandler} from "./component/keyboard/KeySpatialNavigationHandler";
Expand Down
11 changes: 9 additions & 2 deletions src/component/interfaces/IKeyboardConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import {IComponentConfiguration} from "../../Component";
*/
export interface IKeyboardConfiguration extends IComponentConfiguration {
/**
* Enable or disable the `KeyHandler`.
* Enable or disable the `KeyPlayHandler`.
*
* @default true
*/
keyZoom?: boolean;
keyPlay?: boolean;

/**
* Enable or disable the `KeySequenceNavigationHandler`.
Expand All @@ -39,6 +39,13 @@ export interface IKeyboardConfiguration extends IComponentConfiguration {
* @default true
*/
keySpatialNavigation?: boolean;

/**
* Enable or disable the `KeyZoomHandler`.
*
* @default true
*/
keyZoom?: boolean;
}

export default IKeyboardConfiguration;
113 changes: 113 additions & 0 deletions src/component/keyboard/KeyPlayHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/// <reference path="../../../typings/index.d.ts" />

import {Observable} from "rxjs/Observable";
import {Subscription} from "rxjs/Subscription";

import {
IKeyboardConfiguration,
HandlerBase,
} from "../../Component";
import {EdgeDirection} from "../../Edge";
import {
IEdgeStatus,
Node,
} from "../../Graph";

/**
* The `KeyPlayHandler` allows the user to control the play behavior
* using the following key commands:
*
* `Spacebar`: Start or stop playing.
* `SHIFT` + `D`: Switch direction.
* `<`: Decrease speed.
* `>`: Increase speed.
*
* @example
* ```
* var keyboardComponent = viewer.getComponent("keyboard");
*
* keyboardComponent.keyPlay.disable();
* keyboardComponent.keyPlay.enable();
*
* var isEnabled = keyboardComponent.keyPlay.isEnabled;
* ```
*/
export class KeyPlayHandler extends HandlerBase<IKeyboardConfiguration> {
private _keyDownSubscription: Subscription;

protected _enable(): void {
this._keyDownSubscription = this._container.keyboardService.keyDown$
.withLatestFrom(
this._navigator.playService.playing$,
this._navigator.playService.direction$,
this._navigator.playService.speed$,
this._navigator.stateService.currentNode$
.switchMap(
(node: Node): Observable<IEdgeStatus> => {
return node.sequenceEdges$;
}))
.subscribe(
(
[event, playing, direction, speed, status]:
[KeyboardEvent, boolean, EdgeDirection, number, IEdgeStatus]): void => {

if (event.altKey || event.ctrlKey || event.metaKey) {
return;
}

switch (event.key) {
case "D":
if (!event.shiftKey) {
return;
}

const newDirection: EdgeDirection = playing ?
null : direction === EdgeDirection.Next ?
EdgeDirection.Prev : direction === EdgeDirection.Prev ?
EdgeDirection.Next : null;

if (newDirection != null) {
this._navigator.playService.setDirection(newDirection);
}

break;
case " ":
if (event.shiftKey) {
return;
}

if (playing) {
this._navigator.playService.stop();
} else {
for (let edge of status.edges) {
if (edge.data.direction === direction) {
this._navigator.playService.play();
}
}
}

break;
case "<":
this._navigator.playService.setSpeed(speed - 0.05);
break;
case ">":
this._navigator.playService.setSpeed(speed + 0.05);
break;
default:
return;
}

event.preventDefault();
});
}

protected _disable(): void {
this._keyDownSubscription.unsubscribe();
}

protected _getConfiguration(enable: boolean): IKeyboardConfiguration {
return { keyZoom: enable };
}
}

export default KeyPlayHandler;
2 changes: 1 addition & 1 deletion src/component/keyboard/KeySequenceNavigationHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from "../../Graph";

/**
* The `KeySequenceNavigationHandler` allows the user navigate through a sequence using the
* The `KeySequenceNavigationHandler` allows the user to navigate through a sequence using the
* following key commands:
*
* `ALT` + `Up Arrow`: Navigate to next image in the sequence.
Expand Down
2 changes: 1 addition & 1 deletion src/component/keyboard/KeySpatialNavigationHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "../../Viewer";

/**
* The `KeySpatialNavigationHandler` allows the user navigate through a sequence using the
* The `KeySpatialNavigationHandler` allows the user to navigate through a sequence using the
* following key commands:
*
* `Up Arrow`: Step forward.
Expand Down
2 changes: 1 addition & 1 deletion src/component/keyboard/KeyZoomHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from "../../Viewer";

/**
* The `KeyZoomHandler` allows the user zoom in and out using the
* The `KeyZoomHandler` allows the user to zoom in and out using the
* following key commands:
*
* `+`: Zoom in.
Expand Down
40 changes: 29 additions & 11 deletions src/component/keyboard/KeyboardComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import {
ComponentService,
Component,
IKeyboardConfiguration,
KeyZoomHandler,
KeyPlayHandler,
KeySequenceNavigationHandler,
KeySpatialNavigationHandler,
KeyZoomHandler,
} from "../../Component";
import {
Spatial,
Expand Down Expand Up @@ -37,27 +38,29 @@ import {
export class KeyboardComponent extends Component<IKeyboardConfiguration> {
public static componentName: string = "keyboard";

private _keyZoomHandler: KeyZoomHandler;
private _keyPlayHandler: KeyPlayHandler;
private _keySequenceNavigationHandler: KeySequenceNavigationHandler;
private _keySpatialNavigationHandler: KeySpatialNavigationHandler;
private _keyZoomHandler: KeyZoomHandler;

private _configurationSubscription: Subscription;

constructor(name: string, container: Container, navigator: Navigator) {
super(name, container, navigator);

this._keyZoomHandler = new KeyZoomHandler(this, container, navigator, new ViewportCoords());
this._keyPlayHandler = new KeyPlayHandler(this, container, navigator);
this._keySequenceNavigationHandler = new KeySequenceNavigationHandler(this, container, navigator);
this._keySpatialNavigationHandler = new KeySpatialNavigationHandler(this, container, navigator, new Spatial());
this._keyZoomHandler = new KeyZoomHandler(this, container, navigator, new ViewportCoords());
}

/**
* Get key zoom.
* Get key play.
*
* @returns {KeyZoomHandler} The key zoom handler.
* @returns {KeyPlayHandler} The key play handler.
*/
public get keyZoom(): KeyZoomHandler {
return this._keyZoomHandler;
public get keyPlay(): KeyPlayHandler {
return this._keyPlayHandler;
}

/**
Expand All @@ -78,14 +81,23 @@ export class KeyboardComponent extends Component<IKeyboardConfiguration> {
return this._keySpatialNavigationHandler;
}

/**
* Get key zoom.
*
* @returns {KeyZoomHandler} The key zoom handler.
*/
public get keyZoom(): KeyZoomHandler {
return this._keyZoomHandler;
}

protected _activate(): void {
this._configurationSubscription = this._configuration$
.subscribe(
(configuration: IKeyboardConfiguration): void => {
if (configuration.keyZoom) {
this._keyZoomHandler.enable();
if (configuration.keyPlay) {
this._keyPlayHandler.enable();
} else {
this._keyZoomHandler.disable();
this._keyPlayHandler.disable();
}

if (configuration.keySequenceNavigation) {
Expand All @@ -99,6 +111,12 @@ export class KeyboardComponent extends Component<IKeyboardConfiguration> {
} else {
this._keySpatialNavigationHandler.disable();
}

if (configuration.keyZoom) {
this._keyZoomHandler.enable();
} else {
this._keyZoomHandler.disable();
}
});
}

Expand All @@ -107,7 +125,7 @@ export class KeyboardComponent extends Component<IKeyboardConfiguration> {
}

protected _getDefaultConfiguration(): IKeyboardConfiguration {
return { keySequenceNavigation: true, keySpatialNavigation: true, keyZoom: true };
return { keyPlay: true, keySequenceNavigation: true, keySpatialNavigation: true, keyZoom: true };
}
}

Expand Down

0 comments on commit c446227

Please sign in to comment.