Skip to content

Commit

Permalink
fix(ui): zoom in and out from cursor position (#262)
Browse files Browse the repository at this point in the history
* fix(ui): zoom in and out from cursor position

* fix(ui): zoom to fit

Co-authored-by: Samuel Massé <samuelmasse4@gmail.com>
Co-authored-by: Laurent Leclerc-Poulin <laurentleclercpoulin@gmail.com>
  • Loading branch information
3 people committed Feb 7, 2022
1 parent e3a1a43 commit 6ed8110
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 91 deletions.
3 changes: 0 additions & 3 deletions packages/studio-ui/src/web/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,7 @@ export const updateDocumentationModal = createAction('UI/UPDATE_DOCUMENTATION_MO
export const toggleBottomPanel = createAction('UI/TOGGLE_BOTTOM_PANEL')
export const toggleInspector = createAction('UI/TOGGLE_INSPECTOR')
export const toggleBottomPanelExpand = createAction('UI/TOGGLE_BOTTOM_PANEL_EXPAND')
export const zoomIn = createAction('UI/ZOOM_IN_DIAGRAM')
export const zoomOut = createAction('UI/ZOOM_OUT_DIAGRAM')
export const zoomToLevel = createAction('UI/ZOOM_TO_LEVEL_DIAGRAM')
export const zoomToFit = createAction('UI/ZOOM_TO_FIT_DIAGRAM')
export const setEmulatorOpen = createAction('EMULATOR_OPENED')

// User
Expand Down
22 changes: 0 additions & 22 deletions packages/studio-ui/src/web/reducers/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ import {
updateDocumentationModal,
updateGlobalStyle,
viewModeChanged,
zoomIn,
zoomOut,
zoomToFit,
zoomToLevel
} from '~/actions'

Expand Down Expand Up @@ -87,31 +84,12 @@ const reducer = handleActions(
inspectorEnabled: value
}
},
[zoomIn]: (state, {}) => {
return {
...state,
zoomLevel: state.zoomLevel + 25
}
},
[zoomToFit]: (state, {}) => {
return {
...state,
zoomLevel: -1
}
},
[zoomToLevel]: (state, { payload }) => {
return {
...state,
zoomLevel: payload
}
},
[zoomOut]: (state, {}) => {
const newLevel = state.zoomLevel - 25
return {
...state,
zoomLevel: newLevel > 10 ? newLevel : 10
}
},
[setEmulatorOpen]: (state, { payload }) => ({
...state,
emulatorOpen: payload
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import { Button } from '@blueprintjs/core'
import { lang, ToolTip } from 'botpress/shared'
import React, { FC } from 'react'
import React from 'react'
import { connect } from 'react-redux'
import { zoomIn, zoomOut, zoomToLevel, zoomToFit } from '~/actions'

import { RootReducer } from '../../../../reducers'
import { ZOOM_MAX, ZOOM_MIN } from '../constants'

import style from './style.scss'

type StateProps = ReturnType<typeof mapStateToProps>
type DispatchProps = typeof mapDispatchToProps

type Props = DispatchProps & StateProps
type Props = StateProps & {
zoomIn: () => void
zoomOut: () => void
zoomToLevel: (level: number) => void
zoomToFit: () => void
}

const ZoomToolbar: FC<Props> = ({ zoomLevel, zoomIn, zoomOut, zoomToLevel, zoomToFit }) => (
const ZoomToolbar = ({ zoomLevel, zoomIn, zoomOut, zoomToLevel, zoomToFit }: Props) => (
<div className={style.zoomWrapper}>
<ToolTip content={lang.tr('studio.flow.zoomOut')}>
<Button icon="zoom-out" disabled={zoomLevel <= 10} onClick={zoomOut} />
<Button icon="zoom-out" disabled={zoomLevel <= ZOOM_MIN} onClick={zoomOut} />
</ToolTip>
<label>
<span className={style.label}>{zoomLevel}%</span>
Expand All @@ -30,7 +34,7 @@ const ZoomToolbar: FC<Props> = ({ zoomLevel, zoomIn, zoomOut, zoomToLevel, zoomT
</select>
</label>
<ToolTip content={lang.tr('studio.flow.zoomIn')}>
<Button icon="zoom-in" onClick={zoomIn} />
<Button icon="zoom-in" onClick={zoomIn} disabled={zoomLevel >= ZOOM_MAX} />
</ToolTip>
<ToolTip content={lang.tr('studio.flow.zoomToFit')}>
<Button className={style.zoomToFit} icon="zoom-to-fit" onClick={zoomToFit} />
Expand All @@ -42,11 +46,4 @@ const mapStateToProps = (state: RootReducer) => ({
zoomLevel: state.ui.zoomLevel
})

const mapDispatchToProps = {
zoomIn,
zoomOut,
zoomToFit,
zoomToLevel
}

export default connect<StateProps, DispatchProps>(mapStateToProps, mapDispatchToProps)(ZoomToolbar)
export default connect<StateProps>(mapStateToProps)(ZoomToolbar)
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
.label {
display: block;
margin: 0 var(--spacing-medium);
min-width: 35px;
}

label {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const DIAGRAM_PADDING = 50
export const ZOOM_SPEED_SCALAR = 10
export const ZOOM_MIN = 25
export const ZOOM_MAX = 200
export const ZOOM_IN_OUT_AMT = 25
47 changes: 22 additions & 25 deletions packages/studio-ui/src/web/views/FlowBuilder/diagram/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ import {
zoomToLevel
} from '~/actions'
import { getAllFlows, getCurrentFlow, getCurrentFlowNode, RootReducer } from '~/reducers'
import { DIAGRAM_PADDING } from './constants'

import { prepareEventForDiagram } from './debugger'
import DiagramToolbar from './DiagramToolbar'
import { defaultTransition, DiagramManager, DIAGRAM_PADDING, nodeTypes, Point } from './manager'
import { defaultTransition, DiagramManager, nodeTypes, Point } from './manager'
import { BlockModel, BlockProps, BlockWidgetFactory } from './nodes/Block'
import { DeletableLinkFactory } from './nodes/LinkWidget'
import NodeToolbar from './NodeToolbar'
Expand Down Expand Up @@ -216,44 +217,35 @@ class Diagram extends Component<Props> {
componentDidMount() {
this.props.fetchFlows()
this.setState({ expandedNodes: getExpandedNodes() })
const diagramWidgetEl = ReactDOM.findDOMNode(this.diagramWidget) as HTMLDivElement
diagramWidgetEl.addEventListener('click', this.onDiagramClick)
diagramWidgetEl.addEventListener('mousedown', this.onMouseDown)
diagramWidgetEl.addEventListener('dblclick', this.onDiagramDoubleClick)
diagramWidgetEl.addEventListener('wheel', this.manager.handleDiagramWheel)

ReactDOM.findDOMNode(this.diagramWidget).addEventListener('click', this.onDiagramClick)
ReactDOM.findDOMNode(this.diagramWidget).addEventListener('mousedown', this.onMouseDown)
ReactDOM.findDOMNode(this.diagramWidget).addEventListener('dblclick', this.onDiagramDoubleClick)
document.getElementById('diagramContainer').addEventListener('keydown', this.onKeyDown)
this.diagramContainer.addEventListener('keydown', this.onKeyDown)
this.manager.setDiagramContainer(this.diagramWidget, diagramWidgetEl)
}

componentWillUnmount() {
ReactDOM.findDOMNode(this.diagramWidget).removeEventListener('click', this.onDiagramClick)
ReactDOM.findDOMNode(this.diagramWidget).removeEventListener('mousedown', this.onMouseDown)
ReactDOM.findDOMNode(this.diagramWidget).removeEventListener('dblclick', this.onDiagramDoubleClick)
document.getElementById('diagramContainer').removeEventListener('keydown', this.onKeyDown)
const diagramWidgetEl = ReactDOM.findDOMNode(this.diagramWidget) as HTMLDivElement
diagramWidgetEl.removeEventListener('click', this.onDiagramClick)
diagramWidgetEl.removeEventListener('mousedown', this.onMouseDown)
diagramWidgetEl.removeEventListener('dblclick', this.onDiagramDoubleClick)
diagramWidgetEl.addEventListener('wheel', this.manager.handleDiagramWheel)

this.diagramContainer.removeEventListener('keydown', this.onKeyDown)
}

componentDidUpdate(prevProps, prevState) {
this.manager.setCurrentFlow(this.props.currentFlow)
this.manager.setReadOnly(this.props.readOnly)

if (this.diagramContainer) {
this.manager.setDiagramContainer(this.diagramWidget, {
width: this.diagramContainer.offsetWidth,
height: this.diagramContainer.offsetHeight
})
}

if (this.dragPortSource && !prevProps.currentFlowNode && this.props.currentFlowNode) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.linkCreatedNode()
}

if (prevProps.zoomLevel !== this.props.zoomLevel) {
if (this.props.zoomLevel === -1) {
this.manager.updateZoomLevel()
} else {
this.diagramEngine.diagramModel.setZoomLevel(this.props.zoomLevel)
}
}

if (prevProps.debuggerEvent !== this.props.debuggerEvent) {
this.showEventOnDiagram(this.props.debuggerEvent)
}
Expand Down Expand Up @@ -748,7 +740,12 @@ class Diagram extends Component<Props> {
maxNumberPointsPerLink={MAX_NUMBER_OF_POINTS_PER_LINK}
inverseZoom
/>
<ZoomToolbar />
<ZoomToolbar
zoomIn={this.manager.zoomIn.bind(this.manager)}
zoomOut={this.manager.zoomOut.bind(this.manager)}
zoomToLevel={this.manager.zoomToLevel.bind(this.manager)}
zoomToFit={this.manager.zoomToFit.bind(this.manager)}
/>
{canAdd && <NodeToolbar />}
<TriggerEditor
node={this.state.currentTriggerNode}
Expand Down

0 comments on commit 6ed8110

Please sign in to comment.