mapshaper 0.6.66 → 0.6.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4306,6 +4306,7 @@
4306
4306
 
4307
4307
  if (opts.pinnable) classes += ' pinnable';
4308
4308
  if (map.isActiveLayer(lyr)) classes += ' active';
4309
+ if (lyr.hidden) classes += ' invisible';
4309
4310
  if (lyr.pinned) classes += ' pinned';
4310
4311
 
4311
4312
  html = '<!-- ' + lyr.menu_id + '--><div class="' + classes + '">';
@@ -4384,10 +4385,24 @@
4384
4385
  // init pin button
4385
4386
  GUI.onClick(entry.findChild('img.black-eye'), function(e) {
4386
4387
  var target = findLayerById(id);
4387
- var pinned = target.layer.pinned;
4388
+ var lyr = target.layer;
4389
+ var active = map.isActiveLayer(lyr);
4390
+ var hidden = false; // active && lyr.hidden || false;
4391
+ var pinned = false;
4392
+ var unpinned = false;
4388
4393
  e.stopPropagation();
4389
- map.setLayerPinning(target, !pinned);
4390
- entry.classed('pinned', !pinned);
4394
+ if (active) {
4395
+ hidden = !lyr.hidden;
4396
+ pinned = !hidden && lyr.unpinned;
4397
+ unpinned = lyr.pinned && hidden;
4398
+ } else {
4399
+ pinned = !lyr.pinned;
4400
+ }
4401
+ lyr.hidden = hidden;
4402
+ lyr.unpinned = unpinned;
4403
+ map.setLayerPinning(target, pinned);
4404
+ entry.classed('pinned', pinned);
4405
+ entry.classed('invisible', hidden);
4391
4406
  updatePinAllButton();
4392
4407
  map.redraw();
4393
4408
  });
@@ -4413,12 +4428,16 @@
4413
4428
  GUI.onClick(entry, function() {
4414
4429
  var target = findLayerById(id);
4415
4430
  // don't select if user is typing or dragging
4416
- if (!GUI.textIsSelected() && !dragging) {
4417
- gui.clearMode();
4418
- if (!map.isActiveLayer(target.layer)) {
4419
- model.selectLayer(target.layer, target.dataset);
4420
- }
4431
+ if (GUI.textIsSelected() || dragging) return;
4432
+ // undo any temporary hiding when layer is selected
4433
+ target.layer.hidden = false;
4434
+ if (!map.isActiveLayer(target.layer)) {
4435
+ model.selectLayer(target.layer, target.dataset);
4421
4436
  }
4437
+ // close menu after a delay
4438
+ setTimeout(function() {
4439
+ gui.clearMode();
4440
+ }, 230);
4422
4441
  });
4423
4442
  }
4424
4443
 
@@ -7238,7 +7257,7 @@
7238
7257
  self.clearSelection();
7239
7258
  });
7240
7259
 
