Skip to content

Commit 2fd2bfd

Browse files
[Simulator] Add compass module to simulator (#923)
* Finalise module order. * Prevent marker labels from wrapping.
1 parent 17708f7 commit 2fd2bfd

16 files changed

+256
-54
lines changed

lang/ui.en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,10 @@
799799
"defaultMessage": "Collapse {title} module",
800800
"description": "Aria label for collapse simulator module button"
801801
},
802+
"simulator-compass": {
803+
"defaultMessage": "Compass",
804+
"description": "Compass title"
805+
},
802806
"simulator-data-logging-empty": {
803807
"defaultMessage": "No log entries.",
804808
"description": "Shown in the simulator Data logging table when there are no rows"

lang/ui.fr.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,10 @@
798798
"defaultMessage": "Collapse {title} module",
799799
"description": "Aria label for collapse simulator module button"
800800
},
801+
"simulator-compass": {
802+
"defaultMessage": "Compass",
803+
"description": "Compass title"
804+
},
801805
"simulator-data-logging-empty": {
802806
"defaultMessage": "No log entries.",
803807
"description": "Shown in the simulator Data logging table when there are no rows"
@@ -807,7 +811,7 @@
807811
"description": "Shown below the Data logging table to warn that the log is full"
808812
},
809813
"simulator-data-logging-rows": {
810-
"defaultMessage": "{count, plural, =0 {No rows} 1 {# row} other {# rows}}",
814+
"defaultMessage": "{count, plural, =0 {No rows logged} 1 {# row logged} other {# rows logged}}",
811815
"description": "Indicator of the number of rows logged"
812816
},
813817
"simulator-data-logging-save-log": {

lang/ui.lol.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,10 @@
798798
"defaultMessage": "Collapse {title} module",
799799
"description": "Aria label for collapse simulator module button"
800800
},
801+
"simulator-compass": {
802+
"defaultMessage": "Compass",
803+
"description": "Compass title"
804+
},
801805
"simulator-data-logging-empty": {
802806
"defaultMessage": "No log entries.",
803807
"description": "Shown in the simulator Data logging table when there are no rows"
@@ -807,7 +811,7 @@
807811
"description": "Shown below the Data logging table to warn that the log is full"
808812
},
809813
"simulator-data-logging-rows": {
810-
"defaultMessage": "{count, plural, =0 {No rows} 1 {# row} other {# rows}}",
814+
"defaultMessage": "{count, plural, =0 {No rows logged} 1 {# row logged} other {# rows logged}}",
811815
"description": "Indicator of the number of rows logged"
812816
},
813817
"simulator-data-logging-save-log": {

src/device/simulator.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export interface SimulatorState {
7070
accelerometerZ: RangeSensor;
7171
gesture: EnumSensor;
7272

73+
compassX: RangeSensor;
74+
compassY: RangeSensor;
75+
compassZ: RangeSensor;
76+
compassHeading: RangeSensor;
77+
7378
pin0: RangeSensor;
7479
pin1: RangeSensor;
7580
pin2: RangeSensor;
@@ -90,6 +95,10 @@ export type SensorStateKey = Extract<
9095
| "accelerometerX"
9196
| "accelerometerY"
9297
| "accelerometerZ"
98+
| "compassX"
99+
| "compassY"
100+
| "compassZ"
101+
| "compassHeading"
93102
| "gesture"
94103
| "pin0"
95104
| "pin1"

src/messages/ui.en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,12 @@
18111811
"value": " module"
18121812
}
18131813
],
1814+
"simulator-compass": [
1815+
{
1816+
"type": 0,
1817+
"value": "Compass"
1818+
}
1819+
],
18141820
"simulator-data-logging-empty": [
18151821
{
18161822
"type": 0,

src/messages/ui.fr.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,12 @@
18111811
"value": " module"
18121812
}
18131813
],
1814+
"simulator-compass": [
1815+
{
1816+
"type": 0,
1817+
"value": "Compass"
1818+
}
1819+
],
18141820
"simulator-data-logging-empty": [
18151821
{
18161822
"type": 0,
@@ -1834,15 +1840,15 @@
18341840
},
18351841
{
18361842
"type": 0,
1837-
"value": " row"
1843+
"value": " row logged"
18381844
}
18391845
]
18401846
},
18411847
"=0": {
18421848
"value": [
18431849
{
18441850
"type": 0,
1845-
"value": "No rows"
1851+
"value": "No rows logged"
18461852
}
18471853
]
18481854
},
@@ -1853,7 +1859,7 @@
18531859
},
18541860
{
18551861
"type": 0,
1856-
"value": " rows"
1862+
"value": " rows logged"
18571863
}
18581864
]
18591865
}

