Skip to content

Commit 8fca983

Browse files
feat: add on_click to GeomanDrawControl (#1261)
* feat: add on_click to GeomanDrawControl * Fix: sourceTarget (clicked feature) instead of target (all features) * feat: add hover_style to GeomanDrawControl * lint * some workaround * update example --------- Co-authored-by: Oliver Lopez <[email protected]>
1 parent eaee59c commit 8fca983

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

docs/controls/geoman_draw_control.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Example
3636

3737
m = Map(center=(50, 354), zoom=5)
3838

39-
draw_control = GeomanDrawControl()
39+
draw_control = GeomanDrawControl(hover_style={"fillColor": "red"})
4040
draw_control.polyline = {
4141
"pathOptions": {
4242
"color": "#6bc2e5",
@@ -75,6 +75,14 @@ Example
7575
editable_circle = Circle(location=(50, 356), radius=100000, pm_ignore=False, color="red")
7676
m.add(editable_circle)
7777

78+
# Define click handler
79+
def handle_click(control, **kwargs):
80+
print("Click event detected!")
81+
print("Event content:", kwargs)
82+
83+
# Register click handler
84+
draw_control.on_click(handle_click)
85+
7886
m
7987

8088
Methods

python/ipyleaflet/ipyleaflet/leaflet.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2307,6 +2307,8 @@ class GeomanDrawControl(DrawControlBase):
23072307
_view_name = Unicode("LeafletGeomanDrawControlView").tag(sync=True)
23082308
_model_name = Unicode("LeafletGeomanDrawControlModel").tag(sync=True)
23092309

2310+
_click_callbacks = Instance(CallbackDispatcher, ())
2311+
23102312
# Current mode & shape
23112313
# valid values are: 'draw', 'edit', 'drag', 'remove', 'cut', 'rotate'
23122314
# for drawing, the tool can be added after ':' e.g. 'draw:marker'
@@ -2321,6 +2323,9 @@ class GeomanDrawControl(DrawControlBase):
23212323
polygon = Dict({ 'pathOptions': {} }).tag(sync=True)
23222324
circlemarker = Dict({ 'pathOptions': {} }).tag(sync=True)
23232325

2326+
# Hover style (applies for all drawing modes)
2327+
hover_style = Dict().tag(sync=True)
2328+
23242329
# Disabled by default
23252330
text = Dict().tag(sync=True)
23262331

@@ -2346,6 +2351,8 @@ def _handle_leaflet_event(self, _, content, buffers):
23462351
if not isinstance(geo_json, list):
23472352
geo_json = [geo_json]
23482353
self._draw_callbacks(self, action=action, geo_json=geo_json)
2354+
elif content.get('event', '').startswith('click'):
2355+
self._click_callbacks(self, **content)
23492356

23502357
def on_draw(self, callback, remove=False):
23512358
"""Add a draw event listener.
@@ -2359,6 +2366,19 @@ def on_draw(self, callback, remove=False):
23592366
"""
23602367
self._draw_callbacks.register_callback(callback, remove=remove)
23612368

2369+
def on_click(self, callback, remove=False):
2370+
"""Add a click event listener.
2371+
2372+
Parameters
2373+
----------
2374+
callback : callable
2375+
Callback function that will be called on click event.
2376+
remove: boolean
2377+
Whether to remove this callback or not. Defaults to False.
2378+
"""
2379+
self._click_callbacks.register_callback(callback, remove=remove)
2380+
2381+
23622382
def clear_text(self):
23632383
"""Clear all text."""
23642384
self.send({'msg': 'clear_text'})

python/jupyter_leaflet/src/controls/GeomanDrawControl.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,46 @@ export class LeafletGeomanDrawControlView extends LeafletControlView {
9393
}
9494
},
9595
});
96+
97+
// Click event handler
98+
this.feature_group.on('click', (e) => {
99+
this.send({
100+
event: 'click',
101+
geo_json: this.layer_to_json(e.sourceTarget),
102+
latlng: e.latlng,
103+
});
104+
});
105+
106+
// Apply hover styling to a single layer
107+
const applyHoverStyle = (layer: any) => {
108+
layer.on('mouseover', () => {
109+
const style = this.model.get('hover_style');
110+
if (style && typeof layer.setStyle === 'function') {
111+
if (!layer._originalStyle) {
112+
layer._originalStyle = { ...layer.options }; // clone to prevent mutation
113+
}
114+
layer.setStyle(style);
115+
}
116+
});
117+
118+
layer.on('mouseout', () => {
119+
if (layer._originalStyle && typeof layer.setStyle === 'function') {
120+
layer.setStyle(layer._originalStyle);
121+
}
122+
});
123+
};
124+
125+
// Apply to existing layers
126+
this.feature_group.eachLayer((layer: any) => {
127+
applyHoverStyle(layer);
128+
});
129+
130+
// Apply to new layers
131+
this.feature_group.on('layeradd', (e) => {
132+
const layer = e.layer;
133+
applyHoverStyle(layer);
134+
});
135+
96136
this.data_to_layers();
97137
this.map_view.obj.addLayer(this.feature_group);
98138

0 commit comments

Comments
 (0)