Skip to content

Commit 73e8819

Browse files
authored
Merge pull request #2492 from RoboErikG/bitmap-touch
fix: #2463 update event handling for field-bitmap to support touch
2 parents 909de8f + 82d5a48 commit 73e8819

1 file changed

Lines changed: 59 additions & 28 deletions

File tree

plugins/field-bitmap/src/field-bitmap.ts

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class FieldBitmap extends Blockly.Field<number[][]> {
3737
private editorPixels: HTMLElement[][] | null = null;
3838
private blockDisplayPixels: SVGElement[][] | null = null;
3939
/** Stateful variables */
40-
private mouseIsDown = false;
40+
private pointerIsDown = false;
4141
private valToPaintWith?: number;
4242
buttonOptions: Buttons;
4343
pixelSize: number;
@@ -292,9 +292,13 @@ export class FieldBitmap extends Blockly.Field<number[][]> {
292292
// This prevents the normal max-height from adding a scroll bar for large images.
293293
Blockly.DropDownDiv.getContentDiv().classList.add('contains-bitmap-editor');
294294

295-
this.bindEvent(dropdownEditor, 'mouseup', this.onMouseUp);
296-
this.bindEvent(dropdownEditor, 'mouseleave', this.onMouseUp);
297-
this.bindEvent(dropdownEditor, 'dragstart', (e: Event) => {
295+
this.bindEvent(dropdownEditor, 'pointermove', this.onPointerMove);
296+
this.bindEvent(dropdownEditor, 'pointerup', this.onPointerEnd);
297+
this.bindEvent(dropdownEditor, 'pointerleave', this.onPointerEnd);
298+
this.bindEvent(dropdownEditor, 'pointerdown', this.onPointerStart);
299+
this.bindEvent(dropdownEditor, 'pointercancel', this.onPointerEnd);
300+
// Stop the browser from handling touch events and cancelling the event.
301+
this.bindEvent(dropdownEditor, 'touchmove', (e: Event) => {
298302
e.preventDefault();
299303
});
300304

@@ -314,16 +318,9 @@ export class FieldBitmap extends Blockly.Field<number[][]> {
314318
? this.pixelColours.filled
315319
: this.pixelColours.empty;
316320

317-
// Handle clicking a pixel
318-
this.bindEvent(button, 'mousedown', () => {
319-
this.onMouseDownInPixel(r, c);
320-
return true;
321-
});
322-
323-
// Handle dragging into a pixel when mouse is down
324-
this.bindEvent(button, 'mouseenter', () => {
325-
this.onMouseEnterPixel(r, c);
326-
});
321+
// Set the custom data attributes for row and column indices
322+
button.setAttribute('data-row', r.toString());
323+
button.setAttribute('data-col', c.toString());
327324
}
328325
pixelContainer.appendChild(rowDiv);
329326
}
@@ -473,29 +470,63 @@ export class FieldBitmap extends Blockly.Field<number[][]> {
473470
}
474471

475472
/**
476-
* Called when a mousedown event occurs within the bounds of a pixel.
473+
* Checks if a down event is on a pixel in this editor and if it is starts an
474+
* edit gesture.
475+
*
476+
* @param e The down event.
477+
*/
478+
private onPointerStart(e: PointerEvent) {
479+
const currentElement = document.elementFromPoint(e.clientX, e.clientY);
480+
const rowIndex = currentElement?.getAttribute('data-row');
481+
const colIndex = currentElement?.getAttribute('data-col');
482+
if (rowIndex && colIndex) {
483+
this.onPointerDownInPixel(parseInt(rowIndex), parseInt(colIndex));
484+
this.pointerIsDown = true;
485+
e.preventDefault();
486+
}
487+
}
488+
489+
/**
490+
* Updates the editor if we're in an edit gesture and the pointer is over a
491+
* pixel.
492+
*
493+
* @param e The move event.
494+
*/
495+
private onPointerMove(e: PointerEvent) {
496+
if (!this.pointerIsDown) {
497+
return;
498+
}
499+
const currentElement = document.elementFromPoint(e.clientX, e.clientY);
500+
const rowIndex = currentElement?.getAttribute('data-row');
501+
const colIndex = currentElement?.getAttribute('data-col');
502+
if (rowIndex && colIndex) {
503+
this.updatePixelValue(parseInt(rowIndex), parseInt(colIndex));
504+
}
505+
e.preventDefault();
506+
}
507+
508+
/**
509+
* Starts an interaction with the bitmap dropdown when there's a pointerdown
510+
* within one of the pixels in the editor.
477511
*
478512
* @param r Row number of grid.
479513
* @param c Column number of grid.
480514
*/
481-
private onMouseDownInPixel(r: number, c: number) {
515+
private onPointerDownInPixel(r: number, c: number) {
482516
// Toggle that pixel to the opposite of its value
483517
const newPixelValue = 1 - this.getPixel(r, c);
484518
this.setPixel(r, c, newPixelValue);
485-
this.mouseIsDown = true;
519+
this.pointerIsDown = true;
486520
this.valToPaintWith = newPixelValue;
487521
}
488522

489523
/**
490-
* Called when the mouse drags over a pixel in the editor.
524+
* Sets the specified pixel in the editor to the current value being painted.
491525
*
492526
* @param r Row number of grid.
493527
* @param c Column number of grid.
494528
*/
495-
private onMouseEnterPixel(r: number, c: number) {
496-
if (!this.mouseIsDown) {
497-
return;
498-
}
529+
private updatePixelValue(r: number, c: number) {
499530
if (
500531
this.valToPaintWith !== undefined &&
501532
this.getPixel(r, c) !== this.valToPaintWith
@@ -505,11 +536,11 @@ export class FieldBitmap extends Blockly.Field<number[][]> {
505536
}
506537

507538
/**
508-
* Resets mouse state (e.g. After either a mouseup event or if the mouse
509-
* leaves the editor area).
539+
* Resets pointer state (e.g. After either a pointerup event or if the
540+
* gesture is canceled).
510541
*/
511-
private onMouseUp() {
512-
this.mouseIsDown = false;
542+
private onPointerEnd() {
543+
this.pointerIsDown = false;
513544
this.valToPaintWith = undefined;
514545
}
515546

@@ -594,10 +625,10 @@ export class FieldBitmap extends Blockly.Field<number[][]> {
594625
private bindEvent(
595626
element: HTMLElement,
596627
eventName: string,
597-
callback: (e: Event) => void,
628+
callback: (e: PointerEvent) => void,
598629
) {
599630
this.boundEvents.push(
600-
Blockly.browserEvents.conditionalBind(element, eventName, this, callback),
631+
Blockly.browserEvents.bind(element, eventName, this, callback),
601632
);
602633
}
603634

0 commit comments

Comments
 (0)