Merge pull request #280 from mathuo/268-touch-support-for-resizing-panels-3

268 touch support for resizing panels
This commit is contained in:
mathuo 2023-06-13 19:41:43 +01:00 committed by GitHub
commit 782a468b7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 124 additions and 8 deletions

View File

@ -84,6 +84,8 @@ describe('splitview', () => {
beforeEach(() => { beforeEach(() => {
container = document.createElement('div'); container = document.createElement('div');
container.className = 'container'; container.className = 'container';
jest.clearAllMocks();
}); });
test('vertical splitview', () => { test('vertical splitview', () => {
@ -610,6 +612,12 @@ describe('splitview', () => {
splitview.addView(view1); splitview.addView(view1);
splitview.addView(view2); splitview.addView(view2);
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
const removeEventListenerSpy = jest.spyOn(
document,
'removeEventListener'
);
const sashElement = container const sashElement = container
.getElementsByClassName('sash') .getElementsByClassName('sash')
.item(0) as HTMLElement; .item(0) as HTMLElement;
@ -623,6 +631,8 @@ describe('splitview', () => {
// start the drag event // start the drag event
fireEvent.mouseDown(sashElement, { clientX: 50, clientY: 100 }); fireEvent.mouseDown(sashElement, { clientX: 50, clientY: 100 });
expect(addEventListenerSpy).toBeCalledTimes(5);
// during a sash drag the views should have pointer-events disabled // during a sash drag the views should have pointer-events disabled
expect(view1.element.parentElement!.style.pointerEvents).toBe('none'); expect(view1.element.parentElement!.style.pointerEvents).toBe('none');
expect(view2.element.parentElement!.style.pointerEvents).toBe('none'); expect(view2.element.parentElement!.style.pointerEvents).toBe('none');
@ -638,6 +648,8 @@ describe('splitview', () => {
// end the drag event // end the drag event
fireEvent.mouseUp(document); fireEvent.mouseUp(document);
expect(removeEventListenerSpy).toBeCalledTimes(5);
// expect pointer-eventes on views to be restored // expect pointer-eventes on views to be restored
expect(view1.element.parentElement!.style.pointerEvents).toBe(''); expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe(''); expect(view2.element.parentElement!.style.pointerEvents).toBe('');
@ -645,5 +657,79 @@ describe('splitview', () => {
fireEvent.mouseMove(document, { clientX: 100, clientY: 100 }); fireEvent.mouseMove(document, { clientX: 100, clientY: 100 });
// expect no additional resizes // expect no additional resizes
expect([view1.size, view2.size]).toEqual([225, 175]); expect([view1.size, view2.size]).toEqual([225, 175]);
// expect no additional document listeners
expect(addEventListenerSpy).toBeCalledTimes(5);
expect(removeEventListenerSpy).toBeCalledTimes(5);
});
test('dnd: touch events to move sash', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(400, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
const removeEventListenerSpy = jest.spyOn(
document,
'removeEventListener'
);
const sashElement = container
.getElementsByClassName('sash')
.item(0) as HTMLElement;
// validate the expected state before drag
expect([view1.size, view2.size]).toEqual([200, 200]);
expect(sashElement).toBeTruthy();
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
// start the drag event
fireEvent.touchStart(sashElement, {
touches: [{ clientX: 50, clientY: 100 }],
});
expect(addEventListenerSpy).toBeCalledTimes(5);
// during a sash drag the views should have pointer-events disabled
expect(view1.element.parentElement!.style.pointerEvents).toBe('none');
expect(view2.element.parentElement!.style.pointerEvents).toBe('none');
// expect a delta move of 70 - 50 = 20
fireEvent.touchMove(document, {
touches: [{ clientX: 70, clientY: 110 }],
});
expect([view1.size, view2.size]).toEqual([220, 180]);
// expect a delta move of 75 - 70 = 5
fireEvent.touchMove(document, {
touches: [{ clientX: 75, clientY: 110 }],
});
expect([view1.size, view2.size]).toEqual([225, 175]);
// end the drag event
fireEvent.touchEnd(document);
expect(removeEventListenerSpy).toBeCalledTimes(5);
// expect pointer-eventes on views to be restored
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
fireEvent.touchMove(document, {
touches: [{ clientX: 100, clientY: 100 }],
});
// expect no additional resizes
expect([view1.size, view2.size]).toEqual([225, 175]);
// expect no additional document listeners
expect(addEventListenerSpy).toBeCalledTimes(5);
expect(removeEventListenerSpy).toBeCalledTimes(5);
}); });
}); });

View File

@ -393,7 +393,17 @@ export class Splitview {
const sash = document.createElement('div'); const sash = document.createElement('div');
sash.className = 'sash'; sash.className = 'sash';
const onStart = (event: MouseEvent) => { const onTouchStart = (event: TouchEvent) => {
event.preventDefault();
const touch = event.touches[0];
onStart(touch);
};
const onMouseDown = (event: MouseEvent) => {
onStart(event);
};
const onStart = (event: { clientX: number; clientY: number }) => {
for (const item of this.viewItems) { for (const item of this.viewItems) {
item.enabled = false; item.enabled = false;
} }
@ -486,13 +496,25 @@ export class Splitview {
size: snappedViewItem.size, size: snappedViewItem.size,
}; };
} }
//
const mousemove = (mousemoveEvent: MouseEvent) => { const onMouseMove = (event: MouseEvent) => {
reposition(event);
};
const onTouchMove = (event: TouchEvent) => {
event.preventDefault();
const touch = event.touches[0];
reposition(touch);
};
const reposition = (event: {
clientX: number;
clientY: number;
}) => {
const current = const current =
this._orientation === Orientation.HORIZONTAL this._orientation === Orientation.HORIZONTAL
? mousemoveEvent.clientX ? event.clientX
: mousemoveEvent.clientY; : event.clientY;
const delta = current - start; const delta = current - start;
this.resize( this.resize(
@ -521,22 +543,30 @@ export class Splitview {
this.saveProportions(); this.saveProportions();
document.removeEventListener('mousemove', mousemove); document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', end); document.removeEventListener('mouseup', end);
document.removeEventListener('touchmove', onTouchMove);
document.removeEventListener('touchend', end);
document.removeEventListener('touchcancel', end);
this._onDidSashEnd.fire(undefined); this._onDidSashEnd.fire(undefined);
}; };
document.addEventListener('mousemove', mousemove); document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', end); document.addEventListener('mouseup', end);
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', end);
document.addEventListener('touchcancel', end);
}; };
sash.addEventListener('mousedown', onStart); sash.addEventListener('mousedown', onMouseDown);
sash.addEventListener('touchstart', onTouchStart);
const sashItem: ISashItem = { const sashItem: ISashItem = {
container: sash, container: sash,
disposable: () => { disposable: () => {
sash.removeEventListener('mousedown', onStart); sash.removeEventListener('mousedown', onStart);
sash.removeEventListener('touchstart', onTouchStart);
this.sashContainer.removeChild(sash); this.sashContainer.removeChild(sash);
}, },
}; };