Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add subitems to layers (either layers or controls or a mixture of both) #1011

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
f791429
Add subitems to a layer (either layers or controls).
HaudinFlorence Jul 1, 2022
e89f60f
Update the example notebook Subitems.ipynb.
HaudinFlorence Aug 10, 2022
bdd4af2
Fix flake8 formatting issue.
HaudinFlorence Aug 10, 2022
cba6f73
Remove Choropleth.ipynb notebook from commited files.
HaudinFlorence Aug 11, 2022
8ccc3bd
Restore Choropleth notebook.
HaudinFlorence Aug 12, 2022
b2532f2
Take Choropleth notebook version from master.
HaudinFlorence Aug 12, 2022
6845e66
Update the example notebook Subitems.ipynb.
HaudinFlorence Sep 5, 2022
219d4be
Simplify importation from ipyleaflet.
HaudinFlorence Sep 5, 2022
e0eb639
Update ipyleaflet/leaflet.py
HaudinFlorence Sep 5, 2022
4e52717
Update Map.js according to the review comments.
HaudinFlorence Sep 5, 2022
ac03e1f
Update js/src/Map.js
HaudinFlorence Sep 6, 2022
362b484
Update js/src/Map.js
HaudinFlorence Sep 6, 2022
ce5dcec
Update Map.js and update example notebook Subitems.ipynb.
HaudinFlorence Sep 6, 2022
60fa8ff
Update add_subitem_model and remove_subitem_view using instanceof che…
HaudinFlorence Sep 6, 2022
f3750c1
Remove files that should not be tracked.
HaudinFlorence Sep 6, 2022
cac3916
Update js/src/Map.js
HaudinFlorence Sep 6, 2022
9157fc0
Update js/src/Map.js
HaudinFlorence Sep 6, 2022
cc9d01a
Update ipyleaflet/leaflet.py
HaudinFlorence Sep 6, 2022
efb1879
Add a Subitems.ipynb notebooks in ui-tests/notebooks and update the e…
HaudinFlorence Sep 6, 2022
c74e7ab
Retry the CI tests.
HaudinFlorence Sep 12, 2022
b078e34
Update Subitems.ipynb in ui-tests/notebooks.
HaudinFlorence Sep 12, 2022
665018b
Add pandas in install_requires in setup.py.
HaudinFlorence Sep 12, 2022
3bbcb57
Try to remove the MagnifyingGlass item in ui-tests/notebooks/Subitem…
HaudinFlorence Sep 12, 2022
30558c3
Re try CI tests.
HaudinFlorence Sep 12, 2022
b62bf9a
Update Playwright Snapshots
github-actions[bot] Sep 12, 2022
5c1ede7
Fix the failing ui-test by setting spin to false for the icon1 Awesom…
HaudinFlorence Sep 12, 2022
c992a40
Remove the marker with an icon and replace it by a simple one.
HaudinFlorence Sep 12, 2022
e53dc31
Restore the marker with the icon.
HaudinFlorence Sep 12, 2022
70aa0b7
Update Playwright Snapshots
github-actions[bot] Sep 12, 2022
7bedabf
Retry CI tests after the update of the galata references.
HaudinFlorence Sep 12, 2022
57c8fa1
Update Layer.js and Map.js to deal with the model and view of subitem…
HaudinFlorence Sep 20, 2022
88f78fc
Update Layer.js and the example notebook Subitems.ipynb.
HaudinFlorence Sep 20, 2022
b4f91bb
Update setup.py
HaudinFlorence Sep 20, 2022
e4b2804
Add pandas dependency in tests and fix linting in Layers.js.
HaudinFlorence Sep 21, 2022
095ff12
Remove pandas version in tests dependencies.
HaudinFlorence Sep 21, 2022
c52fc55
Change layer2 basemap in ui-tests/notebooks/Subitems, to try to fix t…
HaudinFlorence Sep 22, 2022
e286bf1
Suppress an empty cell in ui-tests/notebooks/Subitems.ipynb.
HaudinFlorence Sep 23, 2022
6e102e8
Remove ui-tests/tests/ipyleaflet.test.ts-snapshots/Subitems-linux.png.
HaudinFlorence Sep 23, 2022
9481f92
Merge branch 'master' into add_subitems_to_layers
martinRenou Sep 23, 2022
5552afc
Update Playwright Snapshots
github-actions[bot] Sep 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ui-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
channels: conda-forge

