Skip to content

Commit 38fabb0

Browse files
authored
Merge pull request #331 from xcube-dev/forman-286-swipe_layers
Compare two variable layers
2 parents bfc76ad + 4b374cd commit 38fabb0

26 files changed

+829
-195
lines changed

CHANGES.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
## Changes in version 1.2.0 (in development)
22

3-
* Users can now define their own color bars.
3+
* Introduced a variable comparison mode. Users can now go to the layer
4+
visibility dropdown menu (see below) and enable the variable compare mode.
5+
This will make the variable layer fully transparent for initially one
6+
half of the map area. User can swipe a bar to shrink or enlarge the area.
7+
By selecting a secondary data variable using a new tool button next to the
8+
variable selector, a second variable layer will be rendered below the current
9+
variable layer. Using the compare mode the following layers can be inspected
10+
next to the currently selected variable (in this order): Variable 2 layer,
11+
Basemap layer Dataset RGB layer. (#286)
12+
13+
* Users can now define their own color bars. The new feature can be found
14+
in the color selector that pops up if clicking the color bar legend.
15+
A new category "Users" provides an add-button to add a new color bar
16+
definition. Existing custom color bars can be edited and deleted.
417
This feature requires xcube server >= 1.6. (#334)
518

619
* Users can now zoom into arbitrary regions of a time-series chart

src/actions/controlActions.tsx

+60
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,42 @@ export function setLayerVisibility(
342342

343343
////////////////////////////////////////////////////////////////////////////////
344344

345+
export const SET_VARIABLE_COMPARE_MODE = "SET_VARIABLE_COMPARE_MODE";
346+
347+
export interface SetVariableCompareMode {
348+
type: typeof SET_VARIABLE_COMPARE_MODE;
349+
variableCompareMode: boolean;
350+
}
351+
352+
export function setVariableCompareMode(
353+
variableCompareMode: boolean,
354+
): SetVariableCompareMode {
355+
return {
356+
type: SET_VARIABLE_COMPARE_MODE,
357+
variableCompareMode,
358+
};
359+
}
360+
361+
////////////////////////////////////////////////////////////////////////////////
362+
363+
export const SET_VARIABLE_SPLIT_POS = "SET_VARIABLE_SPLIT_POS";
364+
365+
export interface SetVariableSplitPos {
366+
type: typeof SET_VARIABLE_SPLIT_POS;
367+
variableSplitPos: number | undefined;
368+
}
369+
370+
export function setVariableSplitPos(
371+
variableSplitPos: number | undefined,
372+
): SetVariableSplitPos {
373+
return {
374+
type: SET_VARIABLE_SPLIT_POS,
375+
variableSplitPos,
376+
};
377+
}
378+
379+
////////////////////////////////////////////////////////////////////////////////
380+
345381
export const SELECT_VARIABLE = "SELECT_VARIABLE";
346382

347383
export interface SelectVariable {
@@ -357,6 +393,27 @@ export function selectVariable(
357393

358394
////////////////////////////////////////////////////////////////////////////////
359395

396+
export const SELECT_VARIABLE_2 = "SELECT_VARIABLE_2";
397+
398+
export interface SelectVariable2 {
399+
type: typeof SELECT_VARIABLE_2;
400+
selectedDataset2Id: string | null;
401+
selectedVariable2Name: string | null;
402+
}
403+
404+
export function selectVariable2(
405+
selectedDataset2Id: string | null,
406+
selectedVariable2Name: string | null,
407+
): SelectVariable2 {
408+
return {
409+
type: SELECT_VARIABLE_2,
410+
selectedDataset2Id,
411+
selectedVariable2Name,
412+
};
413+
}
414+
415+
////////////////////////////////////////////////////////////////////////////////
416+
360417
export const SELECT_TIME = "SELECT_TIME";
361418

362419
export interface SelectTime {
@@ -751,4 +808,7 @@ export type ControlAction =
751808
| ShowInfoCard
752809
| SetVisibleInfoCardElements
753810
| UpdateInfoCardElementCodeMode
811+
| SelectVariable2
812+
| SetVariableCompareMode
813+
| SetVariableSplitPos
754814
| FlyTo;

src/actions/dataActions.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import {
4545
mapProjectionSelector,
4646
selectedDatasetSelector,
4747
selectedDatasetTimeDimensionSelector,
48-
selectedDatasetVariableSelector,
48+
selectedVariableSelector,
4949
selectedPlaceGroupPlacesSelector,
5050
selectedPlaceGroupsSelector,
5151
selectedPlaceIdSelector,
@@ -438,7 +438,7 @@ export function addTimeSeries() {
438438
const selectedDataset = selectedDatasetSelector(getState());
439439
const selectedDatasetTimeDim =
440440
selectedDatasetTimeDimensionSelector(getState());
441-
const selectedVariable = selectedDatasetVariableSelector(getState());
441+
const selectedVariable = selectedVariableSelector(getState());
442442
const selectedPlaceId = selectedPlaceIdSelector(getState());
443443
const selectedPlace = selectedPlaceSelector(getState())!;
444444
const timeSeriesUpdateMode = getState().controlState.timeSeriesUpdateMode;

src/components/ControlBarActions.tsx

+15-1
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,20 @@ interface ControlBarActionsProps extends WithStyles<typeof styles>, WithLocale {
6565
allowRefresh?: boolean;
6666
updateResources: () => void;
6767
compact: boolean;
68+
layerTitles: Record<keyof LayerVisibilities, string>;
69+
layerSubtitles: Record<keyof LayerVisibilities, string>;
6870
layerVisibilities: LayerVisibilities;
6971
setLayerVisibility: (
7072
layerId: keyof LayerVisibilities,
7173
visible: boolean,
7274
) => void;
75+
variableCompareMode: boolean;
76+
setVariableCompareMode: (selected: boolean) => void;
7377
}
7478

7579
const _ControlBarActions: React.FC<ControlBarActionsProps> = ({
7680
classes,
81+
locale,
7782
visible,
7883
volumeCardOpen,
7984
showVolumeCard,
@@ -84,8 +89,12 @@ const _ControlBarActions: React.FC<ControlBarActionsProps> = ({
8489
allowRefresh,
8590
updateResources,
8691
compact,
92+
layerTitles,
93+
layerSubtitles,
8794
layerVisibilities,
8895
setLayerVisibility,
96+
variableCompareMode,
97+
setVariableCompareMode,
8998
}) => {
9099
if (!visible) {
91100
return null;
@@ -95,9 +104,14 @@ const _ControlBarActions: React.FC<ControlBarActionsProps> = ({
95104

96105
const layerSelect = (
97106
<LayerSelect
107+
locale={locale}
108+
openDialog={openDialog}
109+
layerTitles={layerTitles}
110+
layerSubtitles={layerSubtitles}
98111
layerVisibilities={layerVisibilities}
99112
setLayerVisibility={setLayerVisibility}
100-
openDialog={openDialog}
113+
variableCompareMode={variableCompareMode}
114+
setVariableCompareMode={setVariableCompareMode}
101115
/>
102116
);
103117

src/components/LayerMenu.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import MenuItem from "@mui/material/MenuItem";
22
import ListItemText from "@mui/material/ListItemText";
33
import Menu from "@mui/material/Menu";
44

5-
import { getLayerLabel, LayerDefinition } from "@/model/layerDefinition";
5+
import { getLayerTitle, LayerDefinition } from "@/model/layerDefinition";
66

77
interface LayerMenuProps {
88
anchorElement: Element | null;
@@ -36,7 +36,7 @@ const LayerMenu = ({
3636
}
3737
dense
3838
>
39-
<ListItemText primary={getLayerLabel(layer)} />
39+
<ListItemText primary={getLayerTitle(layer)} />
4040
</MenuItem>
4141
))}
4242
</Menu>

src/components/LayerSelect.tsx

+25-8
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,31 @@ import i18n from "@/i18n";
4040
import { WithLocale } from "@/util/lang";
4141
import { LayerVisibilities } from "@/states/controlState";
4242
import LayerSelectItem from "./LayerSelectItem";
43+
import SelectableMenuItem from "@/components/SelectableMenuItem";
4344

4445
// noinspection JSUnusedLocalSymbols
4546
const styles = (_theme: Theme) => createStyles({});
4647

4748
interface LayerSelectProps extends WithStyles<typeof styles>, WithLocale {
4849
openDialog: (dialogId: string) => void;
50+
layerTitles: Record<keyof LayerVisibilities, string>;
51+
layerSubtitles: Record<keyof LayerVisibilities, string>;
4952
layerVisibilities: LayerVisibilities;
5053
setLayerVisibility: (
5154
layerId: keyof LayerVisibilities,
5255
visible: boolean,
5356
) => void;
57+
variableCompareMode: boolean;
58+
setVariableCompareMode: (selected: boolean) => void;
5459
}
5560

5661
const _LayerSelect: React.FC<LayerSelectProps> = (props) => {
57-
const { openDialog, ...otherProps } = props;
62+
const {
63+
openDialog,
64+
variableCompareMode,
65+
setVariableCompareMode,
66+
...layerSelectProps
67+
} = props;
5868
const [menuAnchor, setMenuAnchor] = React.useState<Element | null>(null);
5969

6070
const handleUserOverlays = () => {
@@ -82,13 +92,20 @@ const _LayerSelect: React.FC<LayerSelectProps> = (props) => {
8292
>
8393
<Paper>
8494
<MenuList dense>
85-
<LayerSelectItem layerId="baseMap" {...otherProps} />
86-
<LayerSelectItem layerId="datasetRgb" {...otherProps} />
87-
<LayerSelectItem layerId="datasetVariable" {...otherProps} />
88-
<LayerSelectItem layerId="datasetBoundary" {...otherProps} />
89-
<LayerSelectItem layerId="datasetPlaces" {...otherProps} />
90-
<LayerSelectItem layerId="userPlaces" {...otherProps} />
91-
<LayerSelectItem layerId="overlay" {...otherProps} />
95+
<LayerSelectItem layerId="baseMap" {...layerSelectProps} />
96+
<LayerSelectItem layerId="datasetRgb" {...layerSelectProps} />
97+
<LayerSelectItem layerId="datasetVariable2" {...layerSelectProps} />
98+
<LayerSelectItem layerId="datasetVariable" {...layerSelectProps} />
99+
<LayerSelectItem layerId="datasetBoundary" {...layerSelectProps} />
100+
<LayerSelectItem layerId="datasetPlaces" {...layerSelectProps} />
101+
<LayerSelectItem layerId="userPlaces" {...layerSelectProps} />
102+
<LayerSelectItem layerId="overlay" {...layerSelectProps} />
103+
<Divider />
104+
<SelectableMenuItem
105+
title={i18n.get("Compare Mode (Swipe)")}
106+
selected={variableCompareMode}
107+
onClick={() => setVariableCompareMode(!variableCompareMode)}
108+
/>
92109
<Divider />
93110
<MenuItem onClick={handleUserBaseMaps}>
94111
{i18n.get("User Base Maps") + "..."}

src/components/LayerSelectItem.tsx

+16-37
Original file line numberDiff line numberDiff line change
@@ -22,56 +22,35 @@
2222
* SOFTWARE.
2323
*/
2424

25-
import * as React from "react";
26-
import Check from "@mui/icons-material/Check";
27-
import MenuItem from "@mui/material/MenuItem";
28-
import ListItemText from "@mui/material/ListItemText";
29-
import ListItemIcon from "@mui/material/ListItemIcon";
30-
3125
import i18n from "@/i18n";
3226
import { LayerVisibilities } from "@/states/controlState";
33-
34-
const layerLabels: Record<keyof LayerVisibilities, string> = {
35-
baseMap: "Base Map",
36-
datasetRgb: "Dataset RGB",
37-
datasetVariable: "Dataset Variable",
38-
datasetBoundary: "Dataset Boundary",
39-
datasetPlaces: "Dataset Places",
40-
userPlaces: "User Places",
41-
overlay: "Overlay",
42-
};
27+
import SelectableMenuItem from "@/components/SelectableMenuItem";
4328

4429
interface LayerSelectItemProps {
4530
layerId: keyof LayerVisibilities;
31+
layerTitles: Record<keyof LayerVisibilities, string>;
32+
layerSubtitles: Record<keyof LayerVisibilities, string>;
4633
layerVisibilities: LayerVisibilities;
4734
setLayerVisibility: (
4835
layerId: keyof LayerVisibilities,
4936
visible: boolean,
5037
) => void;
5138
}
5239

53-
const LayerSelectItem: React.FC<LayerSelectItemProps> = ({
40+
export default function LayerSelectItem({
5441
layerId,
42+
layerTitles,
43+
layerSubtitles,
5544
layerVisibilities,
5645
setLayerVisibility,
57-
}) => {
58-
const visible = layerVisibilities[layerId];
59-
const label = i18n.get(layerLabels[layerId]);
60-
61-
const handleClick = () => setLayerVisibility(layerId, !visible);
62-
63-
return visible ? (
64-
<MenuItem onClick={handleClick}>
65-
<ListItemIcon>
66-
<Check />
67-
</ListItemIcon>
68-
{label}
69-
</MenuItem>
70-
) : (
71-
<MenuItem onClick={handleClick}>
72-
<ListItemText inset>{label}</ListItemText>
73-
</MenuItem>
46+
}: LayerSelectItemProps) {
47+
const visible = !!layerVisibilities[layerId];
48+
return (
49+
<SelectableMenuItem
50+
title={i18n.get(layerTitles[layerId])}
51+
subtitle={layerSubtitles[layerId]}
52+
selected={visible}
53+
onClick={() => setLayerVisibility(layerId, !visible)}
54+
/>
7455
);
75-
};
76-
77-
export default LayerSelectItem;
56+
}

0 commit comments

Comments
 (0)