src/messages/ui.lol.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,12 @@
17551755
"value": " module"
17561756
}
17571757
],
1758+
"simulator-compass": [
1759+
{
1760+
"type": 0,
1761+
"value": "Compass"
1762+
}
1763+
],
17581764
"simulator-data-logging-empty": [
17591765
{
17601766
"type": 0,
@@ -1778,15 +1784,15 @@
17781784
},
17791785
{
17801786
"type": 0,
1781-
"value": " row"
1787+
"value": " row logged"
17821788
}
17831789
]
17841790
},
17851791
"=0": {
17861792
"value": [
17871793
{
17881794
"type": 0,
1789-
"value": "No rows"
1795+
"value": "No rows logged"
17901796
}
17911797
]
17921798
},
@@ -1797,7 +1803,7 @@
17971803
},
17981804
{
17991805
"type": 0,
1800-
"value": " rows"
1806+
"value": " rows logged"
18011807
}
18021808
]
18031809
}

src/simulator/AccelerometerModule.tsx

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { HStack, IconButton, Select, Stack, Text } from "@chakra-ui/react";
1+
import { HStack, IconButton, Select, Stack } from "@chakra-ui/react";
22
import { ChangeEvent, ReactNode, useCallback, useState } from "react";
33
import { RiSendPlane2Line } from "react-icons/ri";
44
import { useIntl } from "react-intl";
5-
import {
6-
RangeSensor as RangeSensorType,
7-
SensorStateKey,
8-
SimulatorState,
9-
} from "../device/simulator";
10-
import RangeSensor from "./RangeSensor";
5+
import { SensorStateKey, SimulatorState } from "../device/simulator";
6+
import Axis from "./Axis";
117
import { RunningStatus } from "./Simulator";
128

139
interface AccelerometerModuleProps {
@@ -115,30 +111,4 @@ const Gesture = ({ icon, state, enabled, onValueChange }: GestureProps) => {
115111
);
116112
};
117113

118-
interface AxisProps {
119-
axis: SensorStateKey;
120-
label: string;
121-
state: SimulatorState;
122-
onValueChange: (id: SensorStateKey, value: any) => void;
123-
}
124-
125-
const Axis = ({
126-
axis,
127-
label,
128-
state,
129-
onValueChange: onSensorChange,
130-
}: AxisProps) => (
131-
<RangeSensor
132-
id={axis}
133-
title={label}
134-
icon={
135-
<Text boxSize={6} textAlign="center">
136-
{label}
137-
</Text>
138-
}
139-
sensor={state[axis] as RangeSensorType}
140-
onSensorChange={onSensorChange}
141-
/>
142-
);
143-
144114
export default AccelerometerModule;

src/simulator/Axis.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* (c) 2022, Micro:bit Educational Foundation and contributors
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
import { Text } from "@chakra-ui/react";
7+
import {
8+
RangeSensor as RangeSensorType,
9+
SensorStateKey,
10+
SimulatorState,
11+
} from "../device/simulator";
12+
import RangeSensor from "./RangeSensor";
13+
14+
interface AxisProps {
15+
axis: SensorStateKey;
16+
label: string;
17+
state: SimulatorState;
18+
onValueChange: (id: SensorStateKey, value: any) => void;
19+
}
20+
21+
const Axis = ({
22+
axis,
23+
label,
24+
state,
25+
onValueChange: onSensorChange,
26+
}: AxisProps) => (
27+
<RangeSensor
28+
id={axis}
29+
title={label}
30+
icon={
31+
label ? (
32+
<Text boxSize={6} textAlign="center">
33+
{label}
34+
</Text>
35+
) : (
36+
""
37+
)
38+
}
39+
sensor={state[axis] as RangeSensorType}
40+
onSensorChange={onSensorChange}
41+
/>
42+
);
43+
44+
export default Axis;

