Skip to content

Commit

Permalink
Add a visibility icon and fix the visibility layer with mapLibre
Browse files Browse the repository at this point in the history
  • Loading branch information
brichet committed Jun 25, 2024
1 parent 47eb946 commit 4999398
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 107 deletions.
53 changes: 50 additions & 3 deletions examples/test.jGIS
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,25 @@
"sources": {
"699facc9-e7c4-4f38-acf1-1fd7f02d9f36": {
"type": "RasterSource",
"name": "RasterSource",
"name": "Open Street Map",
"parameters": {
"url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
"minZoom": 0,
"maxZoom": 24
}
},
"5fd42e3b-4681-4607-b15d-65c3a3e89b32": {
"type": "RasterSource",
"name": "Open Topo Map",
"parameters": {
"url": "https://tile.opentopomap.org/{z}/{x}/{y}.png ",
"minZoom": 0,
"maxZoom": 24
}
},
"f22850a8-bfd5-4dfb-ba1e-c3f2c3ccf93b": {
"type": "RasterSource",
"name": "Open Street Map 2",
"parameters": {
"url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
"minZoom": 0,
Expand All @@ -17,12 +35,41 @@
"source": "699facc9-e7c4-4f38-acf1-1fd7f02d9f36"
},
"visible": true,
"name": "RasterSource Layer"
"name": "Open Street Map"
},
"a0044fd7-f167-445f-b3d1-620a8f94b498": {
"type": "RasterLayer",
"parameters": {
"source": "5fd42e3b-4681-4607-b15d-65c3a3e89b32"
},
"visible": true,
"name": "Open Topo Map"
},
"a5ac7671-74bb-4c99-a494-916348397d01": {
"type": "RasterLayer",
"parameters": {
"source": "f22850a8-bfd5-4dfb-ba1e-c3f2c3ccf93b"
},
"visible": true,
"name": "Open Street Map 2"
}
},
"layerTree": {
"name": "",
"layers": ["2467576f-b527-4cb7-998d-fa1d056fb8a1"]
"layers": [
"2467576f-b527-4cb7-998d-fa1d056fb8a1",
{
"name": "level 1 group",
"layers": [
"a0044fd7-f167-445f-b3d1-620a8f94b498",
{
"name": "level 2 group",
"layers": ["a5ac7671-74bb-4c99-a494-916348397d01"]

}
]
}
]
},
"options": {}
}
12 changes: 12 additions & 0 deletions packages/base/src/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@
import { LabIcon } from '@jupyterlab/ui-components';

import rasterSvgStr from '../style/icons/raster.svg';
import visibilitySvgStr from '../style/icons/visibility.svg';
import nonVisibilitySvgStr from '../style/icons/nonvisibility.svg';

export const rasterIcon = new LabIcon({
name: 'jupytergis::raster',
svgstr: rasterSvgStr
});

export const visibilityIcon = new LabIcon({
name: 'jupytergis::visibility',
svgstr: visibilitySvgStr
});

export const nonVisibilityIcon = new LabIcon({
name: 'jupytergis::nonVisibility',
svgstr: nonVisibilitySvgStr
});
27 changes: 20 additions & 7 deletions packages/base/src/mainview/mainview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,26 @@ export class MainView extends React.Component<IProps, IStates> {
// TODO If the source already existed, update it
}

this._Map.addLayer({
id: layerId,
type: 'raster',
source: sourceId,
minzoom: source.minZoom || 0,
maxzoom: source.maxZoom || 24
});
const mapLayer = this._Map.getLayer(layerId);
if (!mapLayer) {
this._Map.addLayer({
id: layerId,
type: 'raster',
layout: {
visibility: layer.visible ? 'visible' : 'none'
},
source: sourceId,
minzoom: source.minZoom || 0,
maxzoom: source.maxZoom || 24
});
} else {
mapLayer.source = sourceId;
this._Map.setLayoutProperty(
layerId,
'visibility',
layer.visible ? 'visible' : 'none'
);
}
}
}
}
Expand Down
93 changes: 58 additions & 35 deletions packages/base/src/panelview/components/layers.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import {
IJGISLayer,
IJGISLayerGroup,
IJupyterGISModel
} from '@jupytergis/schema';
import { LabIcon, ReactWidget, caretDownIcon } from '@jupyterlab/ui-components';
import {IJGISLayerGroup, IJupyterGISModel} from '@jupytergis/schema';
import { Button, LabIcon, ReactWidget, caretDownIcon } from '@jupyterlab/ui-components';
import { ISignal, Signal } from '@lumino/signaling';
import { Panel } from '@lumino/widgets';
import React, { useEffect, useState } from 'react';
import { rasterIcon } from '../../icons';
import { nonVisibilityIcon, rasterIcon, visibilityIcon } from '../../icons';

