Tidied up component structure
This commit is contained in:
parent
c002ceccbd
commit
2327b9b8bf
19 changed files with 224 additions and 379 deletions
165
src/App.vue
165
src/App.vue
|
|
@ -3,50 +3,8 @@
|
||||||
|
|
||||||
<!-- Grid managing whole app -->
|
<!-- Grid managing whole app -->
|
||||||
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove" margin=0>
|
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove" margin=0>
|
||||||
|
<panelLeft/>
|
||||||
<!-- Grid managing the left panel -->
|
<panelRight/>
|
||||||
<div id="panelLeft" class="uk-margin-remove uk-padding-remove uk-height-1-1" uk-grid>
|
|
||||||
|
|
||||||
<!-- Vertical tab bar -->
|
|
||||||
<div id="switcher-left" class="uk-flex uk-flex-column uk-padding-remove uk-width-auto uk-height-1-1">
|
|
||||||
<tabIcon id="connect" name="Connect" uk-icon="server" :requireConnection="false" :currentTab="currentTab" @set-tab="setTab" />
|
|
||||||
<tabIcon id="navigate" name="Navigate" uk-icon="location" :requireConnection="true" :currentTab="currentTab" @set-tab="setTab" />
|
|
||||||
<tabIcon id="capture" name="Capture" uk-icon="camera" :requireConnection="true" :currentTab="currentTab" @set-tab="setTab" />
|
|
||||||
<tabIcon id="settings" name="Settings" uk-icon="cog" :requireConnection="false" :currentTab="currentTab" @set-tab="setTab" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Corresponding vertical tab content -->
|
|
||||||
<div v-bind:hidden="!showControlBar" id="container-left" class="uk-padding-remove uk-height-1-1 uk-width-expand">
|
|
||||||
<div id="component-left" class="uk-padding-small uk-flex uk-flex-1 panel-content">
|
|
||||||
<tabContent id="connect" :requireConnection="false" :currentTab="currentTab">
|
|
||||||
<paneConnect/>
|
|
||||||
</tabContent>
|
|
||||||
<tabContent id="navigate" :requireConnection="true" :currentTab="currentTab">
|
|
||||||
<paneNavigate/>
|
|
||||||
</tabContent>
|
|
||||||
<tabContent id="capture" :requireConnection="true" :currentTab="currentTab">
|
|
||||||
<paneCapture/>
|
|
||||||
</tabContent>
|
|
||||||
<tabContent id="settings" :requireConnection="false" :currentTab="currentTab">
|
|
||||||
<paneSettings/>
|
|
||||||
</tabContent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tabbed panel for gallery and live views -->
|
|
||||||
<div id="panelDisplay" class="uk-flex uk-flex-column uk-margin-remove uk-padding-remove uk-width-expand uk-height-1-1">
|
|
||||||
<ul class="uk-flex-none uk-flex-center uk-margin-remove-bottom uk-text-center" uk-tab="swiping: false">
|
|
||||||
<li><a href="#" uk-switcher-item="preview">Live</a></li>
|
|
||||||
<li v-bind:class="{'uk-disabled': !this.$store.getters.ready}"><a href="#" uk-switcher-item="gallery">Gallery</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul class="uk-switcher uk-flex uk-flex-1">
|
|
||||||
<li class="uk-height-1-1 uk-width-1-1 clickableTab" id="streamDisplayTab"><streamDisplay/></li>
|
|
||||||
<li class="uk-height-1-1 uk-width-1-1 uk-overflow-auto" id="galleryDisplayTab"><galleryDisplay/></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -55,105 +13,29 @@
|
||||||
<script>
|
<script>
|
||||||
// Import axios for HTTP requests
|
// Import axios for HTTP requests
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
// Import basic UIkit
|
|
||||||
import UIkit from 'uikit';
|
|
||||||
|
|
||||||
// Import components
|
// Import components
|
||||||
import tabIcon from './components/tabIcon.vue'
|
import panelLeft from './components/panelLeft.vue'
|
||||||
import tabContent from './components/tabContent.vue'
|
import panelRight from './components/panelRight.vue'
|
||||||
|
|
||||||
// Import components
|
|
||||||
import paneConnect from './components/paneConnect.vue'
|
|
||||||
import paneNavigate from './components/paneNavigate.vue'
|
|
||||||
import paneCapture from './components/paneCapture.vue'
|
|
||||||
import panePlugins from './components/panePlugins.vue'
|
|
||||||
import paneSettings from './components/paneSettings.vue'
|
|
||||||
// Import components
|
|
||||||
import streamDisplay from './components/paneDisplayComponents/streamDisplay.vue'
|
|
||||||
import galleryDisplay from './components/paneDisplayComponents/galleryDisplay.vue'
|
|
||||||
|
|
||||||
// Export main app
|
// Export main app
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
tabIcon,
|
panelRight,
|
||||||
tabContent,
|
panelLeft
|
||||||
streamDisplay,
|
|
||||||
galleryDisplay,
|
|
||||||
paneConnect,
|
|
||||||
paneNavigate,
|
|
||||||
paneCapture,
|
|
||||||
panePlugins,
|
|
||||||
paneSettings
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {}
|
||||||
currentTab: 'connect',
|
|
||||||
showControlBar: true,
|
|
||||||
window: {
|
|
||||||
width: 0,
|
|
||||||
height: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
created: function () {
|
created: function () {
|
||||||
var context = this
|
|
||||||
|
|
||||||
window.addEventListener('resize', this.handleResize)
|
|
||||||
this.handleResize();
|
|
||||||
|
|
||||||
window.addEventListener('beforeunload', this.handleExit)
|
window.addEventListener('beforeunload', this.handleExit)
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
|
||||||
// Attach methods to UIkit events for tab switching
|
|
||||||
var context = this;
|
|
||||||
// Gallery tab
|
|
||||||
UIkit.util.on('#galleryDisplayTab', 'shown', function(event, area) {
|
|
||||||
console.log("Gallery tab entered")
|
|
||||||
if (context.$store.state.globalSettings.trackWindow == true) {
|
|
||||||
context.$root.$emit('globalTogglePreview', false)
|
|
||||||
}
|
|
||||||
context.$root.$emit('globalUpdateCaptureList');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Stream tab
|
|
||||||
UIkit.util.on('#streamDisplayTab', 'shown', function(event, area) {
|
|
||||||
console.log("Stream tab entered")
|
|
||||||
UIkit.update()
|
|
||||||
if (context.$store.state.globalSettings.trackWindow == true) {
|
|
||||||
context.$root.$emit('globalTogglePreview', true)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy: function () {
|
|
||||||
window.removeEventListener('resize', this.handleResize)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
setTab: function(event, tab) {
|
|
||||||
console.log(event)
|
|
||||||
console.log(tab)
|
|
||||||
if (this.currentTab == tab) {
|
|
||||||
this.showControlBar = !this.showControlBar
|
|
||||||
this.currentTab = 'none'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.showControlBar = true
|
|
||||||
this.currentTab = tab
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleResize: function(event) {
|
|
||||||
this.window.width = window.innerWidth;
|
|
||||||
this.window.height = window.innerHeight;
|
|
||||||
},
|
|
||||||
|
|
||||||
handleExit: function(event) {
|
handleExit: function(event) {
|
||||||
console.log("Triggered beforeunload")
|
console.log("Triggered beforeunload")
|
||||||
this.$root.$emit('globalTogglePreview', false)
|
this.$root.$emit('globalTogglePreview', false)
|
||||||
|
|
@ -166,14 +48,6 @@ export default {
|
||||||
'uk-light': this.$store.state.globalSettings.darkMode,
|
'uk-light': this.$store.state.globalSettings.darkMode,
|
||||||
'uk-background-secondary': this.$store.state.globalSettings.darkMode
|
'uk-background-secondary': this.$store.state.globalSettings.darkMode
|
||||||
}
|
}
|
||||||
},
|
|
||||||
disableIfDisconnected: function () {
|
|
||||||
return {
|
|
||||||
'uk-disabled': !this.$store.getters.ready
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onMobile: function () {
|
|
||||||
return (this.window.width <= 800) ? true : false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,29 +78,4 @@ body, html {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uk-tab {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
#component-left {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#container-left {
|
|
||||||
overflow: hidden auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#container-left, #switcher-left {
|
|
||||||
border-width: 0 1px 0 0;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: rgba(180, 180, 180, 0.25)
|
|
||||||
}
|
|
||||||
|
|
||||||
#switcher-left a{
|
|
||||||
padding: 12px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#switcher-left{
|
|
||||||
background-color: rgba(180, 180, 180, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@
|
||||||
|
|
||||||
.hook-inverse() {
|
.hook-inverse() {
|
||||||
.uk-button-primary{
|
.uk-button-primary{
|
||||||
background-color: rgba(180, 180, 180, 0.1);
|
background-color: rgba(180, 180, 180, 0.15);
|
||||||
color: @inverse-primary-muted-color;
|
color: @inverse-primary-muted-color;
|
||||||
border-color: @inverse-primary-muted-color;
|
border-color: @inverse-primary-muted-color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
<div class="host-input">
|
<div class="host-input">
|
||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
|
|
||||||
<h4>Connect</h4>
|
|
||||||
|
|
||||||
<form @submit.prevent="handleSubmit">
|
<form @submit.prevent="handleSubmit">
|
||||||
<div class="uk-form-controls uk-margin">
|
<div class="uk-form-controls uk-margin">
|
||||||
<label><input class="uk-radio" type="radio" name="radio_local" v-model="computedLocalMode" v-bind:value="true"> Connect locally</label><br>
|
<label><input class="uk-radio" type="radio" name="radio_local" v-model="computedLocalMode" v-bind:value="true"> Connect locally</label><br>
|
||||||
|
|
@ -23,10 +21,11 @@
|
||||||
<div class="uk-accordion-content">
|
<div class="uk-accordion-content">
|
||||||
<label class="uk-form-label" for="form-stacked-text">Port</label>
|
<label class="uk-form-label" for="form-stacked-text">Port</label>
|
||||||
<div class="uk-form-controls">
|
<div class="uk-form-controls">
|
||||||
<input v-model="computedPort" class="uk-input uk-form-width-medium uk-form-small" id="form-stacked-text" type="number" value=5000>
|
<input v-model="computedPort" class="uk-input uk-form-small" id="form-stacked-text" type="number" value=5000>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a class="uk-accordion-title" href="#">Status</a>
|
<a class="uk-accordion-title" href="#">Status</a>
|
||||||
<div class="uk-accordion-content">
|
<div class="uk-accordion-content">
|
||||||
|
|
@ -35,23 +34,23 @@
|
||||||
<p><b>Base URI:</b> {{ $store.getters.uri }}</p>
|
<p><b>Base URI:</b> {{ $store.getters.uri }}</p>
|
||||||
<p v-if="$store.state.apiConfig.name"><b>Device name:</b> {{ $store.state.apiConfig.name }}</p>
|
<p v-if="$store.state.apiConfig.name"><b>Device name:</b> {{ $store.state.apiConfig.name }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="$store.state.waiting"><div uk-spinner></div></div>
|
<div v-else-if="$store.state.waiting"><div uk-spinner></div></div>
|
||||||
<div v-else-if="$store.state.error"><b>Error:</b> {{ $store.state.error }}</div>
|
<div v-else-if="$store.state.error"><b>Error:</b> {{ $store.state.error }}</div>
|
||||||
<div v-else>No active connection</div>
|
<div v-else>No active connection</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="!localMode" class="uk-open">
|
<li v-if="!localMode" class="uk-open">
|
||||||
<a class="uk-accordion-title" href="#">Saved hosts</a>
|
<a class="uk-accordion-title" href="#">Saved hosts</a>
|
||||||
<div class="uk-accordion-content">
|
<div class="uk-accordion-content">
|
||||||
<button v-if="$store.getters.ready" v-on:click="saveHost()" class="uk-button uk-button-default uk-form-small uk-margin-small uk-width-1-1">Save Current</button>
|
<button v-if="$store.getters.ready" v-on:click="saveHost()" class="uk-button uk-button-default uk-form-small uk-margin-small uk-width-1-1">Save Current</button>
|
||||||
|
|
||||||
<div v-for="host in savedHosts" :key="host.name" class="uk-margin-small uk-margin-remove-left uk-margin-remove-right uk-grid">
|
<div v-for="host in savedHosts" :key="host.name" class="uk-margin-small uk-margin-remove-left uk-margin-remove-right uk-grid">
|
||||||
<a href="#" v-on:click="autofillHost(host)" class="uk-icon-link uk-padding-remove uk-width-expand"><b>{{ host.name }}</b> ({{ host.hostname }}:{{ host.port }})</a>
|
<a href="#" v-on:click="autofillHost(host)" class="uk-icon-link uk-padding-remove uk-width-expand host-description"><b>{{ host.name }}</b> ({{ host.hostname }}:{{ host.port }})</a>
|
||||||
<a href="#" v-on:click="delSavedHost(host)" class="uk-icon-link uk-width-auto" uk-icon="trash"></a>
|
<a href="#" v-on:click="delSavedHost(host)" class="uk-icon-link uk-width-auto host-delete" uk-icon="trash"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<button class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1">Connect</button>
|
<button class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1">Connect</button>
|
||||||
|
|
@ -246,4 +245,14 @@ export default {
|
||||||
.host-input {
|
.host-input {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.host-description {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.host-delete {
|
||||||
|
padding: 0 2px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="paneSettings">
|
<div id="paneSettings">
|
||||||
|
|
||||||
<h3>Settings</h3>
|
|
||||||
<appSettings/>
|
<appSettings/>
|
||||||
|
|
||||||
<ul uk-accordion="multiple: true">
|
<ul uk-accordion="multiple: true">
|
||||||
|
|
@ -26,10 +25,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import streamSettings from './paneSettingsComponents/streamSettings.vue'
|
import streamSettings from './settingsComponents/streamSettings.vue'
|
||||||
import microscopeSettings from './paneSettingsComponents/microscopeSettings.vue'
|
import microscopeSettings from './settingsComponents/microscopeSettings.vue'
|
||||||
import cameraSettings from './paneSettingsComponents/cameraSettings.vue'
|
import cameraSettings from './settingsComponents/cameraSettings.vue'
|
||||||
import appSettings from './paneSettingsComponents/appSettings.vue'
|
import appSettings from './settingsComponents/appSettings.vue'
|
||||||
|
|
||||||
// Export main app
|
// Export main app
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -5,7 +5,9 @@
|
||||||
v-bind:hidden="currentTab!=id"
|
v-bind:hidden="currentTab!=id"
|
||||||
class="uk-width-expand"
|
class="uk-width-expand"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<div class="section-heading">{{ id }}</div>
|
||||||
|
<div class="section-content"><slot></slot></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -28,4 +30,16 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
.section-heading {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-content, .section-heading {
|
||||||
|
padding: 9px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -16,8 +16,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
id: String,
|
id: String,
|
||||||
currentTab: String,
|
currentTab: String,
|
||||||
requireConnection: Boolean,
|
requireConnection: Boolean
|
||||||
name: String
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -28,7 +27,8 @@ export default {
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
tooltipOptions: function () {
|
tooltipOptions: function () {
|
||||||
return `pos: right; title: ${this.name}; delay: 500`
|
var title = this.id.charAt(0).toUpperCase() + this.id.slice(1);
|
||||||
|
return `pos: right; title: ${title}; delay: 500`
|
||||||
},
|
},
|
||||||
|
|
||||||
classObject: function () {
|
classObject: function () {
|
||||||
|
|
@ -45,7 +45,7 @@ export default {
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
// Custom UIkit CSS modifications
|
// Custom UIkit CSS modifications
|
||||||
@import "../assets/less/theme.less";
|
@import "../../assets/less/theme.less";
|
||||||
|
|
||||||
.tabicon-active {
|
.tabicon-active {
|
||||||
color: @global-primary-background !important;
|
color: @global-primary-background !important;
|
||||||
|
|
@ -1,203 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="streamDisplay uk-width-1-1 uk-height-1-1 scrollTarget" id="streamDisplay" ref="streamDisplay">
|
|
||||||
|
|
||||||
<img class="uk-align-center uk-margin-remove-bottom" v-on:dblclick="clickmonitor" v-if="showStream" v-bind:src="streamImgUri" alt="Stream">
|
|
||||||
|
|
||||||
<div v-else-if="$store.state.waiting" class="uk-position-center">
|
|
||||||
<div uk-spinner="ratio: 4.5" ></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else-if="$store.state.globalSettings.disableStream" class="uk-position-center position-relative text-center">
|
|
||||||
Stream preview disabled
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="uk-position-center position-relative text-center">
|
|
||||||
No active connection
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
// Export main app
|
|
||||||
export default {
|
|
||||||
name: 'streamDisplay',
|
|
||||||
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
displaySize: [0, 0],
|
|
||||||
displayPosition: [0, 0],
|
|
||||||
GpuPreviewActive: false,
|
|
||||||
resizeTeimoutId: setTimeout(this.doneResizing, 500)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
// A global signal listener to change the GPU preview state
|
|
||||||
this.$root.$on('globalResizePreview', (state) => {
|
|
||||||
this.handleDoneResize()
|
|
||||||
})
|
|
||||||
// A global signal listener to change the GPU preview state
|
|
||||||
this.$root.$on('globalTogglePreview', (state) => {
|
|
||||||
console.log(`Toggling preview to ${state}`)
|
|
||||||
this.previewRequest(state)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
created: function () {
|
|
||||||
// Add resize listener
|
|
||||||
window.addEventListener('resize', this.handleResize);
|
|
||||||
|
|
||||||
// Watch for host 'ready'
|
|
||||||
this.$store.watch(
|
|
||||||
(state)=>{
|
|
||||||
return this.$store.getters.ready
|
|
||||||
},
|
|
||||||
(newValue, oldValue)=>{
|
|
||||||
// 'ready' changed, so do something
|
|
||||||
console.log(oldValue)
|
|
||||||
console.log(newValue)
|
|
||||||
this.previewRequest(this.$store.state.globalSettings.autoGpuPreview)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy: function () {
|
|
||||||
// Remove resize listener
|
|
||||||
window.removeEventListener('resize', this.handleResize)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
clickmonitor: function(event) {
|
|
||||||
// Calculate steps from event coordinates and store config FOV
|
|
||||||
var xCoordinate = event.offsetX;
|
|
||||||
var yCoordinate = event.offsetY;
|
|
||||||
|
|
||||||
var xRelative = (0.5*event.target.offsetWidth - xCoordinate)/event.target.offsetWidth;
|
|
||||||
var yRelative = (0.5*event.target.offsetHeight - yCoordinate)/event.target.offsetHeight;
|
|
||||||
|
|
||||||
var xSteps = xRelative * this.$store.state.apiConfig.fov[0];
|
|
||||||
var ySteps = yRelative * this.$store.state.apiConfig.fov[1];
|
|
||||||
|
|
||||||
// Emit a signal to move, acted on by panelNavigate.vue
|
|
||||||
this.$root.$emit('globalMoveEvent', xSteps, ySteps, 0, false)
|
|
||||||
},
|
|
||||||
|
|
||||||
handleResize: function(event) {
|
|
||||||
// Only fires resize event after no resize in 500ms (prevents resize event spam)
|
|
||||||
clearTimeout(this.resizeTeimoutId);
|
|
||||||
this.resizeTeimoutId = setTimeout(this.handleDoneResize, 500)
|
|
||||||
},
|
|
||||||
|
|
||||||
handleDoneResize: function() {
|
|
||||||
// Recalculate size
|
|
||||||
this.recalculateSize();
|
|
||||||
if (this.$store.state.globalSettings.autoGpuPreview == true && this.GpuPreviewActive == true) {
|
|
||||||
// Reload preview
|
|
||||||
this.$root.$emit('globalTogglePreview', true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
recalculateSize: function () {
|
|
||||||
console.log("Recalculating window dimensions...")
|
|
||||||
// Stacking parentNode is a hacky fix
|
|
||||||
// For some reason, when switching tabs, width was always half what it should be,
|
|
||||||
// until the size was recalculated at some later time. Probably something to do
|
|
||||||
// with tab transition. This parentNode stuff instead reads the size of the tab
|
|
||||||
// container, irrespective of WHICH tab is selected. It's nasty, but works.
|
|
||||||
let element = this.$refs.streamDisplay.parentNode.parentNode;
|
|
||||||
|
|
||||||
let size = [element.clientWidth, element.clientHeight];
|
|
||||||
|
|
||||||
let elem_pos = [element.getBoundingClientRect().left, element.getBoundingClientRect().top];
|
|
||||||
let wind_pos = [window.screenX, window.screenY];
|
|
||||||
let navHeight = window.outerHeight - window.innerHeight;
|
|
||||||
let position = [Math.max(0, wind_pos[0] + elem_pos[0]), Math.max(0, wind_pos[1] + elem_pos[1] + navHeight)];
|
|
||||||
|
|
||||||
this.displaySize = size;
|
|
||||||
this.displayPosition = position;
|
|
||||||
},
|
|
||||||
|
|
||||||
previewRequest: function(state) {
|
|
||||||
if (this.$store.getters.ready == true) {
|
|
||||||
// Create URI and set this.GpuPreviewActive depending on if starting or stopping preview
|
|
||||||
if (state == true) {
|
|
||||||
this.GpuPreviewActive = true
|
|
||||||
var requestUri = this.startPreviewUri;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.GpuPreviewActive = false;
|
|
||||||
var requestUri = this.stopPreviewUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate payload if tracking window position
|
|
||||||
if (this.$store.state.globalSettings.trackWindow == true && state == true) {
|
|
||||||
// Recalculate frame dimensions and position
|
|
||||||
this.recalculateSize()
|
|
||||||
// Copy data into payload array
|
|
||||||
var payload = {
|
|
||||||
window : [
|
|
||||||
this.displayPosition[0],
|
|
||||||
this.displayPosition[1],
|
|
||||||
this.displaySize[0],
|
|
||||||
this.displaySize[1],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var letpayload = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send preview request
|
|
||||||
axios.post(requestUri, payload)
|
|
||||||
.then(response => {
|
|
||||||
this.$store.dispatch('updateState'); // Update store state
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
this.modalError(error) // Let mixin handle error
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
showStream: function () {
|
|
||||||
return this.$store.getters.ready && !this.$store.state.globalSettings.disableStream
|
|
||||||
},
|
|
||||||
streamImgUri: function () {
|
|
||||||
return this.$store.getters.uri + "/stream"
|
|
||||||
},
|
|
||||||
startPreviewUri: function () {
|
|
||||||
return this.$store.getters.uri + "/camera/preview/start"
|
|
||||||
},
|
|
||||||
stopPreviewUri: function () {
|
|
||||||
return this.$store.getters.uri + "/camera/preview/stop"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.streamDisplay img {
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
object-fit: contain
|
|
||||||
}
|
|
||||||
|
|
||||||
.streamDisplay {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.position-relative {
|
|
||||||
position: relative !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
111
src/components/panelLeft.vue
Normal file
111
src/components/panelLeft.vue
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
<template>
|
||||||
|
<div id="panel-left" class="uk-margin-remove uk-padding-remove uk-height-1-1" uk-grid>
|
||||||
|
|
||||||
|
<!-- Vertical tab bar -->
|
||||||
|
<div id="switcher-left" class="uk-flex uk-flex-column uk-padding-remove uk-width-auto uk-height-1-1">
|
||||||
|
<tabIcon id="connect" uk-icon="server" :requireConnection="false" :currentTab="currentTab" @set-tab="setTab" />
|
||||||
|
<tabIcon id="navigate" uk-icon="location" :requireConnection="true" :currentTab="currentTab" @set-tab="setTab" />
|
||||||
|
<tabIcon id="capture" uk-icon="camera" :requireConnection="true" :currentTab="currentTab" @set-tab="setTab" />
|
||||||
|
<tabIcon id="settings" uk-icon="cog" :requireConnection="false" :currentTab="currentTab" @set-tab="setTab" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Corresponding vertical tab content -->
|
||||||
|
<div v-bind:hidden="!showControlBar" id="container-left" class="uk-padding-remove uk-height-1-1 uk-width-expand">
|
||||||
|
<div id="component-left" class="uk-padding-remove uk-flex uk-flex-1 panel-content">
|
||||||
|
<tabContent id="connect" :requireConnection="false" :currentTab="currentTab">
|
||||||
|
<paneConnect/>
|
||||||
|
</tabContent>
|
||||||
|
<tabContent id="navigate" :requireConnection="true" :currentTab="currentTab">
|
||||||
|
<paneNavigate/>
|
||||||
|
</tabContent>
|
||||||
|
<tabContent id="capture" :requireConnection="true" :currentTab="currentTab">
|
||||||
|
<paneCapture/>
|
||||||
|
</tabContent>
|
||||||
|
<tabContent id="settings" :requireConnection="false" :currentTab="currentTab">
|
||||||
|
<paneSettings/>
|
||||||
|
</tabContent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Import axios for HTTP requests
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
// Import generic components
|
||||||
|
import tabIcon from './genericComponents/tabIcon.vue'
|
||||||
|
import tabContent from './genericComponents/tabContent.vue'
|
||||||
|
|
||||||
|
// Import pane components
|
||||||
|
import paneConnect from './controlComponents/paneConnect.vue'
|
||||||
|
import paneNavigate from './controlComponents/paneNavigate.vue'
|
||||||
|
import paneCapture from './controlComponents/paneCapture.vue'
|
||||||
|
import paneSettings from './controlComponents/paneSettings.vue'
|
||||||
|
|
||||||
|
// Export main app
|
||||||
|
export default {
|
||||||
|
name: 'panelLeft',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
tabIcon,
|
||||||
|
tabContent,
|
||||||
|
paneConnect,
|
||||||
|
paneNavigate,
|
||||||
|
paneCapture,
|
||||||
|
paneSettings
|
||||||
|
},
|
||||||
|
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
currentTab: 'connect',
|
||||||
|
showControlBar: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
setTab: function(event, tab) {
|
||||||
|
if (this.currentTab == tab) {
|
||||||
|
this.showControlBar = !this.showControlBar
|
||||||
|
this.currentTab = 'none'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.showControlBar = true
|
||||||
|
this.currentTab = tab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
#component-left {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-left {
|
||||||
|
overflow: hidden auto;
|
||||||
|
background-color: rgba(180, 180, 180, 0.025);
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-left, #switcher-left {
|
||||||
|
border-width: 0 1px 0 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: rgba(180, 180, 180, 0.25)
|
||||||
|
}
|
||||||
|
|
||||||
|
#switcher-left a{
|
||||||
|
padding: 12px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#switcher-left{
|
||||||
|
background-color: rgba(180, 180, 180, 0.1);
|
||||||
|
padding-top: 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
66
src/components/panelRight.vue
Normal file
66
src/components/panelRight.vue
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
<template>
|
||||||
|
<!-- Tabbed panel for gallery and live views -->
|
||||||
|
<div id="panel-right" class="uk-flex uk-flex-column uk-margin-remove uk-padding-remove uk-width-expand uk-height-1-1">
|
||||||
|
<ul class="uk-flex-none uk-flex-center uk-margin-remove-bottom uk-text-center" uk-tab="swiping: false">
|
||||||
|
<li><a href="#" uk-switcher-item="preview">Live</a></li>
|
||||||
|
<li v-bind:class="{'uk-disabled': !this.$store.getters.ready}"><a href="#" uk-switcher-item="gallery">Gallery</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul class="uk-switcher uk-flex uk-flex-1">
|
||||||
|
<li class="uk-height-1-1 uk-width-1-1 clickableTab" id="streamDisplayTab"><streamDisplay/></li>
|
||||||
|
<li class="uk-height-1-1 uk-width-1-1 uk-overflow-auto" id="galleryDisplayTab"><galleryDisplay/></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Import axios for HTTP requests
|
||||||
|
import axios from 'axios'
|
||||||
|
// Import basic UIkit
|
||||||
|
import UIkit from 'uikit';
|
||||||
|
|
||||||
|
// Import components
|
||||||
|
import streamDisplay from './viewComponents/streamDisplay.vue'
|
||||||
|
import galleryDisplay from './viewComponents/galleryDisplay.vue'
|
||||||
|
|
||||||
|
// Export main app
|
||||||
|
export default {
|
||||||
|
name: 'panelRight',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
streamDisplay,
|
||||||
|
galleryDisplay,
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
// Attach methods to UIkit events for tab switching
|
||||||
|
var context = this;
|
||||||
|
// Gallery tab
|
||||||
|
UIkit.util.on('#galleryDisplayTab', 'shown', function(event, area) {
|
||||||
|
console.log("Gallery tab entered")
|
||||||
|
if (context.$store.state.globalSettings.trackWindow == true) {
|
||||||
|
context.$root.$emit('globalTogglePreview', false)
|
||||||
|
}
|
||||||
|
context.$root.$emit('globalUpdateCaptureList');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stream tab
|
||||||
|
UIkit.util.on('#streamDisplayTab', 'shown', function(event, area) {
|
||||||
|
console.log("Stream tab entered")
|
||||||
|
UIkit.update()
|
||||||
|
if (context.$store.state.globalSettings.trackWindow == true) {
|
||||||
|
context.$root.$emit('globalTogglePreview', true)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
.uk-tab {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue