From c1d604aacc810c2a8894e3d265964036c4776c87 Mon Sep 17 00:00:00 2001 From: David Evans Date: Fri, 1 Dec 2017 17:19:21 +0000 Subject: [PATCH] Add library for resizing panes in editor [#28] --- index.html | 8 +++- scripts/interface/Interface.js | 82 +++++++++++++++++++++++++++++++--- scripts/stubs/split.js | 19 ++++++++ styles/editor.css | 74 +++++++++++++++++++----------- test.htm | 1 + 5 files changed, 149 insertions(+), 35 deletions(-) create mode 100644 scripts/stubs/split.js diff --git a/index.html b/index.html index e915672..6a28767 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ + + { +], (Split, CodeMirror) => { 'use strict'; const DELAY_AGENTCHANGE = 500; @@ -41,6 +42,47 @@ define([ return code; } + function makeSplit(nodes, options) { + // Patches for: + // https://github.com/nathancahill/Split.js/issues/97 + // https://github.com/nathancahill/Split.js/issues/111 + const parent = nodes[0].parentNode; + const oldAEL = parent.addEventListener; + const oldREL = parent.removeEventListener; + parent.addEventListener = (event, callback) => { + if(event === 'mousemove' || event === 'touchmove') { + window.addEventListener(event, callback, {passive: true}); + } else { + oldAEL.call(parent, event, callback); + } + }; + parent.removeEventListener = (event, callback) => { + if(event === 'mousemove' || event === 'touchmove') { + window.removeEventListener(event, callback); + } else { + oldREL.call(parent, event, callback); + } + }; + + let oldCursor = null; + const resolvedOptions = Object.assign({ + direction: 'vertical', + cursor: (options.direction === 'vertical') ? + 'row-resize' : 'col-resize', + gutterSize: 1, + onDragStart: () => { + oldCursor = document.body.style.cursor; + document.body.style.cursor = resolvedOptions.cursor; + }, + onDragEnd: () => { + document.body.style.cursor = oldCursor; + oldCursor = null; + }, + }, options); + + return new Split(nodes, resolvedOptions); + } + return class Interface { constructor({ sequenceDiagram, @@ -244,19 +286,18 @@ define([ viewPane.appendChild(viewPaneScroller); viewPaneScroller.appendChild(this.viewPaneInner); - viewPane.appendChild(this.buildOptionsLinks()); - viewPane.appendChild(this.buildOptionsDownloads()); viewPane.appendChild(this.buildErrorReport()); return viewPane; } - build(container) { + buildLeftPanes(container) { const codePane = makeNode('div', {'class': 'pane-code'}); container.appendChild(codePane); + let libPane = null; if(this.library.length > 0) { - const libPane = makeNode('div', {'class': 'pane-library'}); + libPane = makeNode('div', {'class': 'pane-library'}); const libPaneScroller = makeNode('div', { 'class': 'pane-library-scroller', }); @@ -266,11 +307,38 @@ define([ libPaneScroller.appendChild(libPaneInner); libPane.appendChild(libPaneScroller); container.appendChild(libPane); - codePane.setAttribute('class', 'pane-code reduced'); this.buildLibrary(libPaneInner); + + makeSplit([codePane, libPane], { + direction: 'vertical', + snapOffset: 5, + sizes: [70, 30], + minSize: [100, 0], + }); } - container.appendChild(this.buildViewPane()); + return {codePane, libPane}; + } + + build(container) { + const hold = makeNode('div', {'class': 'pane-hold'}); + const lPane = makeNode('div', {'class': 'pane-side'}); + hold.appendChild(lPane); + container.appendChild(hold); + const {codePane} = this.buildLeftPanes(lPane); + + const viewPane = this.buildViewPane(); + hold.appendChild(viewPane); + + hold.appendChild(this.buildOptionsLinks()); + hold.appendChild(this.buildOptionsDownloads()); + + makeSplit([lPane, viewPane], { + direction: 'horizontal', + snapOffset: 70, + sizes: [30, 70], + minSize: [10, 10], + }); this.code = this.buildEditor(codePane); this.viewPaneInner.appendChild(this.diagram.dom()); diff --git a/scripts/stubs/split.js b/scripts/stubs/split.js new file mode 100644 index 0000000..7086256 --- /dev/null +++ b/scripts/stubs/split.js @@ -0,0 +1,19 @@ +define([], () => { + 'use strict'; + + function Split(elements, options) { + const spy = jasmine.createSpyObj('Split', [ + 'setSizes', + 'getSizes', + 'collapse', + 'destroy', + ]); + spy.constructor = { + elements, + options, + }; + return spy; + } + + return Split; +}); diff --git a/styles/editor.css b/styles/editor.css index b8a2ed0..8aa5a0b 100644 --- a/styles/editor.css +++ b/styles/editor.css @@ -36,18 +36,56 @@ html, body { margin: 0 10px 10px; } -.pane-code { +.pane-hold { position: absolute; left: 0; top: 0; + right: 0; bottom: 0; - width: 30%; - box-sizing: border-box; - border-right: 1px solid #808080; } -.pane-code.reduced { - bottom: 200px; +.pane-side { + display: inline-block; + height: 100%; +} + +.pane-code { +} + +.pane-library { + background: #EEEEEE; + user-select: none; +} + +.pane-view { + display: inline-block; + height: 100%; + position: relative; +} + +.gutter { + display: inline-block; + background: #808080; + width: 100%; + height: 100%; + position: relative; + z-index: 20; + border: 0px solid transparent; + background-clip: padding-box; +} + +.gutter-horizontal { + margin: 0 -3px; + border-left-width: 3px; + border-right-width: 3px; + cursor: col-resize; +} + +.gutter-vertical { + margin: -3px 0; + border-top-width: 3px; + border-bottom-width: 3px; + cursor: row-resize; } .pane-code .CodeMirror { @@ -79,14 +117,6 @@ html, body { color: #777777; } -.pane-view { - position: absolute; - left: 30%; - top: 0; - bottom: 0; - right: 0; -} - .pane-view-scroller { position: absolute; top: 0; @@ -97,6 +127,8 @@ html, body { } .pane-view-inner { + width: 100%; + height: 100%; } .pane-view svg { @@ -119,19 +151,6 @@ html, body { stroke: rgba(255, 192, 0, 0.5); } -.pane-library { - position: absolute; - left: 0; - bottom: 0; - width: 30%; - height: 200px; - box-sizing: border-box; - background: #EEEEEE; - border-top: 1px solid #808080; - border-right: 1px solid #808080; - user-select: none; -} - .pane-library-scroller { width: 100%; height: 100%; @@ -208,6 +227,7 @@ html, body { background: #FFFFFF; overflow: hidden; user-select: none; + z-index: 30; } .options.links { diff --git a/test.htm b/test.htm index f110157..7db7023 100644 --- a/test.htm +++ b/test.htm @@ -50,6 +50,7 @@ data-integrity="sha256-Re9XxIL3x1flvE6WD58jWPdDzKYQLXwxS2HAVfmM6Z8=" > +