diff --git a/src/components/FacsimileComponent.vue b/src/components/FacsimileComponent.vue index 01ca5c6..7b1f54a 100644 --- a/src/components/FacsimileComponent.vue +++ b/src/components/FacsimileComponent.vue @@ -55,7 +55,7 @@ export default { * in which tabs of the FX shall we render svg shapes? * @return {[type]} [description] */ - renderSvg () { + showSvg () { const tab = this.$store.getters.explorerTab const validTabs = ['pages', 'zones', 'annot', 'diplo'] return validTabs.indexOf(tab) !== -1 @@ -65,7 +65,7 @@ export default { * in which tabs of the FX shall we render rastrums / systems as boxes? * @return {[type]} [description] */ - renderRastrums () { + showSystems () { const tab = this.$store.getters.explorerTab const validTabs = ['pages'] return validTabs.indexOf(tab) !== -1 @@ -159,25 +159,12 @@ export default { * @param {[type]} e [description] * @return {[type]} [description] */ - rastrumClickListener (e) { + systemClickListener (e) { e.preventDefault() e.stopPropagation() - const n = e.target.getAttribute('data-n') - // console.log('clicked rastrum ' + n) - this.$store.dispatch('selectSystemOnCurrentPage', n) - }, - - /** - * triggered by double-clicking onto a rastrum box - * @param {[type]} e [description] - * @return {[type]} [description] - */ - systemDoubleClickListener (e) { - e.preventDefault() - e.stopPropagation() - const n = e.target.getAttribute('data-n') - // console.log('doubleClicked rastrum ' + n) - this.$store.dispatch('editSystemOnCurrentPage', n) + const id = e.target.getAttribute('data-id') + console.log('clicked rastrum ' + id) + // this.$store.dispatch('selectSystemOnCurrentPage', n) }, /** @@ -186,6 +173,7 @@ export default { * @return {[type]} [description] */ svgClickListener (e) { + console.log('FacsimileComponent:svgClickListener()') e.preventDefault() e.stopPropagation() // console.log(e.target) @@ -253,6 +241,10 @@ export default { if (this.showPageBorders) { this.renderPageBorders() } + + this.renderShapes() + this.renderSystems() + console.log('facsimileOpened', data) }, @@ -403,6 +395,145 @@ export default { } }, + /** + * renders SVG shapes as overlay on the facsimile + * @return {[type]} [description] + */ + renderShapes () { + console.log('FacsimileComponent:renderShapes()') + if (!this.showSvg) { + console.log(0.1) + return false + } + const svg = this.$store.getters.svgForCurrentPage + const page = this.$store.getters.currentPageDimensions + + console.log(svg, page, this.viewer) + + if (!svg || !this.viewer || !page) { + console.log(0.2) + return null + } + + const existingOverlay = document.querySelector('#facsimileContainer svg') + console.log(1) + if (existingOverlay !== null) { + const oldActive = existingOverlay.querySelector('.activeWritingZone') + if (oldActive !== null) { + oldActive.classList.remove('activeWritingZone') + } + + // existingOverlay.removeEventListener('click', this.svgClickListener) + // existingOverlay.removeEventListener('click', this.svgDoubleClickListener) + + this.viewer.removeOverlay(existingOverlay) + } + console.log(2) + + if (!svg.documentElement) { + console.warn('FacsimileComponent:renderShapes: Not an XMLDocument', svg) + } + console.log(3) + + const svgClone = svg.documentElement.cloneNode(true) + this.viewer.addOverlay({ + element: svgClone, + x: 0, + y: 0, + width: page.mmWidth, + height: page.mmHeight + }) + console.log(4) + const writingZonesOnCurrentPage = this.$store.getters.writingZonesOnCurrentPage + const activeWritingZone = this.$store.getters.activeWritingZone + const activeWritingLayer = this.$store.getters.activeWritingLayer + + const activeZone = writingZonesOnCurrentPage.find(wz => wz.id === activeWritingZone) + + if (activeZone) { + svgClone.querySelector('#' + activeZone.svgGroupWzId).classList.add('activeWritingZone') + } + + if (activeWritingLayer) { + const activeLayer = activeZone.layers.find(wl => wl.id === activeWritingLayer) + + if (activeLayer) { + svgClone.querySelector('#' + activeLayer.svgGroupWlId).classList.add('activeWritingLayer') + } + } + console.log(5) + + // console.log('done') + svgClone.addEventListener('click', this.svgClickListener) + svgClone.addEventListener('dblclick', this.svgDoubleClickListener) + console.log(6) + }, + + /** + * renders system overlays + * @return {[type]} [description] + */ + renderSystems () { + if (!this.showSystems) { + return null + } + const systems = this.$store.getters.rastrumsOnCurrentPage + const activeSystemId = this.$store.getters.activeSystemId + + const renderedSystems = document.querySelectorAll('.system.overlay') + const renderedIDs = [] + + renderedSystems.forEach(rs => { + renderedIDs.push(rs.getAttribute('data-id')) + const hit = systems.find(s => s.id === rs.getAttribute('data-id')) + if (!hit) { + const rotatedSystem = rs.querySelector('.rotatedSystem') + rotatedSystem.removeEventListener('click', this.systemClickListener) + this.viewer.removeOverlay(rs) + } else { + const overlay = this.viewer.getOverlayById(rs) + const rotatedSystem = rs.querySelector('.rotatedSystem') + rotatedSystem.style.transform = 'rotate(' + hit.rotate + 'deg)' + + if (hit.id === activeSystemId) { + rs.classList.add('active') + } else { + rs.classList.remove('active') + } + + const location = new OpenSeadragon.Rect(hit.x, hit.y, hit.w, hit.h) + overlay.update(location, OpenSeadragon.Placement.TOP_LEFT) + } + }) + + systems.forEach(s => { + if (renderedIDs.indexOf(s.id) === -1) { + const element = document.createElement('div') + element.classList.add('system') + element.classList.add('overlay') + if (s.id === activeSystemId) { + element.classList.add('active') + } + element.setAttribute('data-id', s.id) + + const rotatedSystem = document.createElement('div') + rotatedSystem.classList.add('rotatedSystem') + rotatedSystem.style.transform = 'rotate(' + s.rotate + 'deg)' + rotatedSystem.addEventListener('click', this.systemClickListener) + element.append(rotatedSystem) + + const location = new OpenSeadragon.Rect(s.x, s.y, s.w, s.h) + + this.viewer.addOverlay({ + element, + location, + placement: OpenSeadragon.Placement.TOP_LEFT, + rotationMode: OpenSeadragon.OverlayRotationMode.EXACT + }) + } + }) + }, + /** * rotate the page facsimile */ @@ -557,10 +688,16 @@ export default { pageRotated.style.transform = 'rotate(' + data.rotate.deg + 'deg)' */ }, + unload () { document.querySelectorAll('.overlay, .grid').forEach(overlay => { this.viewer.removeOverlay(overlay) }) + document.querySelectorAll('#facsimileContainer svg').forEach(svg => { + svg.removeEventListener('click', this.svgClickListener) + svg.removeEventListener('click', this.svgDoubleClickListener) + }) + document.querySelectorAll('.overlay.system .rotatedSystem').forEach(rs => rs.removeEventListener('click', this.systemClickListener)) } }, created () { @@ -616,6 +753,16 @@ export default { } this.updateFacsimile(newTs, oldTs) }) + this.unwatchSVG = this.$store.watch((state, getters) => getters.svgForCurrentPage, + (svg) => { + if (svg) { + this.renderShapes() + } + }) + this.unwatchSystems = this.$store.watch((state, getters) => [getters.rastrumsOnCurrentPage, getters.activeSystemId], + ([newArr, newId], [oldArr, oldId]) => { + this.renderSystems() + }) this.openFacsimile() }, @@ -630,6 +777,8 @@ export default { this.unwatchPageRotation() this.unwatchPageDimensions() this.unwatchTileSource() + this.unwatchSVG() + this.unwatchSystems() } } @@ -644,9 +793,24 @@ export default { height: 100%; position: relative; + svg { + width: 100%; + height: 100%; + z-index: 50; + } + .system.overlay { z-index: 0; - background-color: rgba(70 ,255, 70, 0.6); + + .rotatedSystem { + background-color: #ffffff66; + transform-origin: top left; + width: 100%; + height: 100%; + } + &.active .rotatedSystem { + background-color: #85b6ffcc; + } } g.sketchArea { @@ -848,8 +1012,6 @@ export default { .overlay.pageBorder.actualPage { outline: 8px solid #0000ff99; - background: #0000ff33; - z-index: 1; } .grid { diff --git a/src/components/PagesTab.vue b/src/components/PagesTab.vue index 38ea094..86fa452 100644 --- a/src/components/PagesTab.vue +++ b/src/components/PagesTab.vue @@ -6,37 +6,6 @@ - - - - -
@@ -54,7 +23,38 @@
- + +
+

SVG Shapes

+ + +
+
+

Page Dimensions [values in mm]

+
+ + +
+
+
+

Media Fragment [values in px]

+
+ + + + + +
+
+
+

Systems [values in mm]

+ +
+
@@ -67,6 +67,7 @@ import SideBar from '@/components/shared/SideBar.vue' import TopMenu from '@/components/shared/TopMenu.vue' import PageList from '@/components/shared/PageList.vue' import SourceSelector from '@/components/shared/SourceSelector.vue' +import RastrumListing from '@/components/RastrumListing.vue' import SliderInput from '@/components/SliderInput.vue' @@ -82,6 +83,7 @@ export default { PageList, SourceSelector, FacsimileComponent, + RastrumListing, SliderInput // OpenSeadragonComponent }, @@ -89,35 +91,6 @@ export default { toggleSidebar () { this.$store.dispatch('togglePageTabSidebar') }, - addSystem () { - // alert('Hiermit in den Modus schalten, bei dem ein neues System markiert werden kann, indem ein Annotorious-Rechteck angelegt werden kann.') - console.log('addSystem') - if (!this.addSystemModeActive) { - console.log('activating addSystemMode') - this.$store.dispatch('setFacsimileClickMode', 'addSystem') - } else { - this.$store.dispatch('disableFacsimileClicks') - } - }, - removeSystem () { - // alert('Hiermit wird das aktuell ausgewählte System gelöscht. Systeme werden einfach per Klick ausgewählt, und per Doppelklick wird wieder das Annotorious-Rect geladen, um sie anzupassen') - console.log('removeSystem') - if (!this.removeSystemModeActive) { - console.log('activating removeSystemMode') - this.$store.dispatch('setFacsimileClickMode', 'removeSystem') - } else { - this.$store.dispatch('disableFacsimileClicks') - } - }, - setPageMargins () { - // alert('In diesem Modus wird ein Annotorious-Rechteck aufgezogen, um ein #xywh=100,120,3000,2000 - Media-Fragment zu erzeugen, mit welchem die tatsächliche Seitengröße innerhalb der Bilddatei festgelegt wird (für die dann die Angaben in mm gelten).') - if (!this.fragmentModeActive) { - console.log('activating pageMarginMode') - this.$store.dispatch('setFacsimileClickMode', 'pageMargin') - } else { - this.$store.dispatch('disableFacsimileClicks') - } - }, addSVG () { const input = document.createElement('input') input.type = 'file' @@ -146,19 +119,28 @@ export default { } }, computed: { - ...mapGetters(['pageTabSidebarVisible', 'page', 'currentPageZeroBased', 'currentPageAngle', 'pageBorderPoints', 'pageBorderPointsIncomplete', 'currentPageDimensions', 'allDocsLoaded']), - fragmentModeActive () { - return this.$store.getters.facsimileClickMode === 'pageMargin' - }, - addSystemModeActive () { - return this.$store.getters.facsimileClickMode === 'addSystem' - }, - removeSystemModeActive () { - return this.$store.getters.facsimileClickMode === 'removeSystem' - }, + ...mapGetters(['pageTabSidebarVisible', + 'page', + 'currentPageZeroBased', + 'currentPageAngle', + 'pageBorderPoints', + 'pageBorderPointsIncomplete', + 'currentPageDimensions', + 'allDocsLoaded', + 'pageTabRightSidebarVisible', + 'rastrumsOnCurrentPage']), tileSource () { const tileSource = this.$store.getters.osdTileSourceForCurrentPage return tileSource + }, + svgFile () { + const path = this.$store.getters.currentSvgPath + if (path === null) { + return null + } + const tokens = path.split('/') + const name = tokens[tokens.length - 1] + return name } } } @@ -190,6 +172,12 @@ export default { height: calc(100vh - $totalHeaderHeight - $topMenuHeight - 10px); } + .sidebarRight { + flex: 0 0 auto; + order: 3; + height: calc(100vh - $totalHeaderHeight - $topMenuHeight - 10px); + } + .mainStage { // this color is to increase visibility of the image borders // background: repeating-linear-gradient( -30deg, $mainBackgroundColor, $mainBackgroundColor 10px, darken($mainBackgroundColor, 10%) 10px, darken($mainBackgroundColor, 10%) 20px ); @@ -256,18 +244,6 @@ i.showSidebar { } } - .customBtn { - display: inline-block; - margin: 0 .5rem 0 0; - font-weight: 100; - cursor: pointer; - i { - position: relative; - top: -2px; - margin-right: .2rem; - } - } - &.mediaFragment.active, &.systems .customBtn.active { background-color: pink; } @@ -284,4 +260,37 @@ i.showSidebar { } } +.sidebarBox { + + padding: .3rem .3rem .6rem; + + & + .sidebarBox { + border-top: $lightBorder; + } + + .denseFont { + font-weight: 100; + font-size: .7rem; + } + + h1 { + font-size: .8rem; + font-weight: 900; + margin: 0 0 .2rem; + padding: 0; + } + + .customBtn { + display: inline-block; + margin: 0 .5rem 0 0; + font-weight: 100; + cursor: pointer; + i { + position: relative; + top: -2px; + margin-right: .2rem; + } + } +} + diff --git a/src/components/RastrumListing.vue b/src/components/RastrumListing.vue new file mode 100644 index 0000000..cbd7821 --- /dev/null +++ b/src/components/RastrumListing.vue @@ -0,0 +1,93 @@ + + + + + + diff --git a/src/components/SliderInput.vue b/src/components/SliderInput.vue index 1e9ae73..dea899d 100644 --- a/src/components/SliderInput.vue +++ b/src/components/SliderInput.vue @@ -23,7 +23,9 @@ export default { setterName: String, min: Number, max: Number, - step: Number + step: Number, + idParam: String, + val: Number }, components: { // OpenSeadragonComponent @@ -66,10 +68,20 @@ export default { }, data: { get () { - return parseFloat(this.$store.getters[this.getterName]) + if (typeof this.getterName !== 'undefined') { + return parseFloat(this.$store.getters[this.getterName]) + } else if (typeof this.val !== 'undefined') { + return parseFloat(this.val) + } else { + return parseFloat(this.$store.getters[this.getterName](this.idParam)) + } }, set (value) { - this.$store.dispatch(this.setterName, value) + if (typeof this.idParam === 'undefined') { + this.$store.dispatch(this.setterName, value) + } else { + this.$store.dispatch(this.setterName, { id: this.idParam, value }) + } } } } @@ -91,9 +103,11 @@ export default { border: $lightBorder; border-radius: 3px; line-height: .8rem; - margin: .05rem .3rem; + margin: .05rem .5rem .05rem 0; padding: 0 .2rem; font-size: .7rem; + position: relative; + top: -1px; } input[type="number"] { diff --git a/src/components/ZonesTab.vue b/src/components/ZonesTab.vue index 179ee3f..b6719e1 100644 --- a/src/components/ZonesTab.vue +++ b/src/components/ZonesTab.vue @@ -25,7 +25,8 @@ - + +

Writing Zones ({{writingZones.length}})

@@ -46,7 +47,8 @@ import TopMenu from '@/components/shared/TopMenu.vue' import PageList from '@/components/shared/PageList.vue' import SourceSelector from '@/components/shared/SourceSelector.vue' -import OpenSeadragonComponent from '@/components/OpenSeadragonComponent.vue' +// import OpenSeadragonComponent from '@/components/OpenSeadragonComponent.vue' +import FacsimileComponent from '@/components/FacsimileComponent.vue' import WritingZoneListEntry from '@/components/WritingZoneListEntry.vue' export default { @@ -57,7 +59,8 @@ export default { TopMenu, PageList, SourceSelector, - OpenSeadragonComponent, + // OpenSeadragonComponent, + FacsimileComponent, WritingZoneListEntry }, methods: { diff --git a/src/components/shared/SideBar.vue b/src/components/shared/SideBar.vue index 9c9147e..18b51f7 100644 --- a/src/components/shared/SideBar.vue +++ b/src/components/shared/SideBar.vue @@ -19,8 +19,10 @@ export default { }, methods: { closeSidebar () { - if (this.tab === 'pagesTab') { + if (this.tab === 'pagesTab' && this.position === 'left') { this.$store.dispatch('togglePageTabSidebar') + } else if (this.tab === 'pagesTab' && this.position === 'right') { + this.$store.dispatch('togglePageTabRightSidebar') } else if (this.tab === 'zonesTab' && this.position === 'left') { this.$store.dispatch('toggleZonesTabLeftSidebar') } else if (this.tab === 'annotTab' && this.position === 'left') { @@ -31,10 +33,12 @@ export default { } }, computed: { - ...mapGetters(['pageTabSidebarWidth', 'zonesTabLeftSidebarWidth', 'zonesTabRightSidebarWidth', 'annotTabLeftSidebarWidth', 'annotTabRightSidebarWidth']), + ...mapGetters(['pageTabSidebarWidth', 'pageTabRightSidebarWidth', 'zonesTabLeftSidebarWidth', 'zonesTabRightSidebarWidth', 'annotTabLeftSidebarWidth', 'annotTabRightSidebarWidth']), localWidth () { - if (this.tab === 'pagesTab') { + if (this.tab === 'pagesTab' && this.position === 'left') { return this.pageTabSidebarWidth + } else if (this.tab === 'pagesTab' && this.position === 'right') { + return this.pageTabRightSidebarWidth } else if (this.tab === 'zonesTab' && this.position === 'left') { return this.zonesTabLeftSidebarWidth } else if (this.tab === 'zonesTab' && this.position === 'right') { diff --git a/src/store/data/index.js b/src/store/data/index.js index 2303aa8..7bf5e73 100644 --- a/src/store/data/index.js +++ b/src/store/data/index.js @@ -1,6 +1,6 @@ // import { dom2base64, str2base64 } from '@/tools/github' import { uuid } from '@/tools/uuid.js' -import { convertRectUnits, sortRastrumsByVerticalPosition } from '@/tools/mei.js' +import { /* convertRectUnits, */ sortRastrumsByVerticalPosition } from '@/tools/mei.js' // import { getRectFromFragment } from '@/tools/trigonometry.js' // import { Base64 } from 'js-base64' @@ -539,8 +539,6 @@ const dataModule = { dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [graphicId], isNewDocument: false }) - - dispatch('disableFacsimileClicks') }, /** @@ -588,7 +586,6 @@ const dataModule = { dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [graphicId], isNewDocument: false }) - dispatch('disableFacsimileClicks') }, /** @@ -884,7 +881,7 @@ const dataModule = { * @param {[type]} xywh [description] */ addSystem ({ commit, getters, dispatch }, xywh) { - if (!xywh || !xywh.x || !xywh.y || !xywh.w || !xywh.h) { + if (!xywh || !('x' in xywh) || !('y' in xywh) || !('w' in xywh) || !('h' in xywh) || !('rotate' in xywh)) { return null } const modifiedDom = getters.documentWithCurrentPage.cloneNode(true) @@ -896,14 +893,26 @@ const dataModule = { const surfaceId = getters.currentPageId const surface = modifiedDom.querySelector('surface[*|id="' + surfaceId + '"]') + const xmlIDs = [] + // create layout if necessary if (!surface.hasAttribute('decls')) { const physDesc = modifiedDom.querySelector('physDesc') + const physDescId = physDesc.hasAttribute('xml:id') ? physDesc.getAttribute('xml:id') : 'p' + uuid() + if (!physDesc.hasAttribute('xml:id')) { + physDesc.setAttribute('xml:id', physDescId) + } + + const layoutDescId = physDesc.querySelector('layoutDesc[*|id]') ? physDesc.querySelector('layoutDesc').getAttribute('xml:id') : 'l' + uuid() // create layoutDesc if necessary if (!physDesc.querySelector('layoutDesc')) { const layoutDesc = document.createElementNS('http://www.music-encoding.org/ns/mei', 'layoutDesc') + layoutDesc.setAttribute('xml:id', layoutDescId) + xmlIDs.push(physDescId) physDesc.append(layoutDesc) + } else { + xmlIDs.push(layoutDescId) } const layoutDesc = physDesc.querySelector('layoutDesc') @@ -919,6 +928,7 @@ const dataModule = { layoutDesc.append(layout) surface.setAttribute('decls', '#' + layoutId) + xmlIDs.push(surfaceId) } const layoutId = surface.getAttribute('decls').substring(1) @@ -926,46 +936,38 @@ const dataModule = { if (!layout.querySelector('rastrumDesc')) { const rastrumDesc = document.createElementNS('http://www.music-encoding.org/ns/mei', 'rastrumDesc') + const rastrumDescId = 'd' + uuid() + rastrumDesc.setAttribute('xml:id', rastrumDescId) layout.append(rastrumDesc) } // get relevant rastrumDesc const rastrumDesc = layout.querySelector('rastrumDesc') - // convert px to mm coordinates - const mmRect = convertRectUnits(modifiedDom, surfaceId, xywh, 'px2mm') - /* console.log('\n\nHELLO POOOOLLLY:') - console.log(xywh) - console.log(mmRect) - console.log(layout) - console.log(rastrumDesc) */ - // no rastrum so far if (!activeSystemId || !rastrumDesc.querySelector('rastrum[*|id="' + activeSystemId + '"]')) { const rastrum = document.createElementNS('http://www.music-encoding.org/ns/mei', 'rastrum') const rastrumId = 'r' + uuid() rastrum.setAttribute('xml:id', rastrumId) rastrum.setAttribute('systems', 1) - rastrum.setAttribute('system.height', mmRect.h) - rastrum.setAttribute('width', mmRect.w) - rastrum.setAttribute('system.leftmar', mmRect.x) - rastrum.setAttribute('system.topmar', mmRect.y) + rastrum.setAttribute('system.height', xywh.h) + rastrum.setAttribute('width', xywh.w) + rastrum.setAttribute('system.leftmar', xywh.x) + rastrum.setAttribute('system.topmar', xywh.y) + rastrum.setAttribute('rotate', xywh.rotate) rastrumDesc.append(rastrum) dispatch('setActiveSystem', rastrumId) } else { const rastrum = rastrumDesc.querySelector('rastrum[*|id="' + activeSystemId + '"]') - rastrum.setAttribute('system.height', mmRect.h + 'mm') - rastrum.setAttribute('width', mmRect.w + 'mm') - rastrum.setAttribute('system.leftmar', mmRect.x + 'mm') - rastrum.setAttribute('system.topmar', mmRect.y + 'mm') + rastrum.setAttribute('system.height', xywh.h) + rastrum.setAttribute('width', xywh.w) + rastrum.setAttribute('system.leftmar', xywh.x) + rastrum.setAttribute('system.topmar', xywh.y) + rastrum.setAttribute('rotate', xywh.rotate) } sortRastrumsByVerticalPosition(rastrumDesc) - - console.log('\n\nHELLO POLLY') - console.log(modifiedDom) - const path = getters.currentDocPath const docName = getters.documentNameByPath(path) @@ -974,73 +976,168 @@ const dataModule = { dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) // TODO xmlIDs - dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [], isNewDocument: false }) + dispatch('logChange', { path: path, baseMessage, param, xmlIDs, isNewDocument: false }) + }, - dispatch('disableFacsimileClicks') - } + /** + * set the left margin of the active system + * @param {[type]} commit [description] + * @param {[type]} getters [description] + * @param {[type]} dispatch [description] + * @param {[type]} x [description] + */ + setActiveSystemX ({ commit, getters, dispatch }, x) { + if (typeof x === 'undefined') { + return null + } + const modifiedDom = getters.documentWithCurrentPage.cloneNode(true) + + if (!modifiedDom) { + return null + } + + const systemId = getters.activeSystemId + const rastrum = [...modifiedDom.querySelectorAll('rastrum')].find(rastrum => rastrum.getAttribute('xml:id') === systemId) - /* - CREATE_SYSTEM (state, rect) { - const xmlDoc = state.parsedXml.cloneNode(true) - const pageIndex = state.currentPage + 1 - const pageQueryString = 'page:nth-child(' + pageIndex + ')' - const page = xmlDoc.querySelector(pageQueryString) + rastrum.setAttribute('system.leftmar', x) - const pageHeight = parseInt(page.getAttribute('page.height')) - const newSystemUly = pageHeight - rect.y - const left = rect.x - const right = rect.w + rect.x - const height = rect.h + const path = getters.currentDocPath + const docName = getters.documentNameByPath(path) + + const param = getters.currentSurfaceIndexForCurrentDoc + const baseMessage = 'adjust systems on ' + docName + ', p.' - const existingSystems = page.querySelectorAll('system') - let i = 0 + dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) + dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [rastrum.getAttribute('xml:id')], isNewDocument: false }) + }, - while (existingSystems.length > i && parseInt(existingSystems[i].getAttribute('uly')) > newSystemUly) { - i++ + /** + * set the vertical position of the active system + * @param {[type]} commit [description] + * @param {[type]} getters [description] + * @param {[type]} dispatch [description] + * @param {[type]} x [description] + */ + setActiveSystemY ({ commit, getters, dispatch }, y) { + if (typeof y === 'undefined') { + return null } - const newSystem = generateSystemFromRect(newSystemUly, left, right) + const modifiedDom = getters.documentWithCurrentPage.cloneNode(true) - if (existingSystems.length === 0) { - initializePageIfNecessary(page, height) - insertSystem(page, newSystem, null) - } else { - const followingSystem = existingSystems[i] - insertSystem(page, newSystem, followingSystem) + if (!modifiedDom) { + return null } - state.parsedXml = xmlDoc + const systemId = getters.activeSystemId + const rastrum = [...modifiedDom.querySelectorAll('rastrum')].find(rastrum => rastrum.getAttribute('xml:id') === systemId) + + rastrum.setAttribute('system.topmar', y) + + const path = getters.currentDocPath + const docName = getters.documentNameByPath(path) + + const param = getters.currentSurfaceIndexForCurrentDoc + const baseMessage = 'adjust systems on ' + docName + ', p.' + + dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) + dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [rastrum.getAttribute('xml:id')], isNewDocument: false }) }, - SET_SELECTED_SYSTEM_ON_CURRENT_PAGE (state, i) { - state.selectedSystemOnCurrentPage = i + + /** + * set the width of the active system + * @param {[type]} commit [description] + * @param {[type]} getters [description] + * @param {[type]} dispatch [description] + * @param {[type]} x [description] + */ + setActiveSystemW ({ commit, getters, dispatch }, w) { + if (typeof w === 'undefined') { + return null + } + const modifiedDom = getters.documentWithCurrentPage.cloneNode(true) + + if (!modifiedDom) { + return null + } + + const systemId = getters.activeSystemId + const rastrum = [...modifiedDom.querySelectorAll('rastrum')].find(rastrum => rastrum.getAttribute('xml:id') === systemId) + + rastrum.setAttribute('width', w) + + const path = getters.currentDocPath + const docName = getters.documentNameByPath(path) + + const param = getters.currentSurfaceIndexForCurrentDoc + const baseMessage = 'adjust systems on ' + docName + ', p.' + + dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) + dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [rastrum.getAttribute('xml:id')], isNewDocument: false }) }, - SET_EDITING_SYSTEM_ON_CURRENT_PAGE (state, i) { - console.log('working here ' + i) - // if (state.selectionRectEnabled) { - state.editingSystemOnCurrentPage = i - const xmlDoc = state.parsedXml - const pageIndex = state.currentPage + 1 - const pageQueryString = 'page:nth-child(' + pageIndex + ')' - const page = xmlDoc.querySelector(pageQueryString) + /** + * set the height of the active system + * @param {[type]} commit [description] + * @param {[type]} getters [description] + * @param {[type]} dispatch [description] + * @param {[type]} x [description] + */ + setActiveSystemH ({ commit, getters, dispatch }, h) { + if (typeof h === 'undefined') { + return null + } + const modifiedDom = getters.documentWithCurrentPage.cloneNode(true) + + if (!modifiedDom) { + return null + } - const systemIndex = i + 1 - const systemQueryString = 'system:nth-of-type(' + systemIndex + ')' - const system = page.querySelector(systemQueryString) - const measure = page.querySelector('measure') + const systemId = getters.activeSystemId + const rastrum = [...modifiedDom.querySelectorAll('rastrum')].find(rastrum => rastrum.getAttribute('xml:id') === systemId) - const pageHeight = state.pages[state.currentPage].height + rastrum.setAttribute('system.height', h) - console.log(system) + const path = getters.currentDocPath + const docName = getters.documentNameByPath(path) - const x = parseInt(measure.getAttribute('coord.x1')) - const y = parseInt(pageHeight - parseInt(system.getAttribute('uly'))) - const w = parseInt(measure.getAttribute('coord.x2') - x) - const h = parseInt(Math.round(pageHeight / 30)) + const param = getters.currentSurfaceIndexForCurrentDoc + const baseMessage = 'adjust systems on ' + docName + ', p.' - console.log('xywh:', x, y, w, h) - // } + dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) + dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [rastrum.getAttribute('xml:id')], isNewDocument: false }) }, + + /** + * set the rotation of the active system + * @param {[type]} commit [description] + * @param {[type]} getters [description] + * @param {[type]} dispatch [description] + * @param {[type]} x [description] */ + setActiveSystemRotate ({ commit, getters, dispatch }, rotate) { + if (typeof rotate === 'undefined') { + return null + } + const modifiedDom = getters.documentWithCurrentPage.cloneNode(true) + + if (!modifiedDom) { + return null + } + + const systemId = getters.activeSystemId + const rastrum = [...modifiedDom.querySelectorAll('rastrum')].find(rastrum => rastrum.getAttribute('xml:id') === systemId) + + rastrum.setAttribute('rotate', rotate) + + const path = getters.currentDocPath + const docName = getters.documentNameByPath(path) + + const param = getters.currentSurfaceIndexForCurrentDoc + const baseMessage = 'adjust systems on ' + docName + ', p.' + + dispatch('loadDocumentIntoStore', { path: path, dom: modifiedDom }) + dispatch('logChange', { path: path, baseMessage, param, xmlIDs: [rastrum.getAttribute('xml:id')], isNewDocument: false }) + } }, /** @@ -1280,6 +1377,12 @@ const dataModule = { const surfaceLabel = surface.hasAttribute('label') ? surface.getAttributeNS('', 'label').trim() : surfaceN const label = isReconstruction ? i : surfaceLabel + const position = (folium.getAttribute('outer.recto') === match || + folium.getAttribute('inner.recto') === match || + folium.getAttribute('recto') === match) + ? 'recto' + : 'verso' + obj.uri = target obj.id = surfaceId obj.label = label @@ -1293,6 +1396,7 @@ const dataModule = { obj.foliumId = folium.getAttribute('xml:id').trim() obj.mmWidth = parseFloat(folium.getAttribute('width')) obj.mmHeight = parseFloat(folium.getAttribute('height')) + obj.position = position obj.hasSvg = surface.querySelector('graphic[type="shapes"]') !== null // exists(graphic[@type='svg']) inside relevant /surface obj.zonesCount = surface.querySelectorAll('zone[type="writingZone"]').length // exists(mei:zone) inside relevant /surface @@ -1599,6 +1703,21 @@ const dataModule = { return writingLayer }, + /** + * gets the current page object from documentPagesForSidebars + * @param {[type]} state [description] + * @param {[type]} getters [description] + * @return {[type]} [description] + */ + currentPageDetails: (state, getters) => { + const pageIndex = getters.currentPageZeroBased + const path = getters.filepath + const pages = getters.documentPagesForSidebars(path) + + const page = pages[pageIndex] + return page + }, + /** * retrieves the xml:id of the currently displayed surface * @param {[type]} state [description] @@ -2061,14 +2180,15 @@ const dataModule = { x: parseFloat(rastrum.getAttribute('system.leftmar')), y: parseFloat(rastrum.getAttribute('system.topmar')), w: parseFloat(rastrum.getAttribute('width')), - h: parseFloat(rastrum.getAttribute('system.height')) + h: parseFloat(rastrum.getAttribute('system.height')), + rotate: rastrum.hasAttribute('rotate') ? parseFloat(rastrum.getAttribute('rotate')) : 0 } // console.log(mm) - const xywh = convertRectUnits(dom, surfaceId, mm, 'mm2px') + // const xywh = convertRectUnits(dom, surfaceId, mm, 'mm2px') // console.log(xywh) - arr.push({ id: rastrum.getAttribute('xml:id'), xywh }) + arr.push({ id: rastrum.getAttribute('xml:id'), ...mm }) }) return arr diff --git a/src/store/gui/index.js b/src/store/gui/index.js index 82ceab6..1c3f818 100644 --- a/src/store/gui/index.js +++ b/src/store/gui/index.js @@ -22,6 +22,8 @@ const guiModule = { * @property {Boolean} processing whether the app is currently processing bigger data * @property {Boolean} pageTabSidebarVisible if the left sidebar in pageTab is visible * @property {Number} pageTabSidebarWidth width of the left sidebar in pageTab + * @property {Boolean} pageTabRightSidebarVisible if the right sidebar in pageTab is visible + * @property {Number} pageTabRightSidebarWidth width of the right sidebar in pageTab * @property {Boolean} zonesTabLeftSidebarVisible if the left sidebar in zonesTab is visible * @property {Number} zonesTabLeftSidebarWidth width of the left sidebar in zonesTab * @property {Boolean} zonesTabRightSidebarVisible if the left sidebar in zonesTab is visible @@ -34,7 +36,6 @@ const guiModule = { * @property {Number} diploTabSidebarWidth width of the left sidebar in diploTab * @property {String} activeWritingZone ID of the currently active writing zone * @property {String} activeWritingLayer ID of the currently active writing layer - * @property {String} facsimileClickMode whether pageMargin fragment identifier selection mode is active * @property {String} activeSystem ID of the currently active system * @property {Object} focusRect * @property {String} awaitedDocument name of a document to be opened when sufficient data is available. Used to resolve routes @@ -48,19 +49,20 @@ const guiModule = { processing: false, pageTabSidebarVisible: true, pageTabSidebarWidth: 300, + pageTabRightSidebarVisible: true, + pageTabRightSidebarWidth: 430, zonesTabLeftSidebarVisible: true, zonesTabLeftSidebarWidth: 300, zonesTabRightSidebarVisible: true, zonesTabRightSidebarWidth: 250, annotTabLeftSidebarVisible: true, - annotTabLeftSidebarWidth: 200, + annotTabLeftSidebarWidth: 300, annotTabRightSidebarVisible: true, annotTabRightSidebarWidth: 300, diploTabSidebarVisible: true, diploTabSidebarWidth: 300, activeWritingZone: null, activeWritingLayer: null, - facsimileClickMode: 'off', activeSystem: null, focusRect: null, pageBorderPoints: [], @@ -78,7 +80,12 @@ const guiModule = { * @param {[type]} modal [description] */ SET_MODAL (state, modal) { - state.modal = modal + try { + state.modal = modal + } catch (err) { + console.warn('something went wrong with modal "' + modal + '"') + console.log(err) + } }, /** @@ -130,6 +137,24 @@ const guiModule = { TOGGLE_PAGETAB_SIDEBAR_VISIBILITY (state) { state.pageTabSidebarVisible = !state.pageTabSidebarVisible }, + /** + * sets width of right sidebar in pageTab + * @memberof store.gui.mutations + * @param {[type]} state [description] + * @param {[type]} width [description] + */ + SET_PAGETAB_RIGHT_SIDEBAR_WIDTH (state, width) { + state.pageTabRightSidebarWidth = width + }, + /** + * toggles visibility of right sidebar in pageTab + * @memberof store.gui.mutations + * @param {[type]} state [description] + */ + TOGGLE_PAGETAB_RIGHT_SIDEBAR_VISIBILITY (state) { + state.pageTabRightSidebarVisible = !state.pageTabRightSidebarVisible + }, + /** * sets width of left sidebar in zonesTab * @memberof store.gui.mutations @@ -234,17 +259,6 @@ const guiModule = { state.activeWritingLayer = id }, - /** - * set what annotorious is supposed to do on OSD mode - * @param {[type]} state [description] - * @param {[type]} bool [description] - */ - SET_FACSIMILE_CLICK_MODE (state, mode) { - state.facsimileClickMode = mode - state.activeSystem = null - state.activeWritingZone = null - }, - /** * sets the active system * @param {[type]} state [description] @@ -346,7 +360,6 @@ const guiModule = { setExplorerTab ({ commit, getters, dispatch }, val) { if (getters.isAuthenticated) { commit('SET_EXPLORER_TAB', val) - dispatch('disableFacsimileClicks') } }, @@ -359,6 +372,17 @@ const guiModule = { togglePageTabSidebar ({ commit }) { commit('TOGGLE_PAGETAB_SIDEBAR_VISIBILITY') }, + + /** + * toggles visibility of the pageTab right sidebar + * @memberof store.gui.actions + * @param {[type]} commit [description] + * @return {[type]} [description] + */ + togglePageTabRightSidebar ({ commit }) { + commit('TOGGLE_PAGETAB_RIGHT_SIDEBAR_VISIBILITY') + }, + /** * toggles visibility of the zonesTab left sidebar * @memberof store.gui.actions @@ -433,26 +457,6 @@ const guiModule = { commit('SET_ACTIVE_WRITINGLAYER', id) }, - /** - * set the facsimileClickMode - * @param {[type]} commit [description] - * @param {[type]} getters [description] - * @return {[type]} [description] - */ - setFacsimileClickMode ({ commit, getters }, mode) { - commit('SET_FACSIMILE_CLICK_MODE', mode) - }, - - /** - * deactivate annotorious - * @param {[type]} commit [description] - * @param {[type]} getters [description] - * @param {[type]} mode [description] - */ - disableFacsimileClicks ({ commit, getters }) { - commit('SET_FACSIMILE_CLICK_MODE', 'off') - }, - /** * sets ID of active system * @param {[type]} commit [description] @@ -483,9 +487,7 @@ const guiModule = { * @return {[type]} [description] */ facsimileClick ({ commit, getters, dispatch }, { x, y, shift }) { - if (getters.facsimileClickMode === 'pageMargin' && shift) { - dispatch('addPageBorderPoint', { x, y }) - } + // }, /** @@ -597,6 +599,26 @@ const guiModule = { pageTabSidebarWidth: (state) => { return state.pageTabSidebarWidth }, + + /** + * returns visibility of right sidebar on pageTab + * @memberof store.gui.getters + * @param {[type]} state [description] + * @return {[type]} [description] + */ + pageTabRightSidebarVisible: (state) => { + return state.pageTabRightSidebarVisible + }, + /** + * returns width of right sidebar on pageTab + * @memberof store.gui.getters + * @param {[type]} state [description] + * @return {[type]} [description] + */ + pageTabRightSidebarWidth: (state) => { + return state.pageTabRightSidebarWidth + }, + /** * returns visibility of left sidebar on zonesTab * @memberof store.gui.getters @@ -706,15 +728,6 @@ const guiModule = { return state.activeWritingLayer }, - /** - * returns the facsimileClickMode - * @param {[type]} state [description] - * @return {[type]} [description] - */ - facsimileClickMode: (state) => { - return state.facsimileClickMode - }, - /** * returns ID of active system * @param {[type]} state [description] diff --git a/src/tools/facsimileHelpers.js b/src/tools/facsimileHelpers.js index 016cd27..702ca5c 100644 --- a/src/tools/facsimileHelpers.js +++ b/src/tools/facsimileHelpers.js @@ -76,3 +76,60 @@ export function getMediaFragmentInnerBoxRect (OpenSeadragon, getters) { return { location, rotationMode } } + +/** + * returns the suggested position for a new rastrum on the current page + * @return {[type]} [description] + */ +export function suggestRastrum (getters) { + const existingRastrums = getters.rastrumsOnCurrentPage + const page = getters.currentPageDetails + + const pageWidth = parseFloat(page.mmWidth) + + let leftmar = page.position === 'verso' ? 25 : 20 + let rightmar = page.position === 'recto' ? 25 : 20 + let topmar = 20 + let height = 7 + let rotate = 0 + let systemDistance = 6 + + /* + const mm = { + x: parseFloat(rastrum.getAttribute('system.leftmar')), + y: parseFloat(rastrum.getAttribute('system.topmar')), + w: parseFloat(rastrum.getAttribute('width')), + h: parseFloat(rastrum.getAttribute('system.height')), + rotate: rastrum.hasAttribute('rotate') ? parseFloat(rastrum.getAttribute('rotate')) : 0 + } + */ + + if (existingRastrums.length === 1) { + leftmar = parseFloat(existingRastrums[0].x) + rightmar = pageWidth - leftmar - existingRastrums[0].w + topmar = parseFloat(existingRastrums[0].y) + parseFloat(existingRastrums[0].h) + systemDistance + height = parseFloat(existingRastrums[0].h) + rotate = parseFloat(existingRastrums[0].rotate) + } else if (existingRastrums.length > 1) { + systemDistance = parseFloat(existingRastrums[1].y) - parseFloat(existingRastrums[0].y) - parseFloat(existingRastrums[0].h) + const last = existingRastrums.pop() + + leftmar = parseFloat(last.x) + rightmar = pageWidth - leftmar - last.w + topmar = parseFloat(last.y) + parseFloat(last.h) + systemDistance + height = parseFloat(last.h) + rotate = parseFloat(last.rotate) + } + + const w = pageWidth - leftmar - rightmar + + const rastrum = { + x: parseFloat(leftmar.toFixed(1)), + y: parseFloat(topmar.toFixed(1)), + w: parseFloat(w.toFixed(1)), + h: height, + rotate + } + + return rastrum +}