Skip to content
This repository was archived by the owner on Dec 23, 2021. It is now read-only.

Make buttons work with keypresses #86

Merged
merged 4 commits into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/view/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Button: React.FC<IButtonProps> = props => {

return (
<button
id={`${props.label}-button`}
className={`${props.label}-button button`}
onClick={props.onClick}
style={buttonStyle}
Expand Down
69 changes: 42 additions & 27 deletions src/view/components/Simulator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const DEFAULT_CPX_STATE: ICpxState = {
switch: false
};

const SIMULATOR_BUTTO_WIDTH = 60;
const SIMULATOR_BUTTON_WIDTH = 60;

interface vscode {
postMessage(message: any): void;
Expand All @@ -62,7 +62,6 @@ const sendMessage = (type: string, state: any) => {
};

class Simulator extends React.Component<any, IState> {
private keyPressed = false;
constructor(props: IMyProps) {
super(props);
this.state = {
Expand All @@ -75,7 +74,7 @@ class Simulator extends React.Component<any, IState> {
this.onMouseDown = this.onMouseDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
this.playSimulatorClick = this.playSimulatorClick.bind(this);
this.togglePlayClick = this.togglePlayClick.bind(this);
this.refreshSimulatorClick = this.refreshSimulatorClick.bind(this);
}

Expand Down Expand Up @@ -130,53 +129,69 @@ class Simulator extends React.Component<any, IState> {
</div>
<div className="buttons">
<Button
onClick={this.playSimulatorClick}
onClick={this.togglePlayClick}
image={image}
label="play"
width={SIMULATOR_BUTTO_WIDTH}
width={SIMULATOR_BUTTON_WIDTH}
/>
<Button
onClick={this.refreshSimulatorClick}
image={RefreshLogo}
label="refresh"
width={SIMULATOR_BUTTO_WIDTH}
width={SIMULATOR_BUTTON_WIDTH}
/>
</div>
</div>
);
}

protected playSimulatorClick(event: React.MouseEvent<HTMLElement>) {
this.setState({ ...this.state, play_button: !this.state.play_button });
protected togglePlayClick() {
sendMessage("play-simulator", !this.state.play_button);
this.setState({ ...this.state, play_button: !this.state.play_button });
const button =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a play action, would the button focus go to the stop button? The code here seems to keep focus on the play button.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So maybe this is just poorly named. The play button is also the stop button when the code is running so this is grabbing whichever icon is available. I can rename this if that helps! @adclements

window.document.getElementById(CONSTANTS.ID_NAME.PLAY_BUTTON) ||
window.document.getElementById(CONSTANTS.ID_NAME.STOP_BUTTON);
if (button) {
button.focus();
}
}

protected refreshSimulatorClick(event: React.MouseEvent<HTMLElement>) {
protected refreshSimulatorClick() {
sendMessage("refresh-simulator", true);
const button = window.document.getElementById(
CONSTANTS.ID_NAME.REFRESH_BUTTON
);
if (button) {
button.focus();
}
}

protected onKeyEvent(event: KeyboardEvent, active: boolean) {
let button;
const target = event.target as SVGElement;
// Guard Clause
if (target === undefined) {
return;
}

if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if case seems to be building up. If we don't have any more sensors that require key press functionality, this should be fine?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any ideas on how to do this differently? I don't have any off the top of my head

Copy link
Contributor

@markAtMicrosoft markAtMicrosoft Aug 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does changing to a switch statement make sense?

if (target) {
button = window.document.getElementById(target.id);
if (button) {
event.preventDefault();
if (button.id.includes("SWITCH")) {
// Switch
this.handleClick(button, active);
} else if (active && !this.keyPressed) {
// Send one keydown event
this.handleClick(button, active);
this.keyPressed = true;
} else if (!active) {
// Keyup event
this.handleClick(button, active);
this.keyPressed = false;
}
}
}
button = window.document.getElementById(target.id);
} else if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A)) {
button = window.document.getElementById(CONSTANTS.ID_NAME.BUTTON_A);
} else if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B)) {
button = window.document.getElementById(CONSTANTS.ID_NAME.BUTTON_B);
} else if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.S)) {
button = window.document.getElementById(CONSTANTS.ID_NAME.SWITCH);
} else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) {
this.togglePlayClick();
} else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) {
this.refreshSimulatorClick();
}

if (button) {
event.preventDefault();
this.handleClick(button, active);
button.focus();
}
}

Expand Down
20 changes: 20 additions & 0 deletions src/view/components/cpx/Cpx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import * as React from "react";
import CPX_SVG from "./Cpx_svg";
import * as SvgStyle from "./Cpx_svg_style";
import CONSTANTS from "../../constants";
import svg from "./Svg_utils";
import accessibility from "./Accessibility_utils";

Expand All @@ -29,6 +30,7 @@ const Cpx: React.FC<IProps> = props => {
if (firstTime) {
initSvgStyle(svgElement, props.brightness);
setupButtons(props);
setupKeyPresses(props.onKeyEvent);
setupSwitch(props);
firstTime = false;
}
Expand Down Expand Up @@ -280,6 +282,24 @@ const setupButton = (button: HTMLElement, className: string, props: IProps) => {
svgButton.onmouseleave = e => props.onMouseLeave(button, e);
};

const setupKeyPresses = (
onKeyEvent: (event: KeyboardEvent, active: boolean) => void
) => {
window.document.addEventListener("keydown", event => {
const keyEvents = [event.key, event.code];
// Don't listen to keydown events from the switch
if (
!(
keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.S) ||
keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.CAPITAL_F)
)
) {
onKeyEvent(event, true);
}
});
window.document.addEventListener("keyup", event => onKeyEvent(event, false));
};

const setupSwitch = (props: IProps): void => {
const switchElement = window.document.getElementById("SWITCH");
const swInnerElement = window.document.getElementById("SWITCH_INNER");
Expand Down
16 changes: 15 additions & 1 deletion src/view/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@

// Key events
export const CONSTANTS = {
ID_NAME: {
BUTTON_A: "BTN_A_OUTER",
BUTTON_AB: "BTN_AB_OUTER",
BUTTON_B: "BTN_B_OUTER",
PLAY_BUTTON: "play-button",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to keep consistent with naming convention here in the future. There appears to be uppercase with underscores and lowercase with dashes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to just change either the class name or id name since I think having these together is good. I wouldn't separate it.

REFRESH_BUTTON: "refresh-button",
STOP_BUTTON: "stop-button",
SWITCH: "SWITCH"
},
KEYBOARD_KEYS: {
ENTER: "Enter"
A: "KeyA",
B: "KeyB",
CAPITAL_R: "R",
CAPITAL_F: "F",
ENTER: "Enter",
S: "KeyS"
}
}

Expand Down