this.rootWidget= c,
+ }}
/>
);
}
}
MultiImageViewer.propTypes= {
- viewerId : PropTypes.string.isRequired,
- canReceiveNewPlots : PropTypes.string,
- Toolbar : PropTypes.func,
- handleToolbar : PropTypes.bool,
- forceRowSize : PropTypes.number,
- forceColSize : PropTypes.number,
- gridDefFunc : PropTypes.func,
- insideFlex : PropTypes.bool,
- closeFunc : PropTypes.func,
- tableId : PropTypes.string,
- controlViewerMounting : PropTypes.bool
+ viewerId : string.isRequired,
+ canReceiveNewPlots : string,
+ Toolbar : func,
+ Legend : func,
+ handleToolbar : bool,
+ forceRowSize : number,
+ forceColSize : number,
+ gridDefFunc : func,
+ insideFlex : bool,
+ closeFunc : func,
+ tableId : string,
+ controlViewerMounting : bool
};
// function gridDefFunc(plotIdAry) : [ {title :string, plotId:[string]}]
diff --git a/src/firefly/js/visualize/ui/MultiImageViewerView.jsx b/src/firefly/js/visualize/ui/MultiImageViewerView.jsx
index 359e4edb01..553d82c66f 100644
--- a/src/firefly/js/visualize/ui/MultiImageViewerView.jsx
+++ b/src/firefly/js/visualize/ui/MultiImageViewerView.jsx
@@ -2,11 +2,11 @@
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
-
import {Stack} from '@mui/joy';
import React, {useRef} from 'react';
-import PropTypes from 'prop-types';
+import {object, arrayOf, bool, func, number, oneOf, string, elementType, any} from 'prop-types';
import {omit} from 'lodash';
+import {checkProps} from '../../ui/SimpleComponent';
import {SINGLE, GRID, getMultiViewRoot, getViewer} from '../MultiViewCntlr.js';
import {primePlot} from '../PlotViewUtil.js';
import {MultiItemViewerView} from './MultiItemViewerView.jsx';
@@ -29,92 +29,68 @@ function makeState() {
}
export function MultiImageViewerView(props) {
+ checkProps(props, MultiImageViewerView);
const {current:elementWrapper}= useRef({element:undefined});
const {readout, readoutData, readoutShowing}= useMouseStoreConnector(makeState);
- const {Toolbar, visRoot, viewerPlotIds=[], showWhenExpanded=false, mouseReadoutEmbedded=true,
- handleToolbar=true, layoutType=GRID, scrollGrid, viewerId, ref}= props;
+ const {Toolbar, Legend, visRoot, viewerPlotIds=[], showWhenExpanded=false, mouseReadoutEmbedded=true,
+ handleToolbar=true, layoutType=GRID, scrollGrid=false, viewerId, ref}= props;
- const viewer= getViewer(getMultiViewRoot(),viewerId);
+ const viewer= getViewer(getMultiViewRoot(),viewerId) ?? {};
const {bottomUIComponent}= viewer ?? {};
- const makeToolbar = Toolbar ? () => () : undefined;
- const makeItemViewer = (plotId) => ( );
- const makeItemViewerFull = (plotId) => ( );
+ const makeToolbar = Toolbar && (() => ());
+ const makeLegend = Legend && ((plotId) => ());
+ const makeItemViewer = (plotId) => ( );
- const doReadoutAndShowing= readoutShowing && viewerPlotIds.includes(readoutData?.plotId);
+ const newProps = {...omit(props, ['Toolbar', 'visRoot', 'viewerPlotIds', 'showWhenExpanded']),
+ activeItemId: visRoot.activePlotId, viewerItemIds: viewerPlotIds,
+ makeToolbar:handleToolbar?makeToolbar:undefined, makeItemViewer, makeItemViewerFull:makeItemViewer};
- const newProps = Object.assign(omit(props, ['Toolbar', 'visRoot', 'viewerPlotIds', 'showWhenExpanded']),
- {activeItemId: visRoot.activePlotId, viewerItemIds: viewerPlotIds,
- makeToolbar:handleToolbar?makeToolbar:undefined, makeItemViewer, makeItemViewerFull});
+ const insideStyle= props.insideFlex ? {flex:'1 1 auto', maxWidth:'100%'} : {width:'100%', height:'100%'};
+ const style= { display:'flex', flexDirection:'column', position:'relative', ...insideStyle, ...props.style };
- let style= {display:'flex', flexDirection:'column', position:'relative'};
- if (props.insideFlex) {
- style= {...style, flex:'1 1 auto', maxWidth:'100%', ...props.style};
- }
- else {
- style= {...style, width:'100%', height:'100%', ...props.style};
- }
+ const pvToUseForReadout= isLockByClick(readout) ? primePlot(visRoot) : primePlot(visRoot,lastMouseCtx().plotId);
+ const one= layoutType===SINGLE || viewerPlotIds?.length===1;
+ const sStyle= {
+ position: 'absolute',
+ left: 3,
+ bottom:one ? 2 : 3,
+ right: one ? 3 : scrollGrid? 15 : 6,
+ };
- const {readoutPref}= readoutRoot();
- const pvToUse= isLockByClick(readoutRoot()) ? primePlot(visRoot) : primePlot(visRoot,lastMouseCtx().plotId);
- const radix= getFluxRadix(readoutPref, pvToUse);
-
-
- const mouseReadout= (
-
+ return (
+ elementWrapper.element= e}>
+
+
+ {bottomUIComponent?.()}
+
+
+
);
-
- if (layoutType===SINGLE || viewerPlotIds?.length===1) {
- return (
- elementWrapper.element= e}>
-
-
- {bottomUIComponent?.()}
- {mouseReadout}
-
-
- );
- }
- else {
- return (
- elementWrapper.element= e}>
-
-
- {bottomUIComponent?.()}
- {mouseReadout}
-
-
- );
- }
}
MultiImageViewerView.propTypes= {
- visRoot : PropTypes.object,
- viewerPlotIds : PropTypes.arrayOf(PropTypes.string).isRequired,
- showWhenExpanded : PropTypes.bool,
-
- Toolbar : PropTypes.func,
- viewerId : PropTypes.string.isRequired,
- style : PropTypes.object,
- defaultDecoration : PropTypes.bool,
- layoutType : PropTypes.oneOf([GRID,SINGLE]),
- forceRowSize : PropTypes.number, //optional - force a certain number of rows
- forceColSize : PropTypes.number, //optional - force a certain number of columns
- gridDefFunc : PropTypes.func, // optional - a function to return the grid definition
- gridComponent : PropTypes.object, // a react element to define the grid - not implemented, just an idea
- insideFlex : PropTypes.bool,
- handleToolbar: PropTypes.bool,
- scrollGrid: PropTypes.bool,
- mouseReadoutEmbedded: PropTypes.bool
+ visRoot : object,
+ viewerPlotIds : arrayOf(string).isRequired,
+ showWhenExpanded : bool,
+ Toolbar : elementType,
+ Legend : elementType,
+ viewerId : string.isRequired,
+ style : object,
+ defaultDecoration : bool,
+ layoutType : oneOf([GRID,SINGLE]),
+ forceRowSize : number, //optional - force a certain number of rows
+ forceColSize : number, //optional - force a certain number of columns
+ gridDefFunc : func, // optional - a function to return the grid definition
+ gridComponent : object, // a React element to define the grid - not implemented, just an idea
+ insideFlex : bool,
+ handleToolbar: bool,
+ scrollGrid: bool,
+ mouseReadoutEmbedded: bool,
+ ref: any,
};
-
-
-
-
-
diff --git a/src/firefly/js/visualize/ui/MultiItemViewerView.jsx b/src/firefly/js/visualize/ui/MultiItemViewerView.jsx
index c55cb49192..196a31f40a 100644
--- a/src/firefly/js/visualize/ui/MultiItemViewerView.jsx
+++ b/src/firefly/js/visualize/ui/MultiItemViewerView.jsx
@@ -5,7 +5,8 @@
import {debounce} from 'lodash';
import React, {useEffect, useRef, useState} from 'react';
-import PropTypes from 'prop-types';
+import {bool, number, string, object, func, oneOf, arrayOf, any} from 'prop-types';
+import {checkProps} from '../../ui/SimpleComponent';
import {SINGLE, GRID} from '../MultiViewCntlr.js';
import {Divider, Stack} from '@mui/joy';
@@ -23,7 +24,7 @@ const defDecStyle= {
export function MultiItemViewerView(props) {
-
+ checkProps(props, MultiItemViewerView);
const {current:gridContainerElement}= useRef({element:undefined});
const [,setWindowWidth]= useState(window?.innerWidth??1000);
const {layoutType, activeItemId,
@@ -31,7 +32,6 @@ export function MultiItemViewerView(props) {
style, insideFlex=false, defaultDecoration=true, sparseGridTitleLocation= 'top',
scrollGrid=false, ref,
makeToolbar, makeItemViewer, makeItemViewerFull, autoRowOriented=true}= props;
- let wrapperStyle;
useEffect(() => {
if (!scrollGrid) return;
@@ -41,14 +41,12 @@ export function MultiItemViewerView(props) {
return () => {
window.removeEventListener('resize', browserResizeCallback);
};
- },[]);
+ },[]); // eslint-disable-line react-hooks/exhaustive-deps
+
+ const wrapperStyle= insideFlex
+ ? {...flexContainerStyle, flex:'1 1 auto'}
+ : {...flexContainerStyle, width:'100%', height:'100%'};
- if (insideFlex) {
- wrapperStyle= Object.assign({}, flexContainerStyle, {flex:'1 1 auto'});
- }
- else {
- wrapperStyle= Object.assign({}, flexContainerStyle, {width:'100%', height:'100%'});
- }
let container;
if (!viewerItemIds.length && !gridDefFunc) {
container= false;
@@ -74,13 +72,8 @@ export function MultiItemViewerView(props) {
container= makePackedGrid(viewerItemIds,rows,forceColSize,true,makeItemViewer);
}
else if (scrollGrid) {
- let cols;
- const {width:containerWidth}= gridContainerElement?.element ?
- gridContainerElement.element.getBoundingClientRect() : {width:0,height:0};
- if (viewerItemIds.length>16) cols=4;
- else if (viewerItemIds.length>5) cols=3;
- else cols=2;
- container= makeScrollGrid(viewerItemIds,cols,containerWidth, makeItemViewer);
+ const {width:containerWidth=0}= gridContainerElement?.element?.getBoundingClientRect() ?? {};
+ container= makeScrollGrid(viewerItemIds,containerWidth, makeItemViewer);
}
else { // GRID automatic
const dim= findAutoGridDim(viewerItemIds.length, autoRowOriented);
@@ -107,26 +100,27 @@ export function MultiItemViewerView(props) {
}
MultiItemViewerView.propTypes= {
- viewerId : PropTypes.string.isRequired,
- style : PropTypes.object,
- defaultDecoration : PropTypes.bool,
- layoutType : PropTypes.oneOf([GRID,SINGLE]),
- forceRowSize : PropTypes.number, //optional - force a certain number of rows
- forceColSize : PropTypes.number, //optional - force a certain number of columns
- makeCustomLayout : PropTypes.func, //optional - a function to present the items in a custom layout
- gridDefFunc : PropTypes.func, // optional - a function to return the grid definition
- gridComponent : PropTypes.object, // an element to define the grid - not implemented, just an idea
- scrollGrid: PropTypes.bool,
- insideFlex : PropTypes.bool,
- autoRowOriented: PropTypes.bool,
-
- viewerItemIds : PropTypes.arrayOf(PropTypes.string).isRequired,
- activeItemId : PropTypes.string,
- makeToolbar : PropTypes.func,
- makeItemViewer : PropTypes.func,
- makeItemViewerFull : PropTypes.func,
- eventCallback: PropTypes.object,
- sparseGridTitleLocation : PropTypes.oneOf(['top', 'left', 'off', ''])
+ viewerId : string.isRequired,
+ style : object,
+ defaultDecoration : bool,
+ layoutType : oneOf([GRID,SINGLE]),
+ forceRowSize :number, //optional - force a certain number of rows
+ forceColSize : number, //optional - force a certain number of columns
+ makeCustomLayout : func, //optional - a function to present the items in a custom layout
+ gridDefFunc : func, // optional - a function to return the grid definition
+ gridComponent : object, // an element to define the grid - not implemented, just an idea
+ scrollGrid: bool,
+ insideFlex : bool,
+ autoRowOriented: bool,
+
+ viewerItemIds : arrayOf(string).isRequired,
+ activeItemId : string,
+ makeToolbar : func,
+ makeItemViewer : func,
+ makeItemViewerFull : func,
+ eventCallback: object,
+ sparseGridTitleLocation : oneOf(['top', 'left', 'off', '']),
+ ref: any,
};
@@ -143,7 +137,13 @@ function makePackedGrid(viewerItemIds,rows,cols, columnBased,makeItemViewer) {
rowBasedIvAry(viewerItemIds,rows,percentWidth,percentHeight,width,height,makeItemViewer);
}
-function makeScrollGrid(viewerItemIds,cols,containerWidth, makeItemViewer) {
+function makeScrollGrid(viewerItemIds,containerWidth, makeItemViewer) {
+ const cols =
+ viewerItemIds.length>16
+ ? 4
+ : viewerItemIds.length>5
+ ? 3
+ : 2;
const size= 100/cols;
const sizePx= containerWidth ? Math.trunc((size/100)*containerWidth-2) : 0;
const width= `calc(${size}% - 2px)`;
@@ -225,7 +225,7 @@ function findAutoGridDim(size, rowOriented=true) {
* an empty element will act as a placeholder in the row.
*
* @param {Array} viewerItemIds
- * @param {Array.<{string,string[]}>} gridDef
+ * @param {Array.<{title:string,plotIdAry:string[],noDataMessage:string,size:number}>} gridDef
* @param {Function} makeItemViewer
* @param sparseGridTitleLocation
*/
diff --git a/src/firefly/js/visualize/ui/VisInlineToolbarView.jsx b/src/firefly/js/visualize/ui/PvControlsAndFeedback.jsx
similarity index 58%
rename from src/firefly/js/visualize/ui/VisInlineToolbarView.jsx
rename to src/firefly/js/visualize/ui/PvControlsAndFeedback.jsx
index c6176ec19a..b1d8de6308 100644
--- a/src/firefly/js/visualize/ui/VisInlineToolbarView.jsx
+++ b/src/firefly/js/visualize/ui/PvControlsAndFeedback.jsx
@@ -5,8 +5,9 @@
import {Box, ChipDelete, Stack, Typography} from '@mui/joy';
import {isString} from 'lodash';
import React, {memo} from 'react';
-import {object, bool, number, string} from 'prop-types';
+import {object, bool, number, string, func} from 'prop-types';
import {showInfoPopup} from '../../ui/PopupUtil';
+import {checkProps} from '../../ui/SimpleComponent';
import {PlotAttribute} from '../PlotAttribute';
import {makeMouseStatePayload, fireMouseCtxChange, MouseState} from '../VisMouseSync.js';
import {dispatchDeletePlotView, visRoot} from '../ImagePlotCntlr.js';
@@ -16,8 +17,9 @@ import {WarningButton} from './Buttons';
-export const VisInlineToolbarView = memo( (props) => {
- const {pv, showDelete,deleteVisible, topOffset=0}= props;
+export const PvControlsAndFeedback = memo( (props) => {
+ const {pv, showDelete,controlsVisible, makeLegend}= props;
+ checkProps(props, PvControlsAndFeedback);
if (!pv) return undefined;
const deleteClick= () => {
const mouseStatePayload= makeMouseStatePayload(undefined,MouseState.EXIT,undefined,0,0,'');
@@ -26,23 +28,33 @@ export const VisInlineToolbarView = memo( (props) => {
};
const deleteStyle= {
- visibility: deleteVisible ? 'visible' : 'hidden',
- opacity: deleteVisible ? 1 : 0,
- transition: deleteVisible ? 'opacity .15s linear' : 'visibility 0s .15s, opacity .15s linear',
+ visibility: controlsVisible ? 'visible' : 'hidden',
+ opacity: controlsVisible ? 1 : 0,
+ transition: controlsVisible ? 'opacity .15s linear' : 'visibility 0s .15s, opacity .15s linear',
};
const warnAry= getWarningsAry(pv);
- if (!showDelete && !warnAry?.length) return;
+ const legend= makeLegend?.(pv.plotId);
+ if (!showDelete && !warnAry?.length && !legend) return;
+ const legendAdd= pv.plotViewCtx.useForSearchResults && !pv.plotViewCtx.useForCoverage ? deleteStyle : {};
return (
-
-
-
- {showDelete &&
- }
+
+
+
+
+ {showDelete &&
+ }
+
+ { makeLegend &&
+
+ {legend}
+
+ }
+
);
@@ -87,10 +99,11 @@ function WarningsAlert({pv}) {
-VisInlineToolbarView.propTypes= {
+PvControlsAndFeedback.propTypes= {
pv : object,
showDelete : bool,
- deleteVisible : bool,
+ controlsVisible : bool,
help_id : string,
- topOffset: number
+ topOffset: number,
+ makeLegend : func,
};
diff --git a/src/firefly/js/visualize/ui/SelectAreaDropDownView.jsx b/src/firefly/js/visualize/ui/SelectAreaUIComponents.jsx
similarity index 67%
rename from src/firefly/js/visualize/ui/SelectAreaDropDownView.jsx
rename to src/firefly/js/visualize/ui/SelectAreaUIComponents.jsx
index 8ddda318db..881db7661a 100644
--- a/src/firefly/js/visualize/ui/SelectAreaDropDownView.jsx
+++ b/src/firefly/js/visualize/ui/SelectAreaUIComponents.jsx
@@ -2,12 +2,16 @@
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
+import {Button, ChipDelete, Stack, Typography} from '@mui/joy';
import React from 'react';
-import PropTypes from 'prop-types';
+import PropTypes, {object, string} from 'prop-types';
import {once} from 'lodash';
import {SingleColumnMenu} from '../../ui/DropDownMenu.jsx';
+import {checkProps, useStoreConnector} from '../../ui/SimpleComponent';
import {ToolbarButton, DropDownVerticalSeparator} from '../../ui/ToolbarButton.jsx';
-import {getDrawLayerByType, getDrawLayersByType, getPlotViewAry, isDrawLayerAttached} from '../PlotViewUtil.js';
+import {
+ getActivePlotView, getDrawLayerByType, getDrawLayersByType, getPlotViewAry, isDrawLayerAttached
+} from '../PlotViewUtil.js';
import {dispatchCreateDrawLayer,
getDlAry,
dispatchAttachLayerToPlot,
@@ -18,15 +22,23 @@ import {SelectedShape} from '../../drawingLayers/SelectedShape';
import {visRoot} from '../ImagePlotCntlr.js';
import {onOff, SimpleLayerOnOffButton} from 'firefly/visualize/ui/SimpleLayerOnOffButton.jsx';
+import AdsClickIcon from '@mui/icons-material/AdsClick';
+
import SELECT_RECT from 'html/images/icons-2014/Marquee.png';
import SELECT_RECT_ON from 'html/images/icons-2014/Marquee-ON.png';
import SELECT_CIRCLE from 'html/images/icons-2014/28x28_Circle.png';
import SELECT_CIRCLE_ON from 'html/images/icons-2014/28x28_Circle-ON.png';
import SELECT_NONE from 'html/images/icons-2014/28x28_Rect_DD.png';
-import {clearModalEndInfo, setModalEndInfo} from './ToolbarToolModalEnd.js';
+import {clearModalEndInfo, getModalEndInfo, setModalEndInfo} from './ToolbarToolModalEnd.js';
const NONSELECT = 'nonselect';
+export const DEFAULT_SELECTION_TEXT='Draw Area Selection';
+export const DEFAULT_INSTRUCTIONS_CIRCLE='Choose search area: click and draw circle on map';
+export const DEFAULT_INSTRUCTIONS_RECT= 'Choose search area: click and draw rectangle on map';
+
+
+
const selectAreaInfo = once(() => ({
[NONSELECT] : {
typeId: '',
@@ -53,7 +65,7 @@ const selectAreaInfo = once(() => ({
}
}));
-export function getSelectedAreaIcon(isSelected = true) {
+function getSelectedAreaIcon(isSelected = true) {
if (!isSelected) return SELECT_CIRCLE;
const drawLayer = getDrawLayerByType(getDlAry(), SelectArea.TYPE_ID);
@@ -109,7 +121,7 @@ export function detachSelectArea(pv, allPlots = true, id = SelectArea.TYPE_ID) {
});
}
-export function detachImageOutlineLayerForSelectArea(pv, allPlots = true) {
+function detachImageOutlineLayerForSelectArea(pv, allPlots = true) {
const dlAry = getDrawLayersByType(getDlAry(), ImageOutline.TYPE_ID);
dlAry.forEach((dl) => {
@@ -171,3 +183,54 @@ SelectAreaDropDownView.propTypes= {
allPlots: PropTypes.bool,
modalEndInfo: PropTypes.object,
};
+
+function getInstructions(shape, instructionsText) {
+ if (instructionsText) return instructionsText;
+ switch (shape) {
+ case SelectedShape.rect: return DEFAULT_INSTRUCTIONS_RECT;
+ case SelectedShape.circle: return DEFAULT_INSTRUCTIONS_CIRCLE;
+ default : return 'click and draw';
+ }
+
+}
+
+
+export function SelectAreaForEmbedded(props) {
+ const {selectButtonText=DEFAULT_SELECTION_TEXT,instructionsText,shape=SelectedShape.circle, sx}= props;
+ checkProps(props, SelectAreaForEmbedded);
+ const modalEndInfo = useStoreConnector(() => getModalEndInfo());
+ const selectActive= modalEndInfo?.key==='SelectArea';
+ const doSelection= updateSelect(getActivePlotView(visRoot()), shape.key, true, modalEndInfo);
+
+ return (
+
+
+ {!selectActive
+ ? ,
+ onClick: () => doSelection() }}>
+ {selectButtonText}
+
+ :
+ {getInstructions(shape,instructionsText)}
+ {
+ const pv = getActivePlotView(visRoot());
+ if (pv) dispatchDetachLayerFromPlot(SelectArea.TYPE_ID, pv.plotId, true, true);
+ clearModalEndInfo();
+ }
+ }}/>
+
+ }
+
+
+ );
+}
+
+SelectAreaForEmbedded.propTypes = {
+ selectButtonText: string,
+ instructionsText: string,
+ shape: object,
+ sx: object,
+};
\ No newline at end of file
diff --git a/src/firefly/js/visualize/ui/SmallLegend.jsx b/src/firefly/js/visualize/ui/SmallLegend.jsx
new file mode 100644
index 0000000000..ca9c87fbbf
--- /dev/null
+++ b/src/firefly/js/visualize/ui/SmallLegend.jsx
@@ -0,0 +1,151 @@
+
+import Layers from '@mui/icons-material/Layers';
+import {isString} from 'lodash';
+import React, {useRef} from 'react';
+import {Badge, Box, Button, Card, Stack, Typography} from '@mui/joy';
+import {getWorkingTask} from '../../core/AppDataCntlr';
+import Catalog from '../../drawingLayers/Catalog';
+import HpxCatalog from '../../drawingLayers/hpx/HpxCatalog';
+import HiPSMOC from '../../drawingLayers/HiPSMOC.js';
+import {CollapsibleItem} from '../../ui/panel/CollapsiblePanel';
+import {useStoreConnector} from '../../ui/SimpleComponent';
+import BrowserInfo from '../../util/BrowserInfo';
+import {getDlAry} from '../DrawLayerCntlr';
+import {
+ getAllDrawLayersForPlot, getLayerTitle, getPlotViewById, isDrawLayerVisible, primePlot
+} from '../PlotViewUtil';
+import {isHiPS} from '../WebPlot';
+import {DrawLayerLegendView} from './DrawLayerItemView';
+import {showDrawingLayerPopup} from './DrawLayerPanel';
+import {changeVisible, modifyDrawColor} from './DrawLayerUIComponents';
+
+
+export function SmallLegend(props) {
+ const {visRoot,plotId}= props;
+ const dlAry= useStoreConnector(() => getDlAry());
+ const {message}= useStoreConnector(() => getWorkingTask(plotId));
+ const {current:divElementRef}= useRef({divElement:undefined});
+ const pv= getPlotViewById(visRoot,plotId);
+ if (!pv) return;
+ if (pv.viewDim.width<250 || pv.viewDim.height<250) return;
+ const smallWhenClosed= (pv.viewDim.width<400 || pv.viewDim.height<300);
+ const allLayers= getAllDrawLayersForPlot(dlAry,plotId);
+ if (!allLayers) return;
+ const layers= allLayers.filter( (dl) => {
+ const {drawLayerTypeId, mocTable, }= dl;
+ const visible= isDrawLayerVisible(dl,plotId);
+ return (
+ (drawLayerTypeId===HiPSMOC.TYPE_ID && (mocTable || visible))
+ || drawLayerTypeId===HpxCatalog.TYPE_ID
+ || drawLayerTypeId===Catalog.TYPE_ID
+ );
+ });
+
+ const layersLoading= message==='MOC' ? 'Layers Loading...' : undefined;
+
+ const hasLayers= Boolean(layers.length || layersLoading);
+
+ if (!hasLayers) return;
+ const showMoreLayers= pv.plotViewCtx.useForSearchResults;
+
+ const layerCnt= primePlot(pv) ? (allLayers.length + pv.overlayPlotViews.length) : 0;
+ const maxTitleChars= layers.reduce( (max,l) => {
+ const t= getLayerTitle(pv.plotId,l);
+ let tLen= 0;
+ if (t) tLen= l.autoFormatTitle? t.length : 30;
+ return Math.max(max, tLen);
+ },20);
+
+ const sx= (theme) => ({
+ '--Card-padding': '.4rem',
+ mr:.25,
+ overflow:'hidden',
+ backgroundColor: BrowserInfo.supportsCssColorMix() ?
+ `color-mix(in srgb, ${theme.vars.palette.neutral.softBg} 90%, transparent)` :
+ theme.vars.palette.neutral.softBg,
+ });
+
+ return (
+ divElementRef.divElement=e}>
+ (),
+ isOpen:isHiPS(primePlot(pv)),
+ slotProps: {
+ header: {
+ slotProps: {
+ button: {
+ component: 'div',
+ sx: { gap: '2px', border:'none', borderRadius: '5px' },
+ }
+ }
+ },
+ } }} >
+
+
+
+ {layersLoading && Layers Loading....}
+ {layers.map( (dl) => (
+ changeVisible(dl, !isDrawLayerVisible(dl,plotId),plotId ),
+ modifyColor: () => modifyDrawColor(dl,pv.plotId,dl.tbl_id),
+ }}/>
+ )) }
+
+
+ {showMoreLayers &&
+
+
+
+ }
+
+
+
+ );
+}
+
+
+
+const Header= ({isOpen,smallWhenClosed,layers}) => {
+ const text= (isOpen || !layers?.length)
+ ? 'Legend'
+ :smallWhenClosed
+ ? `(${layers.length})`
+ : `Legend (${layers.length})`;
+ return (
+
+ {text}
+
+ );
+};
+
+function getShortTitle(plotId,dl) {
+ const shortTitle= dl.shortTitle;
+ if (shortTitle) return shortTitle;
+ const title= getLayerTitle(plotId,dl);
+ if (isString(title) && title.startsWith('MOC - ')) return title.substr(6);
+ return title;
+}
\ No newline at end of file
diff --git a/src/firefly/js/visualize/ui/TargetHiPSPanel.jsx b/src/firefly/js/visualize/ui/TargetHiPSPanel.jsx
index 64359d160b..84bd68da85 100644
--- a/src/firefly/js/visualize/ui/TargetHiPSPanel.jsx
+++ b/src/firefly/js/visualize/ui/TargetHiPSPanel.jsx
@@ -45,6 +45,7 @@ import {createHiPSMocLayerFromPreloadedTable} from '../task/PlotHipsTask.js';
import {WebPlotRequest} from '../WebPlotRequest.js';
import {CONE_CHOICE_KEY, POLY_CHOICE_KEY} from './CommonUIKeys.js';
import {MultiImageViewer} from './MultiImageViewer.jsx';
+import {SmallLegend} from './SmallLegend';
import {HelpLines, targetHipsDefaultMenuItemKey, TargetHipsPanelToolbar} from './TargetHipsPanelToolbar.jsx';
import {closeToolbarModalLayers} from './ToolbarToolModalEnd.js';
import {
@@ -153,7 +154,7 @@ export const HiPSTargetView = ({sx, hipsDisplayKey='none',
useEffect(() => {
setMocError();
void updateMoc(mocList,plotId,setMocError);
- }, [mocList]);
+ }, [mocList, plotId]);
useEffect(() => { // if plot view changes then update the target or polygon field
const setWhichOverlayWrapper= setWhichOverlay ?
@@ -165,7 +166,7 @@ export const HiPSTargetView = ({sx, hipsDisplayKey='none',
setHiPSRadius,getHiPSRadius,setPolygon,getPolygon,minSize,maxSize,
canUpdateModalEndInfo:false
});
- },[pv]);
+ },[pv]); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => { // if target or radius field change then hips plot to reflect it
const whichOverlay= getWhichOverlay();
@@ -183,7 +184,7 @@ export const HiPSTargetView = ({sx, hipsDisplayKey='none',
useEffect(() => {
attachSRegion(sRegion,plotId);
- }, [sRegion]);
+ }, [plotId, sRegion]);
return (
@@ -198,7 +199,8 @@ export const HiPSTargetView = ({sx, hipsDisplayKey='none',
whichOverlay={getWhichOverlay()}
toolbarHelpId={toolbarHelpId}
handleToolbar={false}
- menuItemKeys={{...targetHipsDefaultMenuItemKey, selectArea:usingRadius}}
+ menuItemKeys={{...targetHipsDefaultMenuItemKey, selectArea:false}}
+ Legend={SmallLegend}
Toolbar={TargetHipsPanelToolbar}/>
);
@@ -312,7 +314,7 @@ function HiPSPanelPopupButton({groupKey:gk, polygonKey, whichOverlay=CONE_CHOICE
connectContext?.setControlConnected(false);
}
};
- },[]);
+ },[]); // eslint-disable-line react-hooks/exhaustive-deps
return (
dispatchAddWorkingTask(plotId, p) );
+ (p) => dispatchAddWorkingTask(plotId, p, 'MOC') );
setMocError();
if (abort) return;
const request= makeFileRequest(title, cacheKey, undefined, {
@@ -464,7 +466,7 @@ function loadMocWithAbort(mocList, plotId,setMocError) {
} );
dispatchTableFetch(request);
await callWhileAwaiting(onTableLoaded(tbl_id),
- (p) => dispatchAddWorkingTask(plotId, p) );
+ (p) => dispatchAddWorkingTask(plotId, p, 'MOC') );
if (abort) return;
add= (status === '200');
}
@@ -477,6 +479,7 @@ function loadMocWithAbort(mocList, plotId,setMocError) {
visible: true,
fitsPath: mocUrl,
title,
+ shortTitle,
color: mocColor ?? colors[i % 2],
mocUrl,
mocGroupDefColorId: `mocForTargetHipsPanelID-${i}-${mocColor??''}`,
diff --git a/src/firefly/js/visualize/ui/TargetHipsPanelToolbar.jsx b/src/firefly/js/visualize/ui/TargetHipsPanelToolbar.jsx
index ff9207b1f3..8e332245c1 100644
--- a/src/firefly/js/visualize/ui/TargetHipsPanelToolbar.jsx
+++ b/src/firefly/js/visualize/ui/TargetHipsPanelToolbar.jsx
@@ -1,23 +1,13 @@
import {Stack, Typography} from '@mui/joy';
-import SELECTED_ZOOM from 'images/icons-2014/ZoomFitToSelectedSpace.png';
import PropTypes from 'prop-types';
import React from 'react';
import {dispatchComponentStateChange, getComponentState} from '../../core/ComponentCntlr.js';
import HelpIcon from '../../ui/HelpIcon.jsx';
import {useStoreConnector} from '../../ui/SimpleComponent.jsx';
-import {ToolbarButton} from '../../ui/ToolbarButton';
import {visRoot} from '../ImagePlotCntlr.js';
import {getActivePlotView} from '../PlotViewUtil.js';
-import {
- CenterOnSelection, CheckedButton, CheckedClearButton, CropButton, FilterAddButton, FiltersOffButton, StatsButton
-} from './Buttons';
import {CONE_CHOICE_KEY} from './CommonUIKeys.js';
-import {
- clearFilterDrawingLayer, crop, filterDrawingLayer, recenterToSelection, selectDrawingLayer, stats,
- unselectDrawingLayer,
- zoomIntoSelection
-} from './CtxToolbarFunctions';
-import {SelectAreaButton} from './SelectAreaDropDownView.jsx';
+import {SelectAreaButton} from './SelectAreaUIComponents.jsx';
import {VisMiniToolbar} from './VisMiniToolbar.jsx';
export const targetHipsDefaultMenuItemKey = {
@@ -58,14 +48,12 @@ export const HelpLines= ({whichOverlay, selectionHelpText, usingRadius}) => {
{whichOverlay===CONE_CHOICE_KEY ?
(<>
- Click to choose a search center, or use the Selection Tools (
- {selectButton}
- ) to choose a search center and radius.
+ Click to choose a search center, or use the Selection Tools
+ to choose a search center and radius.
> ) :
(<>
- Use the Selection Tools (
- {selectButton}
- ) to choose a search polygon. Click to change the center.
+ Use the Selection Tools
+ to choose a search polygon. Click to change the center.
> )}
diff --git a/src/firefly/js/visualize/ui/TriViewImageSection.jsx b/src/firefly/js/visualize/ui/TriViewImageSection.jsx
index e3f02fbafd..7bde7ce70a 100644
--- a/src/firefly/js/visualize/ui/TriViewImageSection.jsx
+++ b/src/firefly/js/visualize/ui/TriViewImageSection.jsx
@@ -35,6 +35,7 @@ import {REINIT_APP} from '../../core/AppDataCntlr.js';
import {MetaDataMultiProductViewer} from './multiProduct/MetaDataMultiProductViewer.jsx';
import {CoverageViewer} from './CoveraeViewer';
import {getPlotViewAry} from 'firefly/visualize/PlotViewUtil.js';
+import {SmallLegend} from './SmallLegend';
/**
@@ -114,6 +115,7 @@ export function makeFitsPinnedTab({id,asTab}) {
const viewer= ();
return (
asTab ?
diff --git a/src/firefly/js/visualize/ui/VisMiniToolbar.jsx b/src/firefly/js/visualize/ui/VisMiniToolbar.jsx
index e817be7dd3..110ae272e6 100644
--- a/src/firefly/js/visualize/ui/VisMiniToolbar.jsx
+++ b/src/firefly/js/visualize/ui/VisMiniToolbar.jsx
@@ -28,7 +28,7 @@ import {MarkerDropDownView} from 'firefly/visualize/ui/MarkerDropDownView.jsx';
import {showMaskDialog} from 'firefly/visualize/ui/MaskAddPanel.jsx';
import {MatchLockDropDown} from 'firefly/visualize/ui/MatchLockDropDown.jsx';
import {showPlotInfoPopup} from 'firefly/visualize/ui/PlotInfoPopup.js';
-import {SelectAreaButton} from 'firefly/visualize/ui/SelectAreaDropDownView.jsx';
+import {SelectAreaButton} from './SelectAreaUIComponents.jsx';
import {SimpleLayerOnOffButton} from 'firefly/visualize/ui/SimpleLayerOnOffButton.jsx';
import {StretchDropDownView} from 'firefly/visualize/ui/StretchDropDownView.jsx';
import {isHiPS} from 'firefly/visualize/WebPlot.js';
diff --git a/src/firefly/js/visualize/ui/multiProduct/MultiProductChoice.jsx b/src/firefly/js/visualize/ui/multiProduct/MultiProductChoice.jsx
index ede797a5e4..305f807cbe 100644
--- a/src/firefly/js/visualize/ui/multiProduct/MultiProductChoice.jsx
+++ b/src/firefly/js/visualize/ui/multiProduct/MultiProductChoice.jsx
@@ -13,6 +13,7 @@ import {NewPlotMode} from '../../MultiViewCntlr.js';
import { convertHDUIdxToImageIdx, getActivePlotView, getHDUIndex, hasImageCubes} from '../../PlotViewUtil';
import {ImageMetaDataToolbar} from '../ImageMetaDataToolbar.jsx';
import {MultiImageViewer} from '../MultiImageViewer.jsx';
+import {SmallLegend} from '../SmallLegend';
const imageOp= {label: 'Image', value: SHOW_IMAGE};
@@ -100,6 +101,7 @@ export function MultiProductChoice({ dataProductsState, dpId,
enableCutoutFullSwitching:cutoutFullPair,
canReceiveNewPlots: NewPlotMode.none.key, tableId:metaDataTableId, controlViewerMounting:false,
forceRowSize: gridForceRowSize,
+ Legend: SmallLegend,
cutoutToFullWarning,
makeDropDown: !mayToggle ? makeDropDown : undefined,
Toolbar:ImageMetaDataToolbar, factoryKey}} />