src/simulator/ButtonsModule.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ const ButtonsModule = ({
3232
icon
3333
) : (
3434
<>
35-
<Text height={8} alignItems="center" display="flex">
35+
<Text height={8} fontSize="sm" alignItems="center" display="flex">
3636
<FormattedMessage id="simulator-input-press" />
3737
</Text>
38-
<Text>
38+
<Text fontSize="sm">
3939
<FormattedMessage id="simulator-input-hold" />
4040
</Text>
4141
</>

src/simulator/CompassModule.tsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* (c) 2022, Micro:bit Educational Foundation and contributors
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
import { Box, HStack, Icon, Stack, Text } from "@chakra-ui/react";
7+
import { ReactNode, useEffect, useRef } from "react";
8+
import {
9+
RangeSensor as RangeSensorType,
10+
SensorStateKey,
11+
SimulatorState,
12+
} from "../device/simulator";
13+
import Axis from "./Axis";
14+
import { ReactComponent as CompassHeadingIcon } from "./icons/compass-heading.svg";
15+
import RangeSensor from "./RangeSensor";
16+
17+
interface CompassModuleProps {
18+
icon: ReactNode;
19+
state: SimulatorState;
20+
onValueChange: (id: SensorStateKey, value: any) => void;
21+
minimised: boolean;
22+
}
23+
24+
const CompassModule = ({
25+
icon,
26+
state,
27+
onValueChange,
28+
minimised,
29+
}: CompassModuleProps) => {
30+
const ref = useRef<SVGSVGElement>(null);
31+
const compassHeading = state["compassHeading"];
32+
useEffect(() => {
33+
const needle = ref.current?.querySelector("#Needle");
34+
if (needle) {
35+
(
36+
needle as HTMLElement
37+
).style.transform = `rotate(${compassHeading.value}deg)`;
38+
}
39+
}, [compassHeading]);
40+
return (
41+
<Box>
42+
{minimised ? (
43+
<RangeSensor
44+
id="compassHeading"
45+
icon={icon}
46+
title="compass heading"
47+
sensor={compassHeading as RangeSensorType}
48+
onSensorChange={onValueChange}
49+
minimised={minimised}
50+
/>
51+
) : (
52+
<>
53+
<Text as="h4" fontSize="sm">
54+
Heading
55+
</Text>
56+
<HStack spacing={3} pl={4} width="100%">
57+
<Axis
58+
axis="compassHeading"
59+
label=""
60+
state={state}
61+
onValueChange={onValueChange}
62+
/>
63+
<Icon
64+
ref={ref}
65+
as={CompassHeadingIcon}
66+
color="blimpTeal.400"
67+
boxSize="20"
68+
/>
69+
</HStack>
70+
<Stack spacing={5} mt={5}>
71+
<Text as="h4" fontSize="sm">
72+
Magnetic field strength
73+
</Text>
74+
<Axis
75+
axis="compassX"
76+
label="x"
77+
state={state}
78+
onValueChange={onValueChange}
79+
/>
80+
<Axis
81+
axis="compassY"
82+
label="y"
83+
state={state}
84+
onValueChange={onValueChange}
85+
/>
86+
<Axis
87+
axis="compassZ"
88+
label="z"
89+
state={state}
90+
onValueChange={onValueChange}
91+
/>
92+
</Stack>
93+
</>
94+
)}
95+
</Box>
96+
);
97+
};
98+
99+
export default CompassModule;

src/simulator/PinsModule.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ const PinsModule = ({
3636
icon
3737
) : (
3838
<>
39-
<Text height={8} alignItems="center" display="flex">
39+
<Text height={8} fontSize="sm" alignItems="center" display="flex">
4040
<FormattedMessage id="simulator-input-press" />
4141
</Text>
42-
<Text>
42+
<Text fontSize="sm">
4343
<FormattedMessage id="simulator-input-hold" />
4444
</Text>
4545
</>

0 commit comments

Comments
 (0)