Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
174 changes: 87 additions & 87 deletions docs/assets/js/celldega.js

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion js/deck-gl/layers/edit_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ const has_edit_layer = (layers_obj) =>
layers_obj?.edit_layer && typeof layers_obj.edit_layer.clone === 'function';

// Forward declaration for function used before definition
function update_edit_layer_mode(layers_obj, mode) {
function update_edit_layer_mode(layers_obj, mode, modeConfig = null) {
if (!has_edit_layer(layers_obj)) {
return;
}

layers_obj.edit_layer = layers_obj.edit_layer.clone({
mode,
...(modeConfig ? { modeConfig } : {}),
});
}

Expand Down Expand Up @@ -148,6 +149,16 @@ const edit_layer_on_edit = async (
data: viz_state.edit.feature_collection,
});

if (editType === 'addTentativePosition' || editType === 'cancelFeature') {
const layers_list = get_layers_list(
layers_obj,
viz_state.close_up,
viz_state
);
deck_ist.setProps({ layers: layers_list });
return;
}

if (editType === 'addFeature') {
update_edit_layer_mode(layers_obj, ViewMode);

Expand Down
140 changes: 113 additions & 27 deletions js/ui/ui_containers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { DrawPolygonMode, ViewMode } from '@deck.gl-community/editable-layers';
import {
DrawPolygonByDraggingMode,
ViewMode,
} from '@deck.gl-community/editable-layers';
import * as d3 from 'd3';

import { toggle_background_layer_visibility } from '../deck-gl/layers/background_layer';
Expand Down Expand Up @@ -101,6 +104,67 @@ export const make_slider_container = (class_name) => {
return slider_container;
};

const SKETCH_MODE_CONFIG = {
throttleMs: 16,
};

const ignores_sketch_shortcut = (event) => {
if (
event.defaultPrevented ||
event.metaKey ||
event.ctrlKey ||
event.altKey
) {
return true;
}

const { target } = event;
const tag_name = target?.tagName?.toLowerCase();
return (
target?.isContentEditable ||
tag_name === 'input' ||
tag_name === 'textarea' ||
tag_name === 'select' ||
tag_name === 'button'
);
};

const set_sketch_mode = (active, deck_ist, layers_obj, viz_state) => {
const sketch_button = viz_state.edit?.buttons?.sktch;
if (!sketch_button) return;

const button = d3.select(sketch_button);

if (active) {
button.classed('active', true).style('color', 'blue');
viz_state.edit.mode = 'sktch';

update_edit_layer_mode(
layers_obj,
DrawPolygonByDraggingMode,
SKETCH_MODE_CONFIG
);
update_cell_pickable_state(layers_obj, false);
update_path_pickable_state(layers_obj, false);
update_trx_pickable_state(layers_obj, false);
} else {
button.classed('active', false).style('color', 'gray');
viz_state.edit.mode = 'view';

update_edit_layer_mode(layers_obj, ViewMode);
update_cell_pickable_state(layers_obj, true);
update_path_pickable_state(layers_obj, true);
update_trx_pickable_state(layers_obj, true);
}

const layers_list = get_layers_list(
layers_obj,
viz_state.close_up,
viz_state
);
deck_ist.setProps({ layers: layers_list });
};

/**
* Get a short display name for an axis entity.
* Returns "Row" or "Col" if no entity is specified or if entity is "N.A.".
Expand Down Expand Up @@ -1064,32 +1128,7 @@ export const make_ist_ui_container = (
const current = d3.select(event.currentTarget);
const is_active = current.classed('active');

if (is_active === false) {
current.classed('active', true).style('color', 'blue');

_viz_state.edit.mode = 'sktch';

update_edit_layer_mode(_layers_obj, DrawPolygonMode);
update_cell_pickable_state(_layers_obj, false);
update_path_pickable_state(_layers_obj, false);
update_trx_pickable_state(_layers_obj, false);
} else {
_viz_state.edit.mode = 'view';

current.classed('active', false).style('color', 'gray');

update_edit_layer_mode(_layers_obj, ViewMode);
update_cell_pickable_state(_layers_obj, true);
update_path_pickable_state(_layers_obj, true);
update_trx_pickable_state(_layers_obj, true);
}

const layers_list = get_layers_list(
_layers_obj,
_viz_state.close_up,
_viz_state
);
_deck_ist.setProps({ layers: layers_list });
set_sketch_mode(!is_active, _deck_ist, _layers_obj, _viz_state);
};

// Create NBHD button when nbhd_edit is true (replaces the old EDIT button)
Expand Down Expand Up @@ -1119,6 +1158,53 @@ export const make_ist_ui_container = (
// SKTCH button is hidden initially, shown when NBHD edit mode is active
d3.select(viz_state.edit.buttons.sktch).style('display', 'none');

// Tear down any listeners left by a previous call on this viz_state before
// possibly re-registering below, so re-running make_ist_ui_container can't
// orphan them (including when nbhd.edit has flipped to false since then).
viz_state.edit.cleanup_shortcuts?.();

if (viz_state.nbhd.edit) {
// The keydown listener is global, but the shortcut is scoped to this
// widget by checking whether the pointer is over this Landscape's root
// at keydown time. Without this, pressing 's' would toggle every
// Landscape on the page (e.g. multiple widgets in a notebook) at once.
const root_el = viz_state.root;

const sketch_keydown_callback = (event) => {
if (!root_el?.matches(':hover')) return;

const key = event.key?.toLowerCase();
if (key !== 's' && event.key !== 'Escape') return;
if (ignores_sketch_shortcut(event)) return;
if (!viz_state.obs_store.viz_edit_layer.get()) return;

// Escape exits sketch mode; 's' enters it. (Completing a stroke also
// auto-exits via the addFeature handler, so sketch mode is single-shot.)
if (event.key === 'Escape') {
if (viz_state.edit.mode !== 'sktch') return;
event.preventDefault();
event.stopPropagation();
set_sketch_mode(false, deck_ist, layers_obj, viz_state);
return;
}

if (viz_state.edit.mode === 'sktch') return;
if (viz_state.edit.mode === 'modify') return;

event.preventDefault();
event.stopPropagation();
set_sketch_mode(true, deck_ist, layers_obj, viz_state);
};

// Capture phase so this scoped shortcut can claim the keystroke (via
// stopPropagation) before page-level handlers like Jupyter's own
// command-mode 's'-to-save binding see it.
document.addEventListener('keydown', sketch_keydown_callback, true);
viz_state.edit.cleanup_shortcuts = () => {
document.removeEventListener('keydown', sketch_keydown_callback, true);
};
}

make_edit_button(
deck_ist,
layers_obj,
Expand Down
3 changes: 3 additions & 0 deletions js/viz/landscape_ist.js
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ export const landscape_ist = async (
.style('display', 'inline-flex')
.style('color', 'gray')
.classed('active', false);
viz_state.edit.mode = 'view';
if (viz_state.nbhd.edit && viz_state.containers.nbhd_opacity_slider) {
d3.select(viz_state.containers.nbhd_opacity_slider).style(
'display',
Expand All @@ -774,6 +775,7 @@ export const landscape_ist = async (
update_cell_pickable_state(layers_obj, true);
update_path_pickable_state(layers_obj, true);
update_trx_pickable_state(layers_obj, true);
viz_state.edit.mode = 'view';
if (viz_state.nbhd.edit && viz_state.containers.nbhd_opacity_slider) {
d3.select(viz_state.containers.nbhd_opacity_slider).style(
'display',
Expand Down Expand Up @@ -1103,6 +1105,7 @@ export const landscape_ist = async (
},
update_layers: () => {},
finalize: () => {
viz_state.edit?.cleanup_shortcuts?.();
deck_ist.finalize();
},
};
Expand Down
3 changes: 2 additions & 1 deletion notebooks/Atera_viz.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
"landscape = dega.viz.Landscape(\n",
" technology='Xenium',\n",
" base_url = base_url,\n",
" max_tiles_to_view=25\n",
" max_tiles_to_view=25,\n",
" nbhd_edit=True\n",
")"
]
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "celldega",
"version": "0.18.1",
"version": "0.19.0",
"type": "module",
"engines": {
"node": ">=16",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build-backend = "hatchling.build"

[project]
name = "celldega"
version = "0.18.1"
version = "0.19.0"
readme = "README.md"
requires-python = ">=3.11,<3.13"
dependencies = [
Expand Down
Loading