7241
- gui.on('box_drag_start', function() {
7260
+ gui.on('shift_drag_start', function() {
7242
7261
  self.clearHover();
7243
7262
  });
7244
7263
 
@@ -7801,6 +7820,7 @@
7801
7820
  function onMouseUp(e) {
7802
7821
  var evt = procMouseEvent(e),
7803
7822
  elapsed, dx, dy;
7823
+ _self.dispatchEvent('mouseup', evt);
7804
7824
  if (_dragging) {
7805
7825
  stopDragging(evt);
7806
7826
  }
@@ -7828,6 +7848,7 @@
7828
7848
 
7829
7849
  function onMouseMove(e) {
7830
7850
  var evt = procMouseEvent(e);
7851
+ _self.dispatchEvent('mousemove', evt);
7831
7852
  if (!_dragging && _downEvt && _downEvt.hover) {
7832
7853
  _dragging = true;
7833
7854
  _self.dispatchEvent('dragstart', evt);
@@ -7894,13 +7915,19 @@
7894
7915
 
7895
7916
  function HighlightBox(gui, optsArg) {
7896
7917
  var el = El('div').addClass('zoom-box').appendTo('body'),
7897
- opts = Object.assign({handles: false, persistent: false}, optsArg),
7918
+ opts = Object.assign({
7919
+ name: 'box',
7920
+ handles: false,
7921
+ persistent: false,
7922
+ draggable: false // does dragging the map draw a box
7923
+ }, optsArg),
7898
7924
  box = new EventDispatcher(),
7899
7925
  stroke = 2,
7900
7926
  activeHandle = null,
7901
7927
  prevXY = null,
7902
7928
  boxCoords = null,
7903
7929
  _on = false,
7930
+ _visible = false,
7904
7931
  handles;
7905
7932
 
7906
7933
  if (opts.classname) {
@@ -7910,19 +7937,20 @@
7910
7937
  el.hide();
7911
7938
 
7912
7939
  gui.on('map_rendered', function() {
7913
- if (!_on) return;
7940
+ if (!_on || !_visible) return;
7914
7941
  redraw();
7915
7942
  });
7916
7943
 
7917
- gui.on('box_drag', function(e) {
7944
+ gui.on('shift_drag', function(e) {
7918
7945
  if (!_on) return;
7946
+ if (!opts.draggable) return;
7919
7947
  boxCoords = getBoxCoords(e.data);
7920
7948
  redraw();
7921
7949
  box.dispatchEvent('drag');
7922
7950
  });
7923
7951
 
7924
- gui.on('box_drag_end', function(e) {
7925
- if (!_on) return;
7952
+ gui.on('shift_drag_end', function(e) {
7953
+ if (!_on || !_visible || !opts.draggable) return;
7926
7954
  boxCoords = getBoxCoords(e.data);
7927
7955
  var pix = coordsToPix(boxCoords, gui.map.getExtent());
7928
7956
  box.dispatchEvent('dragend', {map_bbox: pix});
@@ -7943,31 +7971,21 @@
7943
7971
  });
7944
7972
  });
7945
7973
 
7946
- document.addEventListener('mousemove', function(e) {
7947
- if (!_on || !activeHandle || !prevXY || !boxCoords) return;
7974
+ gui.map.getMouse().on('mousemove', function(e) {
7975
+ if (!_on || !activeHandle || !prevXY || !boxCoords || !_visible) return;
7948
7976
  var xy = {x: e.pageX, y: e.pageY};
7949
- var scale = gui.map.getExtent().getPixelSize();
7950
- var dx = (xy.x - prevXY.x) * scale;
7951
- var dy = -(xy.y - prevXY.y) * scale;
7952
- var center = activeHandle.col == 'center' && activeHandle.row == 'center';
7953
- if (activeHandle.col == 'left' || center) {
7954
- boxCoords[0] += dx;
7955
- }
7956
- if (activeHandle.col == 'right' || center) {
7957
- boxCoords[2] += dx;
7958
- }
7959
- if (activeHandle.row == 'top' || center) {
7960
- boxCoords[3] += dy;
7961
- }
7962
- if (activeHandle.row == 'bottom' || center) {
7963
- boxCoords[1] += dy;
7977
+ var scaling = gui.keyboard.shiftIsPressed() && activeHandle.type == 'corner';
7978
+ if (scaling) {
7979
+ rescaleBox(e.x, e.y);
7980
+ } else {
7981
+ resizeBox(xy.x - prevXY.x, xy.y - prevXY.y, activeHandle);
7964
7982
  }
7965
7983
  prevXY = xy;
7966
7984
  redraw();
7967
7985
  box.dispatchEvent('handle_drag');
7968
7986
  });
7969
7987
 
7970
- document.addEventListener('mouseup', function() {
7988
+ gui.map.getMouse().on('mouseup', function(e) {
7971
7989
  if (activeHandle && _on) {
7972
7990
  activeHandle.el.css('background', null);
7973
7991
  activeHandle = null;
@@ -7980,6 +7998,43 @@
7980
7998
  });
7981
7999
  }
7982
8000
 
8001
+ function resizeBox(dx, dy, activeHandle) {
8002
+ var shifting = activeHandle.type == 'center';
8003
+ var centered = gui.keyboard.shiftIsPressed() && activeHandle.type == 'edge';
8004
+ var scale = gui.map.getExtent().getPixelSize();
8005
+ dx *= scale;
8006
+ dy *= -scale;
8007
+
8008
+ if (activeHandle.col == 'left' || shifting) {
8009
+ boxCoords[0] += dx;
8010
+ if (centered) boxCoords[2] -= dx;
8011
+ }
8012
+ if (activeHandle.col == 'right' || shifting) {
8013
+ boxCoords[2] += dx;
8014
+ if (centered) boxCoords[0] -= dx;
8015
+ }
8016
+ if (activeHandle.row == 'top' || shifting) {
8017
+ boxCoords[3] += dy;
8018
+ if (centered) boxCoords[1] -= dy;
8019
+ }
8020
+ if (activeHandle.row == 'bottom' || shifting) {
8021
+ boxCoords[1] += dy;
8022
+ if (centered) boxCoords[3] -= dy;
8023
+ }
8024
+ }
8025
+
8026
+ function rescaleBox(x, y) {
8027
+ var p = gui.map.getExtent().translatePixelCoords(x, y);
8028
+ var cx = (boxCoords[0] + boxCoords[2])/2;
8029
+ var cy = (boxCoords[1] + boxCoords[3])/2;
8030
+ var dist2 = geom.distance2D(cx, cy, p[0], p[1]);
8031
+ var dist = geom.distance2D(cx, cy, boxCoords[0], boxCoords[1]);
8032
+ var k = dist2 / dist;
8033
+ var dx = (boxCoords[2] - cx) * k;
8034
+ var dy = (boxCoords[3] - cy) * k;
8035
+ boxCoords = [cx - dx, cy - dy, cx + dx, cy + dy];
8036
+ }
8037
+
7983
8038
  box.setDataCoords = function(bbox) {
7984
8039
  boxCoords = bbox;
7985
8040
  redraw();
@@ -8003,9 +8058,11 @@
8003
8058
  box.hide = function() {
8004
8059
  el.hide();
8005
8060
  boxCoords = null;
8061
+ _visible = false;
8006
8062
  };
8007
8063
 
8008
8064
  box.show = function(x1, y1, x2, y2) {
8065
+ _visible = true;
8009
8066
  var w = Math.abs(x1 - x2),
8010
8067
  h = Math.abs(y1 - y2),
8011
8068
  props = {
@@ -8073,8 +8130,10 @@
8073
8130
  // if (i == 4) continue; // skip middle handle
8074
8131
  var c = Math.floor(i / 3);
8075
8132
  var r = i % 3;
8133
+ var type = i == 4 && 'center' || c != 1 && r != 1 && 'corner' || 'edge';
8076
8134
  handles.push({
8077
8135
  el: El('div').addClass('handle').appendTo(el),
8136
+ type: type,
8078
8137
  col: c == 0 && 'left' || c == 1 && 'center' || 'right',
8079
8138
  row: r == 0 && 'top' || r == 1 && 'center' || 'bottom'
8080
8139
  });
@@ -8116,13 +8175,14 @@
8116
8175
  function MapNav(gui, ext, mouse) {
8117
8176
  var wheel = new MouseWheel(mouse),
8118
8177
  zoomTween = new Tween(Tween.sineInOut),
8119
- zoomBox = new HighlightBox(gui), // .addClass('zooming'),
8120
- boxDrag = false,
8178
+ zoomBox = new HighlightBox(gui, {draggable: true, name: 'zoom-box'}), // .addClass('zooming'),
8179
+ shiftDrag = false,
8121
8180
  zoomScaleMultiplier = 1,
8122
8181
  inBtn, outBtn,
8123
8182
  dragStartEvt,
8124
8183
  _fx, _fy; // zoom foci, [0,1]
8125
8184
 
8185
+ // Was used in old frame view... remove?
8126
8186
  this.setZoomFactor = function(k) {
8127
8187
  zoomScaleMultiplier = k || 1;
8128
8188
  };
@@ -8167,18 +8227,18 @@
8167
8227
  if (disabled()) return;
8168
8228
  if (!internal.layerHasGeometry(gui.model.getActiveLayer().layer)) return;
8169
8229
  // zoomDrag = !!e.metaKey || !!e.ctrlKey; // meta is command on mac, windows key on windows
8170
- boxDrag = !!e.shiftKey;
8171
- if (boxDrag) {
8230
+ shiftDrag = !!e.shiftKey;
8231
+ if (shiftDrag) {
8172
8232
  if (useBoxZoom()) zoomBox.turnOn();
8173
8233
  dragStartEvt = e;
8174
- gui.dispatchEvent('box_drag_start');
8234
+ gui.dispatchEvent('shift_drag_start');
8175
8235
  }
8176
8236
  });
8177
8237
 
8178
8238
  mouse.on('drag', function(e) {
8179
8239
  if (disabled()) return;
8180
- if (boxDrag) {
8181
- gui.dispatchEvent('box_drag', getBoxData(e));
8240
+ if (shiftDrag) {
8241
+ gui.dispatchEvent('shift_drag', getBoxData(e));
8182
8242
  } else {
8183
8243
  ext.pan(e.dx, e.dy);
8184
8244
  }
@@ -8187,9 +8247,9 @@
8187
8247
  mouse.on('dragend', function(e) {
8188
8248
  var bbox;
8189
8249
  if (disabled()) return;
8190
- if (boxDrag) {
8191
- boxDrag = false;
8192
- gui.dispatchEvent('box_drag_end', getBoxData(e));
8250
+ if (shiftDrag) {
8251
+ shiftDrag = false;
8252
+ gui.dispatchEvent('shift_drag_end', getBoxData(e));
8193
8253
  zoomBox.turnOff();
8194
8254
  }
8195
8255
  });
@@ -8207,7 +8267,9 @@
8207
8267
  });
8208
8268
 
8209
8269
  function useBoxZoom() {
8210
- return gui.getMode() != 'selection_tool' && gui.getMode() != 'box_tool';
8270
+ var mode = gui.getMode();
8271
+ var disabled = ['selection_tool', 'box_tool', 'rectangle_tool'].includes(mode);
8272
+ return !disabled;
8211
8273
  }
8212
8274
 
8213
8275
  function getBoxData(e) {
@@ -8263,7 +8325,7 @@
8263
8325
 
8264
8326
  function SelectionTool(gui, ext, hit) {
8265
8327
  var popup = gui.container.findChild('.selection-tool-options');
8266
- var box = new HighlightBox(gui);
8328
+ var box = new HighlightBox(gui, {draggable: true});
8267
8329
  var coords = popup.findChild('.box-coords').hide();
8268
8330
  var _on = false;
8269
8331
 
@@ -9310,50 +9372,22 @@
9310
9372
  dotColor: violet,
9311
9373
  dotSize: 3
9312
9374
  }, polyline: {
9313
- strokeColor: black, // violet,
9375
+ strokeColor: violet, // black, // violet,
9314
9376
  strokeWidth: 3
9315
9377
  }
9316
9378
  };
9317
9379
 
9318
- function getIntersectionStyle(lyr) {
9380
+ function getIntersectionStyle(lyr, opts) {
9319
9381
  return getDefaultStyle(lyr, intersectionStyle);
9320
9382
  }
9321
9383
 
9322
- function getDefaultStyle(lyr, baseStyle) {
9323
- var style = utils$1.extend({}, baseStyle);
9324
- // reduce the dot size of large point layers
9325
- if (lyr.geometry_type == 'point' && style.dotSize > 0) {
9326
- style.dotSize *= getDotScale$1(lyr);
9327
- }
9328
- return style;
9329
- }
9330
-
9331
- function getDotScale$1(lyr) {
9332
- var topTier = 50000;
9333
- var n = countPoints(lyr.shapes, topTier + 2); // short-circuit point counting above top threshold
9334
- var k = n < 200 && 4 || n < 2500 && 3 || n < 10000 && 2 || 1;
9335
- // var k = n >= topTier && 0.25 || n > 10000 && 0.45 || n > 2500 && 0.65 || n > 200 && 0.85 || 1;
9336
- return k;
9337
- }
9338
-
9339
- function countPoints(shapes, max) {
9340
- var count = 0;
9341
- var i, n, shp;
9342
- max = max || Infinity;
9343
- for (i=0, n=shapes.length; i<n && count<=max; i++) {
9344
- shp = shapes[i];
9345
- count += shp ? shp.length : 0;
9346
- }
9347
- return count;
9348
- }
9349
-
9350
9384
  // Style for unselected layers with visibility turned on
9351
9385
  // (styled layers have)
9352
- function getReferenceStyle(lyr) {
9386
+ function getReferenceLayerStyle(lyr, opts) {
9353
9387
  var style;
9354
- if (layerHasCanvasDisplayStyle(lyr)) {
9388
+ if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
9355
9389
  style = getCanvasDisplayStyle(lyr);
9356
- } else if (internal.layerHasLabels(lyr)) {
9390
+ } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
9357
9391
  style = {dotSize: 0}; // no reference dots if labels are visible
9358
9392
  } else {
9359
9393
  style = getDefaultStyle(lyr, referenceStyle);
@@ -9361,13 +9395,13 @@
9361
9395
  return style;
9362
9396
  }
9363
9397
 
9364
- function getActiveStyle(lyr, darkMode) {
9398
+ function getActiveLayerStyle(lyr, opts) {
9365
9399
  var style;
9366
- if (layerHasCanvasDisplayStyle(lyr)) {
9400
+ if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
9367
9401
  style = getCanvasDisplayStyle(lyr);
9368
- } else if (internal.layerHasLabels(lyr)) {
9402
+ } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
9369
9403
  style = getDefaultStyle(lyr, activeStyleForLabels);
9370
- } else if (darkMode) {
9404
+ } else if (opts.darkMode) {
9371
9405
  style = getDefaultStyle(lyr, activeStyleDarkMode);
9372
9406
  } else {
9373
9407
  style = getDefaultStyle(lyr, activeStyle);
@@ -9375,21 +9409,6 @@
9375
9409
  return style;
9376
9410
  }
9377
9411
 
9378
- // style for vertex edit mode
9379
- function getVertexStyle(lyr, o) {
9380
- return {
9381
- ids: o.ids,
9382
- overlay: true,
9383
- strokeColor: black,
9384
- strokeWidth: 1.5,
9385
- vertices: true,
9386
- vertex_overlay_color: violet,
9387
- vertex_overlay: o.hit_coordinates || null,
9388
- selected_points: o.selected_points || null,
9389
- fillColor: null
9390
- };
9391
- }
9392
-
9393
9412
  // Returns a display style for the overlay layer.
9394
9413
  // The overlay layer renders several kinds of feature, each of which is displayed
9395
9414
  // with a different style.
@@ -9398,47 +9417,103 @@
9398
9417
  // * selected shapes
9399
9418
  // * pinned shapes
9400
9419
  //
9401
- function getOverlayStyle(lyr, o) {
9402
- if (o.mode == 'vertices') {
9403
- return getVertexStyle(lyr, o);
9420
+ function getOverlayStyle(baseLyr, o, opts) {
9421
+ if (opts.interactionMode == 'vertices') {
9422
+ return getVertexStyle(baseLyr, o);
9404
9423
  }
9405
- var geomType = lyr.geometry_type;
9424
+ var geomType = baseLyr.geometry_type;
9406
9425
  var topId = o.id; // pinned id (if pinned) or hover id
9407
9426
  var topIdx = -1;
9408
9427
  var styler = function(style, i) {
9409
- utils$1.extend(style, i === topIdx ? topStyle: baseStyle);
9428
+ var defaultStyle = i === topIdx ? topStyle : outlineStyle;
9429
+ if (baseStyle.styler) {
9430
+ Object.assign(style, baseStyle);
9431
+ baseStyle.styler(style, i);
9432
+ style.strokeColor = defaultStyle.strokeColor;
9433
+ style.fillColor = defaultStyle.fillColor;
9434
+ } else {
9435
+ Object.assign(style, defaultStyle);
9436
+ }
9410
9437
  };
9411
- var baseStyle = getDefaultStyle(lyr, selectionStyles[geomType]);
9438
+ // var baseStyle = getDefaultStyle(baseLyr, selectionStyles[geomType]);
9439
+ var baseStyle = getActiveLayerStyle(baseLyr, opts);
9440
+ var outlineStyle = getDefaultStyle(baseLyr, selectionStyles[geomType]);
9412
9441
  var topStyle;
9413
9442
  var ids = o.ids.filter(function(i) {
9414
9443
  return i != o.id; // move selected id to the end
9415
9444
  });
9416
9445
  if (o.id > -1) { // pinned or hover style
9417
- topStyle = getSelectedFeatureStyle(lyr, o);
9446
+ topStyle = getSelectedFeatureStyle(baseLyr, o, opts);
9418
9447
  topIdx = ids.length;
9419
9448
  ids.push(o.id); // put the pinned/hover feature last in the render order
9420
9449
  }
9421
9450
  var style = {
9422
- styler: styler,
9423
- ids: ids,
9451
+ baseStyle: baseStyle,
9452
+ styler,
9453
+ ids,
9424
9454
  overlay: true
9425
9455
  };
9426
9456
 
9427
- if (layerHasCanvasDisplayStyle(lyr)) {
9457
+ if (layerHasCanvasDisplayStyle(baseLyr) && !opts.outlineMode) {
9428
9458
  if (geomType == 'point') {
9429
- style.styler = getOverlayPointStyler(getCanvasDisplayStyle(lyr).styler, styler);
9459
+ style.styler = getOverlayPointStyler(getCanvasDisplayStyle(baseLyr).styler, styler);
9430
9460
  }
9431
9461
  style.type = 'styled';
9432
9462
  }
9433
9463
  return ids.length > 0 ? style : null;
9434
9464
  }
9435
9465
 
9436
- function getSelectedFeatureStyle(lyr, o) {
9466
+
9467
+ function getDefaultStyle(lyr, baseStyle) {
9468
+ var style = Object.assign({}, baseStyle);
9469
+ // reduce the dot size of large point layers
9470
+ if (lyr.geometry_type == 'point' && style.dotSize > 0) {
9471
+ style.dotSize *= getDotScale$1(lyr);
9472
+ }
9473
+ return style;
9474
+ }
9475
+
9476
+ function getDotScale$1(lyr) {
9477
+ var topTier = 10000;
9478
+ var n = countPoints(lyr.shapes, topTier); // short-circuit point counting above top threshold
9479
+ var k = n < 200 && 4 || n < 2500 && 3 || n < topTier && 2 || 1;
9480
+ return k;
9481
+ }
9482
+
9483
+ function countPoints(shapes, max) {
9484
+ var count = 0;
9485
+ var i, n, shp;
9486
+ max = max || Infinity;
9487
+ for (i=0, n=shapes.length; i<n && count<max; i++) {
9488
+ shp = shapes[i];
9489
+ count += shp ? shp.length : 0;
9490
+ }
9491
+ return count;
9492
+ }
9493
+
9494
+
9495
+ // style for vertex edit mode
9496
+ function getVertexStyle(lyr, o) {
9497
+ return {
9498
+ ids: o.ids,
9499
+ overlay: true,
9500
+ strokeColor: black,
9501
+ strokeWidth: 1.5,
9502
+ vertices: true,
9503
+ vertex_overlay_color: violet,
9504
+ vertex_overlay: o.hit_coordinates || null,
9505
+ selected_points: o.selected_points || null,
9506
+ fillColor: null
9507
+ };
9508
+ }
9509
+
9510
+
9511
+ function getSelectedFeatureStyle(lyr, o, opts) {
9437
9512
  var isPinned = o.pinned;
9438
9513
  var inSelection = o.ids.indexOf(o.id) > -1;
9439
9514
  var geomType = lyr.geometry_type;
9440
9515
  var style;
9441
- if (isPinned && o.mode == 'rectangles') {
9516
+ if (isPinned && opts.interactionMode == 'rectangles') {
9442
9517
  // kludge for rectangle editing mode
9443
9518
  style = selectionStyles[geomType];
9444
9519
  } else if (isPinned) {
@@ -9582,11 +9657,90 @@
9582
9657
  }
9583
9658
  }
9584
9659
 
9585
- // import { initLineDrawing } from './gui-draw-lines';
9660
+ function initLineDrawing(gui, ext, mouse, hit) {
9661
+ var _on = false;
9662
+ var _coords;
9663
+ var _lastClick;
9664
+
9665
+ gui.on('interaction_mode_change', function(e) {
9666
+ _on = e.mode === 'draw-lines';
9667
+ gui.container.findChild('.map-layers').classed('draw-lines', _on);
9668
+ });
9669
+
9670
+ function active() {
9671
+ return _on;
9672
+ }
9673
+
9674
+ function extending() {
9675
+ return active() && !!_coords;
9676
+ }
9677
+
9678
+ function startPath(e) {
9679
+
9680
+ }
9681
+
9682
+ function extendPath(e) {
9683
+
9684
+ }
9685
+
9686
+ function finishPath() {
9687
+ _coords = null;
9688
+ }
9689
+
9690
+ gui.keyboard.on('keydown', function(evt) {
9691
+ if (!active()) return;
9692
+ if (evt.keyCode == 27) { // esc
9693
+ finishPath();
9694
+ }
9695
+ });
9696
+
9697
+ mouse.on('click', function(e) {
9698
+ if (!active()) return;
9699
+ // console.log('[click]', e)
9700
+ // addPoint(e.x, e.y);
9701
+ // gui.dispatchEvent('map-needs-refresh');
9702
+ _lastClick = e;
9703
+ });
9704
+
9705
+ // note: second click event is fired before this
9706
+ mouse.on('dblclick', function(e) {
9707
+ if (!active()) return;
9708
+ // block navigation
9709
+ e.stopPropagation();
9710
+ finishPath();
9711
+
9712
+ }, null, 3); // hit detection is priority 2
9713
+
9714
+ mouse.on('hover', function(e) {
9715
+ if (!active()) return;
9716
+ });
9717
+
9718
+ // x, y: pixel coordinates
9719
+ function addPoint(x, y) {
9720
+ var p = ext.translatePixelCoords(x, y);
9721
+ var target = hit.getHitTarget();
9722
+ var lyr = target.layer;
9723
+ var fid = lyr.shapes.length;
9724
+ if (lyr.data) {
9725
+ // this seems to work even for projected layers -- the data tables
9726
+ // of projected and original data seem to be shared.
9727
+ lyr.data.getRecords()[fid] = getEmptyDataRecord(lyr.data);
9728
+ }
9729
+ lyr.shapes[fid] = [p];
9730
+ updatePointCoords(target, fid);
9731
+ }
9732
+
9733
+ function getEmptyDataRecord(table) {
9734
+ return table.getFields().reduce(function(memo, name) {
9735
+ memo[name] = null;
9736
+ return memo;
9737
+ }, {});
9738
+ }
9739
+ }
9586
9740
 
9587
9741
  function initDrawing(gui, ext, mouse, hit) {
9588
9742
  initPointDrawing(gui, ext, mouse, hit);
9589
- // initLineDrawing(gui, ext, mouse, hit);
9743
+ initLineDrawing(gui, ext, mouse, hit);
9590
9744
  }
9591
9745
 
9592
9746
  function MapExtent(_position) {
@@ -9595,7 +9749,7 @@
9595
9749
  _fullBounds, // full (zoomed-out) content bounds, including any padding
9596
9750
  _strictBounds, // full extent must fit inside, if set
9597
9751
  _self = this,
9598
- _frame;
9752
+ _frame; // optional frame data (bbox, width, height)
9599
9753
 
9600
9754
  _position.on('resize', function(e) {
9601
9755
  if (ready()) {
@@ -9713,16 +9867,16 @@
9713
9867
  return this.getTransform().transform(x, y);
9714
9868
  };
9715
9869
 
9716
- this.setFrame = function(frame) {
9870
+ this.setFrameData = function(frame) {
9717
9871
  _frame = frame || null;
9718
9872
  };
9719
9873
 
9720
- this.getFrame = function() {
9874
+ this.getFrameData = function() {
9721
9875
  return _frame || null;
9722
9876
  };
9723
9877
 
9724
9878
  this.getSymbolScale = function() {
9725
- if (!_frame) return 0;
9879
+ if (!_frame) return 1;
9726
9880
  var bounds = new Bounds(_frame.bbox);
9727
9881
  var bounds2 = bounds.clone().transform(this.getTransform());
9728
9882
  return bounds2.width() / _frame.width;
@@ -9787,19 +9941,13 @@
9787
9941
  }
9788
9942
 
9789
9943
  function calcBounds(cx, cy, scale) {
9790
- var full, bounds, w, h;
9791
- if (_frame) {
9792
- full = fillOutFrameBounds(_frame);
9793
- } else {
9794
- full = fillOut(_fullBounds);
9795
- }
9944
+ var full = fillOut(_fullBounds);
9796
9945
  if (_strictBounds) {
9797
9946
  full = fitIn(full, _strictBounds);
9798
9947
  }
9799
- w = full.width() / scale;
9800
- h = full.height() / scale;
9801
- bounds = new Bounds(cx - w/2, cy - h/2, cx + w/2, cy + h/2);
9802
- return bounds;
9948
+ var w = full.width() / scale;
9949
+ var h = full.height() / scale;
9950
+ return new Bounds(cx - w/2, cy - h/2, cx + w/2, cy + h/2);
9803
9951
  }
9804
9952
 
9805
9953
  // Calculate viewport bounds from frame data
@@ -10119,7 +10267,7 @@
10119
10267
  var iter = new internal.ShapeIter(arcs);
10120
10268
  var t = getScaledTransform(_ext);
10121
10269
  var bounds = _ext.getBounds();
10122
- var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext);
10270
+ var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext, style);
10123
10271
  var color = style.strokeColor || 'black';
10124
10272
 
10125
10273
  var i, j, p;
@@ -10153,7 +10301,7 @@
10153
10301
  _self.drawStyledPaths = function(shapes, arcs, style, filter) {
10154
10302
  var styleIndex = {};
10155
10303
  var batchSize = 1500;
10156
- var startPath = getPathStart(_ext, getScaledLineScale(_ext));
10304
+ var startPath = getPathStart(_ext, getScaledLineScale(_ext, style));
10157
10305
  var draw = getShapePencil(arcs, _ext);
10158
10306
  var key, item, shp;
10159
10307
  var styler = style.styler || null;
@@ -10329,18 +10477,26 @@
10329
10477
  return (style.strokeWidth > 0 ? style.strokeColor + '~' + style.strokeWidth +
10330
10478
  '~' + (style.lineDash ? style.lineDash + '~' : '') : '') +
10331
10479
  (style.fillColor || '') +
10332
- // styles with <1 opacity are no longer batch-rendered
10480
+ // styles with <1 opacity are no longer batch-rendered, not relevent to key
10333
10481
  // (style.strokeOpacity >= 0 ? style.strokeOpacity + '~' : '') : '') +
10334
10482
  // (style.fillOpacity ? '~' + style.fillOpacity : '') +
10335
10483
  // (style.opacity < 1 ? '~' + style.opacity : '') +
10336
10484
  (style.fillPattern ? '~' + style.fillPattern : '');
10337
10485
  }
10338
-
10339
10486
  return _self;
10340
10487
  }
10341
10488
 
10342
- function getScaledLineScale(ext) {
10343
- return ext.getSymbolScale() || getLineScale(ext);
10489
+ function getScaledLineScale(ext, style) {
10490
+ var previewScale = ext.getSymbolScale();
10491
+ var k = 1;
10492
+ if (previewScale == 1 || style.type != 'styled' || style.baseStyle && style.baseStyle.type != 'styled') {
10493
+ return getLineScale(ext);
10494
+ }
10495
+ if (style.baseStyle?.type == 'styled') {
10496
+ // bump up overlay line width in preview mode
10497
+ k = previewScale < 2 && 2 || previewScale < 5 && 1.5 || previewScale < 10 && 1.25 || 1.1;
10498
+ }
10499
+ return previewScale * k;
10344
10500
  }
10345
10501
 
10346
10502
  // Vary line width according to zoom ratio.
@@ -10510,15 +10666,13 @@
10510
10666
  return function(ctx, style) {
10511
10667
  var strokeWidth;
10512
10668
  ctx.beginPath();
10513
- // if (style.opacity >= 0) {
10514
- // ctx.globalAlpha = style.opacity;
10515
- // }
10516
10669
  if (style.strokeWidth > 0) {
10517
10670
  strokeWidth = style.strokeWidth;
10518
10671
  if (pixRatio > 1) {
10519
10672
  // bump up thin lines on retina, but not to more than 1px
10520
10673
  // (tests on Chrome showed much faster rendering of 1px lines)
10521
- strokeWidth = strokeWidth < 1 ? 1 : strokeWidth * pixRatio;
10674
+ // strokeWidth = strokeWidth < 1 ? 1 : strokeWidth * pixRatio;
10675
+ strokeWidth = strokeWidth * pixRatio;
10522
10676
  }
10523
10677
  ctx.lineCap = style.lineCap || 'round';
10524
10678
  ctx.lineJoin = style.lineJoin || 'round';
@@ -10568,7 +10722,7 @@
10568
10722
 
10569
10723
  function getSvgFurnitureTransform(ext) {
10570
10724
  var scale = ext.getSymbolScale();
10571
- var frame = ext.getFrame();
10725
+ var frame = ext.getFrameData();
10572
10726
  var p = ext.translateCoords(frame.bbox[0], frame.bbox[3]);
10573
10727
  return internal.svg.getTransform(p, scale);
10574
10728
  }
@@ -10579,7 +10733,7 @@
10579
10733
  }
10580
10734
 
10581
10735
  function renderFurniture(lyr, ext) {
10582
- var frame = ext.getFrame(); // frame should be set if we're rendering a furniture layer
10736
+ var frame = ext.getFrameData(); // frame should be set if we're rendering a furniture layer
10583
10737
  var obj = internal.getEmptyLayerForSVG(lyr, {});
10584
10738
  if (!frame) {
10585
10739
  stop$1('Missing map frame data');
@@ -10745,7 +10899,7 @@
10745
10899
  //
10746
10900
  function BoxTool(gui, ext, nav) {
10747
10901
  var self = new EventDispatcher();
10748
- var box = new HighlightBox(gui, {persistent: true, handles: true});
10902
+ var box = new HighlightBox(gui, {name: 'box-tool', persistent: true, handles: true, draggable: true});
10749
10903
  var popup = gui.container.findChild('.box-tool-options');
10750
10904
  var coords = popup.findChild('.box-coords');
10751
10905
  var _on = false;
@@ -10792,7 +10946,7 @@
10792
10946
  }
10793
10947
  });
10794
10948
 
10795
- gui.on('box_drag_start', function() {
10949
+ gui.on('shift_drag_start', function() {
10796
10950
  // box.classed('zooming', inZoomMode());
10797
10951
  hideCoords();
10798
10952
  });
@@ -10858,7 +11012,7 @@
10858
11012
  }
10859
11013
 
10860
11014
  function RectangleControl(gui, hit) {
10861
- var box = new HighlightBox(gui, {persistent: true, handles: true, classname: 'rectangles'});
11015
+ var box = new HighlightBox(gui, {name: 'rectangle-tool', persistent: true, handles: true, classname: 'rectangles', draggable: false});
10862
11016
  var _on = false;
10863
11017
  var dragInfo;
10864
11018
 
@@ -11470,7 +11624,7 @@
11470
11624
  if (lyr == _intersectionLyr) return; // no change
11471
11625
  if (lyr) {
11472
11626
  _intersectionLyr = getDisplayLayer(lyr, dataset, getDisplayOptions());
11473
- _intersectionLyr.style = getIntersectionStyle(_intersectionLyr.layer);
11627
+ _intersectionLyr.style = getIntersectionStyle(_intersectionLyr.layer, getGlobalStyleOptions());
11474
11628
  } else {
11475
11629
  _intersectionLyr = null;
11476
11630
  }
@@ -11506,6 +11660,7 @@
11506
11660
  };
11507
11661
 
11508
11662
  this.getExtent = function() {return _ext;};
11663
+ this.getMouse = function() {return _mouse;};
11509
11664
  this.isActiveLayer = isActiveLayer;
11510
11665
  this.isVisibleLayer = isVisibleLayer;
11511
11666
  this.getActiveLayer = function() { return _activeLyr; };
@@ -11530,18 +11685,27 @@
11530
11685
  clearAllDisplayArcs();
11531
11686
 
11532
11687
  // Reproject all visible map layers
11533
- getDrawableContentLayers().forEach(function(lyr) {
11688
+ getContentLayers().forEach(function(lyr) {
11534
11689
  projectDisplayLayer(lyr, newCRS);
11535
11690
  });
11536
11691
 
11537
11692
  // kludge to make sure all layers have styles
11538
- updateLayerStyles(getDrawableContentLayers());
11693
+ updateLayerStyles(getContentLayers());
11539
11694
 
11540
11695
  // Update map extent (also triggers redraw)
11541
11696
  projectMapExtent(_ext, oldCRS, this.getDisplayCRS(), calcFullBounds());
11542
11697
  updateFullBounds();
11543
11698
  };
11544
11699
 
11700
+ function getGlobalStyleOptions() {
11701
+ var mode = gui.state.interaction_mode;
11702
+ return {
11703
+ darkMode: !!gui.state.dark_basemap,
11704
+ outlineMode: mode == 'vertices',
11705
+ interactionMode: mode
11706
+ };
11707
+ }
11708
+
11545
11709
  // Refresh map display in response to data changes, layer selection, etc.
11546
11710
  function onUpdate(e) {
11547
11711
  var prevLyr = _activeLyr || null;
@@ -11574,7 +11738,6 @@
11574
11738
  }
11575
11739
 
11576
11740
  _activeLyr = getDisplayLayer(e.layer, e.dataset, getDisplayOptions());
11577
- _activeLyr.style = getActiveStyle(_activeLyr.layer, gui.state.dark_basemap);
11578
11741
  _activeLyr.active = true;
11579
11742
 
11580
11743
  if (popupCanStayOpen(e.flags)) {
@@ -11588,19 +11751,12 @@
11588
11751
  updateVisibleMapLayers();
11589
11752
  fullBounds = calcFullBounds();
11590
11753
 
11591
- if (!prevLyr || prevLyr.tabular || _activeLyr.tabular || isFrameView()) {
11754
+ if (!prevLyr || prevLyr.tabular || _activeLyr.tabular) {
11592
11755
  needReset = true;
11593
11756
  } else {
11594
11757
  needReset = mapNeedsReset(fullBounds, _ext.getFullBounds(), _ext.getBounds(), e.flags);
11595
11758
  }
11596
11759
 
11597
- if (isFrameView()) {
11598
- _nav.setZoomFactor(0.05); // slow zooming way down to allow fine-tuning frame placement // 0.03
11599
- _ext.setFrame(calcFullBounds()); // TODO: remove redundancy with drawLayers()
11600
- needReset = true; // snap to frame extent
11601
- } else {
11602
- _nav.setZoomFactor(1);
11603
- }
11604
11760
  _ext.setFullBounds(fullBounds, getStrictBounds()); // update 'home' button extent
11605
11761
 
11606
11762
  if (needReset) {
@@ -11630,9 +11786,6 @@
11630
11786
  _ext.on('change', function(e) {
11631
11787
  if (_basemap) _basemap.refresh(); // keep basemap synced up (if enabled)
11632
11788
  if (e.reset) return; // don't need to redraw map here if extent has been reset
11633
- if (isFrameView()) {
11634
- updateFrameExtent();
11635
- }
11636
11789
  drawLayers('nav');
11637
11790
  });
11638
11791
 
@@ -11642,7 +11795,7 @@
11642
11795
  }
11643
11796
 
11644
11797
  function updateOverlayLayer(e) {
11645
- var style = getOverlayStyle(_activeLyr.layer, e);
11798
+ var style = getOverlayStyle(_activeLyr.layer, e, getGlobalStyleOptions());
11646
11799
  if (style) {
11647
11800
  _overlayLyr = utils$1.defaults({
11648
11801
  layer: filterLayerByIds(_activeLyr.layer, style.ids),
@@ -11662,21 +11815,6 @@
11662
11815
  };
11663
11816
  }
11664
11817
 
11665
- // Update map frame after user navigates the map in frame edit mode
11666
- function updateFrameExtent() {
11667
- var frameLyr = internal.findFrameLayer(model);
11668
- var rec = frameLyr.data.getRecordAt(0);
11669
- var viewBounds = _ext.getBounds();
11670
- var w = viewBounds.width() * rec.width / _ext.width();
11671
- var h = w * rec.height / rec.width;
11672
- var cx = viewBounds.centerX();
11673
- var cy = viewBounds.centerY();
11674
- rec.bbox = [cx - w/2, cy - h/2, cx + w/2, cy + h/2];
11675
- _ext.setFrame(getFrameData());
11676
- _ext.setFullBounds(new Bounds(rec.bbox));
11677
- _ext.reset();
11678
- }
11679
-
11680
11818
  function getStrictBounds() {
11681
11819
  if (internal.isWebMercator(map.getDisplayCRS())) {
11682
11820
  return getMapboxBounds();
@@ -11688,9 +11826,9 @@
11688
11826
  _ext.setFullBounds(calcFullBounds(), getStrictBounds());
11689
11827
  }
11690
11828
 
11691
- function getVisibleContentBounds() {
11829
+ function getContentLayerBounds() {
11692
11830
  var b = new Bounds();
11693
- var layers = getDrawableContentLayers();
11831
+ var layers = getContentLayers();
11694
11832
  layers.forEach(function(lyr) {
11695
11833
  b.mergeBounds(lyr.bounds);
11696
11834
  });
@@ -11703,10 +11841,7 @@
11703
11841
  }
11704
11842
 
11705
11843
  function calcFullBounds() {
11706
- if (isPreviewView()) {
11707
- return internal.getFrameLayerBounds(internal.findFrameLayer(model));
11708
- }
11709
- var b = getVisibleContentBounds();
11844
+ var b = getContentLayerBounds();
11710
11845
 
11711
11846
  // add margin
11712
11847
  // use larger margin for small sizes
@@ -11736,25 +11871,21 @@
11736
11871
  return !isPreviewView() && !!_activeLyr.tabular;
11737
11872
  }
11738
11873
 
11739
- // Preview view: a special view centering the map 'frame'
11740
- // (disabling this pending interface rethink)
11741
- function isPreviewView() {
11742
- return false;
11743
- // var frameLyr = internal.findFrameLayer(model);
11744
- // return !!frameLyr; // && isVisibleLayer(frameLyr)
11874
+ function findFrameLayer() {
11875
+ return getVisibleMapLayers().find(function(lyr) {
11876
+ return internal.isFrameLayer(lyr.layer, lyr.arcs);
11877
+ });
11745
11878
  }
11746
11879
 
11747
- // Frame view means frame layer is visible and active (selected)
11748
- // (disabling pending rethink)
11749
- function isFrameView() {
11750
- return false;
11751
- // var frameLyr = internal.findFrameLayer(model);
11752
- // return isActiveLayer(frameLyr) && isVisibleLayer(frameLyr);
11880
+ // Preview view: symbols are scaled based on display size of frame layer
11881
+ function isPreviewView() {
11882
+ var data = getFrameData();
11883
+ return !!data;
11753
11884
  }
11754
11885
 
11755
11886
  function getFrameData() {
11756
- var frameLyr = internal.findFrameLayer(model);
11757
- return frameLyr && internal.getFurnitureLayerData(frameLyr) || null;
11887
+ var lyr = findFrameLayer();
11888
+ return lyr && internal.getFrameLayerData(lyr.layer, lyr.arcs) || null;
11758
11889
  }
11759
11890
 
11760
11891
  function clearAllDisplayArcs() {
@@ -11786,7 +11917,7 @@
11786
11917
  });
11787
11918
  }
11788
11919
 
11789
- function getDrawableContentLayers() {
11920
+ function getContentLayers() {
11790
11921
  var layers = getVisibleMapLayers();
11791
11922
  if (isTableView()) return findActiveLayer(layers);
11792
11923
  return layers.filter(function(o) {
@@ -11794,6 +11925,13 @@
11794
11925
  });
11795
11926
  }
11796
11927
 
11928
+ function getDrawableContentLayers() {
11929
+ return getContentLayers().filter(function(lyr) {
11930
+ if (isActiveLayer(lyr.layer) && lyr.layer.hidden) return false;
11931
+ return true;
11932
+ });
11933
+ }
11934
+
11797
11935
  function getDrawableFurnitureLayers(layers) {
11798
11936
  if (!isPreviewView()) return [];
11799
11937
  return getVisibleMapLayers().filter(function(o) {
@@ -11804,9 +11942,10 @@
11804
11942
  function updateLayerStyles(layers) {
11805
11943
  layers.forEach(function(mapLayer, i) {
11806
11944
  if (mapLayer.active) {
11807
- // assume: style is already assigned
11945
+ // regenerating active style everytime, to support style change when
11946
+ // switching between outline and preview modes.
11947
+ mapLayer.style = getActiveLayerStyle(mapLayer.layer, getGlobalStyleOptions());
11808
11948
  if (mapLayer.style.type != 'styled' && layers.length > 1 && mapLayer.style.strokeColors) {
11809
- // if (false) { // always show ghosted arcs
11810
11949
  // kludge to hide ghosted layers when reference layers are present
11811
11950
  // TODO: consider never showing ghosted layers (which appear after
11812
11951
  // commands like dissolve and filter).
@@ -11818,7 +11957,7 @@
11818
11957
  if (mapLayer.layer == _activeLyr.layer) {
11819
11958
  console.error("Error: shared map layer");
11820
11959
  }
11821
- mapLayer.style = getReferenceStyle(mapLayer.layer);
11960
+ mapLayer.style = getReferenceLayerStyle(mapLayer.layer, getGlobalStyleOptions());
11822
11961
  }
11823
11962
  });
11824
11963
  }
@@ -11844,7 +11983,7 @@
11844
11983
  var layersMayHaveChanged = action != 'nav'; // !action;
11845
11984
  var fullBounds;
11846
11985
  var contentLayers = getDrawableContentLayers();
11847
- var furnitureLayers = getDrawableFurnitureLayers();
11986
+ // var furnitureLayers = getDrawableFurnitureLayers();
11848
11987
  if (!(_ext.width() > 0 && _ext.height() > 0)) {
11849
11988
  // TODO: track down source of these errors
11850
11989
  console.error("Collapsed map container, unable to draw.");
@@ -11852,7 +11991,7 @@
11852
11991
  }
11853
11992
  if (layersMayHaveChanged) {
11854
11993
  // kludge to handle layer visibility toggling
11855
- _ext.setFrame(isPreviewView() ? getFrameData() : null);
11994
+ _ext.setFrameData(isPreviewView() ? getFrameData() : null);
11856
11995
  updateFullBounds();
11857
11996
  updateLayerStyles(contentLayers);
11858
11997
  updateLayerStackOrder(model.getLayers());// update menu_order property of all layers