const LAYERS_PANEL_CLASS = 'jp-gis-layerPanel';
const LAYERS_ENTRY_CLASS = 'jp-gis-layerEntry';
const LAYERS_GROUP_CLASS = 'jp-gis-layerGroup';
const LAYERS_GROUP_HEADER_CLASS = 'jp-gis-layerGroupHeader';
const LAYERS_GROUP_COLLAPSER_CLASS = 'jp-gis-layerGroupCollapser';
const LAYERS_ITEM_CLASS = 'jp-gis-layerItem';
const LAYERS_ITEM_TITLE_CLASS = 'jp-gis-layerItemTitle';
const LAYERS_ICON_CLASS = 'jp-gis-layerIcon';

/**
Expand All @@ -32,21 +29,21 @@ export namespace LayersPanel {
*/
export interface IBodyProps extends IOptions {
modelChanged: ISignal<LayersPanel, IJupyterGISModel | undefined>;
onSelect: (layer?: IJGISLayer) => void;
onSelect: (layer?: string) => void;
}
/**
* Properties of the layer group component.
*/
export interface ILayerGroupProps extends IOptions {
group: IJGISLayerGroup | undefined;
onClick: (item?: IJGISLayer) => void;
onClick: (item?: string) => void;
}
/**
* Properties of the layer item component.
*/
export interface ILayerItemProps extends IOptions {
layer: IJGISLayer | undefined;
onClick: (item?: IJGISLayer) => void;
layerId: string;
onClick: (item?: string) => void;
}
}

