diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html index 65bd7abfbf9c02838ad6b5704cbcaaf88ef966e1..cdd41d6c245ea567d49cd90eddedd8315e75d443 100644 --- a/src/atlasViewer/atlasViewer.template.html +++ b/src/atlasViewer/atlasViewer.template.html @@ -182,7 +182,7 @@ #iavMouseHoverConetxtualBlock="iavMouseHover" contextualBlock> - <ng-container *ngFor="let labelText of iavMouseHoverConetxtualBlock.currentOnHoverObs$ | async | mouseOverTextPipe"> + <ng-container *ngFor="let labelText of iavMouseHoverConetxtualBlock.currentOnHoverObs$ | async | mouseOverTextPipe : selectedParcellation"> <mat-list dense> diff --git a/src/atlasViewer/onhoverSegment.pipe.ts b/src/atlasViewer/onhoverSegment.pipe.ts index 9119b115f7595ac1d412d6c9728803cd79c0745f..640772c63ddc32876f38e8ac708bcf3130d5f73b 100644 --- a/src/atlasViewer/onhoverSegment.pipe.ts +++ b/src/atlasViewer/onhoverSegment.pipe.ts @@ -10,13 +10,17 @@ export class TransformOnhoverSegmentPipe implements PipeTransform{ } + private sanitizeHtml(inc:string):SafeHtml{ + return this.sanitizer.sanitize(SecurityContext.HTML, inc) + } + private getStatus(text:string) { - return ` <span class="text-muted">(${this.sanitizer.sanitize(SecurityContext.HTML, text)})</span>` + return ` <span class="text-muted">(${this.sanitizeHtml(text)})</span>` } public transform(segment: any | number): SafeHtml{ return this.sanitizer.bypassSecurityTrustHtml(( - (segment.name || segment) + + ( this.sanitizeHtml(segment.name) || segment) + (segment.status ? this.getStatus(segment.status) : '') diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index 5b0b0a25baaf8e2941753742b455d40d0892bd8b..b7ac08924c4523515e4c680ef2b0e3540d5e26b3 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -606,11 +606,6 @@ mat-icon[fontset="far"] outline: none!important; } -.font-2x -{ - font-size: 200%; -} - .no-max-width { max-width: none!important; diff --git a/src/res/ext/MNI152.json b/src/res/ext/MNI152.json index a44f6b36aa9cceecf4b885409fe664c2433ecaea..a0a752dfc28b7c667c4531d60f1e0246ff76531d 100644 --- a/src/res/ext/MNI152.json +++ b/src/res/ext/MNI152.json @@ -9,6 +9,7 @@ { "name": "JuBrain Cytoarchitectonic Atlas", "ngId": "jubrain v17 left", + "auxillaryMeshIndices": [ 65535 ], "originDatasets":[{ "kgSchema": "minds/core/dataset/v1.0.0", "kgId": "4ac9f0bc-560d-47e0-8916-7b24da9bb0ce" @@ -5734,6 +5735,7 @@ }, { "ngId": "fibre bundle long", + "auxillaryMeshIndices": [ 65535 ], "type": "parcellation", "surfaceParcellation": true, "ngData": null, @@ -6005,6 +6007,7 @@ }, { "ngId": "fibre bundle short", + "auxillaryMeshIndices": [ 65535 ], "type": "parcellation", "surfaceParcellation": true, "ngData": null, diff --git a/src/res/ext/colin.json b/src/res/ext/colin.json index c1404ab4d3909dbeb6f69a79558d0318775f08e7..b4c761e687031a9a417ab7320fabc7e481b11e32 100644 --- a/src/res/ext/colin.json +++ b/src/res/ext/colin.json @@ -9,6 +9,7 @@ { "name": "JuBrain Cytoarchitectonic Atlas", "ngId": "jubrain colin v17 left", + "auxillaryMeshIndices": [ 65535 ], "originDatasets":[{ "kgSchema": "minds/core/dataset/v1.0.0", "kgId": "4ac9f0bc-560d-47e0-8916-7b24da9bb0ce" diff --git a/src/ui/databrowserModule/databrowser/databrowser.template.html b/src/ui/databrowserModule/databrowser/databrowser.template.html index 10147fe43734cc11d061f4b8a7cf0d627565dc96..733920c7961b66dc4b856cc7bb7597f0219f5457 100644 --- a/src/ui/databrowserModule/databrowser/databrowser.template.html +++ b/src/ui/databrowserModule/databrowser/databrowser.template.html @@ -110,32 +110,31 @@ <mat-expansion-panel-header class="align-items-center"> <mat-panel-title class="d-inline-flex align-items-center"> - Filter - </mat-panel-title> - - <mat-panel-description class="d-flex flex-row justify-content-end align-items-center"> - - <small *ngIf="dataentries.length > 0" class="text-muted mr-2"> - <ng-template [ngIf]="modalityPickerCmp && modalityPickerCmp.checkedModality.length > 0" - [ngIfElse]="noFilterTmpl"> - {{ (dataentries | filterDataEntriesByMethods : visibleCountedDataM).length }} / {{ dataentries.length }} - </ng-template> - - <ng-template #noFilterTmpl> - {{ dataentries.length }} datasets - </ng-template> - </small> + <div class="flex-grow-1 flex-shrink-1 d-flex flex-column"> + <span> + Related datasets + </span> + <small *ngIf="dataentries.length > 0" class="text-muted"> + <ng-template [ngIf]="modalityPickerCmp && modalityPickerCmp.checkedModality.length > 0" + [ngIfElse]="noFilterTmpl"> + {{ (dataentries | filterDataEntriesByMethods : visibleCountedDataM).length }} filtered / {{ dataentries.length }} datasets + </ng-template> + + <ng-template #noFilterTmpl> + {{ dataentries.length }} datasets + </ng-template> + </small> + </div> <button mat-icon-button - matTooltip="Clear filters" - iav-stop="mousedown click" + [matTooltip]="visibleCountedDataM.length > 0 ? 'Reset filters' : null" iav-delay-event="click" - (delayedEmit)="modalityPickerCmp && modalityPickerCmp.clearAll()" - *ngIf="modalityPickerCmp.checkedModality.length > 0" - color="primary"> - <i class="fas fa-backspace"></i> + (delayedEmit)="visibleCountedDataM.length > 0 ? clearAll() : null" + [iav-stop]="visibleCountedDataM.length > 0 ? 'click' : null" + [color]="visibleCountedDataM.length > 0 ? 'primary' : 'basic'"> + <i class="fas fa-filter"></i> </button> - </mat-panel-description> + </mat-panel-title> </mat-expansion-panel-header> diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html index 6357c153788073facc9282a2c0a8c0397bd6d74e..ee562aba48d6b0c6e301d36c63a4dc074c9a785b 100644 --- a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html +++ b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html @@ -1,16 +1,14 @@ <mat-card mat-ripple [matRippleDisabled]="!ripple"> <!-- title --> - <mat-card-header *ngIf="!simpleMode"> - <mat-card-title> - {{ name }} - </mat-card-title> - </mat-card-header> + <mat-card-subtitle *ngIf="!simpleMode"> + {{ name }} + </mat-card-subtitle> <mat-card-content *ngIf="simpleMode"> - <p> + <small> {{ name }} - </p> + </small> <mat-grid-list [cols]="kgReference.length + (preview ? 1 : 0) + (downloadEnabled ? 2 : 0)" rowHeight="4em"> <!-- explore --> @@ -64,7 +62,7 @@ <!-- description --> <mat-card-content *ngIf="!simpleMode"> - <p>{{ description }}</p> + <small>{{ description }}</small> </mat-card-content> <!-- publications --> diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts index 4d941cdbb4ff525a642de17fbe28dce7b2302ec6..aa78bdeebfbe5fd8e709ef5d871beaf23c17c9da 100644 --- a/src/ui/nehubaContainer/nehubaContainer.component.ts +++ b/src/ui/nehubaContainer/nehubaContainer.component.ts @@ -13,10 +13,8 @@ import { NEHUBA_READY, H_ONE_THREE, V_ONE_THREE, FOUR_PANEL, SINGLE_PANEL, NG_VI import { MOUSE_OVER_SEGMENTS } from "src/services/state/uiState.store"; import { getHorizontalOneThree, getVerticalOneThree, getFourPanel, getSinglePanel } from "./util"; import { SELECT_REGIONS_WITH_ID, NEHUBA_LAYER_CHANGED, VIEWERSTATE_ACTION_TYPES } from "src/services/state/viewerState.store"; -import { MatBottomSheet, MatButton } from "@angular/material"; -import { DATASETS_ACTIONS_TYPES } from "src/services/state/dataStore.store"; +import { MatBottomSheet } from "@angular/material"; import { KgSingleDatasetService } from "../databrowserModule/kgSingleDatasetService.service"; -import { getIdFromDataEntry } from "../databrowserModule/databrowser.service"; const getProxyUrl = (ngUrl) => `nifti://${BACKEND_URL}preview/file?fileUrl=${encodeURIComponent(ngUrl.replace(/^nifti:\/\//,''))}` const getProxyOther = ({source}) => /AUTH_227176556f3c4bb38df9feea4b91200c/.test(source) @@ -952,6 +950,7 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy{ this.multiNgIdsRegionsLabelIndexMap = getMultiNgIdsRegionsLabelIndexMap(parcellation) this.nehubaViewer.multiNgIdsLabelIndexMap = this.multiNgIdsRegionsLabelIndexMap + this.nehubaViewer.auxilaryMeshIndices = parcellation.auxillaryMeshIndices || [] /* TODO replace with proper KG id */ /** diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts index 3d86c2cfe5915ad9959032433c08099d164f6fbf..5a5ec2d04f0e9102a1782dd01236762c81df35fc 100644 --- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts +++ b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts @@ -64,6 +64,8 @@ export class NehubaViewerUnit implements OnInit, OnDestroy{ @Output() regionSelectionEmitter : EventEmitter<{segment:number, layer:{name?: string, url?: string}}> = new EventEmitter() @Output() errorEmitter : EventEmitter<any> = new EventEmitter() + public auxilaryMeshIndices: number[] = [] + /* only used to set initial navigation state */ initNav : any initRegions : any[] @@ -818,7 +820,7 @@ export class NehubaViewerUnit implements OnInit, OnDestroy{ const indicies = [ ...Array.from(this.multiNgIdsLabelIndexMap.get(id).keys()), - ...getAuxilliaryLabelIndices() + ...this.auxilaryMeshIndices ] this.loadMeshes(indicies, { name: id }) @@ -830,8 +832,8 @@ export class NehubaViewerUnit implements OnInit, OnDestroy{ new Map(Array.from( [ ...this.multiNgIdsLabelIndexMap.get(ngId).entries(), - ...getAuxilliaryLabelIndices().map(i => { - return [i, {}] + ...this.auxilaryMeshIndices.map(val => { + return [val, {}] }) ] ).map((val:[number,any])=>([val[0],this.getRgb(val[0],val[1].rgb)])) as any) @@ -942,11 +944,6 @@ export interface ViewerState{ zoom : number } -export function getAuxilliaryLabelIndices(){ - return [65535] - // return Array.from(Array(36)).map((_,i)=>65500+i) -} - export const ICOSAHEDRON = `# vtk DataFile Version 2.0 Converted using https://github.com/HumanBrainProject/neuroglancer-scripts ASCII diff --git a/src/ui/nehubaContainer/statusCard/statusCard.template.html b/src/ui/nehubaContainer/statusCard/statusCard.template.html index d26e90e06c6116184a518398365932abeceb401e..9ccb604a3909ac6c06e0a73a12b79f1fa9106277 100644 --- a/src/ui/nehubaContainer/statusCard/statusCard.template.html +++ b/src/ui/nehubaContainer/statusCard/statusCard.template.html @@ -1,62 +1,56 @@ <div statusCard> + <div linksContainer> + <span> + reset: + </span> + <a + href="#" + (click)="$event.preventDefault();resetNavigation({position:true})"> + position + </a> - <div> - <layer-browser #layerBrowser> - </layer-browser> - </div> + <a + href="#" + (click)="$event.preventDefault();resetNavigation({rotation:true})"> + rotation + </a> - <div linksContainer> - <span> - reset: - </span> - <a - href="#" - (click)="$event.preventDefault();resetNavigation({position:true})"> - position - </a> + <a + href="#" + (click)="$event.preventDefault();resetNavigation({zoom:true})"> + zoom + </a> - <a - href="#" - (click)="$event.preventDefault();resetNavigation({rotation:true})"> - rotation - </a> + <br /> + <span> + space: + </span> + + <a href="#" (click)="$event.preventDefault();statusPanelRealSpace=!statusPanelRealSpace"> + {{statusPanelRealSpace ? 'physical' : 'voxel'}} + </a> - <a - href="#" - (click)="$event.preventDefault();resetNavigation({zoom:true})"> - zoom - </a> + </div> - <br /> - <span> - space: - </span> - - <a href="#" (click)="$event.preventDefault();statusPanelRealSpace=!statusPanelRealSpace"> - {{statusPanelRealSpace ? 'physical' : 'voxel'}} - </a> - - </div> + <br /> + <div textContainer> + <small>Navigation: </small> + <input + (keydown.enter)="textNavigateTo(navigateInput.value)" + (keydown.tab)="textNavigateTo(navigateInput.value)" + [ngModel]="navigationValue()" + spellcheck="false" + #navigateInput + navigateInput/> <br /> - <div textContainer> - <small>Navigation: </small> - <input - (keydown.enter)="textNavigateTo(navigateInput.value)" - (keydown.tab)="textNavigateTo(navigateInput.value)" - [ngModel]="navigationValue()" - spellcheck="false" - #navigateInput - navigateInput/> - - <br /> - <small *ngIf="!isMobile">Mouse: </small> - <small *ngIf="!isMobile"> - {{ mouseCoord }} - </small> - <br *ngIf="!isMobile" /> - <small onHoverSegment> - {{ onHoverSegmentName }} - </small> - </div> + <small *ngIf="!isMobile">Mouse: </small> + <small *ngIf="!isMobile"> + {{ mouseCoord }} + </small> + <br *ngIf="!isMobile" /> + <small onHoverSegment> + {{ onHoverSegmentName }} + </small> </div> +</div> diff --git a/src/ui/searchSideNav/searchSideNav.style.css b/src/ui/searchSideNav/searchSideNav.style.css index 0e8a183c297a23062a4367233ef7429dd5469e69..9cacc7579319e32ff43c04793d4cd5ace7deb6b1 100644 --- a/src/ui/searchSideNav/searchSideNav.style.css +++ b/src/ui/searchSideNav/searchSideNav.style.css @@ -1,6 +1,6 @@ .region-wrapper { - height:78px; + height: 55px; } /* exactly 1.5 line height */ @@ -9,3 +9,10 @@ { min-height:117px!important; } + +.mat-divider-full-width +{ + margin-right:-1.5rem; + margin-left:-1.5rem; + width: calc(100% + 3rem); +} diff --git a/src/ui/searchSideNav/searchSideNav.template.html b/src/ui/searchSideNav/searchSideNav.template.html index 93fb21bb0aa479d2f1999cd70302d09553414c1d..45d7d8f7422c467488aa58326722218043c1c42e 100644 --- a/src/ui/searchSideNav/searchSideNav.template.html +++ b/src/ui/searchSideNav/searchSideNav.template.html @@ -25,71 +25,6 @@ <ng-container *ngIf="showDataset"> - <!-- selected regions container --> - <mat-card *ngIf="false && viewerStateController.regionsSelected$ | async as regionsSelected" - [ngClass]="{'h-117px flex-grow-1': regionsSelected.length > 1, 'flex-grow-0': regionsSelected.length < 2}" - class="flex-shrink-0 mb-1 pe-all"> - - <!-- show when no region is selected --> - <mat-card-content *ngIf="regionsSelected.length === 0"> - <div class="pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> - <i *ngIf="false" class="fas fa-brain font-2x mr-2"></i> - - <span class="font-weight-bold"> - In this parcellation atlas - </span> - </div> - </mat-card-content> - - <!-- show when regions are selected --> - <mat-card-content *ngIf="regionsSelected.length > 0" class="h-100"> - - <!-- single region --> - <ng-template [ngIf]="regionsSelected.length === 1" [ngIfElse]="multiRegionTemplate"> - - <!-- selected brain region --> - <div class="pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> - <i class="fas fa-brain font-2x mr-2"></i> - - <span class="font-weight-bold"> - {{ regionsSelected[0].name }} - </span> - - <button (click)="removeRegion(regionsSelected[0])" mat-icon-button> - <i class="fas fa-trash"></i> - </button> - </div> - </ng-template> - - <!-- multi region --> - <ng-template #multiRegionTemplate> - <cdk-virtual-scroll-viewport class="h-100" itemSize="78"> - <div *cdkVirtualFor="let region of regionsSelected; trackBy: trackByFn ; let index = index" - class="region-wrapper d-flex flex-column" > - <!-- divider if index !== 0 --> - <mat-divider class="flex-grow-0 flex-shrink-0" *ngIf="index !== 0"></mat-divider> - - <!-- selected brain region --> - <div class="flex-grow-1 flex-shrink-1 pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> - <i class="flex-grow-0 flex-shrink-0 fas fa-brain font-2x mr-2"></i> - - <span class="flex-grow-1 flex-shrink-1 font-weight-bold"> - {{ region.name }} - </span> - - <button mat-icon-button - class="flex-grow-0 flex-shrink-0" - (click)="removeRegion(region)" > - <i class="fas fa-trash"></i> - </button> - </div> - </div> - </cdk-virtual-scroll-viewport> - </ng-template> - - </mat-card-content> - </mat-card> - <data-browser class="pe-all flex-grow-5 flex-shrink-1" [template]="viewerStateController.templateSelected$ | async" @@ -102,12 +37,7 @@ </ng-container> - <mat-divider class="mt-2 mb-4 position-relative"></mat-divider> - - <mat-card-subtitle card-header> - Related datasets - </mat-card-subtitle> - + <mat-divider class="position-relative mt-2 mb-2 mat-divider-full-width"></mat-divider> </ng-container> <!-- footer content --> @@ -154,14 +84,13 @@ <!-- show when no region is selected --> <div *ngIf="regionsSelected.length === 0" class="pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> - <i *ngIf="false" class="fas fa-brain font-2x mr-2"></i> + <i *ngIf="false" class="fas fa-brain mr-2"></i> - <span class="font-weight-bold"> + <small> In this parcellation atlas - </span> + </small> </div> - <!-- show when regions are selected --> <div *ngIf="regionsSelected.length > 0" class="h-100"> @@ -170,11 +99,11 @@ <!-- selected brain region --> <div class="pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> - <i class="fas fa-brain font-2x mr-2"></i> + <i class="fas fa-brain mr-2"></i> - <span class="font-weight-bold"> + <small> {{ regionsSelected[0].name }} - </span> + </small> <button (click)="removeRegion(regionsSelected[0])" mat-icon-button> <i class="fas fa-trash"></i> @@ -184,7 +113,7 @@ <!-- multi region --> <ng-template #multiRegionTemplate> - <cdk-virtual-scroll-viewport class="h-100" itemSize="78"> + <cdk-virtual-scroll-viewport class="h-100" itemSize="55"> <div *cdkVirtualFor="let region of regionsSelected; trackBy: trackByFn ; let index = index" class="region-wrapper d-flex flex-column" > <!-- divider if index !== 0 --> @@ -192,11 +121,11 @@ <!-- selected brain region --> <div class="flex-grow-1 flex-shrink-1 pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> - <i class="flex-grow-0 flex-shrink-0 fas fa-brain font-2x mr-2"></i> + <i class="flex-grow-0 flex-shrink-0 fas fa-brain mr-2"></i> - <span class="flex-grow-1 flex-shrink-1 font-weight-bold"> + <small class="flex-grow-1 flex-shrink-1 "> {{ region.name }} - </span> + </small> <button mat-icon-button class="flex-grow-0 flex-shrink-0" diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.component.ts b/src/ui/viewerStateController/regionSearch/regionSearch.component.ts index d68c6e5d63b10a3cdfd3c267fad3ccadf57be0c5..fb0e259472c064cb64e322fa436f584d60a3acf7 100644 --- a/src/ui/viewerStateController/regionSearch/regionSearch.component.ts +++ b/src/ui/viewerStateController/regionSearch/regionSearch.component.ts @@ -1,10 +1,10 @@ -import { Component, EventEmitter, Output, ViewChild, ElementRef, TemplateRef, Input } from "@angular/core"; +import { Component, EventEmitter, Output, ViewChild, ElementRef, TemplateRef, Input, ChangeDetectionStrategy } from "@angular/core"; import { Store, select } from "@ngrx/store"; -import { Observable, BehaviorSubject } from "rxjs"; -import { map, distinctUntilChanged, startWith, withLatestFrom, debounceTime, shareReplay, take, filter, tap } from "rxjs/operators"; +import { Observable } from "rxjs"; +import { map, distinctUntilChanged, startWith, withLatestFrom, debounceTime, shareReplay, take, tap } from "rxjs/operators"; import { getMultiNgIdsRegionsLabelIndexMap, generateLabelIndexId } from "src/services/stateStore.service"; import { FormControl } from "@angular/forms"; -import { MatAutocompleteSelectedEvent, MatDialog } from "@angular/material"; +import { MatAutocompleteSelectedEvent, MatDialog, AUTOCOMPLETE_OPTION_HEIGHT, AUTOCOMPLETE_PANEL_HEIGHT } from "@angular/material"; import { ADD_TO_REGIONS_SELECTION_WITH_IDS, SELECT_REGIONS, CHANGE_NAVIGATION } from "src/services/state/viewerState.store"; import { VIEWERSTATE_CONTROLLER_ACTION_TYPES } from "../viewerState.base"; import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service"; @@ -17,7 +17,8 @@ const filterRegionBasedOnText = searchTerm => region => region.name.toLowerCase( templateUrl: './regionSearch.template.html', styleUrls: [ './regionSearch.style.css' - ] + ], + changeDetection: ChangeDetectionStrategy.OnPush }) export class RegionTextSearchAutocomplete{ @@ -30,9 +31,6 @@ export class RegionTextSearchAutocomplete{ public useMobileUI$: Observable<boolean> - private focusedRegionId$: BehaviorSubject<string> = new BehaviorSubject(null) - public focusedRegion$: Observable<any> - public selectedRegionLabelIndexSet: Set<string> = new Set() constructor( @@ -69,16 +67,9 @@ export class RegionTextSearchAutocomplete{ shareReplay(1) ) - this.focusedRegion$ = this.focusedRegionId$.pipe( - withLatestFrom(this.regionsWithLabelIndex$), - map(([ id, regions ]) => { - if (!id) return null - return regions.find(({ labelIndexId }) => labelIndexId === id) - }) - ) - this.autocompleteList$ = this.formControl.valueChanges.pipe( startWith(''), + distinctUntilChanged(), debounceTime(200), withLatestFrom(this.regionsWithLabelIndex$.pipe( startWith([]) @@ -131,13 +122,6 @@ export class RegionTextSearchAutocomplete{ public optionSelected(ev: MatAutocompleteSelectedEvent){ const id = ev.option.value this.autoTrigger.nativeElement.value = '' - this.focusedRegionId$.next(id) - } - - public openRegionFocusDialog(tmpl:TemplateRef<any>){ - this.dialog.open(tmpl).afterClosed().subscribe(() => { - this.autoTrigger.nativeElement.focus() - }) } private regionsWithLabelIndex$: Observable<any[]> @@ -184,7 +168,13 @@ export class RegionTextSearchAutocomplete{ // mat-card-content has a max height of 65vh const dialog = this.dialog.open(this.regionHierarchyDialogTemplate, { height: '65vh', - width: '90vw' + panelClass: [ + 'col-10', + 'col-sm-10', + 'col-md-8', + 'col-lg-8', + 'col-xl-6' + ] }) /** diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.style.css b/src/ui/viewerStateController/regionSearch/regionSearch.style.css index 17cda15a41ee862383f3f4e802121021525894f9..697cf662c0ed5ca19e9ccce62972112a79905000 100644 --- a/src/ui/viewerStateController/regionSearch/regionSearch.style.css +++ b/src/ui/viewerStateController/regionSearch/regionSearch.style.css @@ -1,4 +1,9 @@ region-hierarchy { height: 100%; -} \ No newline at end of file +} + +.regionAutocompleteOption +{ + height:38px; +} diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.template.html b/src/ui/viewerStateController/regionSearch/regionSearch.template.html index b8bacd2acc6ebdde5811c577d86466a8786cfaac..59e9a2060832fbb49b661fd14827580bd0da1044 100644 --- a/src/ui/viewerStateController/regionSearch/regionSearch.template.html +++ b/src/ui/viewerStateController/regionSearch/regionSearch.template.html @@ -14,13 +14,43 @@ <mat-autocomplete (opened)="focused = true" (closed)="focused = false" - (optionSelected)="optionSelected($event); openRegionFocusDialog(regionFocusDialog)" + panelWidth="auto" + (optionSelected)="optionSelected($event)" autoActiveFirstOption #auto="matAutocomplete"> <mat-option + class="regionAutocompleteOption" *ngFor="let region of autocompleteList$ | async" [value]="region.labelIndexId"> - {{ region.name }} + + <div class="d-flex flex-row"> + + <small class="text-truncate flex-shrink-1 flex-grow-1"> + {{ region.name }} + </small> + + <div class="flex-grow-0 flex-shrink-0 d-flex flex-row"> + + <!-- if has position defined --> + <button *ngIf="region.position" + iav-stop="click" + (click)="navigateTo(region.position)" + mat-icon-button> + <i class="fas fa-map-marked-alt"></i> + </button> + + <!-- region selected --> + <button mat-icon-button + iav-stop="click" + (click)="toggleRegionWithId(region.labelIndexId, selectedRegionLabelIndexSet.has(region.labelIndexId))" + [color]="selectedRegionLabelIndexSet.has(region.labelIndexId) ? 'primary' : 'basic'"> + <i class="far" + [ngClass]="{'fa-check-square': selectedRegionLabelIndexSet.has(region.labelIndexId), 'fa-square': !selectedRegionLabelIndexSet.has(region.labelIndexId)}"> + </i> + </button> + </div> + + </div> </mat-option> </mat-autocomplete> </form> @@ -36,41 +66,6 @@ </button> </div> -<ng-template #regionFocusDialog> - <ng-container *ngIf="focusedRegion$ | async as focusedRegion; else noRegionSelected"> - <div mat-dialog-title> - {{ focusedRegion.name }} - </div> - <div class="justify-content-end" mat-dialog-actions> - <button mat-flat-button - *ngIf="focusedRegion.position" - (click)="navigateTo(focusedRegion.position)" - mat-dialog-close - class="ml-1" - color="primary"> - Navigate - </button> - <button mat-flat-button - *ngIf="focusedRegion.labelIndexId" - mat-dialog-close - (click)="toggleRegionWithId(focusedRegion.labelIndexId, selectedRegionLabelIndexSet.has(focusedRegion.labelIndexId))" - class="ml-1" - [color]="selectedRegionLabelIndexSet.has(focusedRegion.labelIndexId) ? 'warn' : 'primary'"> - {{ selectedRegionLabelIndexSet.has(focusedRegion.labelIndexId) ? 'Remove from selection' : 'Add to selection' }} - </button> - <button mat-button - [mat-dialog-close]="null" - class="ml-1"> - Dismiss - </button> - </div> - </ng-container> - - <ng-template #noRegionSelected> - No region selected. - </ng-template> -</ng-template> - <ng-template #regionHierarchyDialog> <div class="h-100 d-flex flex-column"> <mat-dialog-content class="flex-grow-1 flex-shrink-1"> diff --git a/src/ui/viewerStateController/regionsListView/simpleRegionsListView/regionListView.template.html b/src/ui/viewerStateController/regionsListView/simpleRegionsListView/regionListView.template.html index beb854bc7e2e05eacdb833760be1d71e0bfaec8c..82f37f44b76aae6af087a2714eef32d241186f01 100644 --- a/src/ui/viewerStateController/regionsListView/simpleRegionsListView/regionListView.template.html +++ b/src/ui/viewerStateController/regionsListView/simpleRegionsListView/regionListView.template.html @@ -10,10 +10,11 @@ TODO check if this can be achieved with detach/attach --> <cdk-virtual-scroll-viewport orientation="vertical" - class="w-100 h-100" + class="w-100 h-100 overflow-hidden" itemSize="32"> <mat-chip *cdkVirtualFor="let region of regionsSelected" + [matTooltip]="region.name" class="w-100" > <span class="flex-grow-1 flex-shrink-1 text-truncate"> {{ region.name }} diff --git a/src/util/directives/delayEvent.directive.ts b/src/util/directives/delayEvent.directive.ts index 1a405b6e0e613de71dc630bdf2d349ff023b98bf..0194e0dab10d9594a4e8ecefe279afc9ac73b063 100644 --- a/src/util/directives/delayEvent.directive.ts +++ b/src/util/directives/delayEvent.directive.ts @@ -31,7 +31,9 @@ export class DelayEventDirective implements OnChanges, OnDestroy { private destroyCb: (() => void)[] = [] ngOnChanges(){ + this.ngOnDestroy() + if (!this.delayEvent || this.delayEvent === '') return const el = this.el.nativeElement as HTMLElement for (const evName of this.delayEvent.split(' ')){ if (VALID_EVENTNAMES.has(evName)) { diff --git a/src/util/directives/mouseOver.directive.ts b/src/util/directives/mouseOver.directive.ts index 24ca7ddee904b862b16396c3fd5fb18c8c6ea434..4fa1fd26aa9d319be3f32a133427ca8f30ae236d 100644 --- a/src/util/directives/mouseOver.directive.ts +++ b/src/util/directives/mouseOver.directive.ts @@ -1,9 +1,10 @@ import { Directive, Pipe, PipeTransform, SecurityContext } from "@angular/core"; import { Store, select } from "@ngrx/store"; -import { filter, distinctUntilChanged, map, shareReplay, scan, startWith } from "rxjs/operators"; +import { filter, distinctUntilChanged, map, shareReplay, scan, startWith, withLatestFrom, tap } from "rxjs/operators"; import { merge, Observable, combineLatest } from "rxjs"; import { TransformOnhoverSegmentPipe } from "src/atlasViewer/onhoverSegment.pipe"; import { SafeHtml, DomSanitizer } from "@angular/platform-browser"; +import { getNgIdLabelIndexFromId } from "src/services/stateStore.service"; /** @@ -76,6 +77,21 @@ export class MouseHoverDirective{ select('uiState'), select('mouseOverSegments'), filter(v => !!v), + withLatestFrom( + this.store$.pipe( + select('viewerState'), + select('parcellationSelected'), + startWith(null) + ) + ), + map(([ arr, parcellationSelected ]) => parcellationSelected && parcellationSelected.auxillaryMeshIndices + ? arr.filter(({ segment }) => { + // if segment is not a string (i.e., not labelIndexId) return true + if (typeof segment !== 'string') return true + const { labelIndex } = getNgIdLabelIndexFromId({ labelIndexId: segment }) + return parcellationSelected.auxillaryMeshIndices.indexOf(labelIndex) < 0 + }) + : arr), distinctUntilChanged((o, n) => o.length === n.length && n.every(segment => o.find(oSegment => oSegment.layer.name === segment.layer.name diff --git a/src/util/directives/stopPropagation.directive.ts b/src/util/directives/stopPropagation.directive.ts index a3cc308fae91e1f6cf8cf14389d7bdfb044e7b7a..6378efd89fa6360b039492af0487869ff3e8ceeb 100644 --- a/src/util/directives/stopPropagation.directive.ts +++ b/src/util/directives/stopPropagation.directive.ts @@ -29,6 +29,8 @@ export class StopPropagationDirective implements OnChanges, OnDestroy{ this.ngOnDestroy() + if (!this.stopString || this.stopString === '') return + const element = (this.el.nativeElement as HTMLElement) for (const evName of this.stopString.split(' ')){ if(VALID_EVENTNAMES.has(evName)){