Swap windows for tabs
Each ImJoy window now gets its own top-level tab. This involved some fairly significant refactoring of the ImJoy component, but I think it's cleaner now. I've moved imjoy-related stuff into a store "module" to keep it clean.
This commit is contained in:
parent
0e16835e1b
commit
7585e24744
6 changed files with 224 additions and 157 deletions
|
|
@ -60,6 +60,26 @@
|
||||||
src="https://imjoy.io/static/img/imjoy-icon.svg"
|
src="https://imjoy.io/static/img/imjoy-icon.svg"
|
||||||
/>
|
/>
|
||||||
</tabIcon>
|
</tabIcon>
|
||||||
|
|
||||||
|
<tabIcon
|
||||||
|
v-for="imjoyTab in imjoyTabs"
|
||||||
|
:key="imjoyTab.id"
|
||||||
|
:tab-i-d="'ImJoy-Plugin-' + imjoyTab.id"
|
||||||
|
:title="imjoyTab.name"
|
||||||
|
:require-connection="false"
|
||||||
|
:current-tab="currentTab"
|
||||||
|
@set-tab="setTab"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="imjoyTab.iconURL"
|
||||||
|
style="filter: grayscale(100%);width: 22px;margin-top: 5px;margin-bottom: 8px;"
|
||||||
|
:src="imjoyTab.iconURL"
|
||||||
|
/>
|
||||||
|
<i v-if="!imjoyTab.iconURL" class="material-icons">
|
||||||
|
{{ imjoyTab.iconName || "extension" }}
|
||||||
|
</i>
|
||||||
|
</tabIcon>
|
||||||
|
|
||||||
<hr id="extension-tab-divider" />
|
<hr id="extension-tab-divider" />
|
||||||
|
|
||||||
<!-- For each bottom tab -->
|
<!-- For each bottom tab -->
|
||||||
|
|
@ -124,6 +144,16 @@
|
||||||
<ImJoyContent />
|
<ImJoyContent />
|
||||||
</tabContent>
|
</tabContent>
|
||||||
|
|
||||||
|
<tabContent
|
||||||
|
v-for="imjoyTab in imjoyTabs"
|
||||||
|
:key="imjoyTab.id"
|
||||||
|
:tab-i-d="'ImJoy-Plugin-' + imjoyTab.id"
|
||||||
|
:require-connection="false"
|
||||||
|
:current-tab="currentTab"
|
||||||
|
>
|
||||||
|
<div :id="imjoyTab.window_id" class="window-container">Loading...</div>
|
||||||
|
</tabContent>
|
||||||
|
|
||||||
<!-- For each bottom tab -->
|
<!-- For each bottom tab -->
|
||||||
<tabContent
|
<tabContent
|
||||||
v-for="item in bottomTabs"
|
v-for="item in bottomTabs"
|
||||||
|
|
@ -141,6 +171,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
|
||||||
// Import generic components
|
// Import generic components
|
||||||
import tabIcon from "./genericComponents/tabIcon";
|
import tabIcon from "./genericComponents/tabIcon";
|
||||||
|
|
@ -264,7 +295,9 @@ export default {
|
||||||
|
|
||||||
currentTabIndex: function() {
|
currentTabIndex: function() {
|
||||||
return this.tabOrder.indexOf(this.currentTab);
|
return this.tabOrder.indexOf(this.currentTab);
|
||||||
}
|
},
|
||||||
|
|
||||||
|
...mapState("imjoy", { imjoyTabs: "tabs" })
|
||||||
},
|
},
|
||||||
|
|
||||||
created: function() {
|
created: function() {
|
||||||
|
|
@ -370,6 +403,10 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
.window-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
#component-left {
|
#component-left {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="uk-card-footer uk-padding-small">
|
<div class="uk-card-footer uk-padding-small">
|
||||||
<button class="uk-icon" type="button">
|
<button
|
||||||
|
v-if="openInImjoyMenuItems.length != 0"
|
||||||
|
class="uk-icon"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
style="width:25px;"
|
style="width:25px;"
|
||||||
src="https://imjoy.io/static/img/imjoy-icon.svg"
|
src="https://imjoy.io/static/img/imjoy-icon.svg"
|
||||||
|
|
@ -163,6 +167,7 @@
|
||||||
<script>
|
<script>
|
||||||
import UIkit from "uikit";
|
import UIkit from "uikit";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
|
||||||
import keyvalList from "../../fieldComponents/keyvalList";
|
import keyvalList from "../../fieldComponents/keyvalList";
|
||||||
|
|
||||||
|
|
@ -223,9 +228,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
openInImjoyMenuItems: function() {
|
|
||||||
return this.$store.state.openInImjoyMenuItems;
|
|
||||||
},
|
|
||||||
tagModalID: function() {
|
tagModalID: function() {
|
||||||
return this.makeModalName("tag-modal-");
|
return this.makeModalName("tag-modal-");
|
||||||
},
|
},
|
||||||
|
|
@ -252,7 +254,8 @@ export default {
|
||||||
},
|
},
|
||||||
captureURL: function() {
|
captureURL: function() {
|
||||||
return this.links.self.href;
|
return this.links.self.href;
|
||||||
}
|
},
|
||||||
|
...mapState("imjoy", { openInImjoyMenuItems: "openImageMenu" })
|
||||||
},
|
},
|
||||||
|
|
||||||
created: function() {},
|
created: function() {},
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
<div class="uk-card-footer uk-padding-small">
|
<div class="uk-card-footer uk-padding-small">
|
||||||
<button
|
<button
|
||||||
v-if="openScanInImjoyMenuItemsPresent"
|
v-if="openInImjoyMenuItems.length != 0"
|
||||||
class="uk-icon"
|
class="uk-icon"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
</button>
|
</button>
|
||||||
<div uk-dropdown="pos: top-center">
|
<div uk-dropdown="pos: top-center">
|
||||||
<ul class="uk-nav uk-dropdown-nav">
|
<ul class="uk-nav uk-dropdown-nav">
|
||||||
<li v-for="item in openScanInImjoyMenuItems" :key="item.name">
|
<li v-for="item in openInImjoyMenuItems" :key="item.name">
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
style="color:black"
|
style="color:black"
|
||||||
|
|
@ -125,10 +125,7 @@ export default {
|
||||||
}
|
}
|
||||||
return urls;
|
return urls;
|
||||||
},
|
},
|
||||||
openScanInImjoyMenuItemsPresent: function() {
|
...mapState("imjoy", { openInImjoyMenuItems: "openScanMenu" })
|
||||||
return this.openScanInImjoyMenuItems.length > 0;
|
|
||||||
},
|
|
||||||
...mapState(["openScanInImjoyMenuItems"])
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="uk-card uk-card-hover uk-card-default uk-width-medium"
|
||||||
|
:class="{ 'uk-card-secondary': $store.state.darkMode }"
|
||||||
|
>
|
||||||
|
<a href="#" class="uk-link-text" @click="$emit('click')">
|
||||||
|
<h3 class="uk-card-header">{{ name }}</h3>
|
||||||
|
<div class="uk-card-body">
|
||||||
|
<div class="uk-align-center">
|
||||||
|
<img
|
||||||
|
v-if="iconURL"
|
||||||
|
class="uk-width-1-1"
|
||||||
|
:data-src="iconURL"
|
||||||
|
:alt="name + ' icon'"
|
||||||
|
uk-img
|
||||||
|
/>
|
||||||
|
<i v-if="!iconURL" class="material-icons" style="font-size:96px">
|
||||||
|
{{ iconName }}
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ImjoyPluginCard",
|
||||||
|
|
||||||
|
props: {
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
iconURL: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: () => ""
|
||||||
|
},
|
||||||
|
iconName: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: () => "extension"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -7,83 +7,31 @@
|
||||||
class="uk-progress"
|
class="uk-progress"
|
||||||
max="100"
|
max="100"
|
||||||
></progress>
|
></progress>
|
||||||
<button
|
|
||||||
v-if="activeWindow"
|
|
||||||
class="uk-button uk-button-default close-button"
|
|
||||||
type="button"
|
|
||||||
@click="closeActiveWindow()"
|
|
||||||
>
|
|
||||||
<i class="material-icons">close</i>
|
|
||||||
</button>
|
|
||||||
<button class="uk-button uk-button-default plugins-button" type="button">
|
|
||||||
<img
|
|
||||||
style="width:18px;"
|
|
||||||
src="https://imjoy.io/static/img/imjoy-icon.svg"
|
|
||||||
/> Plugins
|
|
||||||
</button>
|
|
||||||
<div uk-dropdown>
|
|
||||||
<ul class="uk-nav uk-dropdown-nav">
|
|
||||||
<li>
|
|
||||||
<a href="#" @click="loadPluginDialog()">
|
|
||||||
<i class="material-icons">add</i> Load Plugin</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
v-if="Object.keys(loadedPlugins).length > 0"
|
|
||||||
class="uk-nav-divider"
|
|
||||||
></li>
|
|
||||||
<li>
|
|
||||||
<a href="#" @click="startImageJ()"
|
|
||||||
><img
|
|
||||||
alt="ImageJ.JS icon"
|
|
||||||
style="width:20px;"
|
|
||||||
src="https://ij.imjoy.io/assets/icons/chrome/chrome-installprocess-128-128.png"
|
|
||||||
/> ImageJ.JS</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#" @click="startKaibu()"
|
|
||||||
><img
|
|
||||||
alt="Kaibu icon"
|
|
||||||
style="width:20px;"
|
|
||||||
src="https://kaibu.org/static/img/kaibu-icon.svg"
|
|
||||||
/> Kaibu</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
v-for="(p, name) in loadedPlugins"
|
|
||||||
:key="p.id"
|
|
||||||
href="#"
|
|
||||||
@click="runPlugin(p)"
|
|
||||||
><i class="material-icons">extension</i>{{ name }}</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li class="uk-nav-divider"></li>
|
|
||||||
<li>
|
|
||||||
<a v-for="w in windows" :key="w.id" href="#" @click="activeWindow = w"
|
|
||||||
><i class="material-icons">filter_none</i> {{ w.name }}</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div class="uk-child-width-1-3@m uk-grid-match" uk-grid>
|
||||||
v-for="w in windows"
|
<imjoy-plugin-card
|
||||||
v-show="w === activeWindow"
|
name="New"
|
||||||
:key="w.id"
|
icon-u-r-l="https://imjoy.io/static/img/imjoy-icon.svg"
|
||||||
style="height: 100%;"
|
@click="loadPluginDialog()"
|
||||||
>
|
>
|
||||||
<h4 class="window-title">{{ w.name }}</h4>
|
Load plugin from URL
|
||||||
<div :id="w.window_id" class="window-container"></div>
|
</imjoy-plugin-card>
|
||||||
</div>
|
<imjoy-plugin-card
|
||||||
<div
|
name="ImageJ.JS"
|
||||||
v-if="!activeWindow || windows.length <= 0"
|
icon-u-r-l="https://ij.imjoy.io/assets/icons/chrome/chrome-installprocess-128-128.png"
|
||||||
class="uk-position-center position-relative text-center"
|
@click="openImageJ()"
|
||||||
>
|
/>
|
||||||
<img
|
<imjoy-plugin-card
|
||||||
style="width:80px;"
|
name="Kaibu"
|
||||||
src="https://imjoy.io/static/img/imjoy-icon.svg"
|
icon-u-r-l="https://kaibu.org/static/img/kaibu-icon.svg"
|
||||||
|
@click="startKaibu()"
|
||||||
|
/>
|
||||||
|
<imjoy-plugin-card
|
||||||
|
v-for="(p, name) in loadedPlugins"
|
||||||
|
:key="p.id"
|
||||||
|
:name="name"
|
||||||
|
icon-name="extension"
|
||||||
|
@click="runPlugin(p)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -97,6 +45,8 @@
|
||||||
import * as imjoyCore from "imjoy-core";
|
import * as imjoyCore from "imjoy-core";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import UIkit from "uikit";
|
import UIkit from "uikit";
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
import ImjoyPluginCard from "./imjoyComponents/imjoyPluginCard.vue";
|
||||||
|
|
||||||
// TODO: move this to a module or something...
|
// TODO: move this to a module or something...
|
||||||
async function pollAction(response) {
|
async function pollAction(response) {
|
||||||
|
|
@ -174,13 +124,11 @@ async function imageUrlToNdarray(url) {
|
||||||
export default {
|
export default {
|
||||||
name: "ImJoyContent",
|
name: "ImJoyContent",
|
||||||
|
|
||||||
components: {},
|
components: { ImjoyPluginCard },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
windows: [],
|
|
||||||
loading: false,
|
loading: false,
|
||||||
loadedPlugins: {},
|
loadedPlugins: {},
|
||||||
activeWindow: null,
|
|
||||||
viewers: {}
|
viewers: {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -199,7 +147,8 @@ export default {
|
||||||
},
|
},
|
||||||
baseUri: function() {
|
baseUri: function() {
|
||||||
return this.$store.getters.baseUri;
|
return this.$store.getters.baseUri;
|
||||||
}
|
},
|
||||||
|
...mapState("imjoy", { windows: "tabs" })
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
@ -405,28 +354,31 @@ export default {
|
||||||
};
|
};
|
||||||
this.imjoy.pm.registerService({ name: "openflexure" }, service);
|
this.imjoy.pm.registerService({ name: "openflexure" }, service);
|
||||||
},
|
},
|
||||||
closeActiveWindow() {
|
closeWindow(w) {
|
||||||
if (this.activeWindow) {
|
if (w) {
|
||||||
this.activeWindow.api.close();
|
w.api.close();
|
||||||
const index = this.windows.indexOf(this.activeWindow);
|
this.$store.commit("imjoy/removeTab", w);
|
||||||
if (index > -1) {
|
|
||||||
this.windows.splice(index, 1);
|
|
||||||
}
|
|
||||||
if (this.windows.length > 0) {
|
|
||||||
this.activeWindow = this.windows[this.windows.length - 1];
|
|
||||||
} else {
|
|
||||||
this.activeWindow = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectWindow(name) {
|
/**
|
||||||
|
* Activate a window - you can pass the window object, its name, or its id.
|
||||||
|
*/
|
||||||
|
selectWindow(window) {
|
||||||
for (let w of this.windows) {
|
for (let w of this.windows) {
|
||||||
if (w.name === name) {
|
if ((w === window) | (w.name === window) | (w.id === window)) {
|
||||||
this.activeWindow = w;
|
// Make the relevant window visible by switching to its tab
|
||||||
|
this.$root.$emit("globalSwitchTab", `ImJoy-Plugin-${w.id}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setWindowIconUrl(window, iconURL) {
|
||||||
|
this.$store.commit("imjoy/setTabProperty", {
|
||||||
|
tab: window,
|
||||||
|
key: "iconURL",
|
||||||
|
value: iconURL
|
||||||
|
});
|
||||||
|
},
|
||||||
async startKaibu() {
|
async startKaibu() {
|
||||||
this.viewers.kaibu = await this.imjoy.pm.createWindow(null, {
|
this.viewers.kaibu = await this.imjoy.pm.createWindow(null, {
|
||||||
name: "Kaibu",
|
name: "Kaibu",
|
||||||
|
|
@ -435,8 +387,11 @@ export default {
|
||||||
this.viewers.kaibu.on("close", () => {
|
this.viewers.kaibu.on("close", () => {
|
||||||
delete this.viewers.kaibu;
|
delete this.viewers.kaibu;
|
||||||
});
|
});
|
||||||
|
this.setWindowIconUrl(
|
||||||
|
"Kaibu",
|
||||||
|
"https://kaibu.org/static/img/kaibu-icon.svg"
|
||||||
|
);
|
||||||
this.viewers.kaibu.set_mode("full");
|
this.viewers.kaibu.set_mode("full");
|
||||||
this.selectWindow("Kaibu");
|
|
||||||
},
|
},
|
||||||
async startImageJ() {
|
async startImageJ() {
|
||||||
this.viewers.imagej = await this.imjoy.pm.createWindow(null, {
|
this.viewers.imagej = await this.imjoy.pm.createWindow(null, {
|
||||||
|
|
@ -446,17 +401,19 @@ export default {
|
||||||
this.viewers.imagej.on("close", () => {
|
this.viewers.imagej.on("close", () => {
|
||||||
delete this.viewers.imagej;
|
delete this.viewers.imagej;
|
||||||
});
|
});
|
||||||
|
this.setWindowIconUrl(
|
||||||
|
"ImageJ.JS",
|
||||||
|
"https://ij.imjoy.io/assets/icons/chrome/chrome-installprocess-128-128.png"
|
||||||
|
);
|
||||||
// load the ITK/VTK viewer for imagej.js
|
// load the ITK/VTK viewer for imagej.js
|
||||||
this.loadPlugin(
|
this.loadPlugin(
|
||||||
"https://gist.githubusercontent.com/oeway/e5c980fbf6582f25fde795262a7e33ec/raw/itk-vtk-viewer-imagej.imjoy.html"
|
"https://gist.githubusercontent.com/oeway/e5c980fbf6582f25fde795262a7e33ec/raw/itk-vtk-viewer-imagej.imjoy.html"
|
||||||
);
|
);
|
||||||
this.selectWindow("ImageJ.JS");
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Switch to the ImageJ window, starting it if necessary.
|
* Switch to the ImageJ window, starting it if necessary.
|
||||||
*/
|
*/
|
||||||
async openImageJ() {
|
async openImageJ() {
|
||||||
this.$root.$emit("globalSwitchTab", "ImJoy");
|
|
||||||
if (!this.viewers.imagej) {
|
if (!this.viewers.imagej) {
|
||||||
await this.startImageJ();
|
await this.startImageJ();
|
||||||
}
|
}
|
||||||
|
|
@ -467,11 +424,10 @@ export default {
|
||||||
* Switch to the Kaibu window, starting it if necessary.
|
* Switch to the Kaibu window, starting it if necessary.
|
||||||
*/
|
*/
|
||||||
async openKaibu() {
|
async openKaibu() {
|
||||||
this.$root.$emit("globalSwitchTab", "ImJoy");
|
|
||||||
if (!this.viewers.kaibu) {
|
if (!this.viewers.kaibu) {
|
||||||
await this.startKaibu();
|
await this.startKaibu();
|
||||||
}
|
}
|
||||||
this.selectWindow("Kaibu");
|
this.selectWindow("Kaibu"); // TODO: make this behave more nicely when we have multiple Kaibu windows
|
||||||
return this.viewers.kaibu;
|
return this.viewers.kaibu;
|
||||||
},
|
},
|
||||||
async setupViewers() {
|
async setupViewers() {
|
||||||
|
|
@ -485,16 +441,7 @@ export default {
|
||||||
try {
|
try {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
/*async function obtainImageJ() {
|
this.$store.commit("imjoy/addOpenImageItem", {
|
||||||
self.$root.$emit("globalSwitchTab", "ImJoy");
|
|
||||||
if(!self.viewers.imagej) {
|
|
||||||
await self.startImageJ();
|
|
||||||
}
|
|
||||||
self.selectWindow("ImageJ.JS");
|
|
||||||
return self.viewers.imagej;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
this.$store.commit("addOpenInImjoyMenuItem", {
|
|
||||||
title: "Kaibu",
|
title: "Kaibu",
|
||||||
async callback(name, imageUrl) {
|
async callback(name, imageUrl) {
|
||||||
const viewer = await self.openKaibu();
|
const viewer = await self.openKaibu();
|
||||||
|
|
@ -503,7 +450,7 @@ export default {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$store.commit("addOpenInImjoyMenuItem", {
|
this.$store.commit("imjoy/addOpenImageItem", {
|
||||||
title: "ImageJ.JS",
|
title: "ImageJ.JS",
|
||||||
async callback(name, imageUrl) {
|
async callback(name, imageUrl) {
|
||||||
const viewer = await self.openImageJ();
|
const viewer = await self.openImageJ();
|
||||||
|
|
@ -514,7 +461,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$store.commit("addOpenInImjoyMenuItem", {
|
this.$store.commit("imjoy/addOpenImageItem", {
|
||||||
title: "ImageJ.JS [ndarray]",
|
title: "ImageJ.JS [ndarray]",
|
||||||
async callback(name, imageUrl) {
|
async callback(name, imageUrl) {
|
||||||
const viewer = await self.openImageJ();
|
const viewer = await self.openImageJ();
|
||||||
|
|
@ -524,7 +471,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$store.commit("addOpenScanInImjoyMenuItem", {
|
this.$store.commit("imjoy/addOpenScanItem", {
|
||||||
title: "ImageJ.JS",
|
title: "ImageJ.JS",
|
||||||
async callback(name, allURLs) {
|
async callback(name, allURLs) {
|
||||||
const viewer = await self.openImageJ();
|
const viewer = await self.openImageJ();
|
||||||
|
|
@ -566,7 +513,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$store.commit("addOpenScanInImjoyMenuItem", {
|
this.$store.commit("imjoy/addOpenScanItem", {
|
||||||
title: "ImageJ.JS [JPEGs]",
|
title: "ImageJ.JS [JPEGs]",
|
||||||
async callback(name, allURLs) {
|
async callback(name, allURLs) {
|
||||||
const viewer = await self.openImageJ();
|
const viewer = await self.openImageJ();
|
||||||
|
|
@ -592,11 +539,11 @@ export default {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addWindow(w) {
|
async addWindow(w) {
|
||||||
this.windows = this.windows || [];
|
this.$store.commit("imjoy/addTab", w);
|
||||||
this.windows.push(w);
|
await this.$nextTick();
|
||||||
this.activeWindow = w;
|
//this.$forceUpdate();
|
||||||
this.$forceUpdate();
|
this.selectWindow(w);
|
||||||
},
|
},
|
||||||
loadPlugin(uri) {
|
loadPlugin(uri) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
@ -629,22 +576,7 @@ export default {
|
||||||
if (uri) {
|
if (uri) {
|
||||||
this.loadPlugin(uri);
|
this.loadPlugin(uri);
|
||||||
}
|
}
|
||||||
} /*
|
},
|
||||||
async getPosition() {
|
|
||||||
const pos = await service.getXYZPosition();
|
|
||||||
return pos.z;
|
|
||||||
},
|
|
||||||
async setXYPosition(x, y) {
|
|
||||||
return service.setXYZPosition({
|
|
||||||
"x": x,
|
|
||||||
"y": y,
|
|
||||||
"absolute": true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async getXYPosition() {
|
|
||||||
const pos = await service.getXYZPosition();
|
|
||||||
return [pos.x, pos.y];
|
|
||||||
},*/,
|
|
||||||
async getStagePosition() {
|
async getStagePosition() {
|
||||||
return axios.get(this.getPositionUri).then(r => r.data);
|
return axios.get(this.getPositionUri).then(r => r.data);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,65 @@ import Vuex from "vuex";
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
const moduleImjoy = {
|
||||||
|
namespaced: true,
|
||||||
|
state: () => ({
|
||||||
|
tabs: [],
|
||||||
|
openImageMenu: [],
|
||||||
|
openScanMenu: []
|
||||||
|
}),
|
||||||
|
mutations: {
|
||||||
|
addOpenImageItem(state, newItem) {
|
||||||
|
state.openImageMenu.push(newItem);
|
||||||
|
}, // TODO: add a mutation to remove items when plugins are unloaded
|
||||||
|
addOpenScanItem(state, newItem) {
|
||||||
|
state.openScanMenu.push(newItem);
|
||||||
|
}, // TODO: add a mutation to remove items when plugins are unloaded
|
||||||
|
clearMenus(state) {
|
||||||
|
// This is primarily useful to reset the state in hot-reloads of
|
||||||
|
// imjoyContent.vue
|
||||||
|
state.openImageMenu = [];
|
||||||
|
state.openScanMenu = [];
|
||||||
|
},
|
||||||
|
addTab(state, newItem) {
|
||||||
|
// Add a tab to the list of ImJoy tabs
|
||||||
|
state.tabs.push(newItem);
|
||||||
|
},
|
||||||
|
removeTab(state, tabToRemove) {
|
||||||
|
const index = state.tabs.indexOf(tabToRemove);
|
||||||
|
if (index > -1) {
|
||||||
|
state.tabs.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
`Attempted to remove a non-existing ImJoy tab ${tabToRemove}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Set a parameter on any matching tab objects
|
||||||
|
*/
|
||||||
|
setTabProperty(state, payload) {
|
||||||
|
let tab = payload.tab;
|
||||||
|
let key = payload.key;
|
||||||
|
let value = payload.value;
|
||||||
|
for (let i = 0; i < state.tabs.length; i++) {
|
||||||
|
let t = state.tabs[i];
|
||||||
|
if ((t === tab) | (t.name === tab) | (t.id === tab)) {
|
||||||
|
t[key] = value;
|
||||||
|
}
|
||||||
|
state.tabs.splice(i, 1, t); // This should work nicely with reactive stuff
|
||||||
|
}
|
||||||
|
//state.tabs = tablist; // This should force an update
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {},
|
||||||
|
getters: {}
|
||||||
|
};
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
imjoy: moduleImjoy
|
||||||
|
},
|
||||||
state: {
|
state: {
|
||||||
origin: window.location.origin,
|
origin: window.location.origin,
|
||||||
available: false,
|
available: false,
|
||||||
|
|
@ -14,9 +72,7 @@ export default new Vuex.Store({
|
||||||
trackWindow: true,
|
trackWindow: true,
|
||||||
IHIEnabled: false,
|
IHIEnabled: false,
|
||||||
appTheme: "system",
|
appTheme: "system",
|
||||||
activeStreams: {},
|
activeStreams: {}
|
||||||
openInImjoyMenuItems: [],
|
|
||||||
openScanInImjoyMenuItems: []
|
|
||||||
},
|
},
|
||||||
|
|
||||||
mutations: {
|
mutations: {
|
||||||
|
|
@ -58,13 +114,7 @@ export default new Vuex.Store({
|
||||||
},
|
},
|
||||||
removeStream(state, id) {
|
removeStream(state, id) {
|
||||||
state.activeStreams[id] = false;
|
state.activeStreams[id] = false;
|
||||||
},
|
}
|
||||||
addOpenInImjoyMenuItem(state, newItem) {
|
|
||||||
state.openInImjoyMenuItems.push(newItem);
|
|
||||||
}, // TODO: add a mutation to remove items when plugins are unloaded
|
|
||||||
addOpenScanInImjoyMenuItem(state, newItem) {
|
|
||||||
state.openScanInImjoyMenuItems.push(newItem);
|
|
||||||
} // TODO: add a mutation to remove items when plugins are unloaded
|
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {},
|
actions: {},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue