Skip to content

Commit 54ad5f0

Browse files
authored
Merge pull request Kitware#479 from PaulHax/layer-names
fix(LayerProperties): handle long layer names
2 parents bf88bc2 + db6e4fe commit 54ad5f0

File tree

5 files changed

+41
-14
lines changed

5 files changed

+41
-14
lines changed

src/components/LayerList.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ export default defineComponent({
2121

2222
<template>
2323
<div class="mx-2">
24-
<layer-properties v-for="layer in layers" :key="layer.id" :layer="layer">
24+
<layer-properties
25+
v-for="layer in layers"
26+
:key="layer.id"
27+
:layer="layer"
28+
class="py-4"
29+
>
2530
</layer-properties>
2631
</div>
2732
</template>

src/components/LayerProperties.vue

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { InitViewSpecs } from '../config';
44
import { useImageStore } from '../store/datasets-images';
55
import { BlendConfig } from '../types/views';
66
import { Layer } from '../store/datasets-layers';
7-
import { useDICOMStore } from '../store/datasets-dicom';
87
import useLayerColoringStore from '../store/view-configs/layers';
8+
import { getImageID } from '../store/datasets';
99
1010
const VIEWS_2D = Object.entries(InitViewSpecs)
1111
.filter(([, { viewType }]) => viewType === '2D')
@@ -25,13 +25,9 @@ export default defineComponent({
2525
2626
const imageName = computed(() => {
2727
const { selection } = props.layer;
28-
if (selection.type === 'dicom')
29-
return useDICOMStore().volumeInfo[selection.volumeKey].Modality;
30-
if (selection.type === 'image')
31-
return imageStore.metadata[selection.dataID].name;
32-
33-
const _exhaustiveCheck: never = selection;
34-
throw new Error(`invalid selection type ${_exhaustiveCheck}`);
28+
const imageID = getImageID(selection);
29+
if (imageID === undefined) throw new Error('imageID is undefined');
30+
return imageStore.metadata[imageID].name;
3531
});
3632
3733
const layerColoringStore = useLayerColoringStore();
@@ -70,8 +66,15 @@ export default defineComponent({
7066

7167
<template>
7268
<div class="mx-2" v-if="blendConfig">
69+
<v-tooltip :text="imageName" location="top">
70+
<template v-slot:activator="{ props }">
71+
<h4 class="text-ellipsis" v-bind="props">{{ imageName }}</h4>
72+
</template>
73+
</v-tooltip>
74+
<!-- padding top so thumb value tip does not overlap image name too much -->
7375
<v-slider
74-
:label="imageName + ' Opacity'"
76+
class="pt-4"
77+
label="Opacity"
7578
min="0"
7679
max="1"
7780
step="0.01"

src/components/PatientStudyVolumeBrowser.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { computed, defineComponent, reactive, toRefs, watch } from 'vue';
33
import { Image } from 'itk-wasm';
44
import type { PropType } from 'vue';
55
import GroupableItem from '@/src/components/GroupableItem.vue';
6-
import { useDICOMStore } from '../store/datasets-dicom';
6+
import { getDisplayName, useDICOMStore } from '../store/datasets-dicom';
77
import {
88
DataSelection,
99
DICOMSelection,
@@ -104,6 +104,7 @@ export default defineComponent({
104104
// for thumbnailing
105105
cacheKey: dicomCacheKey(volumeKey),
106106
info: volumeInfo[volumeKey],
107+
name: getDisplayName(volumeInfo[volumeKey]),
107108
// for UI selection
108109
selectionKey,
109110
layerable,
@@ -300,7 +301,7 @@ export default defineComponent({
300301
class="text--primary text-caption text-center series-desc mt-n3"
301302
>
302303
<div class="text-ellipsis">
303-
{{ volume.info.SeriesDescription || '(no description)' }}
304+
{{ volume.name }}
304305
</div>
305306
</v-card-text>
306307
</v-card>

src/store/datasets-dicom.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ const readDicomTags = (dicomIO: DICOMIO, file: File) =>
101101
{ name: 'WindowWidth', tag: '0028|1051' },
102102
]);
103103

104+
/**
105+
* Trims and collapses multiple spaces into one.
106+
* @param name
107+
* @returns string
108+
*/
109+
const cleanupName = (name: string) => {
110+
return name.trim().replace(/\s+/g, ' ');
111+
};
112+
113+
export const getDisplayName = (info: VolumeInfo) => {
114+
return (
115+
cleanupName(info.SeriesDescription || info.SeriesNumber) ||
116+
info.SeriesInstanceUID
117+
);
118+
};
119+
104120
export const useDICOMStore = defineStore('dicom', {
105121
state: (): State => ({
106122
sliceData: {},

src/store/datasets.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ export type DataSelection = DICOMSelection | ImageSelection;
3434

3535
export const getImageID = (selection: DataSelection) => {
3636
if (selection.type === 'image') return selection.dataID;
37-
if (selection.type === 'dicom')
38-
return useDICOMStore().volumeToImageID[selection.volumeKey]; // volume selected, but image may not have been made yet
37+
if (selection.type === 'dicom') {
38+
// possibly undefined because image may not have been made yet
39+
return useDICOMStore().volumeToImageID[selection.volumeKey];
40+
}
3941

4042
const _exhaustiveCheck: never = selection;
4143
throw new Error(`invalid selection type ${_exhaustiveCheck}`);

0 commit comments

Comments
 (0)