@@ -15,12 +15,74 @@ const arrowDownSVGUrl = `data:image/svg+xml;base64,${btoa(arrowDownSVG)}`;
1515const turnLeftSVGUrl = `data:image/svg+xml;base64,${ btoa ( turnLeftSVG ) } ` ;
1616const turnRightSVGUrl = `data:image/svg+xml;base64,${ btoa ( turnRightSVG ) } ` ;
1717import { UseSignal } from '@jupyterlab/apputils' ;
18+ import { Button } from '@jupyterlab/ui-components' ;
19+ import { Poll } from '@lumino/polling' ;
20+ const LONG_PRESS_THRESHOLD = 1000 ;
1821
1922export interface IMoveHubControlProps {
2023 device : MoveHub ;
2124}
2225
2326export function ManualControl ( { device, themeManager } : IMoveHubPanelWithThemeProps ) {
27+ let pressStartTime : number = 0 ;
28+ let pressDuration : number = 0 ;
29+ let poll : Poll | null = null ;
30+
31+ const handleMouseDown = ( ) => {
32+ pressStartTime = Date . now ( ) ;
33+
34+ poll = new Poll ( {
35+ auto : true ,
36+ name : 'click-duration-polling' ,
37+ factory : async ( ) => {
38+ pressDuration = Date . now ( ) - pressStartTime ;
39+ } ,
40+ frequency : {
41+ interval : 100 ,
42+ backoff : true ,
43+ } ,
44+ standby : 'when-hidden' ,
45+ } ) ;
46+
47+ poll . start ( ) ;
48+ } ;
49+
50+ const handleMouseUp = async ( action : string , direction : number ) => {
51+ if ( poll ) {
52+ poll . stop ( ) ;
53+ }
54+ if ( action === "inactive" ) {
55+ console . error ( 'Inactive button, no control available.' ) ;
56+ }
57+ if ( action === "stop" ) {
58+ device . stop ( ) ;
59+ }
60+
61+ if ( pressDuration < LONG_PRESS_THRESHOLD ) {
62+ if ( action === "drive" ) {
63+ await device . hub . drive ( 20 * direction ) ;
64+ }
65+ else if ( action === "turn" ) {
66+ await device . hub . turn ( 90 * direction ) ;
67+ }
68+
69+ } else {
70+ if ( action === "drive" ) {
71+ await device . hub . driveToDirection ( direction ) ;
72+ }
73+
74+ else if ( action === "turn" ) {
75+ await device . hub . turn ( 3600 * direction ) ;
76+ }
77+ } ;
78+ }
79+
80+ const handleMouseLeave = ( ) => {
81+ if ( poll ) {
82+ poll . stop ( ) ;
83+ }
84+ } ;
85+
2486 const theme = themeManager . theme ;
2587 if ( theme ) {
2688 const isThemeLight = themeManager . isLight ( theme ! ) ;
@@ -30,71 +92,91 @@ export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemePr
3092 id : 1 ,
3193 src : currentEmptySVGUrl ,
3294 alt : 'Image 1' ,
33- handleClick : ( ) => {
34- console . error ( 'Inactive button, no control available.' ) ;
35- }
95+ action : "inactive" ,
96+ direction : 0 ,
97+ handleMouseDown : handleMouseDown ,
98+ handleMouseUp : handleMouseUp ,
99+ handleMouseLeave : handleMouseLeave
36100 } ,
37101 {
38102 id : 2 ,
39103 src : arrowUpSVGUrl ,
40104 alt : 'Image 2' ,
41- handleClick : async ( ) => {
42- await device . hub . driveToDirection ( 1 ) ;
43- }
105+ action : 'drive' ,
106+ direction : 1 ,
107+ handleMouseDown : handleMouseDown ,
108+ handleMouseUp : handleMouseUp ,
109+ handleMouseLeave : handleMouseLeave
44110 } ,
45111 {
46112 id : 3 ,
47113 src : currentEmptySVGUrl ,
48114 alt : 'Image 3' ,
49- handleClick : ( ) => {
50- console . error ( 'Inactive button, no control available.' ) ;
51- }
115+ action : "inactive" ,
116+ direction : 0 ,
117+ handleMouseDown : handleMouseDown ,
118+ handleMouseUp : handleMouseUp ,
119+ handleMouseLeave : handleMouseLeave
52120 } ,
53121 {
54122 id : 4 ,
55123 src : turnLeftSVGUrl ,
124+ action : "turn" ,
125+ direction : - 1 ,
56126 alt : 'Image 4' ,
57- handleClick : async ( ) => {
58- await device . hub . turn ( - 90 ) ;
59- }
127+ handleMouseDown : handleMouseDown ,
128+ handleMouseUp : handleMouseUp ,
129+ handleMouseLeave : handleMouseLeave
60130 } ,
61131 {
62132 id : 5 ,
63133 src : stopSVGUrl ,
64134 alt : 'Image 5' ,
65- handleClick : async ( ) => {
66- device . stop ( ) ;
67- }
135+ action : "stop" ,
136+ direction : 0 ,
137+ handleMouseDown : handleMouseDown ,
138+ handleMouseUp : handleMouseUp ,
139+ handleMouseLeave : handleMouseLeave
68140 } ,
69141 {
70142 id : 6 ,
71143 src : turnRightSVGUrl ,
72144 alt : 'Image 6' ,
73- handleClick : async ( ) => {
74- device . hub . turn ( 90 ) ;
75- }
145+ action : "turn" ,
146+ direction : 1 ,
147+ handleMouseDown : handleMouseDown ,
148+ handleMouseUp : handleMouseUp ,
149+ handleMouseLeave : handleMouseLeave
76150 } ,
77151 {
78152 id : 7 ,
79153 src : currentEmptySVGUrl ,
80154 alt : 'Image 7' ,
81- handleClick : ( ) => {
82- console . error ( 'Inactive button, no control available.' ) ;
83- }
155+ action : "inactive" ,
156+ direction : 0 ,
157+ handleMouseDown : handleMouseDown ,
158+ handleMouseUp : handleMouseUp ,
159+ handleMouseLeave : handleMouseLeave
84160 } ,
85161 {
86162 id : 8 ,
87163 src : arrowDownSVGUrl ,
88164 alt : 'Image 8' ,
89- handleClick : async ( ) => await device . hub . driveToDirection ( 0 )
165+ action : "drive" ,
166+ direction : - 1 ,
167+ handleMouseDown : handleMouseDown ,
168+ handleMouseUp : handleMouseUp ,
169+ handleMouseLeave : handleMouseLeave
90170 } ,
91171 {
92172 id : 9 ,
93173 src : currentEmptySVGUrl ,
94174 alt : 'Image 9' ,
95- handleClick : ( ) => {
96- console . error ( 'Inactive button, no control available.' ) ;
97- }
175+ action : "inactive" ,
176+ direction : 0 ,
177+ handleMouseDown : handleMouseDown ,
178+ handleMouseUp : handleMouseUp ,
179+ handleMouseLeave : handleMouseLeave
98180 }
99181 ] ;
100182
@@ -103,13 +185,15 @@ export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemePr
103185 < div className = "manual-control-grid" >
104186 { images . map ( ( image , index ) => (
105187 < div className = "manual-control-grid-item" >
106- < button
188+ < Button
107189 key = { index }
108- onClick = { image . handleClick }
190+ onMouseDown = { image . handleMouseDown }
191+ onMouseUp = { ( e ) => { handleMouseUp ( image . action , image . direction ) } }
192+ onMouseLeave = { image . handleMouseLeave }
109193 className = "image-button"
110194 >
111195 < img src = { image . src } alt = { image . alt } />
112- </ button >
196+ </ Button >
113197 </ div >
114198 ) ) }
115199 </ div >
@@ -124,90 +208,115 @@ export function ManualControl({ device, themeManager }: IMoveHubPanelWithThemePr
124208 id : 1 ,
125209 src : emptyLightSVGUrl ,
126210 alt : 'Image 1' ,
127- handleClick : ( ) => {
128- console . error ( 'Inactive button, no control available.' ) ;
129- }
211+ action : "inactive" ,
212+ direction : 0 ,
213+ handleMouseDown : handleMouseDown ,
214+ handleMouseUp : handleMouseUp ,
215+ handleMouseLeave : handleMouseLeave
130216 } ,
131217 {
132218 id : 2 ,
133219 src : arrowUpSVGUrl ,
134220 alt : 'Image 2' ,
135- handleClick : async ( ) => {
136- await device . hub . driveToDirection ( 1 ) ;
137- }
221+ action : 'drive' ,
222+ direction : 1 ,
223+ handleMouseDown : handleMouseDown ,
224+ handleMouseUp : handleMouseUp ,
225+ handleMouseLeave : handleMouseLeave
138226 } ,
139227 {
140228 id : 3 ,
141229 src : emptyLightSVGUrl ,
142230 alt : 'Image 3' ,
143- handleClick : ( ) => {
144- console . error ( 'Inactive button, no control available.' ) ;
145- }
231+ action : "inactive" ,
232+ direction : 0 ,
233+ handleMouseDown : handleMouseDown ,
234+ handleMouseUp : handleMouseUp ,
235+ handleMouseLeave : handleMouseLeave
146236 } ,
147237 {
148238 id : 4 ,
149239 src : turnLeftSVGUrl ,
240+ action : "turn" ,
241+ direction : - 1 ,
150242 alt : 'Image 4' ,
151- handleClick : async ( ) => {
152- await device . hub . turn ( - 90 ) ;
153- }
243+ handleMouseDown : handleMouseDown ,
244+ handleMouseUp : handleMouseUp ,
245+ handleMouseLeave : handleMouseLeave
154246 } ,
155247 {
156248 id : 5 ,
157249 src : stopSVGUrl ,
158250 alt : 'Image 5' ,
159- handleClick : async ( ) => {
160- device . stop ( ) ;
161- }
251+ action : "stop" ,
252+ direction : 0 ,
253+ handleMouseDown : handleMouseDown ,
254+ handleMouseUp : handleMouseUp ,
255+ handleMouseLeave : handleMouseLeave
162256 } ,
163257 {
164258 id : 6 ,
165259 src : turnRightSVGUrl ,
166260 alt : 'Image 6' ,
167- handleClick : async ( ) => {
168- device . hub . turn ( 90 ) ;
169- }
261+ action : "turn" ,
262+ direction : 1 ,
263+ handleMouseDown : handleMouseDown ,
264+ handleMouseUp : handleMouseUp ,
265+ handleMouseLeave : handleMouseLeave
170266 } ,
171267 {
172268 id : 7 ,
173269 src : emptyLightSVGUrl ,
174270 alt : 'Image 7' ,
175- handleClick : ( ) => {
176- console . error ( 'Inactive button, no control available.' ) ;
177- }
271+ action : "inactive" ,
272+ direction : 0 ,
273+ handleMouseDown : handleMouseDown ,
274+ handleMouseUp : handleMouseUp ,
275+ handleMouseLeave : handleMouseLeave
178276 } ,
179277 {
180278 id : 8 ,
181279 src : arrowDownSVGUrl ,
182280 alt : 'Image 8' ,
183- handleClick : async ( ) => await device . hub . driveToDirection ( 0 )
281+ action : "drive" ,
282+ direction : - 1 ,
283+ handleMouseDown : handleMouseDown ,
284+ handleMouseUp : handleMouseUp ,
285+ handleMouseLeave : handleMouseLeave
184286 } ,
185287 {
186288 id : 9 ,
187289 src : emptyLightSVGUrl ,
188290 alt : 'Image 9' ,
189- handleClick : ( ) => {
190- console . error ( 'Inactive button, no control available.' ) ;
191- }
291+ action : "inactive" ,
292+ direction : 0 ,
293+ handleMouseDown : handleMouseDown ,
294+ handleMouseUp : handleMouseUp ,
295+ handleMouseLeave : handleMouseLeave
192296 }
193297 ] ;
194298
195- return (
196- < div className = "manual-control-grid" >
197- { images . map ( ( image , index ) => (
198- < div className = "manual-control-grid-item" >
199- < button
200- key = { index }
201- onClick = { image . handleClick }
202- className = "image-button"
203- >
204- < img src = { image . src } alt = { image . alt } />
205- </ button >
206- </ div >
207- ) ) }
208- </ div >
209- )
299+ return ( < UseSignal signal = { themeManager . themeChanged } >
300+ { ( ) : JSX . Element => (
301+ < div className = "manual-control-grid" >
302+ { images . map ( ( image , index ) => (
303+ < div className = "manual-control-grid-item" >
304+ < Button
305+ key = { index }
306+ onMouseDown = { image . handleMouseDown }
307+ onMouseUp = { ( e ) => { handleMouseUp ( image . action , image . direction ) } }
308+ onMouseLeave = { image . handleMouseLeave }
309+
310+ className = "image-button"
311+ >
312+ < img src = { image . src } alt = { image . alt } />
313+ </ Button >
314+ </ div >
315+ ) ) }
316+ </ div >
317+ ) }
318+ </ UseSignal >
319+ ) ;
210320 }
211321}
212322
213-
0 commit comments