- name: Mamba install dependencies
run: mamba install python=${{ matrix.python-version }} pip nodejs=16 flake8 jupyterlab ipywidgets>=8.0.1 jupyter-packaging~=0.7.9
run: mamba install python=${{ matrix.python-version }} pip nodejs=16 flake8 jupyterlab ipywidgets>=8.0.1 jupyter-packaging~=0.7.9 pandas

- name: Install ipyleaflet
run: pip install .
Expand Down
182 changes: 182 additions & 0 deletions examples/Subitems.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Set up for JupyterLite\n",
"try:\n",
" import piplite\n",
" await piplite.install('ipyleaflet')\n",
"except ImportError:\n",
" pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ipyleaflet import Map, Marker, Choropleth, MagnifyingGlass, ColormapControl, AwesomeIcon, basemaps, basemap_to_tiles\n",
"import json\n",
"import pandas as pd\n",
"from ipywidgets import link, FloatSlider\n",
"from branca.colormap import linear\n",
"center = (43, -100)\n",
"zoom = 4"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"geo_json_data = json.load(open(\"us-states.json\"))\n",
"m1 = Map(center=center, zoom=zoom)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"unemployment = pd.read_csv(\"US_Unemployment_Oct2012.csv\")\n",
"unemployment = dict(\n",
" zip(unemployment[\"State\"].tolist(), unemployment[\"Unemployment\"].tolist())\n",
")\n",
"\n",
"marker1 = Marker(location=(center))\n",
"\n",
"layer1 = Choropleth(\n",
" geo_data=geo_json_data,\n",
" choro_data=unemployment,\n",
" colormap=linear.YlOrRd_04,\n",
" style={\"fillOpacity\": 0.8, \"dashArray\": \"5, 5\"},\n",
" subitems= (marker1,)\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1.add(layer1)\n",
"m1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1.remove(layer1)\n",
"m1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1.add(layer1)\n",
"colormap_control1 = ColormapControl(\n",
" caption='Unemployment rate',\n",
" colormap=layer1.colormap,\n",
" value_min=layer1.value_min,\n",
" value_max=layer1.value_max,\n",
" position='topright',\n",
" transparent_bg=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"layer1.subitems = layer1.subitems+(colormap_control1,)\n",
"m1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"marker2 = Marker(location=(center[0]-4, center[1] - 4))\n",
"marker3 = Marker(location=(center[0]-8, center[1] - 8))\n",
"layer2 = basemap_to_tiles(basemaps.Strava.Water, subitems= (marker2,))\n",
"icon1 = AwesomeIcon(\n",
" name='gear',\n",
" marker_color='blue',\n",
" icon_color='darkblue',\n",
" spin=True\n",
" \n",
")\n",
"marker4 = Marker(icon=icon1, location=(center[0], center[1] - 4))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"layer2.subitems = layer2.subitems+(marker3, marker4)\n",
"m1.add(layer2)\n",
"m1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1.remove(layer1)\n",
"m1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1.remove(layer2)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
15 changes: 15 additions & 0 deletions ipyleaflet/leaflet.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,19 @@ class Layer(Widget, InteractMixin):
pane = Unicode('').tag(sync=True)

options = List(trait=Unicode()).tag(sync=True)
subitems = Tuple().tag(trait=Instance(Widget), sync=True, **widget_serialization)

@validate('subitems')
def _validate_subitems(self, proposal):
'''Validate subitems list.

Makes sure only one instance of any given subitem can exist in the
subitem list.
'''
subitem_ids = [subitem.model_id for subitem in proposal.value]
if len(set(subitem_ids)) != len(subitem_ids):
raise Exception('duplicate subitem detected, only use each subitem once')
return proposal.value

def __init__(self, **kwargs):
super(Layer, self).__init__(**kwargs)
Expand Down Expand Up @@ -2537,6 +2550,7 @@ def add(self, item):
if item.model_id in self._control_ids:
raise ControlException('control already on map: %r' % item)
self.controls = tuple([control for control in self.controls] + [item])

return self

def remove(self, item):
Expand Down Expand Up @@ -2635,4 +2649,5 @@ async def _fit_bounds(self, bounds):
else:
self.zoom -= 1
await wait_for_change(self, 'bounds')

break
9 changes: 4 additions & 5 deletions js/src/Map.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.


const widgets = require('@jupyter-widgets/base');
const L = require('./leaflet.js');
const utils = require('./utils.js');
Expand Down Expand Up @@ -158,6 +157,7 @@ LeafletMapModel.serializers = {
dragging_style: { deserialize: widgets.unpack_models }
};


export class LeafletMapView extends utils.LeafletDOMWidgetView {
initialize(options) {
super.initialize(options);
Expand Down Expand Up @@ -188,12 +188,11 @@ export class LeafletMapView extends utils.LeafletDOMWidgetView {
}).then(view => {
this.obj.addLayer(view.obj);

// Trigger the displayed event of the child view.
this.displayed.then(() => {
view.trigger('displayed', this);
});

return view;

});
}

Expand All @@ -208,11 +207,11 @@ export class LeafletMapView extends utils.LeafletDOMWidgetView {
}).then(view => {
this.obj.addControl(view.obj);


// Trigger the displayed event of the child view.
this.displayed.then(() => {
view.trigger('displayed', this);
});

return view;
});
}
Expand Down Expand Up @@ -483,4 +482,4 @@ export class LeafletMapView extends utils.LeafletDOMWidgetView {
break;
}
}
}
}
50 changes: 48 additions & 2 deletions js/src/layers/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ export class LeafletLayerModel extends widgets.WidgetModel {
popup_min_width: 50,
popup_max_width: 300,
popup_max_height: null,
pane: ''
pane: '',
subitems: []
};
}
}

LeafletLayerModel.serializers = {
...widgets.WidgetModel.serializers,
popup: { deserialize: widgets.unpack_models }
popup: { deserialize: widgets.unpack_models },
subitems: { deserialize: widgets.unpack_models }
};



export class LeafletUILayerModel extends LeafletLayerModel {
defaults() {
return {
Expand All @@ -51,6 +55,33 @@ export class LeafletLayerView extends utils.LeafletWidgetView {
this.popup_content_promise = Promise.resolve();
}

remove_subitem_view(child_view) {
if(child_view instanceof LeafletLayerView) {
this.map_view.obj.removeLayer(child_view.obj);
} else {
this.map_view.obj.removeControl(child_view.obj);
}
child_view.remove();
}

add_subitem_model(child_model) {
return this.create_child_view(child_model, {
map_view: this
}).then(view => {
if (child_model instanceof LeafletLayerModel) {
this.map_view.obj.addLayer(view.obj);
} else {
this.map_view.obj.addControl(view.obj);
}

//Trigger the displayed event of the child view.
this.displayed.then(() => {
view.trigger('displayed', this);
});
return view;
});
}

render() {
return Promise.resolve(this.create_obj()).then(() => {
this.leaflet_events();
Expand All @@ -60,6 +91,12 @@ export class LeafletLayerView extends utils.LeafletWidgetView {
this.bind_popup(value);
});
this.update_pane();
this.subitem_views = new widgets.ViewList(
this.add_subitem_model,
this.remove_subitem_view,
this
);
martinRenou marked this conversation as resolved.
Show resolved Hide resolved
this.subitem_views.update(this.model.get('subitems'));
});
}

Expand Down Expand Up @@ -128,10 +165,19 @@ export class LeafletLayerView extends utils.LeafletWidgetView {
},
this
);
this.listenTo(
this.model,
'change:subitems',
function () {
this.subitem_views.update(this.subitems);
},
this
);
}

remove() {
martinRenou marked this conversation as resolved.
Show resolved Hide resolved
super.remove();
this.subitem_views.remove();
this.popup_content_promise.then(() => {
if (this.popup_content) {
this.popup_content.remove();
Expand Down
2 changes: 1 addition & 1 deletion js/src/layers/LayerGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class LeafletLayerGroupModel extends layer.LeafletLayerModel {
}

LeafletLayerGroupModel.serializers = {
...widgets.WidgetModel.serializers,
...layer.LeafletLayerModel.serializers,
layers: { deserialize: widgets.unpack_models }
};

Expand Down
Loading