Skip to content

Commit

Permalink
Fix #126 - Initial Mouse Capture API (#130)
Browse files Browse the repository at this point in the history
* Initial capture API

* Add interface for Mouse

* Add test, refactor API, get test green

* Formatting
  • Loading branch information
bryphe committed Dec 21, 2018
1 parent b3c4274 commit b460574
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 12 deletions.
60 changes: 51 additions & 9 deletions src/UI/Mouse.re
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,47 @@ module Cursor = {
};
};

type capturedEventState = {
onMouseDown: ref(option(mouseButtonHandler)),
onMouseMove: ref(option(mouseMoveHandler)),
onMouseUp: ref(option(mouseButtonHandler)),
};

let capturedEventStateInstance: capturedEventState = {
onMouseDown: ref(None),
onMouseMove: ref(None),
onMouseUp: ref(None),
};

let setCapture = (~onMouseDown=?, ~onMouseMove=?, ~onMouseUp=?, ()) => {
capturedEventStateInstance.onMouseDown := onMouseDown;
capturedEventStateInstance.onMouseMove := onMouseMove;
capturedEventStateInstance.onMouseUp := onMouseUp;
};

let releaseCapture = () => {
capturedEventStateInstance.onMouseDown := None;
capturedEventStateInstance.onMouseMove := None;
capturedEventStateInstance.onMouseUp := None;
};

let handleCapture = (mouseEvent: mouseEvent) => {
let ce = capturedEventStateInstance;

switch (ce.onMouseDown^, ce.onMouseMove^, ce.onMouseUp^, mouseEvent) {
| (Some(h), _, _, MouseDown(evt)) =>
h(evt);
true;
| (_, Some(h), _, MouseMove(evt)) =>
h(evt);
true;
| (_, _, Some(h), MouseUp(evt)) =>
h(evt);
true;
| (_, _, _, _) => false
};
};

let getPositionFromMouseEvent = (c: Cursor.t, evt: Events.internalMouseEvents) =>
switch (evt) {
| InternalMouseDown(_) => Cursor.toVec2(c)
Expand All @@ -47,15 +88,16 @@ let dispatch =

let eventToSend = internalToExternalEvent(cursor, evt);

let isNodeImpacted = n => n#hitTest(pos);

let nodes: ref(list(Node.node('a))) = ref([]);
let collect = n =>
if (isNodeImpacted(n)) {
nodes := List.append(nodes^, [n]);
};
if (!handleCapture(eventToSend)) {
let isNodeImpacted = n => n#hitTest(pos);
let nodes: ref(list(Node.node('a))) = ref([]);
let collect = n =>
if (isNodeImpacted(n)) {
nodes := List.append(nodes^, [n]);
};
Node.iter(collect, node);
List.iter(n => n#handleEvent(eventToSend), nodes^);
};

Node.iter(collect, node);
List.iter(n => n#handleEvent(eventToSend), nodes^);
Cursor.set(cursor, pos);
};
22 changes: 22 additions & 0 deletions src/UI/Mouse.rei
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* Mouse Input */
open Revery_Core;
open Revery_Math;

open NodeEvents;

module Cursor {
type t;

let make: unit => t;

let toVec2: t => Vec2.t;

let set: (t, Vec2.t) => unit;
};

let setCapture: (~onMouseDown:mouseButtonHandler=?, ~onMouseMove:mouseMoveHandler=?, ~onMouseUp:mouseButtonHandler=?, unit) => unit;

let releaseCapture: unit => unit;

let dispatch:
(Cursor.t, Events.internalMouseEvents, Node.node('a)) => unit;
40 changes: 37 additions & 3 deletions test/UI/MouseTest.re
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ let createNodeWithStyle = style => {
node;
};

test("Mouse", () =>
test("Mouse", () => {
test("dispatch", () => {
test("triggers onMouseDown event for node", () => {
let cursor = Mouse.Cursor.make();
Expand Down Expand Up @@ -47,5 +47,39 @@ test("Mouse", () =>

expect(count^).toBe(0);
});
})
);
});
test("setCapture/releaseCapture", () =>
test("captured events override dispatching to node", () => {
let cursor = Mouse.Cursor.make();

let nodeCount = ref(0);
let captureCount = ref(0);
let nodeCounter = _evt => nodeCount := nodeCount^ + 1;
let captureCounter = _evt => captureCount := captureCount^ + 1;

let node =
createNodeWithStyle(Style.make(~width=100, ~height=100, ()));

Mouse.setCapture(~onMouseDown=captureCounter, ());

node#setEvents(NodeEvents.make(~onMouseDown=nodeCounter, ()));

Mouse.dispatch(
cursor,
InternalMouseMove({mouseX: 50., mouseY: 50.}),
node,
);

Mouse.dispatch(cursor, InternalMouseDown({button: BUTTON_LEFT}), node);

expect(nodeCount^).toBe(0);
expect(captureCount^).toBe(1);

Mouse.releaseCapture();
Mouse.dispatch(cursor, InternalMouseDown({button: BUTTON_LEFT}), node);

expect(nodeCount^).toBe(1);
expect(captureCount^).toBe(1);
})
);
});

0 comments on commit b460574

Please sign in to comment.