Skip to content

Commit

Permalink
add selection mode single as default
Browse files Browse the repository at this point in the history
  • Loading branch information
Korbinian Eckstein committed Jan 28, 2024
1 parent 391a306 commit f5a3a2a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 26 deletions.
11 changes: 9 additions & 2 deletions niivue/src/components/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ export const App = () => {
<//>
`
}

export const enum SelectionMode {
NONE,
SINGLE,
MULTIPLE,
}

export interface AppProps {
nvArray: Signal<ExtendedNiivue[]>
selection: Signal<Array<number>>
selectionMode: Signal<number>
selectionMode: Signal<SelectionMode>
hideUI: Signal<number>
sliceType: Signal<number>
location: Signal<string>
Expand All @@ -44,7 +51,7 @@ function useAppState(): AppProps {
return {
nvArray: useSignal<ExtendedNiivue[]>([]),
selection: useSignal<Array<number>>([]),
selectionMode: useSignal(0),
selectionMode: useSignal(SelectionMode.NONE),
hideUI: useSignal(3), // 0: hide all, 1: show name, 2: hide overlay, 3: show-all
sliceType: useSignal<number>(SLICE_TYPE.MULTIPLANAR), // all views
location: useSignal(''),
Expand Down
47 changes: 33 additions & 14 deletions niivue/src/components/Menu.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { html } from 'htm/preact'
import { AppProps } from './App'
import { Signal, computed, effect, useSignal } from '@preact/signals'
import { addDcmFolderEvent, addImagesEvent, addOverlayEvent, openImageFromURL } from '../events'
import { SLICE_TYPE } from '@niivue/niivue'
import { AppProps, SelectionMode } from './App'
import { ScalingBox } from './ScalingBox'
import { getMetadataString, getNumberOfPoints } from '../utility'
import {
addDcmFolderEvent,
addImagesEvent,
addOverlayEvent,
openImageFromURL,
ExtendedNiivue,
} from '../events'
import {
HeaderDialog,
ImageSelect,
Expand All @@ -14,7 +20,6 @@ import {
ToggleEntry,
toggle,
} from './MenuElements'
import { ExtendedNiivue } from '../events'

export const Menu = (props: AppProps) => {
const { selection, selectionMode, nvArray, sliceType, hideUI } = props
Expand All @@ -28,12 +33,14 @@ export const Menu = (props: AppProps) => {
const crosshair = useSignal(true)
const radiologicalConvention = useSignal(false)
const colorbar = useSignal(false)
const selectionActive = useSignal(false)
const selectMultiple = useSignal(false)

// Computed
const isOverlay = computed(() => nvArraySelected.value[0]?.volumes?.length > 1)
const multipleVolumes = computed(() => nvArray.value.length > 1)
const nvArraySelected = computed(() =>
selectionMode.value > 0 && selection.value.length > 0
selectionMode.value != SelectionMode.NONE && selection.value.length > 0
? nvArray.value.filter((_, i) => selection.value.includes(i))
: nvArray.value,
)
Expand All @@ -55,7 +62,8 @@ export const Menu = (props: AppProps) => {
})

// Effects that occur when state or computed changes
effect(() => ensureAlwaysSelectedAvailable(selection, nvArray, selectionMode))
effect(() => applySelectionModeChange(selectionMode, selectionActive, selectMultiple))
effect(() => ensureValidSelection(selection, nvArray, selectionMode))
effect(() => applyInterpolation(nvArray, interpolation))
effect(() => applyCrosshairWidth(nvArray, crosshair))
effect(() => applyRadiologicalConvention(nvArray, radiologicalConvention))
Expand Down Expand Up @@ -147,6 +155,7 @@ export const Menu = (props: AppProps) => {
}

const selectAll = () => {
selectMultiple.value = true
selection.value = nvArray.value.map((_, i) => i)
}

Expand Down Expand Up @@ -219,7 +228,8 @@ export const Menu = (props: AppProps) => {
console.log('Not implemented yet')} /> -->
<${MenuEntry} label="Set Headers to 1" onClick=${setVoxelSize1AndOrigin0} />
</${MenuItem}>
<${ImageSelect} label="Select" state=${selectionMode} visible=${multipleVolumes}>
<${ImageSelect} label="Select" state=${selectionActive} visible=${multipleVolumes}>
<${ToggleEntry} label="Multiple" state=${selectMultiple} />
<${MenuEntry} label="Select All" onClick=${selectAll} />
</${ImageSelect}>
</div>
Expand All @@ -235,17 +245,26 @@ export const Menu = (props: AppProps) => {
`
}

function ensureAlwaysSelectedAvailable(
function applySelectionModeChange(
selectionMode: Signal<SelectionMode>,
selectionActive: Signal<boolean>,
selectMultiple: Signal<boolean>,
) {
if (!selectionActive.value) selectionMode.value = SelectionMode.NONE
else if (selectMultiple.value) selectionMode.value = SelectionMode.MULTIPLE
else selectionMode.value = SelectionMode.SINGLE
}

function ensureValidSelection(
selection: Signal<number[]>,
nvArray: Signal<ExtendedNiivue[]>,
selectionMode: Signal<number>,
selectionMode: Signal<SelectionMode>,
) {
if (selection.value.length == 0 && nvArray.value.length > 0) {
if (selectionMode.value == 1) {
selection.value = [0]
} else {
selection.value = nvArray.value.map((_, i) => i)
}
if (nvArray.value.length == 0) return
else if (selectionMode.value == SelectionMode.SINGLE && selection.value.length != 1)
selection.value = [0]
else if (selectionMode.value == SelectionMode.MULTIPLE && selection.value.length == 0) {
selection.value = nvArray.value.map((_, i) => i)
}
}

Expand Down
5 changes: 4 additions & 1 deletion niivue/src/components/MenuElements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ export const ImageSelect = ({ label, state, children, visible }: any) => {
</button>
<button
class="hover:bg-gray-700 pr-2 rounded-r-md h-6 align-middle"
onClick=${toggle(isOpen)}
onClick=${() => {
toggle(isOpen)()
state.value = true
}}
>
<${DownArrow} />
</button>
Expand Down
20 changes: 11 additions & 9 deletions niivue/src/components/Volume.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { html } from 'htm/preact'
import { NiiVueCanvas } from './NiiVueCanvas'
import { computed, useSignal } from '@preact/signals'
import { AppProps } from './App'
import { AppProps, SelectionMode } from './App'
import { ExtendedNiivue } from '../events'

export interface VolumeProps {
Expand All @@ -20,15 +20,17 @@ export const Volume = (props: AppProps & VolumeProps) => {
const selected = computed(() => selection.value.includes(volumeIndex))

// it would maybe need a invisible box over the volume to prevent the click event, stopPropagation and preventDefault don't work
const selectClick = selectionMode.value
? () => {
if (selected.value) {
selection.value = selection.value.filter((i) => i != volumeIndex)
} else {
selection.value = [...selection.value, volumeIndex]
}
const selectClick = () => {
if (selectionMode.value == SelectionMode.SINGLE) {
selection.value = [volumeIndex]
} else if (selectionMode.value == SelectionMode.MULTIPLE) {
if (selected.value) {
selection.value = selection.value.filter((i) => i != volumeIndex)
} else {
selection.value = [...selection.value, volumeIndex]
}
: () => {}
}
}

const nextVolume = () => {
const currentVol = nv.volumes[0].frame4D
Expand Down

0 comments on commit f5a3a2a

Please sign in to comment.