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

Improve mouse support #28

Merged
merged 4 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading