1
0
Fork 0

Fixed button hover being stuck

This commit is contained in:
Michaël Lemaire 2017-08-22 23:56:27 +02:00
parent b5101261a4
commit 19469c5946
3 changed files with 59 additions and 14 deletions

View file

@ -82,7 +82,6 @@ Common UI
---------
* Add caret/focus to text input
* Fix hover being stuck when the cursor exits the window, or the item moves or is hidden
* Add a standard confirm dialog
* Mobile: think UI layout so that fingers do not block the view (right and left handed)
* Mobile: display tooltips larger and on the side of screen where the finger is not

View file

@ -16,7 +16,8 @@ module TS.SpaceTac.UI.Specs {
});
it("handles hover and click on desktops and mobile targets", function (done) {
let newButton: () => [Phaser.Button, any] = () => {
let pointer = new Phaser.Pointer(testgame.ui, 0);
function newButton(): [Phaser.Button, any] {
var button = new Phaser.Button(testgame.ui);
var funcs = {
enter: () => null,
@ -27,52 +28,81 @@ module TS.SpaceTac.UI.Specs {
spyOn(funcs, "leave");
spyOn(funcs, "click");
UITools.setHoverClick(button, funcs.enter, funcs.leave, funcs.click, 50, 100);
UITools.hovered = null;
return [button, funcs];
}
let enter = (button: Phaser.Button) => (<any>button.input)._pointerOverHandler(pointer);
let leave = (button: Phaser.Button) => (<any>button.input)._pointerOutHandler(pointer);
let press = (button: Phaser.Button) => button.onInputDown.dispatch(button, pointer);
let release = (button: Phaser.Button) => button.onInputUp.dispatch(button, pointer);
let destroy = (button: Phaser.Button) => button.events.onDestroy.dispatch();
// Simple click on desktop
let [button, funcs] = newButton();
button.onInputOver.dispatch();
button.onInputDown.dispatch();
button.onInputUp.dispatch();
enter(button);
press(button);
release(button);
expect(funcs.enter).toHaveBeenCalledTimes(0);
expect(funcs.leave).toHaveBeenCalledTimes(0);
expect(funcs.click).toHaveBeenCalledTimes(1);
// Simple click on mobile
[button, funcs] = newButton();
button.onInputDown.dispatch();
button.onInputUp.dispatch();
press(button);
release(button);
expect(funcs.enter).toHaveBeenCalledTimes(1);
expect(funcs.leave).toHaveBeenCalledTimes(1);
expect(funcs.click).toHaveBeenCalledTimes(1);
// Leaves on destroy
[button, funcs] = newButton();
button.onInputDown.dispatch();
press(button);
jasmine.clock().tick(150);
expect(funcs.enter).toHaveBeenCalledTimes(1);
expect(funcs.leave).toHaveBeenCalledTimes(0);
expect(funcs.click).toHaveBeenCalledTimes(0);
button.events.onDestroy.dispatch();
destroy(button);
expect(funcs.enter).toHaveBeenCalledTimes(1);
expect(funcs.leave).toHaveBeenCalledTimes(1);
expect(funcs.click).toHaveBeenCalledTimes(0);
button.onInputDown.dispatch();
button.onInputUp.dispatch();
press(button);
release(button);
expect(funcs.enter).toHaveBeenCalledTimes(1);
expect(funcs.leave).toHaveBeenCalledTimes(1);
expect(funcs.click).toHaveBeenCalledTimes(0);
// Force-leave when hovering another button without clean leaving a first one
let [button1, funcs1] = newButton();
let [button2, funcs2] = newButton();
enter(button1);
jasmine.clock().tick(150);
expect(funcs1.enter).toHaveBeenCalledTimes(1);
expect(funcs1.leave).toHaveBeenCalledTimes(0);
expect(funcs1.click).toHaveBeenCalledTimes(0);
enter(button2);
expect(funcs1.enter).toHaveBeenCalledTimes(1);
expect(funcs1.leave).toHaveBeenCalledTimes(1);
expect(funcs1.click).toHaveBeenCalledTimes(0);
expect(funcs2.enter).toHaveBeenCalledTimes(0);
expect(funcs2.leave).toHaveBeenCalledTimes(0);
expect(funcs2.click).toHaveBeenCalledTimes(0);
jasmine.clock().tick(150);
expect(funcs1.enter).toHaveBeenCalledTimes(1);
expect(funcs1.leave).toHaveBeenCalledTimes(1);
expect(funcs1.click).toHaveBeenCalledTimes(0);
expect(funcs2.enter).toHaveBeenCalledTimes(1);
expect(funcs2.leave).toHaveBeenCalledTimes(0);
expect(funcs2.click).toHaveBeenCalledTimes(0);
// Hold to hover on mobile
jasmine.clock().uninstall();
[button, funcs] = newButton();
button.onInputDown.dispatch();
button.onInputDown.dispatch(button, pointer);
Timer.global.schedule(150, () => {
expect(funcs.enter).toHaveBeenCalledTimes(1);
expect(funcs.leave).toHaveBeenCalledTimes(0);
expect(funcs.click).toHaveBeenCalledTimes(0);
button.onInputUp.dispatch();
button.onInputUp.dispatch(button, pointer);
expect(funcs.enter).toHaveBeenCalledTimes(1);
expect(funcs.leave).toHaveBeenCalledTimes(1);
expect(funcs.click).toHaveBeenCalledTimes(0);

View file

@ -8,6 +8,8 @@ module TS.SpaceTac.UI {
// Common UI tools functions
export class UITools {
static hovered: Phaser.Button | null = null;
/**
* Get the position of an object, adjusted to remain inside a container
*/
@ -90,9 +92,19 @@ module TS.SpaceTac.UI {
});
}
obj.onInputOver.add(() => {
obj.onInputOver.add((_: any, pointer: Phaser.Pointer) => {
if (destroyed) return;
if (UITools.hovered) {
if (UITools.hovered === obj) {
return;
} else {
// Dirty fix - Force a "pointer out" on previously hovered, if it did not go out cleanly
(<any>UITools.hovered.input)._pointerOutHandler(pointer);
}
}
UITools.hovered = obj;
if (obj.visible && obj.alpha) {
cursorinside = true;
enternext = Timer.global.schedule(hovertime, effectiveenter);
@ -102,6 +114,10 @@ module TS.SpaceTac.UI {
obj.onInputOut.add(() => {
if (destroyed) return;
if (UITools.hovered === obj) {
UITools.hovered = null;
}
cursorinside = false;
effectiveleave();
});