Expand Down Expand Up @@ -90,7 +87,7 @@ export class LayersPanel extends Panel {
*
* @param layer - the selected layer.
*/
private _onSelect = (layer?: IJGISLayer) => {
private _onSelect = (layer?: string) => {
if (this._model) {
this._model.currentLayer = layer ?? null;
}
Expand All @@ -114,7 +111,7 @@ export function LayersBody(props: LayersPanel.IBodyProps): JSX.Element {
/**
* Propagate the layer selection.
*/
const onItemClick = (item?: IJGISLayer) => {
const onItemClick = (item?: string) => {
props.onSelect(item);
};

Expand Down Expand Up @@ -148,7 +145,7 @@ export function LayersBody(props: LayersPanel.IBodyProps): JSX.Element {
typeof layer === 'string' ? (
<LayerItem
model={model}
layer={model?.getLayer(layer)}
layerId={layer}
onClick={onItemClick}
/>
) : (
Expand All @@ -163,12 +160,16 @@ export function LayersBody(props: LayersPanel.IBodyProps): JSX.Element {
* The component to handle group of layers.
*/
function LayerGroup(props: LayersPanel.ILayerGroupProps): JSX.Element {
const { group, model } = props;
if (group === undefined) {
return <></>;
}
const [open, setOpen] = useState<boolean>(false);
const name = props.group?.name ?? 'Undefined group';
const layers = props.group?.layers ?? [];
const name = group?.name ?? 'Undefined group';
const layers = group?.layers ?? [];

return (
<li className={`${LAYERS_ENTRY_CLASS} ${LAYERS_GROUP_CLASS}`}>
<div className={`${LAYERS_ENTRY_CLASS} ${LAYERS_GROUP_CLASS}`}>
<div onClick={() => setOpen(!open)} className={LAYERS_GROUP_HEADER_CLASS}>
<LabIcon.resolveReact
icon={caretDownIcon}
Expand All @@ -184,59 +185,81 @@ function LayerGroup(props: LayersPanel.ILayerGroupProps): JSX.Element {
{layers.map(layer =>
typeof layer === 'string' ? (
<LayerItem
model={props.model}
layer={props.model?.getLayer(layer)}
model={model}
layerId={layer}
onClick={props.onClick}
/>
) : (
<LayerGroup
model={props.model}
model={model}
group={layer}
onClick={props.onClick}
/>
)
)}
</div>
)}
</li>
</div>
);
}

/**
* The component to display a single layer.
*/
function LayerItem(props: LayersPanel.ILayerItemProps): JSX.Element {
if (props.layer === undefined) {
const { layerId, model } = props;
const layer = model?.getLayer(layerId);
if (layer === undefined) {
return <></>;
}
const [selected, setSelected] = useState<boolean>(
props.model?.currentLayer === props.layer
model?.currentLayer === layerId
);
const name = props.layer.name;
const name = layer.name;

/**
* Listen to the changes on the current layer.
*/
useEffect(() => {
const isSelected = () => {
setSelected(props.model?.currentLayer === props.layer);
setSelected(model?.currentLayer === layerId);
};
props.model?.currentLayerChanged.connect(isSelected);
model?.currentLayerChanged.connect(isSelected);

return () => {
props.model?.currentLayerChanged.disconnect(isSelected);
model?.currentLayerChanged.disconnect(isSelected);
};
}, []);
}, [model]);

/**
* Toggle layer visibility.
*/
const toggleVisibility = () => {
layer.visible = !layer.visible;
model?.sharedModel.updateLayer(layerId, layer);
}

return (
<li
<div
className={`${LAYERS_ENTRY_CLASS} ${LAYERS_ITEM_CLASS} ${selected ? 'jp-mod-selected' : ''}`}
onClick={() => props.onClick(props.layer)}
>
{props.layer.type === 'RasterLayer' && (
<LabIcon.resolveReact icon={rasterIcon} className={LAYERS_ICON_CLASS} />
)}
<span>{name}</span>
</li>
<div className={LAYERS_ITEM_TITLE_CLASS} onClick={() => props.onClick(layerId)}>
{layer.type === 'RasterLayer' && (
<LabIcon.resolveReact icon={rasterIcon} className={LAYERS_ICON_CLASS} />
)}
<span>{name}</span>
</div>
<Button
title={layer.visible ? 'Hide layer' : 'Show layer'}
onClick={toggleVisibility}
minimal
>
<LabIcon.resolveReact
icon={layer.visible ? visibilityIcon : nonVisibilityIcon}
className={LAYERS_ICON_CLASS}
tag='span'
/>
</Button>
</div>
);
}
51 changes: 1 addition & 50 deletions packages/base/style/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,4 @@
| Distributed under the terms of the Modified BSD License.
|---------------------------------------------------------------------------- */

.jp-gis-layerPanel {
list-style-type: none;
}

.jp-gis-layerEntry {
padding: 2px 12px;
}

.jp-gis-layerGroup {
display: flex;
flex-direction: column;
}

.jp-gis-layerGroupHeader {
display: flex;
margin-left: -2px;
padding-bottom: 4px;
}

.jp-gis-layerGroupHeader:hover {
cursor: pointer;
}

.jp-gis-layerGroupCollapser {
transform: rotate(-90deg);
margin: auto 0;
height: 16px;
}

.jp-gis-layerGroupCollapser.jp-mod-expanded {
transform: rotate(0deg);
}

.jp-gis-layerItem {
display: flex;
flex-direction: row;
}

.jp-gis-layerItem.jp-mod-selected {
color: var(--jp-ui-inverse-font-color1);
background: var(--jp-brand-color1);
}

.jp-gis-layerItem:hover {
cursor: pointer;
}

.jp-gis-layerItem .jp-gis-layerIcon {
padding-right: 4px;
}
@import url('./leftPanel.css');
8 changes: 8 additions & 0 deletions packages/base/style/icons/nonvisibility.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions packages/base/style/icons/visibility.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4999398

Please sign in to comment.