Skip to content
This repository has been archived by the owner on Jul 15, 2024. It is now read-only.

Commit

Permalink
Improve mouse support (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszradomski authored May 29, 2024
1 parent 9be443a commit a6f0540
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 21 deletions.
1 change: 1 addition & 0 deletions packages/frontend/src/store/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface State {
readonly middleMouseButton: boolean
readonly shiftKey: boolean
readonly spaceKey: boolean
readonly ctrlKey: boolean
}
readonly resizingNode?: {
readonly id: string
Expand Down
5 changes: 4 additions & 1 deletion packages/frontend/src/store/actions/onKeyDown.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { State } from '../State'
import { SHIFT_KEY, SPACE_KEY } from '../utils/constants'
import { CTRL_KEY, SHIFT_KEY, SPACE_KEY } from '../utils/constants'
import { updateNodePositions } from '../utils/updateNodePositions'

export function onKeyDown(state: State, event: KeyboardEvent): Partial<State> {
if (event.key === SPACE_KEY) {
return { pressed: { ...state.pressed, spaceKey: true } }
}
if (event.key === CTRL_KEY) {
return { pressed: { ...state.pressed, ctrlKey: true } }
}
if (event.key === SHIFT_KEY) {
return updateNodePositions({
...state,
Expand Down
5 changes: 4 additions & 1 deletion packages/frontend/src/store/actions/onKeyUp.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { State } from '../State'
import { SHIFT_KEY, SPACE_KEY } from '../utils/constants'
import { CTRL_KEY, SHIFT_KEY, SPACE_KEY } from '../utils/constants'
import { updateNodePositions } from '../utils/updateNodePositions'

export function onKeyUp(state: State, event: KeyboardEvent): Partial<State> {
if (event.key === SPACE_KEY) {
return { pressed: { ...state.pressed, spaceKey: false } }
}
if (event.key === CTRL_KEY) {
return { pressed: { ...state.pressed, ctrlKey: false } }
}
if (event.key === SHIFT_KEY) {
return updateNodePositions({
...state,
Expand Down
11 changes: 8 additions & 3 deletions packages/frontend/src/store/actions/onMouseDown.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { isResizeHandle } from '../../view/ResizeHandle'
import { State } from '../State'
import { LEFT_MOUSE_BUTTON, MIDDLE_MOUSE_BUTTON } from '../utils/constants'
import {
CLICKED_LEFT_MOUSE_BUTTON,
CLICKED_MIDDLE_MOUSE_BUTTON,
} from '../utils/constants'
import { toViewCoordinates } from '../utils/coordinates'
import { reverseIter } from '../utils/reverseIter'

Expand All @@ -27,7 +30,7 @@ export function onMouseDown(
}
}

if (event.button === LEFT_MOUSE_BUTTON && !state.mouseMoveAction) {
if (event.button === CLICKED_LEFT_MOUSE_BUTTON && !state.mouseMoveAction) {
if (state.pressed.spaceKey) {
const [x, y] = [event.clientX, event.clientY]
return {
Expand Down Expand Up @@ -93,10 +96,12 @@ export function onMouseDown(
}
}

if (event.button === MIDDLE_MOUSE_BUTTON && !state.mouseMoveAction) {
if (event.button === CLICKED_MIDDLE_MOUSE_BUTTON && !state.mouseMoveAction) {
const [x, y] = [event.clientX, event.clientY]
return {
pressed: { ...state.pressed, middleMouseButton: true },
mouseMoveAction: 'pan',
mouseMove: { startX: x, startY: y, currentX: x, currentY: y },
}
}

Expand Down
13 changes: 11 additions & 2 deletions packages/frontend/src/store/actions/onMouseMove.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Box, State } from '../State'
import { LEFT_MOUSE_BUTTON, NODE_WIDTH } from '../utils/constants'
import {
HELD_LEFT_MOUSE_BUTTON_MASK,
HELD_MIDDLE_MOUSE_BUTTON_MASK,
NODE_WIDTH,
} from '../utils/constants'
import { toViewCoordinates } from '../utils/coordinates'
import { toContainerCoordinates } from '../utils/toContainerCoordinates'
import { updateNodePositions } from '../utils/updateNodePositions'
Expand All @@ -13,7 +17,12 @@ export function onMouseMove(
return {}
}

if (state.pressed.leftMouseButton && event.button === LEFT_MOUSE_BUTTON) {
const isLeftMouse =
state.pressed.leftMouseButton && event.buttons & HELD_LEFT_MOUSE_BUTTON_MASK
const isMiddleMouse =
state.pressed.middleMouseButton &&
event.buttons & HELD_MIDDLE_MOUSE_BUTTON_MASK
if (isLeftMouse || isMiddleMouse) {
switch (state.mouseMoveAction) {
case undefined: {
return { ...state, mouseUpAction: undefined }
Expand Down
9 changes: 6 additions & 3 deletions packages/frontend/src/store/actions/onMouseUp.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { State } from '../State'
import { LEFT_MOUSE_BUTTON, MIDDLE_MOUSE_BUTTON } from '../utils/constants'
import {
CLICKED_LEFT_MOUSE_BUTTON,
CLICKED_MIDDLE_MOUSE_BUTTON,
} from '../utils/constants'

export function onMouseUp(state: State, event: MouseEvent): Partial<State> {
if (event.button === LEFT_MOUSE_BUTTON) {
if (event.button === CLICKED_LEFT_MOUSE_BUTTON) {
let selectedNodeIds = state.selectedNodeIds
if (state.mouseUpAction?.type === 'DeselectOne') {
const removeId = state.mouseUpAction.id
Expand All @@ -20,7 +23,7 @@ export function onMouseUp(state: State, event: MouseEvent): Partial<State> {
}
}

if (event.button === MIDDLE_MOUSE_BUTTON) {
if (event.button === CLICKED_MIDDLE_MOUSE_BUTTON) {
return {
pressed: { ...state.pressed, middleMouseButton: false },
mouseMoveAction:
Expand Down
21 changes: 16 additions & 5 deletions packages/frontend/src/store/actions/onWheel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { State } from '../State'
import {
IS_MACOS,
MAX_ZOOM,
MIN_ZOOM,
SCROLL_LINE_HEIGHT,
Expand All @@ -20,7 +19,20 @@ export function onWheel(
if (event.ctrlKey || event.metaKey) {
const rect = view.getBoundingClientRect()

const desiredChange = -deltaY * ZOOM_SENSITIVITY
let desiredChange = -deltaY * ZOOM_SENSITIVITY
if (event.ctrlKey && !state.pressed.ctrlKey) {
// NOTE(radomski): This is a magic value but there is no other way to
// handle this nicely in a compact way. The `onwheel` event triggers
// for mouse scrolling, touchpad scrolling AND touchpad pinching.
// Pinching is the only case where the numbers are reaaaaaaaly small
// for some reason. We multiply this by 8 to get a delta that feels
// more natural.
//
// You know that the event is a pinch event when the `ctrlKey` is set.
// Yes. Really. I'm not joking.
desiredChange = desiredChange * 8
}

let newScale = scale * (1 + desiredChange)
newScale = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, newScale))
const change = newScale / scale - 1
Expand All @@ -33,11 +45,10 @@ export function onWheel(
},
}
} else {
const invert = event.shiftKey && !IS_MACOS
return {
transform: {
offsetX: offsetX - (!invert ? event.deltaX : deltaY),
offsetY: offsetY - (!invert ? event.deltaY : deltaX),
offsetX: offsetX - deltaX,
offsetY: offsetY - deltaY,
scale,
},
}
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const useStore = create<State & Actions>()(
pressed: {
leftMouseButton: false,
middleMouseButton: false,
ctrlKey: false,
shiftKey: false,
spaceKey: false,
},
Expand Down
16 changes: 10 additions & 6 deletions packages/frontend/src/store/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
export const LEFT_MOUSE_BUTTON = 0
export const MIDDLE_MOUSE_BUTTON = 1
export const CLICKED_LEFT_MOUSE_BUTTON = 0
export const CLICKED_MIDDLE_MOUSE_BUTTON = 1

export const HELD_LEFT_MOUSE_BUTTON_MASK = 1
export const HELD_MIDDLE_MOUSE_BUTTON_MASK = 4

export const SPACE_KEY = ' '
export const CTRL_KEY = 'Control'
export const SHIFT_KEY = 'Shift'

export const IS_MACOS = navigator.userAgent.toLowerCase().includes('mac os')
Expand All @@ -15,9 +19,9 @@ export const NODE_SPACING = 25

export const RESIZE_HANDLE_SPACING = 15

export const ZOOM_SENSITIVITY = 0.02
export const MAX_ZOOM = 3
export const MIN_ZOOM = 0.3
export const ZOOM_SENSITIVITY = 0.002
export const MAX_ZOOM = 10
export const MIN_ZOOM = 0.03

export const SCROLL_LINE_HEIGHT = 40
export const SCROLL_LINE_HEIGHT = 20
export const SCROLL_PAGE_HEIGHT = 800

0 comments on commit a6f0540

Please sign in to comment.