Skip to content

Commit

Permalink
Merge pull request #331 from xcube-dev/forman-286-swipe_layers
Browse files Browse the repository at this point in the history
Compare two variable layers
  • Loading branch information
forman authored May 7, 2024
2 parents bfc76ad + 4b374cd commit 38fabb0
Show file tree
Hide file tree
Showing 26 changed files with 829 additions and 195 deletions.
15 changes: 14 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
## Changes in version 1.2.0 (in development)

* Users can now define their own color bars.
* Introduced a variable comparison mode. Users can now go to the layer
visibility dropdown menu (see below) and enable the variable compare mode.
This will make the variable layer fully transparent for initially one
half of the map area. User can swipe a bar to shrink or enlarge the area.
By selecting a secondary data variable using a new tool button next to the
variable selector, a second variable layer will be rendered below the current
variable layer. Using the compare mode the following layers can be inspected
next to the currently selected variable (in this order): Variable 2 layer,
Basemap layer Dataset RGB layer. (#286)

* Users can now define their own color bars. The new feature can be found
in the color selector that pops up if clicking the color bar legend.
A new category "Users" provides an add-button to add a new color bar
definition. Existing custom color bars can be edited and deleted.
This feature requires xcube server >= 1.6. (#334)

* Users can now zoom into arbitrary regions of a time-series chart
Expand Down
60 changes: 60 additions & 0 deletions src/actions/controlActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,42 @@ export function setLayerVisibility(

////////////////////////////////////////////////////////////////////////////////

export const SET_VARIABLE_COMPARE_MODE = "SET_VARIABLE_COMPARE_MODE";

export interface SetVariableCompareMode {
type: typeof SET_VARIABLE_COMPARE_MODE;
variableCompareMode: boolean;
}

export function setVariableCompareMode(
variableCompareMode: boolean,
): SetVariableCompareMode {
return {
type: SET_VARIABLE_COMPARE_MODE,
variableCompareMode,
};
}

////////////////////////////////////////////////////////////////////////////////

export const SET_VARIABLE_SPLIT_POS = "SET_VARIABLE_SPLIT_POS";

export interface SetVariableSplitPos {
type: typeof SET_VARIABLE_SPLIT_POS;
variableSplitPos: number | undefined;
}

export function setVariableSplitPos(
variableSplitPos: number | undefined,
): SetVariableSplitPos {
return {
type: SET_VARIABLE_SPLIT_POS,
variableSplitPos,
};
}

////////////////////////////////////////////////////////////////////////////////

export const SELECT_VARIABLE = "SELECT_VARIABLE";

export interface SelectVariable {
Expand All @@ -357,6 +393,27 @@ export function selectVariable(

////////////////////////////////////////////////////////////////////////////////

export const SELECT_VARIABLE_2 = "SELECT_VARIABLE_2";

export interface SelectVariable2 {
type: typeof SELECT_VARIABLE_2;
selectedDataset2Id: string | null;
selectedVariable2Name: string | null;
}

export function selectVariable2(
selectedDataset2Id: string | null,
selectedVariable2Name: string | null,
): SelectVariable2 {
return {
type: SELECT_VARIABLE_2,
selectedDataset2Id,
selectedVariable2Name,
};
}

////////////////////////////////////////////////////////////////////////////////

export const SELECT_TIME = "SELECT_TIME";

export interface SelectTime {
Expand Down Expand Up @@ -751,4 +808,7 @@ export type ControlAction =
| ShowInfoCard
| SetVisibleInfoCardElements
| UpdateInfoCardElementCodeMode
| SelectVariable2
| SetVariableCompareMode
| SetVariableSplitPos
| FlyTo;
4 changes: 2 additions & 2 deletions src/actions/dataActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
mapProjectionSelector,
selectedDatasetSelector,
selectedDatasetTimeDimensionSelector,
selectedDatasetVariableSelector,
selectedVariableSelector,
selectedPlaceGroupPlacesSelector,
selectedPlaceGroupsSelector,
selectedPlaceIdSelector,
Expand Down Expand Up @@ -438,7 +438,7 @@ export function addTimeSeries() {
const selectedDataset = selectedDatasetSelector(getState());
const selectedDatasetTimeDim =
selectedDatasetTimeDimensionSelector(getState());
const selectedVariable = selectedDatasetVariableSelector(getState());
const selectedVariable = selectedVariableSelector(getState());
const selectedPlaceId = selectedPlaceIdSelector(getState());
const selectedPlace = selectedPlaceSelector(getState())!;
const timeSeriesUpdateMode = getState().controlState.timeSeriesUpdateMode;
Expand Down
16 changes: 15 additions & 1 deletion src/components/ControlBarActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,20 @@ interface ControlBarActionsProps extends WithStyles<typeof styles>, WithLocale {
allowRefresh?: boolean;
updateResources: () => void;
compact: boolean;
layerTitles: Record<keyof LayerVisibilities, string>;
layerSubtitles: Record<keyof LayerVisibilities, string>;
layerVisibilities: LayerVisibilities;
setLayerVisibility: (
layerId: keyof LayerVisibilities,
visible: boolean,
) => void;
variableCompareMode: boolean;
setVariableCompareMode: (selected: boolean) => void;
}

const _ControlBarActions: React.FC<ControlBarActionsProps> = ({
classes,
locale,
visible,
volumeCardOpen,
showVolumeCard,
Expand All @@ -84,8 +89,12 @@ const _ControlBarActions: React.FC<ControlBarActionsProps> = ({
allowRefresh,
updateResources,
compact,
layerTitles,
layerSubtitles,
layerVisibilities,
setLayerVisibility,
variableCompareMode,
setVariableCompareMode,
}) => {
if (!visible) {
return null;
Expand All @@ -95,9 +104,14 @@ const _ControlBarActions: React.FC<ControlBarActionsProps> = ({

const layerSelect = (
<LayerSelect
locale={locale}
openDialog={openDialog}
layerTitles={layerTitles}
layerSubtitles={layerSubtitles}
layerVisibilities={layerVisibilities}
setLayerVisibility={setLayerVisibility}
openDialog={openDialog}
variableCompareMode={variableCompareMode}
setVariableCompareMode={setVariableCompareMode}
/>
);

Expand Down
4 changes: 2 additions & 2 deletions src/components/LayerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import MenuItem from "@mui/material/MenuItem";
import ListItemText from "@mui/material/ListItemText";
import Menu from "@mui/material/Menu";

import { getLayerLabel, LayerDefinition } from "@/model/layerDefinition";
import { getLayerTitle, LayerDefinition } from "@/model/layerDefinition";

interface LayerMenuProps {
anchorElement: Element | null;
Expand Down Expand Up @@ -36,7 +36,7 @@ const LayerMenu = ({
}
dense
>
<ListItemText primary={getLayerLabel(layer)} />
<ListItemText primary={getLayerTitle(layer)} />
</MenuItem>
))}
</Menu>
Expand Down
33 changes: 25 additions & 8 deletions src/components/LayerSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,31 @@ import i18n from "@/i18n";
import { WithLocale } from "@/util/lang";
import { LayerVisibilities } from "@/states/controlState";
import LayerSelectItem from "./LayerSelectItem";
import SelectableMenuItem from "@/components/SelectableMenuItem";

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

interface LayerSelectProps extends WithStyles<typeof styles>, WithLocale {
openDialog: (dialogId: string) => void;
layerTitles: Record<keyof LayerVisibilities, string>;
layerSubtitles: Record<keyof LayerVisibilities, string>;
layerVisibilities: LayerVisibilities;
setLayerVisibility: (
layerId: keyof LayerVisibilities,
visible: boolean,
) => void;
variableCompareMode: boolean;
setVariableCompareMode: (selected: boolean) => void;
}

const _LayerSelect: React.FC<LayerSelectProps> = (props) => {
const { openDialog, ...otherProps } = props;
const {
openDialog,
variableCompareMode,
setVariableCompareMode,
...layerSelectProps
} = props;
const [menuAnchor, setMenuAnchor] = React.useState<Element | null>(null);

const handleUserOverlays = () => {
Expand Down Expand Up @@ -82,13 +92,20 @@ const _LayerSelect: React.FC<LayerSelectProps> = (props) => {
>
<Paper>
<MenuList dense>
<LayerSelectItem layerId="baseMap" {...otherProps} />
<LayerSelectItem layerId="datasetRgb" {...otherProps} />
<LayerSelectItem layerId="datasetVariable" {...otherProps} />
<LayerSelectItem layerId="datasetBoundary" {...otherProps} />
<LayerSelectItem layerId="datasetPlaces" {...otherProps} />
<LayerSelectItem layerId="userPlaces" {...otherProps} />
<LayerSelectItem layerId="overlay" {...otherProps} />
<LayerSelectItem layerId="baseMap" {...layerSelectProps} />
<LayerSelectItem layerId="datasetRgb" {...layerSelectProps} />
<LayerSelectItem layerId="datasetVariable2" {...layerSelectProps} />
<LayerSelectItem layerId="datasetVariable" {...layerSelectProps} />
<LayerSelectItem layerId="datasetBoundary" {...layerSelectProps} />
<LayerSelectItem layerId="datasetPlaces" {...layerSelectProps} />
<LayerSelectItem layerId="userPlaces" {...layerSelectProps} />
<LayerSelectItem layerId="overlay" {...layerSelectProps} />
<Divider />
<SelectableMenuItem
title={i18n.get("Compare Mode (Swipe)")}
selected={variableCompareMode}
onClick={() => setVariableCompareMode(!variableCompareMode)}
/>
<Divider />
<MenuItem onClick={handleUserBaseMaps}>
{i18n.get("User Base Maps") + "..."}
Expand Down
53 changes: 16 additions & 37 deletions src/components/LayerSelectItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,56 +22,35 @@
* SOFTWARE.
*/

import * as React from "react";
import Check from "@mui/icons-material/Check";
import MenuItem from "@mui/material/MenuItem";
import ListItemText from "@mui/material/ListItemText";
import ListItemIcon from "@mui/material/ListItemIcon";

import i18n from "@/i18n";
import { LayerVisibilities } from "@/states/controlState";

const layerLabels: Record<keyof LayerVisibilities, string> = {
baseMap: "Base Map",
datasetRgb: "Dataset RGB",
datasetVariable: "Dataset Variable",
datasetBoundary: "Dataset Boundary",
datasetPlaces: "Dataset Places",
userPlaces: "User Places",
overlay: "Overlay",
};
import SelectableMenuItem from "@/components/SelectableMenuItem";

interface LayerSelectItemProps {
layerId: keyof LayerVisibilities;
layerTitles: Record<keyof LayerVisibilities, string>;
layerSubtitles: Record<keyof LayerVisibilities, string>;
layerVisibilities: LayerVisibilities;
setLayerVisibility: (
layerId: keyof LayerVisibilities,
visible: boolean,
) => void;
}

const LayerSelectItem: React.FC<LayerSelectItemProps> = ({
export default function LayerSelectItem({
layerId,
layerTitles,
layerSubtitles,
layerVisibilities,
setLayerVisibility,
}) => {
const visible = layerVisibilities[layerId];
const label = i18n.get(layerLabels[layerId]);

const handleClick = () => setLayerVisibility(layerId, !visible);

return visible ? (
<MenuItem onClick={handleClick}>
<ListItemIcon>
<Check />
</ListItemIcon>
{label}
</MenuItem>
) : (
<MenuItem onClick={handleClick}>
<ListItemText inset>{label}</ListItemText>
</MenuItem>
}: LayerSelectItemProps) {
const visible = !!layerVisibilities[layerId];
return (
<SelectableMenuItem
title={i18n.get(layerTitles[layerId])}
subtitle={layerSubtitles[layerId]}
selected={visible}
onClick={() => setLayerVisibility(layerId, !visible)}
/>
);
};

export default LayerSelectItem;
}
Loading

0 comments on commit 38fabb0

Please sign in to comment.