Skip to content

Commit 5f91826

Browse files
committed
feat(arduino-uno): add reset button
wokwi/wokwi-features#282
1 parent 9ead1e0 commit 5f91826

File tree

4 files changed

+149
-2
lines changed

4 files changed

+149
-2
lines changed

src/arduino-mega-element.stories.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { boolean, withKnobs } from '@storybook/addon-knobs';
22
import { storiesOf } from '@storybook/web-components';
33
import { html } from 'lit';
44
import './arduino-mega-element';
5+
import { action } from '@storybook/addon-actions';
56

67
storiesOf('Arduino Mega', module)
78
.addParameters({ component: 'wokwi-arduino-mega' })
@@ -14,6 +15,8 @@ storiesOf('Arduino Mega', module)
1415
.ledTX=${boolean('TX LED', false)}
1516
.ledRX=${boolean('RX LED', false)}
1617
.ledPower=${boolean('Power LED', true)}
18+
@button-press=${action('button-press')}
19+
@button-release=${action('button-release')}
1720
></wokwi-arduino-mega>
1821
`
1922
);

src/arduino-mega-element.ts

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { css, html, LitElement, svg } from 'lit';
2-
import { customElement, property } from 'lit/decorators.js';
2+
import { customElement, property, query } from 'lit/decorators.js';
33
import { pinsFemalePattern } from './patterns/pins-female';
44
import { analog, ElementPin, i2c, spi, usart } from './pin';
5+
import { SPACE_KEYS } from './utils/keys';
56

67
@customElement('wokwi-arduino-mega')
78
export class ArduinoMegaElement extends LitElement {
89
@property() led13 = false;
910
@property() ledRX = false;
1011
@property() ledTX = false;
1112
@property() ledPower = false;
13+
@property() resetPressed = false;
14+
@query('#reset-button') resetButton!: SVGCircleElement;
1215

1316
readonly pinInfo: ElementPin[] = [
1417
{ name: 'SCL', x: 90, y: 9, signals: [i2c('SCL')] },
@@ -106,6 +109,11 @@ export class ArduinoMegaElement extends LitElement {
106109
font-size: 2px;
107110
font-family: monospace;
108111
}
112+
circle[tabindex]:hover,
113+
circle[tabindex]:focus {
114+
stroke: white;
115+
outline: none;
116+
}
109117
`;
110118
}
111119

@@ -144,6 +152,41 @@ export class ArduinoMegaElement extends LitElement {
144152
fill="#2b6b99"
145153
/>
146154
155+
<!-- reset button -->
156+
<rect
157+
transform="rotate(269.81)"
158+
x="-28.046"
159+
y="68.977"
160+
width="6.2151"
161+
height="6.0268"
162+
fill="#9b9b9b"
163+
/>
164+
<g fill="#e6e6e6">
165+
<rect transform="rotate(269.81)" x="-29.725" y="69.518" width="1.695" height=".84994" />
166+
<rect transform="rotate(269.81)" x="-29.741" y="71.4" width="1.695" height=".84994" />
167+
<rect transform="rotate(269.81)" x="-29.764" y="73.425" width="1.695" height=".84994" />
168+
<rect transform="rotate(269.81)" x="-21.831" y="73.59" width="1.695" height=".84994" />
169+
<rect transform="rotate(269.81)" x="-21.854" y="69.517" width="1.695" height=".84994" />
170+
</g>
171+
<circle
172+
id="reset-button"
173+
transform="rotate(269.81)"
174+
cx="-24.9"
175+
cy="72.092"
176+
r="1.5405"
177+
fill="#960000"
178+
stroke="#777"
179+
stroke-width="0.15"
180+
tabindex="0"
181+
@mousedown=${() => this.down()}
182+
@touchstart=${() => this.down()}
183+
@mouseup=${() => this.up()}
184+
@mouseleave=${() => this.leave()}
185+
@touchend=${() => this.leave()}
186+
@keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()}
187+
@keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()}
188+
/>
189+
147190
<!-- USB Connector -->
148191
<g style="fill:#b3b2b2;stroke:#b3b2b2;stroke-width:0.010">
149192
<ellipse cx="3.84" cy="9.56" rx="1.12" ry="1.03" />
@@ -341,4 +384,34 @@ export class ArduinoMegaElement extends LitElement {
341384
</svg>
342385
`;
343386
}
387+
private down() {
388+
if (this.resetPressed) {
389+
return;
390+
}
391+
this.resetPressed = true;
392+
this.resetButton.style.stroke = '#333';
393+
this.dispatchEvent(
394+
new CustomEvent('button-press', {
395+
detail: 'reset',
396+
})
397+
);
398+
}
399+
400+
private up() {
401+
if (!this.resetPressed) {
402+
return;
403+
}
404+
this.resetPressed = false;
405+
this.resetButton.style.stroke = '';
406+
this.dispatchEvent(
407+
new CustomEvent('button-release', {
408+
detail: 'reset',
409+
})
410+
);
411+
}
412+
413+
private leave() {
414+
this.resetButton.blur();
415+
this.up();
416+
}
344417
}

src/arduino-uno-element.stories.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { action } from '@storybook/addon-actions';
12
import { withKnobs, boolean } from '@storybook/addon-knobs';
23
import { storiesOf } from '@storybook/web-components';
34
import { html } from 'lit';
@@ -14,6 +15,8 @@ storiesOf('Arduino Uno', module)
1415
.ledTX=${boolean('TX LED', false)}
1516
.ledRX=${boolean('RX LED', false)}
1617
.ledPower=${boolean('Power LED', true)}
18+
@button-press=${action('button-press')}
19+
@button-release=${action('button-release')}
1720
></wokwi-arduino-uno>
1821
`
1922
)
@@ -26,6 +29,8 @@ storiesOf('Arduino Uno', module)
2629
.ledTX=${boolean('TX LED', false)}
2730
.ledRX=${boolean('RX LED', false)}
2831
.ledPower=${boolean('Power LED', true)}
32+
@button-press=${action('button-press')}
33+
@button-release=${action('button-release')}
2934
></wokwi-arduino-uno>
3035
`
3136
);

src/arduino-uno-element.ts

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { css, html, LitElement, svg } from 'lit';
2-
import { customElement, property } from 'lit/decorators.js';
2+
import { customElement, property, query } from 'lit/decorators.js';
33
import { pinsFemalePattern } from './patterns/pins-female';
44
import { analog, ElementPin, i2c, spi, usart } from './pin';
5+
import { SPACE_KEYS } from './utils/keys';
56

67
@customElement('wokwi-arduino-uno')
78
export class ArduinoUnoElement extends LitElement {
89
@property() led13 = false;
910
@property() ledRX = false;
1011
@property() ledTX = false;
1112
@property() ledPower = false;
13+
@property() resetPressed = false;
14+
@query('#reset-button') resetButton!: SVGCircleElement;
1215

1316
readonly pinInfo: ElementPin[] = [
1417
{ name: 'A5.2', x: 87, y: 9, signals: [analog(5), i2c('SCL')] },
@@ -51,6 +54,12 @@ export class ArduinoUnoElement extends LitElement {
5154
font-family: monospace;
5255
user-select: none;
5356
}
57+
58+
circle[tabindex]:hover,
59+
circle[tabindex]:focus {
60+
stroke: white;
61+
outline: none;
62+
}
5463
`;
5564
}
5665

