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

Button interaction #195

Merged
merged 14 commits into from
Feb 11, 2020
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
13 changes: 13 additions & 0 deletions src/adafruit_circuitplayground/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@

EVENTS_BUTTON_PRESS = ["button_a", "button_b", "switch"]
EVENTS_SENSOR_CHANGED = ["temperature", "light", "motion_x", "motion_y", "motion_z"]

ALL_EXPECTED_INPUT_EVENTS = [
"button_a",
"button_b",
"switch",
"temperature",
"light",
"shake",
"motion_x",
"motion_y",
"motion_z",
"touch",
]
6 changes: 6 additions & 0 deletions src/adafruit_circuitplayground/express.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,11 @@ def stop_tone(self):
telemetry_py.send_telemetry("STOP_TONE")
raise NotImplementedError(CONSTANTS.NOT_IMPLEMENTED_ERROR)

def update_state(self, new_state):
for event in CONSTANTS.ALL_EXPECTED_INPUT_EVENTS:
self._Express__state[event] = new_state.get(
event, self._Express__state[event]
)


cpx = Express()
5 changes: 4 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ export async function activate(context: vscode.ExtensionContext) {
// Handle messages from webview
messageListener = currentPanel.webview.onDidReceiveMessage(
message => {
const messageJson = JSON.stringify(message.text);
const messageJson = JSON.stringify({
active_device: currentActiveDevice,
state: message.text,
});
switch (message.command) {
case WEBVIEW_MESSAGES.BUTTON_PRESS:
// Send input to the Python process
Expand Down
5 changes: 5 additions & 0 deletions src/microbit/__model/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,8 @@
SAME_SIZE_ERR = "images must be the same size"

TIME_DELAY = 0.03

EXPECTED_INPUT_BUTTONS = [
"button_a",
"button_b",
]
19 changes: 19 additions & 0 deletions src/microbit/__model/microbit_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .button import Button
from .display import Display
from . import constants as CONSTANTS


class MicrobitModel:
Expand All @@ -12,12 +13,30 @@ def __init__(self):
self.__start_time = time.time()
self.display = Display()

self.microbit_button_dict = {
"button_a": self.button_a,
"button_b": self.button_b,
}

def sleep(self, n):
time.sleep(n / 1000)

def running_time(self):
print(f"time. time: {time.time()}")
return time.time() - self.__start_time

def update_state(self, new_state):
for button_name in CONSTANTS.EXPECTED_INPUT_BUTTONS:
button = self.microbit_button_dict[button_name]

previous_pressed = button.is_pressed()
button_pressed = new_state.get(button_name, previous_pressed)

if button_pressed != previous_pressed:
if button_pressed:
button._Button__press_down()
else:
button._Button__release()


__mb = MicrobitModel()
17 changes: 12 additions & 5 deletions src/process_user_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
# This import must happen after the sys.path is modified
from adafruit_circuitplayground.express import cpx
from adafruit_circuitplayground.telemetry import telemetry_py
from adafruit_circuitplayground.constants import CPX

from microbit.__model.microbit_model import __mb as mb
from microbit.__model.constants import MICROBIT


# Handle User Inputs Thread
Expand All @@ -39,15 +42,19 @@ def __init__(self):
threading.Thread.__init__(self)

def run(self):
device_dict = {CPX: cpx, MICROBIT: mb}
while True:
read_val = sys.stdin.readline()
sys.stdin.flush()
try:
new_state = json.loads(read_val)
for event in CONSTANTS.EXPECTED_INPUT_EVENTS_CPX:
cpx._Express__state[event] = new_state.get(
event, cpx._Express__state[event]
)
new_state_message = json.loads(read_val)
device = new_state_message.get(CONSTANTS.ACTIVE_DEVICE_FIELD)
new_state = new_state_message.get(CONSTANTS.STATE_FIELD, {})

if device in device_dict:
device_dict[device].update_state(new_state)
else:
raise Exception(CONSTANTS.DEVICE_NOT_IMPLEMENTED_ERROR)

except Exception as e:
print(CONSTANTS.ERROR_SENDING_EVENT, e, file=sys.stderr, flush=True)
Expand Down
18 changes: 6 additions & 12 deletions src/python_constants.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

ACTIVE_DEVICE_FIELD = "active_device"

CPX_DRIVE_NAME = "CIRCUITPY"

DEVICE_NOT_IMPLEMENTED_ERROR = "Device not implemented."

ENABLE_TELEMETRY = "enable_telemetry"
EXPECTED_INPUT_EVENTS_CPX = [
"button_a",
"button_b",
"switch",
"temperature",
"light",
"shake",
"motion_x",
"motion_y",
"motion_z",
"touch",
]

EXEC_COMMAND = "exec"
ERROR_SENDING_EVENT = "Error trying to send event to the process : "
Expand All @@ -37,6 +29,8 @@

PYTHON_LIBS_DIR = "python_libs"

STATE_FIELD = "state"

UTF_FORMAT = "utf-8"

WINDOWS_OS = "win32"
Expand Down
1 change: 0 additions & 1 deletion src/view/components/cpx/CpxSimulator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ class Simulator extends React.Component<{}, IState> {

protected togglePlayClick() {
sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, {
active_device: CONSTANTS.DEVICE_NAME.CPX,
selected_file: this.state.selected_file,
state: !this.state.play_button,
});
Expand Down
16 changes: 6 additions & 10 deletions src/view/components/microbit/MicrobitImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@ import "../../styles/Microbit.css";
import { MicrobitSvg } from "./Microbit_svg";

interface EventTriggers {
onMouseUp: (button: HTMLElement, event: Event, buttonKey: string) => void;
onMouseDown: (button: HTMLElement, event: Event, buttonKey: string) => void;
onMouseLeave: (
button: HTMLElement,
event: Event,
buttonKey: string
) => void;
onMouseUp: (event: Event, buttonKey: string) => void;
onMouseDown: (event: Event, buttonKey: string) => void;
onMouseLeave: (event: Event, buttonKey: string) => void;
}
interface IProps {
eventTriggers: EventTriggers;
Expand Down Expand Up @@ -47,13 +43,13 @@ const setupButton = (
key: string
) => {
buttonElement.onmousedown = e => {
eventTriggers.onMouseDown(buttonElement, e, key);
eventTriggers.onMouseDown(e, key);
};
buttonElement.onmouseup = e => {
eventTriggers.onMouseUp(buttonElement, e, key);
eventTriggers.onMouseUp(e, key);
};
buttonElement.onmouseleave = e => {
eventTriggers.onMouseLeave(buttonElement, e, key);
eventTriggers.onMouseLeave(e, key);
};
};
const setupAllButtons = (eventTriggers: EventTriggers, buttonRefs: Object) => {
Expand Down
83 changes: 61 additions & 22 deletions src/view/components/microbit/MicrobitSimulator.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
import * as React from "react";
import CONSTANTS, { WEBVIEW_MESSAGES, DEVICE_LIST_KEY } from "../../constants";
import {
WEBVIEW_MESSAGES,
MICROBIT_BUTTONS_KEYS,
DEVICE_LIST_KEY,
} from "../../constants";
import PlayLogo from "../../svgs/play_svg";
import StopLogo from "../../svgs/stop_svg";
import { sendMessage } from "../../utils/MessageUtils";
import Dropdown from "../Dropdown";
import ActionBar from "../simulator/ActionBar";
import { MicrobitImage } from "./MicrobitImage";

const initialLedState = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
];
const DEFAULT_MICROBIT_STATE: IMicrobitState = {
leds: [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
],
buttons: { button_a: false, button_b: false },
};

interface IState {
active_editors: string[];
running_file: string;
leds: number[][];
play_button: boolean;
selected_file: string;
microbit: IMicrobitState;
}

interface IMicrobitState {
leds: number[][];
buttons: { button_a: boolean; button_b: boolean };
}
export class MicrobitSimulator extends React.Component<any, IState> {
constructor() {
super({});
this.state = {
leds: initialLedState,
microbit: DEFAULT_MICROBIT_STATE,
play_button: false,
selected_file: "",
active_editors: [],
Expand All @@ -43,13 +55,16 @@ export class MicrobitSimulator extends React.Component<any, IState> {
switch (message.command) {
case "reset-state":
this.setState({
leds: initialLedState,
microbit: DEFAULT_MICROBIT_STATE,
play_button: false,
});
break;
case "set-state":
this.setState({
leds: message.state.leds,
microbit: {
...this.state.microbit,
leds: message.state.leds,
},
});
break;
case "activate-play":
Expand Down Expand Up @@ -101,7 +116,7 @@ export class MicrobitSimulator extends React.Component<any, IState> {
onMouseUp: this.onMouseUp,
onMouseLeave: this.onMouseLeave,
}}
leds={this.state.leds}
leds={this.state.microbit.leds}
/>
</div>
<ActionBar
Expand All @@ -114,7 +129,6 @@ export class MicrobitSimulator extends React.Component<any, IState> {
}
protected togglePlayClick = () => {
sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, {
active_device: CONSTANTS.DEVICE_NAME.MICROBIT,
selected_file: this.state.selected_file,
state: !this.state.play_button,
});
Expand All @@ -127,16 +141,41 @@ export class MicrobitSimulator extends React.Component<any, IState> {
protected refreshSimulatorClick = () => {
sendMessage(WEBVIEW_MESSAGES.REFRESH_SIMULATOR, true);
};
protected onMouseUp(button: HTMLElement, event: Event, key: string) {
protected handleButtonClick = (key: string, isActive: boolean) => {
let newButtonState = this.state.microbit.buttons;
switch (key) {
case MICROBIT_BUTTONS_KEYS.BTN_A:
newButtonState.button_a = isActive;
break;
case MICROBIT_BUTTONS_KEYS.BTN_B:
newButtonState.button_b = isActive;
break;
case MICROBIT_BUTTONS_KEYS.BTN_AB:
newButtonState = {
button_a: isActive,
button_b: isActive,
};
break;
}
sendMessage(WEBVIEW_MESSAGES.BUTTON_PRESS, newButtonState);
this.setState({
microbit: {
...this.state.microbit,
buttons: newButtonState,
},
});
};
protected onMouseUp = (event: Event, key: string) => {
event.preventDefault();
console.log(`To implement onMouseUp on ${key}`);
}
protected onMouseDown(button: HTMLElement, event: Event, key: string) {
this.handleButtonClick(key, false);
};
protected onMouseDown = (event: Event, key: string) => {
event.preventDefault();
console.log(`To implement onMouseDown ${key}`);
}
protected onMouseLeave(button: HTMLElement, event: Event, key: string) {
this.handleButtonClick(key, true);
};

protected onMouseLeave = (event: Event, key: string) => {
event.preventDefault();
console.log(`To implement onMouseLeave ${key}`);
}
};
}
5 changes: 5 additions & 0 deletions src/view/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export const CONSTANTS = {
SIMULATOR_BUTTON_WIDTH: 60,
TOOLBAR_INFO: `Explore what's on the board:`,
};
export const MICROBIT_BUTTONS_KEYS = {
BTN_A: "BTN_A",
BTN_B: "BTN_B",
BTN_AB: "BTN_AB",
};
export enum DEVICE_LIST_KEY {
CPX = "CPX",
MICROBIT = "micro:bit",
Expand Down