summaryrefslogtreecommitdiff
path: root/frontend/views
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/views')
-rw-r--r--frontend/views/graph/components/graph.editor.js108
-rw-r--r--frontend/views/graph/graph.css5
2 files changed, 109 insertions, 4 deletions
diff --git a/frontend/views/graph/components/graph.editor.js b/frontend/views/graph/components/graph.editor.js
index 5093327..c21c624 100644
--- a/frontend/views/graph/components/graph.editor.js
+++ b/frontend/views/graph/components/graph.editor.js
@@ -9,7 +9,7 @@ import actions from '../../../actions'
import * as graphActions from '../graph.actions'
import { Loader } from '../../../common'
-import { clamp, dist } from '../../../util'
+import { clamp, dist, mod } from '../../../util'
const defaultState = {
dragging: false,
@@ -144,19 +144,24 @@ class GraphEditor extends Component {
render(){
// console.log(this.props.graph.show.res)
- const currentPage = this.state.page
- const currentBox = this.state.box
+ const { page: currentPage, box } = this.state
const { res: graph } = this.props.graph.show
// console.log(res.pages)
return (
<div className='graph' ref={this.graphRef}>
+ <GraphCanvas
+ bounds={this.state.bounds}
+ pages={graph.pages}
+ currentPage={currentPage}
+ box={box}
+ />
{this.state.bounds && graph.pages.map(page => (
<PageHandle
key={page.id}
graph={graph}
page={page}
bounds={this.state.bounds}
- box={currentPage && page.id === currentPage.id && currentBox}
+ box={currentPage && page.id === currentPage.id && box}
onMouseDown={e => this.handleMouseDown(e, page)}
/>
))}
@@ -165,6 +170,101 @@ class GraphEditor extends Component {
}
}
+class GraphCanvas extends Component {
+ constructor(props) {
+ super(props)
+ this.canvasRef = React.createRef()
+ }
+
+ componentDidMount() {
+ if (this.props.bounds) {
+ this.draw({})
+ }
+ }
+
+ componentDidUpdate(prevProps) {
+ this.draw(prevProps)
+ }
+
+ draw(prevProps) {
+ const { current: canvas } = this.canvasRef
+ const { bounds, pages, currentPage, box } = this.props
+ const { width, height } = bounds
+ if (prevProps.bounds !== bounds) {
+ canvas.width = width
+ canvas.height = height
+ }
+ const ctx = canvas.getContext('2d')
+ ctx.clearRect(0, 0, width, height)
+ ctx.lineWidth = 2
+ const coordsLookup = pages.reduce((a,b) => {
+ if (currentPage && box && b.id === currentPage.id) {
+ a[b.id] = {
+ x: box.x,
+ y: box.y,
+ backlinks: new Set([]),
+ }
+ } else {
+ a[b.id] = {
+ x: b.settings.x,
+ y: b.settings.y,
+ backlinks: new Set([]),
+ }
+ }
+ return a
+ }, {})
+ pages.map(page => {
+ const sourceCoord = coordsLookup[page.id]
+ page.backlinks.map(tile => {
+ if (tile.target_page_id <= 0) return
+ const targetCoord = coordsLookup[tile.page_id]
+ let xOffset = 16
+ let yOffset = 16
+ // console.log(tile.page_id, tile.target_page_id, sourceCoord.backlinks, targetCoord.backlinks)
+ if (targetCoord.backlinks.has(tile.target_page_id)) {
+ xOffset += 10
+ ctx.strokeStyle = "#88ffff"
+ } else {
+ sourceCoord.backlinks.add(tile.page_id)
+ ctx.strokeStyle = "#ff88ff"
+ }
+ ctx.beginPath()
+ const x1 = targetCoord.x * width + xOffset
+ const y1 = targetCoord.y * height + yOffset
+ const x2 = sourceCoord.x * width + xOffset
+ const y2 = sourceCoord.y * height + yOffset
+ this.arrow(ctx, x1, y1, x2, y2)
+ ctx.stroke()
+ })
+ })
+ }
+
+ arrow(ctx, x1, y1, x2, y2) {
+ const headlen = 10 // length of head in pixels
+ const dx = x2 - x1
+ const dy = y2 - y1
+ const angle = Math.atan2(dy, dx)
+ const farOffset = 20
+ x1 += Math.cos(angle) * 0
+ x2 -= Math.cos(angle) * farOffset
+ y1 += Math.sin(angle) * 0
+ y2 -= Math.sin(angle) * farOffset
+ const leftAngle = mod(angle - Math.PI / 6, Math.PI * 2)
+ const rightAngle = mod(angle + Math.PI / 6, Math.PI * 2)
+ ctx.moveTo(x1, y1)
+ ctx.lineTo(x2, y2)
+ ctx.lineTo(x2 - headlen * Math.cos(leftAngle), y2 - headlen * Math.sin(leftAngle))
+ ctx.moveTo(x2, y2)
+ ctx.lineTo(x2 - headlen * Math.cos(rightAngle), y2 - headlen * Math.sin(rightAngle))
+ }
+
+ render() {
+ return (
+ <canvas ref={this.canvasRef} />
+ )
+ }
+}
+
const PageHandle = ({ graph, page, bounds, box, onMouseDown }) => {
let style;
if (box) {
diff --git a/frontend/views/graph/graph.css b/frontend/views/graph/graph.css
index 511d15e..52f1a7e 100644
--- a/frontend/views/graph/graph.css
+++ b/frontend/views/graph/graph.css
@@ -12,6 +12,11 @@
rgba(128, 0, 64, 0.2)
);
}
+.graph canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
/* Sidebar boxes */