@@ -96,6 +105,33 @@ export class ArduinoUnoElement extends LitElement {
96105
fill="#2b6b99"
97106
/>
98107
108+
<!-- reset button -->
109+
<rect x="3.816" y="1.4125" width="6.2151" height="6.0268" fill="#9b9b9b" />
110+
<g fill="#e6e6e6">
111+
<rect x="2.1368" y="1.954" width="1.695" height=".84994" />
112+
<rect x="2.121" y="3.8362" width="1.695" height=".84994" />
113+
<rect x="2.0974" y="5.8608" width="1.695" height=".84994" />
114+
<rect x="10.031" y="6.0256" width="1.695" height=".84994" />
115+
<rect x="10.008" y="1.9528" width="1.695" height=".84994" />
116+
</g>
117+
<circle
118+
id="reset-button"
119+
cx="6.9619"
120+
cy="4.5279"
121+
r="1.5405"
122+
fill="#960000"
123+
stroke="#777"
124+
stroke-width="0.15"
125+
tabindex="0"
126+
@mousedown=${() => this.down()}
127+
@touchstart=${() => this.down()}
128+
@mouseup=${() => this.up()}
129+
@mouseleave=${() => this.leave()}
130+
@touchend=${() => this.leave()}
131+
@keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()}
132+
@keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()}
133+
/>
134+
99135
<!-- USB Connector -->
100136
<g style="fill:#b3b2b2;stroke:#b3b2b2;stroke-width:0.010">
101137
<ellipse cx="3.84" cy="9.56" rx="1.12" ry="1.03" />
@@ -314,4 +350,34 @@ export class ArduinoUnoElement extends LitElement {
314350
</svg>
315351
`;
316352
}
353+
private down() {
354+
if (this.resetPressed) {
355+
return;
356+
}
357+
this.resetPressed = true;
358+
this.resetButton.style.stroke = '#333';
359+
this.dispatchEvent(
360+
new CustomEvent('button-press', {
361+
detail: 'reset',
362+
})
363+
);
364+
}
365+
366+
private up() {
367+
if (!this.resetPressed) {
368+
return;
369+
}
370+
this.resetPressed = false;
371+
this.resetButton.style.stroke = '';
372+
this.dispatchEvent(
373+
new CustomEvent('button-release', {
374+
detail: 'reset',
375+
})
376+
);
377+
}
378+
379+
private leave() {
380+
this.resetButton.blur();
381+
this.up();
382+
}
317383
}

0 commit comments

Comments
 (0)