@opencor/opencor 0.20250826.0 → 0.20250827.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/opencor.es.js +1 -1
- package/package.json +5 -6
- package/src/App.vue +0 -7
- package/src/ContainerApp.vue +0 -21
- package/src/assets/app.css +0 -14
- package/src/assets/base.css +0 -31
- package/src/assets/logo.svg +0 -17
- package/src/common/common.ts +0 -86
- package/src/common/constants.ts +0 -12
- package/src/common/electron.ts +0 -23
- package/src/common/electronApi.ts +0 -63
- package/src/common/locCommon.ts +0 -170
- package/src/common/settings.ts +0 -95
- package/src/common/vueCommon.ts +0 -69
- package/src/components/BackgroundComponent.vue +0 -26
- package/src/components/BlockingMessageComponent.vue +0 -34
- package/src/components/ContentsComponent.vue +0 -277
- package/src/components/DragNDropComponent.vue +0 -35
- package/src/components/MainMenu.vue +0 -225
- package/src/components/OpenCOR.vue +0 -624
- package/src/components/dialogs/AboutDialog.vue +0 -51
- package/src/components/dialogs/BaseDialog.vue +0 -58
- package/src/components/dialogs/OpenRemoteDialog.vue +0 -37
- package/src/components/dialogs/ResetAllDialog.vue +0 -13
- package/src/components/dialogs/SettingsDialog.vue +0 -42
- package/src/components/dialogs/UpdateAvailableDialog.vue +0 -16
- package/src/components/dialogs/UpdateDownloadProgressDialog.vue +0 -11
- package/src/components/dialogs/UpdateErrorDialog.vue +0 -18
- package/src/components/dialogs/UpdateNotAvailableDialog.vue +0 -12
- package/src/components/propertyEditors/GraphsPropertyEditor.vue +0 -3
- package/src/components/propertyEditors/ParametersPropertyEditor.vue +0 -3
- package/src/components/propertyEditors/PropertyEditor.vue +0 -60
- package/src/components/propertyEditors/SimulationPropertyEditor.vue +0 -45
- package/src/components/propertyEditors/SolversPropertyEditor.vue +0 -3
- package/src/components/views/IssuesView.vue +0 -50
- package/src/components/views/SimulationExperimentUiView.vue +0 -154
- package/src/components/views/SimulationExperimentView.vue +0 -218
- package/src/components/widgets/GraphPanelWidget.vue +0 -140
- package/src/components/widgets/InputWidget.vue +0 -128
- package/src/libopencor/locApi.ts +0 -167
- package/src/libopencor/locFileApi.ts +0 -263
- package/src/libopencor/locLoggerApi.ts +0 -36
- package/src/libopencor/locSedApi.ts +0 -486
- package/src/libopencor/locUiJsonApi.ts +0 -485
- package/src/libopencor/locVersionApi.ts +0 -17
- package/src/libopencor/src/common.cpp +0 -67
- package/src/libopencor/src/common.h +0 -27
- package/src/libopencor/src/file.cpp +0 -72
- package/src/libopencor/src/file.h +0 -15
- package/src/libopencor/src/main.cpp +0 -78
- package/src/libopencor/src/sed.cpp +0 -348
- package/src/libopencor/src/sed.h +0 -53
- package/src/libopencor/src/version.cpp +0 -8
- package/src/libopencor/src/version.h +0 -5
- package/src/main.ts +0 -6
- package/src/types/types.d.ts +0 -9
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Dialog :modal="true" appendTo="self" :pt:mask:style="{ position: 'absolute' }" @show="onShow" @hide="onHide">
|
|
3
|
-
<template v-for="(_event, slot) of $slots" #[slot]="scope">
|
|
4
|
-
<slot :name="slot" v-bind="scope" />
|
|
5
|
-
</template>
|
|
6
|
-
</Dialog>
|
|
7
|
-
</template>
|
|
8
|
-
|
|
9
|
-
<script setup lang="ts">
|
|
10
|
-
import * as vue from 'vue'
|
|
11
|
-
|
|
12
|
-
import { enableDisableMainMenu } from '../../common/common'
|
|
13
|
-
|
|
14
|
-
let dialogElement: HTMLElement | null = null
|
|
15
|
-
let containerElement: HTMLElement | null | undefined = null
|
|
16
|
-
let mutationObserver: MutationObserver | null = null
|
|
17
|
-
|
|
18
|
-
function checkDialogPosition() {
|
|
19
|
-
if (dialogElement instanceof HTMLElement && containerElement instanceof HTMLElement) {
|
|
20
|
-
const dialogRect = dialogElement.getBoundingClientRect()
|
|
21
|
-
const containerRect = containerElement.getBoundingClientRect()
|
|
22
|
-
|
|
23
|
-
dialogElement.style.top = `${String(Math.max(Math.min(dialogRect.top, containerRect.bottom - dialogRect.height), containerRect.top))}px`
|
|
24
|
-
dialogElement.style.left = `${String(Math.max(Math.min(dialogRect.left, containerRect.right - dialogRect.width), containerRect.left))}px`
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function onShow() {
|
|
29
|
-
enableDisableMainMenu(false)
|
|
30
|
-
|
|
31
|
-
void vue.nextTick().then(() => {
|
|
32
|
-
dialogElement = document.querySelector('.p-dialog')
|
|
33
|
-
containerElement = dialogElement?.closest('[data-pc-section="mask"]')
|
|
34
|
-
|
|
35
|
-
if (dialogElement !== null && containerElement !== null) {
|
|
36
|
-
mutationObserver = new MutationObserver(() => {
|
|
37
|
-
checkDialogPosition()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
mutationObserver.observe(dialogElement, { attributes: true, attributeFilter: ['style'] })
|
|
41
|
-
|
|
42
|
-
checkDialogPosition()
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function onHide() {
|
|
48
|
-
enableDisableMainMenu(true)
|
|
49
|
-
|
|
50
|
-
void vue.nextTick().then(() => {
|
|
51
|
-
if (mutationObserver !== null) {
|
|
52
|
-
mutationObserver.disconnect()
|
|
53
|
-
|
|
54
|
-
mutationObserver = null
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
</script>
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog header="Open Remote..." style="width: 39rem">
|
|
3
|
-
<div class="items-center mt-2 mb-4">
|
|
4
|
-
<FloatLabel variant="on">
|
|
5
|
-
<InputText autofocus fluid v-model="url" @keyup.enter="emitOpenRemote()" />
|
|
6
|
-
<label>URL</label>
|
|
7
|
-
</FloatLabel>
|
|
8
|
-
</div>
|
|
9
|
-
<template #footer>
|
|
10
|
-
<Button label="Open" :disabled="url === ''" @click="emitOpenRemote()" />
|
|
11
|
-
<Button label="Cancel" severity="secondary" @click="emitClose()" />
|
|
12
|
-
</template>
|
|
13
|
-
</BaseDialog>
|
|
14
|
-
</template>
|
|
15
|
-
|
|
16
|
-
<script setup lang="ts">
|
|
17
|
-
import * as vue from 'vue'
|
|
18
|
-
|
|
19
|
-
const emit = defineEmits(['openRemote', 'close'])
|
|
20
|
-
const url = vue.ref<string>('')
|
|
21
|
-
|
|
22
|
-
function emitOpenRemote(): void {
|
|
23
|
-
if (url.value === '') {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
emit('openRemote', url.value)
|
|
28
|
-
|
|
29
|
-
emitClose()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function emitClose(): void {
|
|
33
|
-
url.value = ''
|
|
34
|
-
|
|
35
|
-
emit('close')
|
|
36
|
-
}
|
|
37
|
-
</script>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog header="Reset All...">
|
|
3
|
-
<div class="mt-2 mb-4">You are about to reset all of your settings. Do you want to proceed?</div>
|
|
4
|
-
<template #footer>
|
|
5
|
-
<Button autofocus label="Yes" severity="danger" @click="$emit('resetAll')" />
|
|
6
|
-
<Button label="No" severity="secondary" @click="$emit('close')" />
|
|
7
|
-
</template>
|
|
8
|
-
</BaseDialog>
|
|
9
|
-
</template>
|
|
10
|
-
|
|
11
|
-
<script setup lang="ts">
|
|
12
|
-
defineEmits(['resetAll', 'close'])
|
|
13
|
-
</script>
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog header="Settings..." @hide="initialiseDialog">
|
|
3
|
-
<div class="flex gap-2 items-center">
|
|
4
|
-
<Checkbox inputId="checkForUpdatesAtStartup" :binary="true" v-model="checkForUpdatesAtStartup" />
|
|
5
|
-
<label for="checkForUpdatesAtStartup">Check for updates at startup</label>
|
|
6
|
-
</div>
|
|
7
|
-
<template #footer>
|
|
8
|
-
<Button autofocus label="OK" @click="onOk" />
|
|
9
|
-
<Button label="Cancel" severity="secondary" @click="$emit('close')" />
|
|
10
|
-
</template>
|
|
11
|
-
</BaseDialog>
|
|
12
|
-
</template>
|
|
13
|
-
|
|
14
|
-
<script setup lang="ts">
|
|
15
|
-
import * as vue from 'vue'
|
|
16
|
-
|
|
17
|
-
import { settings } from '../../common/settings'
|
|
18
|
-
|
|
19
|
-
const emit = defineEmits(['close'])
|
|
20
|
-
|
|
21
|
-
const checkForUpdatesAtStartup = vue.ref(settings.general.checkForUpdatesAtStartup)
|
|
22
|
-
|
|
23
|
-
function initialiseDialog() {
|
|
24
|
-
// Note: we can come here as a result of hiding the dialog and this in case the dialog gets opened multiple times. We
|
|
25
|
-
// could do this when showing the dialog, but it might result in the UI flashing (e.g., a checkbox was checked
|
|
26
|
-
// and then it gets unchecked), hence we do it when hiding the dialog.
|
|
27
|
-
|
|
28
|
-
checkForUpdatesAtStartup.value = settings.general.checkForUpdatesAtStartup
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
settings.onInitialised(() => {
|
|
32
|
-
initialiseDialog()
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
function onOk() {
|
|
36
|
-
settings.general.checkForUpdatesAtStartup = checkForUpdatesAtStartup.value
|
|
37
|
-
|
|
38
|
-
settings.save()
|
|
39
|
-
|
|
40
|
-
emit('close')
|
|
41
|
-
}
|
|
42
|
-
</script>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog header="Check For Updates...">
|
|
3
|
-
<div class="mt-2 mb-4">Version {{ version }} is available. Do you want to download it and install it?</div>
|
|
4
|
-
<template #footer>
|
|
5
|
-
<Button autofocus label="Yes" @click="$emit('downloadAndInstall')" />
|
|
6
|
-
<Button label="No" severity="secondary" @click="$emit('close')" />
|
|
7
|
-
</template>
|
|
8
|
-
</BaseDialog>
|
|
9
|
-
</template>
|
|
10
|
-
|
|
11
|
-
<script setup lang="ts">
|
|
12
|
-
defineEmits(['downloadAndInstall', 'close'])
|
|
13
|
-
defineProps<{
|
|
14
|
-
version: string
|
|
15
|
-
}>()
|
|
16
|
-
</script>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog header="Downloading Update..." :closable="false" :closeOnEscape="false" style="width: 39rem">
|
|
3
|
-
<ProgressBar class="no-animation" :showValue="false" :value="percent" />
|
|
4
|
-
</BaseDialog>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
defineProps<{
|
|
9
|
-
percent: number
|
|
10
|
-
}>()
|
|
11
|
-
</script>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog :header="title">
|
|
3
|
-
<div class="mt-2 mb-4">
|
|
4
|
-
{{ issue }}
|
|
5
|
-
</div>
|
|
6
|
-
<template #footer>
|
|
7
|
-
<Button autofocus label="OK" @click="$emit('close')" />
|
|
8
|
-
</template>
|
|
9
|
-
</BaseDialog>
|
|
10
|
-
</template>
|
|
11
|
-
|
|
12
|
-
<script setup lang="ts">
|
|
13
|
-
defineEmits(['close'])
|
|
14
|
-
defineProps<{
|
|
15
|
-
title: string
|
|
16
|
-
issue: string
|
|
17
|
-
}>()
|
|
18
|
-
</script>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<BaseDialog header="Check For Updates...">
|
|
3
|
-
<div class="mt-2 mb-4">No updates are available at this time.</div>
|
|
4
|
-
<template #footer>
|
|
5
|
-
<Button autofocus label="OK" @click="$emit('close')" />
|
|
6
|
-
</template>
|
|
7
|
-
</BaseDialog>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script setup lang="ts">
|
|
11
|
-
defineEmits(['close'])
|
|
12
|
-
</script>
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Fieldset :legend="name">
|
|
3
|
-
<DataTable
|
|
4
|
-
editMode="cell"
|
|
5
|
-
resizableColumns
|
|
6
|
-
showGridlines
|
|
7
|
-
size="small"
|
|
8
|
-
:value="properties"
|
|
9
|
-
@cell-edit-complete="onCellEditComplete"
|
|
10
|
-
>
|
|
11
|
-
<Column field="property" header="Property" :style="columnWidth" />
|
|
12
|
-
<Column field="value" header="Value" :style="columnWidth">
|
|
13
|
-
<template #body="{ data, field }">
|
|
14
|
-
{{ data[field as string] }}
|
|
15
|
-
</template>
|
|
16
|
-
<template #editor="{ data, field }">
|
|
17
|
-
<InputNumber fluid :maxFractionDigits="15" v-model="data[field]" size="small" />
|
|
18
|
-
</template>
|
|
19
|
-
</Column>
|
|
20
|
-
<Column v-if="hasUnits" field="unit" header="Unit" :style="columnWidth" />
|
|
21
|
-
</DataTable>
|
|
22
|
-
</Fieldset>
|
|
23
|
-
</template>
|
|
24
|
-
|
|
25
|
-
<script setup lang="ts">
|
|
26
|
-
import { type DataTableCellEditCompleteEvent } from 'primevue/datatable'
|
|
27
|
-
|
|
28
|
-
const props = withDefaults(
|
|
29
|
-
defineProps<{
|
|
30
|
-
name: string
|
|
31
|
-
hasUnits?: boolean
|
|
32
|
-
properties: {
|
|
33
|
-
property: string
|
|
34
|
-
value: number
|
|
35
|
-
unit?: string
|
|
36
|
-
}[]
|
|
37
|
-
}>(),
|
|
38
|
-
{
|
|
39
|
-
hasUnits: true
|
|
40
|
-
}
|
|
41
|
-
)
|
|
42
|
-
const columnWidth = `width: calc(100% / ${props.hasUnits ? '3' : '2'})`
|
|
43
|
-
const emit = defineEmits(['propertyUpdated'])
|
|
44
|
-
|
|
45
|
-
function onCellEditComplete(event: DataTableCellEditCompleteEvent): void {
|
|
46
|
-
const { data, newValue, field } = event
|
|
47
|
-
|
|
48
|
-
data[field] = newValue
|
|
49
|
-
|
|
50
|
-
emit('propertyUpdated', event.index, event.newValue)
|
|
51
|
-
}
|
|
52
|
-
</script>
|
|
53
|
-
|
|
54
|
-
<style scoped>
|
|
55
|
-
:deep(.p-inputnumber-input) {
|
|
56
|
-
padding: 0 2px !important;
|
|
57
|
-
margin: 0 !important;
|
|
58
|
-
line-height: 1.2px !important;
|
|
59
|
-
}
|
|
60
|
-
</style>
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<PropertyEditor name="Simulation" :properties="properties" @propertyUpdated="onPropertyUpdated" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
import * as vue from 'vue'
|
|
7
|
-
|
|
8
|
-
import * as locApi from '../../libopencor/locApi'
|
|
9
|
-
|
|
10
|
-
const props = defineProps<{
|
|
11
|
-
file: locApi.File
|
|
12
|
-
}>()
|
|
13
|
-
|
|
14
|
-
const uniformTimeCourse = props.file.document().simulation(0) as locApi.SedSimulationUniformTimeCourse
|
|
15
|
-
const voiUnit = props.file.instance().task(0).voiUnit()
|
|
16
|
-
|
|
17
|
-
const properties = vue.ref([
|
|
18
|
-
{
|
|
19
|
-
property: 'Starting point',
|
|
20
|
-
value: uniformTimeCourse.outputStartTime(),
|
|
21
|
-
unit: voiUnit
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
property: 'Ending point',
|
|
25
|
-
value: uniformTimeCourse.outputEndTime(),
|
|
26
|
-
unit: voiUnit
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
property: 'Point interval',
|
|
30
|
-
value:
|
|
31
|
-
(uniformTimeCourse.outputEndTime() - uniformTimeCourse.outputStartTime()) / uniformTimeCourse.numberOfSteps(),
|
|
32
|
-
unit: voiUnit
|
|
33
|
-
}
|
|
34
|
-
])
|
|
35
|
-
|
|
36
|
-
function onPropertyUpdated(index: number, value: number): void {
|
|
37
|
-
if (index === 0) {
|
|
38
|
-
uniformTimeCourse.setOutputStartTime(value)
|
|
39
|
-
} else if (index === 1) {
|
|
40
|
-
uniformTimeCourse.setOutputEndTime(value)
|
|
41
|
-
} else if (index === 2) {
|
|
42
|
-
uniformTimeCourse.setNumberOfSteps((properties.value[1].value - properties.value[0].value) / value)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
</script>
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Fieldset :class="'ml-4! mr-4! mb-4! ' + (simulationOnly ? 'fieldset-simulation-only' : 'fieldset')" legend="Issues">
|
|
3
|
-
<ScrollPanel :class="simulationOnly ? 'scroll-panel-simulation-only' : 'scroll-panel'">
|
|
4
|
-
<div v-for="(issue, index) in issues" :key="`issue_${index}`" :class="`issue ${index > 0 ? 'mt-4!' : ''}`">
|
|
5
|
-
<Message v-if="issue.type === locApi.EIssueType.ERROR" severity="error" icon="pi pi-times-circle">
|
|
6
|
-
{{ issue.description }}
|
|
7
|
-
</Message>
|
|
8
|
-
<Message v-else severity="warn" icon="pi pi-exclamation-triangle">
|
|
9
|
-
{{ issue.description }}
|
|
10
|
-
</Message>
|
|
11
|
-
</div>
|
|
12
|
-
</ScrollPanel>
|
|
13
|
-
</Fieldset>
|
|
14
|
-
</template>
|
|
15
|
-
|
|
16
|
-
<script setup lang="ts">
|
|
17
|
-
import * as locApi from '../../libopencor/locApi'
|
|
18
|
-
|
|
19
|
-
defineProps<{
|
|
20
|
-
issues: locApi.IIssue[]
|
|
21
|
-
simulationOnly?: boolean
|
|
22
|
-
}>()
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<style scoped>
|
|
26
|
-
.fieldset,
|
|
27
|
-
.fieldset-simulation-only {
|
|
28
|
-
overflow: hidden;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.fieldset {
|
|
32
|
-
height: calc(var(--block-ui-height) - var(--main-menu-height) - var(--file-tablist-height) - 1rem);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.fieldset-simulation-only {
|
|
36
|
-
height: calc(var(--block-ui-height) - 1rem);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.issue {
|
|
40
|
-
user-select: text;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.scroll-panel {
|
|
44
|
-
height: calc(var(--block-ui-height) - var(--main-menu-height) - var(--file-tablist-height) - 4.75rem);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.scroll-panel-simulation-only {
|
|
48
|
-
height: calc(var(--block-ui-height) - 4.75rem);
|
|
49
|
-
}
|
|
50
|
-
</style>
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :class="`flex flex-row h-full ${simulationOnly ? 'div-simulation-only' : 'div-simulation'}`">
|
|
3
|
-
<IssuesView v-if="issues.length !== 0" class="grow" :issues="issues" :simulationOnly="simulationOnly" />
|
|
4
|
-
<div v-else class="flex flex-row grow">
|
|
5
|
-
<div class="ml-4 mr-4 mb-4">
|
|
6
|
-
<ScrollPanel class="h-full">
|
|
7
|
-
<Fieldset legend="Input parameters">
|
|
8
|
-
<InputWidget
|
|
9
|
-
v-for="(input, index) in (uiJson as any).input"
|
|
10
|
-
v-model="inputValues[index]"
|
|
11
|
-
v-show="showInput[index]"
|
|
12
|
-
:key="`input_${index}`"
|
|
13
|
-
:name="input.name"
|
|
14
|
-
:maximumValue="input.maximumValue"
|
|
15
|
-
:minimumValue="input.minimumValue"
|
|
16
|
-
:possibleValues="input.possibleValues"
|
|
17
|
-
:stepValue="input.stepValue"
|
|
18
|
-
:class="index !== 0 ? 'mt-6' : ''"
|
|
19
|
-
@change="updateUiAndSimulation"
|
|
20
|
-
/>
|
|
21
|
-
</Fieldset>
|
|
22
|
-
</ScrollPanel>
|
|
23
|
-
</div>
|
|
24
|
-
<div :id="plotsDivId" class="grow">
|
|
25
|
-
<GraphPanelWidget
|
|
26
|
-
v-for="(_plot, index) in (uiJson as any).output.plots"
|
|
27
|
-
:key="`plot_${index}`"
|
|
28
|
-
class="graph-panel-widget"
|
|
29
|
-
:plots="plots.length !== 0 ? plots[index] : []"
|
|
30
|
-
/>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
</template>
|
|
35
|
-
|
|
36
|
-
<script setup lang="ts">
|
|
37
|
-
import * as mathjs from 'https://cdn.jsdelivr.net/npm/mathjs@14.6.0/+esm'
|
|
38
|
-
import * as vue from 'vue'
|
|
39
|
-
|
|
40
|
-
import * as locCommon from '../../common/locCommon'
|
|
41
|
-
import * as locApi from '../../libopencor/locApi'
|
|
42
|
-
|
|
43
|
-
import { type IGraphPanelPlot } from '../widgets/GraphPanelWidget.vue'
|
|
44
|
-
|
|
45
|
-
const props = defineProps<{
|
|
46
|
-
file: locApi.File
|
|
47
|
-
simulationOnly?: boolean
|
|
48
|
-
uiJson: locApi.IUiJson
|
|
49
|
-
}>()
|
|
50
|
-
|
|
51
|
-
const math = mathjs.create(mathjs.all ?? {}, {})
|
|
52
|
-
const model = props.file.document().model(0)
|
|
53
|
-
const instance = props.file.instance()
|
|
54
|
-
const instanceTask = instance.task(0)
|
|
55
|
-
const plotsDivId = `plotsDiv_${props.file.path()}`
|
|
56
|
-
const plots = vue.ref<IGraphPanelPlot[][]>([])
|
|
57
|
-
const issues = vue.ref(locApi.uiJsonIssues(props.uiJson))
|
|
58
|
-
const inputValues = vue.ref<number[]>([])
|
|
59
|
-
const showInput = vue.ref<boolean[]>([])
|
|
60
|
-
const idToInfo: Record<string, locCommon.ISimulationDataInfo> = {}
|
|
61
|
-
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
-
function evaluateValue(value: string): any {
|
|
64
|
-
let index = -1
|
|
65
|
-
const parser = math.parser()
|
|
66
|
-
|
|
67
|
-
props.uiJson.input.forEach((input: locApi.IUiJsonInput) => {
|
|
68
|
-
if (input.id !== undefined && input.id !== '') {
|
|
69
|
-
parser.set(input.id, inputValues.value[++index])
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
return parser.evaluate(value)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
props.uiJson.input.forEach((input: locApi.IUiJsonInput) => {
|
|
77
|
-
inputValues.value.push(input.defaultValue)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
props.uiJson.input.forEach((input: locApi.IUiJsonInput) => {
|
|
81
|
-
showInput.value.push(evaluateValue(input.visible ?? 'true'))
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
props.uiJson.output.data.forEach((data: locApi.IUiJsonOutputData) => {
|
|
85
|
-
idToInfo[data.id] = locCommon.simulationDataInfo(instanceTask, data.name)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
vue.onMounted(() => {
|
|
89
|
-
updateUiAndSimulation()
|
|
90
|
-
|
|
91
|
-
// Determine the number of graph panel widgets (needed to set their height).
|
|
92
|
-
|
|
93
|
-
const plotsDiv = document.getElementById(plotsDivId)
|
|
94
|
-
|
|
95
|
-
plotsDiv?.style.setProperty('--graph-panel-widget-count', String(plotsDiv.children.length))
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
function updateUiAndSimulation() {
|
|
99
|
-
// Make sure that there are no issues.
|
|
100
|
-
|
|
101
|
-
if (issues.value.length > 0) {
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Show/hide the input widgets.
|
|
106
|
-
|
|
107
|
-
props.uiJson.input.forEach((input: locApi.IUiJsonInput, index: number) => {
|
|
108
|
-
showInput.value[index] = evaluateValue(input.visible ?? 'true')
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
// Update the SED-ML document.
|
|
112
|
-
|
|
113
|
-
model.removeAllChanges()
|
|
114
|
-
|
|
115
|
-
props.uiJson.parameters.forEach((parameter: locApi.IUiJsonParameter) => {
|
|
116
|
-
const componentVariableNames = parameter.name.split('/')
|
|
117
|
-
|
|
118
|
-
model.addChange(componentVariableNames[0], componentVariableNames[1], String(evaluateValue(parameter.value)))
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
// Run the instance and update the plots.
|
|
122
|
-
|
|
123
|
-
instance.run()
|
|
124
|
-
|
|
125
|
-
const parser = math.parser()
|
|
126
|
-
|
|
127
|
-
props.uiJson.output.data.forEach((data: locApi.IUiJsonOutputData) => {
|
|
128
|
-
parser.set(data.id, locCommon.simulationData(instanceTask, idToInfo[data.id]))
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
plots.value = props.uiJson.output.plots.map((plot: locApi.IUiJsonOutputPlot) => {
|
|
132
|
-
return [
|
|
133
|
-
{
|
|
134
|
-
x: { data: parser.evaluate(plot.xValue) },
|
|
135
|
-
y: { data: parser.evaluate(plot.yValue) }
|
|
136
|
-
}
|
|
137
|
-
]
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
</script>
|
|
141
|
-
|
|
142
|
-
<style scoped>
|
|
143
|
-
.graph-panel-widget {
|
|
144
|
-
height: calc(100% / var(--graph-panel-widget-count));
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.div-simulation-only {
|
|
148
|
-
height: var(--block-ui-height);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.div-simulation {
|
|
152
|
-
height: calc(var(--block-ui-height) - var(--main-menu-height) - var(--file-tablist-height));
|
|
153
|
-
}
|
|
154
|
-
</style>
|