girder-large-image 1.23.1.dev44__tar.gz → 1.23.2.dev6__tar.gz

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.
Files changed (77) hide show
  1. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/PKG-INFO +1 -1
  2. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/itemList.pug +17 -6
  3. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/itemList.js +45 -1
  4. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/metadataWidget.js +42 -27
  5. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/components/CompositeLayers.vue +184 -111
  6. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/components/FrameSelector.vue +2 -0
  7. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/PKG-INFO +1 -1
  8. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/requires.txt +2 -2
  9. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/LICENSE +0 -0
  10. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/README.rst +0 -0
  11. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/__init__.py +0 -0
  12. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/constants.py +0 -0
  13. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/girder_tilesource.py +0 -0
  14. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/loadmodelcache.py +0 -0
  15. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/models/__init__.py +0 -0
  16. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/models/image_item.py +0 -0
  17. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/rest/__init__.py +0 -0
  18. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/rest/large_image_resource.py +0 -0
  19. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/rest/tiles.py +0 -0
  20. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/eventStream.js +0 -0
  21. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/extra/.gitignore +0 -0
  22. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/index.js +0 -0
  23. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/main.js +0 -0
  24. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/package.json +0 -0
  25. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/routes.js +0 -0
  26. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/fileList.styl +0 -0
  27. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/imageViewerSelectWidget.styl +0 -0
  28. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/itemList.styl +0 -0
  29. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/itemView.styl +0 -0
  30. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/itemViewCodemirror.styl +0 -0
  31. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/largeImageConfig.styl +0 -0
  32. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/stylesheets/metadataWidget.styl +0 -0
  33. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/imageViewerSelectWidget.pug +0 -0
  34. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/itemView.pug +0 -0
  35. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/itemViewCodemirror.pug +0 -0
  36. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/largeImageConfig.pug +0 -0
  37. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/largeImage_fileAction.pug +0 -0
  38. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/metadataWidget.pug +0 -0
  39. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/templates/metadatumEditWidget.pug +0 -0
  40. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/configView.js +0 -0
  41. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/fileList.js +0 -0
  42. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerSelectWidget.js +0 -0
  43. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/base.js +0 -0
  44. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/geojs.js +0 -0
  45. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/index.js +0 -0
  46. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/leaflet.js +0 -0
  47. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/openlayers.js +0 -0
  48. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/openseadragon.js +0 -0
  49. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/setFrameQuad.js +0 -0
  50. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/imageViewerWidget/slideatlas.js +0 -0
  51. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/index.js +0 -0
  52. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/itemView.js +0 -0
  53. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/itemViewCodemirror.js +0 -0
  54. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/views/itemViewWidget.js +0 -0
  55. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/components/DualInput.vue +0 -0
  56. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/components/HistogramEditor.vue +0 -0
  57. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/utils/clamp.js +0 -0
  58. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/utils/colors.js +0 -0
  59. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/vue/utils/drag.js +0 -0
  60. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image/web_client/webpack.helper.js +0 -0
  61. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/SOURCES.txt +0 -0
  62. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/dependency_links.txt +0 -0
  63. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/entry_points.txt +0 -0
  64. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/not-zip-safe +0 -0
  65. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/girder_large_image.egg-info/top_level.txt +0 -0
  66. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/setup.cfg +0 -0
  67. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/setup.py +0 -0
  68. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/__init__.py +0 -0
  69. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/conftest.py +0 -0
  70. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/girder_utilities.py +0 -0
  71. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/test_large_image.py +0 -0
  72. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/test_tiles_rest.py +0 -0
  73. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/test_web_client.py +0 -0
  74. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/web_client_specs/.eslintrc +0 -0
  75. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/web_client_specs/imageViewerSpec.js +0 -0
  76. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/web_client_specs/largeImageSpec.js +0 -0
  77. {girder-large-image-1.23.1.dev44 → girder-large-image-1.23.2.dev6}/test_girder/web_client_specs/otherFeatures.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: girder-large-image
3
- Version: 1.23.1.dev44
3
+ Version: 1.23.2.dev6
4
4
  Summary: A Girder plugin to work with large, multiresolution images.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -16,7 +16,7 @@ ul.g-item-list.li-item-list
16
16
  if checkboxes
17
17
  span.li-item-list-cell
18
18
  input.g-list-checkbox(type="checkbox", g-item-cid=item.cid)
19
- for column in itemList.columns
19
+ for column, colidx in itemList.columns
20
20
  if column.type !== 'image' || hasAnyLargeImage
21
21
  -
22
22
  var divtype = column.type !== 'record' || column.value !== 'controls' ? 'a' : 'span';
@@ -51,11 +51,22 @@ ul.g-item-list.li-item-list
51
51
  column.value.split('.').forEach((part) => {
52
52
  value = (value || {})[part];
53
53
  })
54
- span.large_image_metadata
55
- = value
56
- if value
57
- span.li-item-list-cell-filter(title="Only show items that match this metadata value exactly", filter-value=value, column-value=column.value)
58
- i.icon-filter
54
+ if column.edit && accessLevel >= AccessType.WRITE
55
+ - if ((value === '' || value === undefined) && column.default) { value = column.default; }
56
+ span.large_image_metadata.lientry_edit(column-idx=colidx)
57
+ if column.enum
58
+ select.input-sm.form-control.g-widget-metadata-value-input.g-widget-metadata-lientry(title=column.description)
59
+ for enumval in column.enum
60
+ option(value=enumval, selected=enumval === value ? 'selected' : null)
61
+ = enumval
62
+ else
63
+ input.input-sm.form-control.g-widget-metadata-value-input.g-widget-metadata-column(placeholder=column.description || "Value", value=value, title=column.description)
64
+ else
65
+ span.large_image_metadata
66
+ = value
67
+ if value
68
+ span.li-item-list-cell-filter(title="Only show items that match this metadata value exactly", filter-value=value, column-value=column.value)
69
+ i.icon-filter
59
70
  if (hasMore && !paginated)
60
71
  li.g-show-more
61
72
  a.g-show-more-items
@@ -16,6 +16,7 @@ import {addToRoute} from '../routes';
16
16
 
17
17
  import '../stylesheets/itemList.styl';
18
18
  import ItemListTemplate from '../templates/itemList.pug';
19
+ import {MetadatumWidget, validateMetadataValue} from './metadataWidget';
19
20
 
20
21
  wrap(HierarchyWidget, 'render', function (render) {
21
22
  render.call(this);
@@ -85,6 +86,9 @@ wrap(ItemListWidget, 'initialize', function (initialize, settings) {
85
86
  });
86
87
  this.events['click .li-item-list-header.sortable'] = (evt) => sortColumn.call(this, evt);
87
88
  this.events['click .li-item-list-cell-filter'] = (evt) => itemListCellFilter.call(this, evt);
89
+ this.events['click .large_image_metadata.lientry_edit'] = (evt) => itemListMetadataEdit.call(this, evt);
90
+ this.events['change .large_image_metadata.lientry_edit'] = (evt) => itemListMetadataEdit.call(this, evt);
91
+ this.events['input .large_image_metadata.lientry_edit'] = (evt) => itemListMetadataEdit.call(this, evt);
88
92
  this.delegateEvents();
89
93
  this.setFlatten = (flatten) => {
90
94
  if (!!flatten !== !!this._recurse) {
@@ -395,7 +399,11 @@ wrap(ItemListWidget, 'render', function (render) {
395
399
  apiRoot: getApiRoot(),
396
400
  hasAnyLargeImage: this._hasAnyLargeImage,
397
401
  itemList: this._confList(),
398
- sort: this._lastSort
402
+ sort: this._lastSort,
403
+ MetadatumWidget: MetadatumWidget,
404
+ accessLevel: this.accessLevel,
405
+ parentView: this,
406
+ AccessType: AccessType
399
407
  }));
400
408
 
401
409
  const parent = this.$el;
@@ -514,4 +522,40 @@ function itemListCellFilter(evt) {
514
522
  return false;
515
523
  }
516
524
 
525
+ function itemListMetadataEdit(evt) {
526
+ evt.preventDefault();
527
+ if (evt.type === 'click') {
528
+ return false;
529
+ }
530
+ const ctrl = $(evt.target).closest('.lientry_edit');
531
+ const columns = (this._confList() || {}).columns || [];
532
+ const column = columns[+ctrl.attr('column-idx')];
533
+ let tempValue = ctrl.find('.g-widget-metadata-value-input').val();
534
+ tempValue = tempValue.trim();
535
+ let valResult = validateMetadataValue(column, tempValue, self._lastValidationError || (tempValue === '' && !column.required));
536
+ if (tempValue === '' && !column.required) {
537
+ valResult = {value: tempValue};
538
+ }
539
+ if (!valResult) {
540
+ self._lastValidationError = true;
541
+ return false;
542
+ }
543
+ self._lastValidationError = false;
544
+ const item = this.collection.get(ctrl.closest('[g-item-cid]').attr('g-item-cid'));
545
+ let value = item.get('meta') || {};
546
+ let meta;
547
+ let key;
548
+ column.value.split('.').forEach((part) => {
549
+ meta = value;
550
+ key = part;
551
+ value = (value || {})[part];
552
+ });
553
+ if (value === valResult.value) {
554
+ return;
555
+ }
556
+ meta[key] = valResult.value;
557
+ item._sendMetadata(item.get('meta'));
558
+ return false;
559
+ }
560
+
517
561
  export default ItemListWidget;
@@ -55,6 +55,43 @@ function liMetadataKeyEntry(limetadata, key) {
55
55
  return result;
56
56
  }
57
57
 
58
+ function validateMetadataValue(lientry, tempValue, nowarn) {
59
+ if (lientry && lientry.regex && !(new RegExp(lientry.regex).exec(tempValue))) {
60
+ if (!nowarn) {
61
+ events.trigger('g:alert', {
62
+ text: 'The value does not match the required format.',
63
+ type: 'warning'
64
+ });
65
+ }
66
+ return false;
67
+ }
68
+ if (lientry && ((lientry.format || lientry.type) === 'number' || (lientry.format || lientry.type) === 'integer')) {
69
+ if (!Number.isFinite(parseFloat(tempValue)) || ((lientry.format || lientry.type) === 'integer' && !Number.isInteger(parseFloat(tempValue)))) {
70
+ if (!nowarn) {
71
+ events.trigger('g:alert', {
72
+ text: `The value must be a ${(lientry.format || lientry.type)}.`,
73
+ type: 'warning'
74
+ });
75
+ }
76
+ return false;
77
+ }
78
+ tempValue = parseFloat(tempValue);
79
+ if ((lientry.minimum !== undefined && tempValue < lientry.minimum) ||
80
+ (lientry.exclusiveMinimum !== undefined && tempValue <= lientry.exclusiveMinimum) ||
81
+ (lientry.maximum !== undefined && tempValue > lientry.maximum) ||
82
+ (lientry.exclusiveMaximum !== undefined && tempValue >= lientry.exclusiveMaximum)) {
83
+ if (!nowarn) {
84
+ events.trigger('g:alert', {
85
+ text: 'The value is outside of the allowed range.',
86
+ type: 'warning'
87
+ });
88
+ }
89
+ return false;
90
+ }
91
+ }
92
+ return {value: tempValue};
93
+ }
94
+
58
95
  var MetadatumWidget = View.extend({
59
96
  className: 'g-widget-metadata-row',
60
97
 
@@ -286,34 +323,11 @@ var MetadatumEditWidget = View.extend({
286
323
  if (keyMode && lientry) {
287
324
  tempValue = tempValue.trim();
288
325
  }
289
- if (lientry && lientry.regex && !(new RegExp(lientry.regex).exec(tempValue))) {
290
- events.trigger('g:alert', {
291
- text: 'The value does not match the required format.',
292
- type: 'warning'
293
- });
326
+ const valResult = validateMetadataValue(lientry, tempValue);
327
+ if (!valResult) {
294
328
  return false;
295
329
  }
296
- if (lientry && (lientry.type === 'number' || lientry.type === 'integer')) {
297
- if (!Number.isFinite(parseFloat(tempValue)) || (lientry.type === 'integer' && !Number.isInteger(parseFloat(tempValue)))) {
298
- events.trigger('g:alert', {
299
- text: `The value must be a ${lientry.type}.`,
300
- type: 'warning'
301
- });
302
- return false;
303
- }
304
- tempValue = parseFloat(tempValue);
305
- if ((lientry.minimum !== undefined && tempValue < lientry.minimum) ||
306
- (lientry.exclusiveMinimum !== undefined && tempValue <= lientry.exclusiveMinimum) ||
307
- (lientry.maximum !== undefined && tempValue > lientry.maximum) ||
308
- (lientry.exclusiveMaximum !== undefined && tempValue >= lientry.exclusiveMaximum)) {
309
- events.trigger('g:alert', {
310
- text: 'The value is outside of the allowed range.',
311
- type: 'warning'
312
- });
313
- return false;
314
- }
315
- }
316
-
330
+ tempValue = valResult.value;
317
331
  var saveCallback = () => {
318
332
  this.key = tempKey;
319
333
  this.value = tempValue;
@@ -668,5 +682,6 @@ export {
668
682
  MetadatumWidget,
669
683
  MetadatumEditWidget,
670
684
  JsonMetadatumEditWidget,
671
- liMetadataKeyEntry
685
+ liMetadataKeyEntry,
686
+ validateMetadataValue
672
687
  };
@@ -5,7 +5,7 @@ import { CHANNEL_COLORS, OTHER_COLORS } from '../utils/colors'
5
5
  import HistogramEditor from './HistogramEditor.vue';
6
6
 
7
7
  export default {
8
- props: ['itemId', 'currentFrame', 'layers', 'layerMap'],
8
+ props: ['itemId', 'currentFrame', 'layers', 'layerMap', 'active'],
9
9
  emits: ['updateStyle'],
10
10
  components: {
11
11
  'color-picker': Chrome,
@@ -27,10 +27,33 @@ export default {
27
27
  resample: false,
28
28
  style: '{}',
29
29
  roundRange: true,
30
- }
30
+ },
31
+ showKeyboardShortcuts: false,
31
32
  }
32
33
  },
33
34
  methods: {
35
+ keyHandler(e) {
36
+ let numericKey = parseFloat(e.key)
37
+ if (e.ctrlKey && !isNaN(numericKey)) {
38
+ e.preventDefault()
39
+ if (numericKey === 0) {
40
+ numericKey += 10
41
+ }
42
+ if (e.altKey) {
43
+ numericKey += 10
44
+ }
45
+ const layerIndex = numericKey - 1
46
+ if (layerIndex < this.layers.length) {
47
+ const targetLayer = this.layers[layerIndex]
48
+ if (this.compositeLayerInfo[targetLayer].enabled) {
49
+ this.enabledLayers = this.enabledLayers.filter((v) => v !== targetLayer)
50
+ } else {
51
+ this.enabledLayers.push(targetLayer)
52
+ }
53
+ this.updateActiveLayers()
54
+ }
55
+ }
56
+ },
34
57
  initializeLayerInfo() {
35
58
  const usedColors = []
36
59
  this.compositeLayerInfo = {}
@@ -211,126 +234,165 @@ export default {
211
234
  }
212
235
  this.updateActiveLayers()
213
236
  this.updateStyle()
237
+ if (this.active) {
238
+ document.addEventListener('keydown', this.keyHandler)
239
+ }
240
+ },
241
+ watch: {
242
+ active() {
243
+ if (this.active) {
244
+ document.addEventListener('keydown', this.keyHandler)
245
+ } else {
246
+ document.removeEventListener('keydown', this.keyHandler)
247
+ }
248
+ }
214
249
  }
215
250
  }
216
251
  </script>
217
252
 
218
253
  <template>
219
- <div :class="colorPickerShown ? 'table-container tall' : 'table-container'">
220
- <table id="composite-layer-table" class="table table-condensed">
221
- <thead class="table-header">
222
- <tr>
223
- <th>
224
- <input
225
- type="checkbox"
226
- class="input-80"
227
- :checked="enabledLayers === layers"
228
- @input="toggleEnableAll"
229
- >
230
- </th>
231
- <th></th>
232
- <th></th>
233
- <th>
234
- <div class="auto-range-col">
235
- <div class="auto-range-label">
236
- <span class="small-text">Auto Range</span>
254
+ <div>
255
+ <i
256
+ class="icon-keyboard"
257
+ @click="showKeyboardShortcuts = !showKeyboardShortcuts"
258
+ />
259
+ <div class="shortcuts" v-if="showKeyboardShortcuts">
260
+ <div class="h5">Keyboard Shortcuts</div>
261
+ <div>
262
+ <span class="monospace">ctrl + number</span>
263
+ Toggle visibility of the layer at the number position
264
+ </div>
265
+ <div>
266
+ <span style="font-weight: bold;">Example: </span>
267
+ <span class="monospace">ctrl + 1</span>
268
+ Toggle visibility of the first layer in the table
269
+ </div>
270
+ <div>
271
+ <span class="monospace">ctrl + alt + number</span>
272
+ Toggle visibility of the layer at the position of the number plus 10
273
+ </div>
274
+ <div>
275
+ <span style="font-weight: bold;">Example: </span>
276
+ <span class="monospace">ctrl + alt + 1</span>
277
+ Toggle visibility of the eleventh layer in the table
278
+ </div>
279
+ </div>
280
+ <div :class="colorPickerShown ? 'table-container tall' : 'table-container'">
281
+ <table id="composite-layer-table" class="table table-condensed">
282
+ <thead class="table-header">
283
+ <tr>
284
+ <th>
285
+ <input
286
+ type="checkbox"
287
+ class="input-80"
288
+ :checked="enabledLayers === layers"
289
+ @input="toggleEnableAll"
290
+ >
291
+ </th>
292
+ <th></th>
293
+ <th></th>
294
+ <th>
295
+ <div class="auto-range-col">
296
+ <div class="auto-range-label">
297
+ <span class="small-text">Auto Range</span>
298
+ <label class="switch">
299
+ <span
300
+ :class="allAutoRange() ? 'slider checked' : 'slider'"
301
+ @click="() => updateAllAutoRanges(allAutoRange() ? undefined : 0.2)"
302
+ />
303
+ </label>
304
+ </div>
305
+ <span
306
+ v-if="allAutoRange()"
307
+ class="percentage-input"
308
+ >
309
+ <input
310
+ type="number"
311
+ class="input-80"
312
+ :max="50"
313
+ :min="0"
314
+ :value="autoRangeForAll"
315
+ @input="(e) => updateAllAutoRanges(e.target.value)"
316
+ >
317
+ </span>
318
+ </div>
319
+ <i
320
+ :class="expandedRows.length === layers.length ? 'expand-btn icon-up-open' : 'expand-btn icon-down-open'"
321
+ @click="toggleAllExpanded"
322
+ />
323
+ </th>
324
+ </tr>
325
+ <!-- color picker should display relative to sticky table head -->
326
+ <color-picker
327
+ v-if="colorPickerShown"
328
+ id="color_picker"
329
+ class="picker-offset"
330
+ :disableAlpha="true"
331
+ :value="Object.values(compositeLayerInfo).find((({layerName}) => layerName === colorPickerShown)).palette"
332
+ @input="(swatch) => {updateLayerColor(colorPickerShown, swatch)}"
333
+ />
334
+ </thead>
335
+ <tbody>
336
+ <tr
337
+ v-for="{
338
+ layerName, index, palette,
339
+ autoRange, min, max,
340
+ framedelta
341
+ } in Object.values(compositeLayerInfo)"
342
+ :key="layerName"
343
+ :class="expandedRows.includes(index) ? 'tall-row' : ''"
344
+ >
345
+ <td class="enable-col">
346
+ <input
347
+ type="checkbox"
348
+ class="input-80"
349
+ :value="layerName"
350
+ v-model="enabledLayers"
351
+ @change="updateActiveLayers"
352
+ >
353
+ </td>
354
+ <td class="name-col">{{ layerName }}</td>
355
+ <td class="color-col">
356
+ <span
357
+ class="current-color"
358
+ :style="{ 'background-color': palette }"
359
+ @click="() => toggleColorPicker(layerName)"
360
+ />
361
+ </td>
362
+ <td class="auto-range-col">
363
+ <div class="auto-range-toggle">
237
364
  <label class="switch">
238
365
  <span
239
- :class="allAutoRange() ? 'slider checked' : 'slider'"
240
- @click="() => updateAllAutoRanges(allAutoRange() ? undefined : 0.2)"
366
+ :class="autoRange ? 'slider checked' : 'slider'"
367
+ @click="() => updateLayerAutoRange(layerName, autoRange ? undefined : 0.2)"
241
368
  />
242
369
  </label>
243
370
  </div>
244
- <span
245
- v-if="allAutoRange()"
246
- class="percentage-input"
247
- >
248
- <input
249
- type="number"
250
- class="input-80"
251
- :max="50"
252
- :min="0"
253
- :value="autoRangeForAll"
254
- @input="(e) => updateAllAutoRanges(e.target.value)"
255
- >
256
- </span>
257
- </div>
258
- <i
259
- :class="expandedRows.length === layers.length ? 'expand-btn icon-up-open' : 'expand-btn icon-down-open'"
260
- @click="toggleAllExpanded"
261
- />
262
- </th>
263
- </tr>
264
- <!-- color picker should display relative to sticky table head -->
265
- <color-picker
266
- v-if="colorPickerShown"
267
- id="color_picker"
268
- class="picker-offset"
269
- :disableAlpha="true"
270
- :value="Object.values(compositeLayerInfo).find((({layerName}) => layerName === colorPickerShown)).palette"
271
- @input="(swatch) => {updateLayerColor(colorPickerShown, swatch)}"
272
- />
273
- </thead>
274
- <tbody>
275
- <tr
276
- v-for="{
277
- layerName, index, palette,
278
- autoRange, min, max,
279
- framedelta
280
- } in Object.values(compositeLayerInfo)"
281
- :key="layerName"
282
- :class="expandedRows.includes(index) ? 'tall-row' : ''"
283
- >
284
- <td class="enable-col">
285
- <input
286
- type="checkbox"
287
- class="input-80"
288
- :value="layerName"
289
- v-model="enabledLayers"
290
- @change="updateActiveLayers"
291
- >
292
- </td>
293
- <td class="name-col">{{ layerName }}</td>
294
- <td class="color-col">
295
- <span
296
- class="current-color"
297
- :style="{ 'background-color': palette }"
298
- @click="() => toggleColorPicker(layerName)"
299
- />
300
- </td>
301
- <td class="auto-range-col">
302
- <div class="auto-range-toggle">
303
- <label class="switch">
304
- <span
305
- :class="autoRange ? 'slider checked' : 'slider'"
306
- @click="() => updateLayerAutoRange(layerName, autoRange ? undefined : 0.2)"
307
- />
308
- </label>
371
+ <i
372
+ :class="expandedRows.includes(index) ? 'expand-btn icon-up-open' : 'expand-btn icon-down-open'"
373
+ @click="() => toggleExpanded(index)"
374
+ />
375
+ </td>
376
+ <div v-if="expandedRows.includes(index)" class="advanced-section">
377
+ <histogram-editor
378
+ :itemId="itemId"
379
+ :layerIndex="index"
380
+ :currentFrame="currentFrame"
381
+ :currentFrameHistogram="currentFrameHistogram"
382
+ :histogramParams="histogramParams"
383
+ :framedelta="framedelta"
384
+ :autoRange="autoRange"
385
+ :currentMin="min"
386
+ :currentMax="max"
387
+ @updateMin="(v, d) => updateLayerMin(layerName, v, d)"
388
+ @updateMax="(v, d) => updateLayerMax(layerName, v, d)"
389
+ @updateAutoRange="(v) => updateLayerAutoRange(layerName, v)"
390
+ />
309
391
  </div>
310
- <i
311
- :class="expandedRows.includes(index) ? 'expand-btn icon-up-open' : 'expand-btn icon-down-open'"
312
- @click="() => toggleExpanded(index)"
313
- />
314
- </td>
315
- <div v-if="expandedRows.includes(index)" class="advanced-section">
316
- <histogram-editor
317
- :itemId="itemId"
318
- :layerIndex="index"
319
- :currentFrame="currentFrame"
320
- :currentFrameHistogram="currentFrameHistogram"
321
- :histogramParams="histogramParams"
322
- :framedelta="framedelta"
323
- :autoRange="autoRange"
324
- :currentMin="min"
325
- :currentMax="max"
326
- @updateMin="(v, d) => updateLayerMin(layerName, v, d)"
327
- @updateMax="(v, d) => updateLayerMax(layerName, v, d)"
328
- @updateAutoRange="(v) => updateLayerAutoRange(layerName, v)"
329
- />
330
- </div>
331
- </tr>
332
- </tbody>
333
- </table>
392
+ </tr>
393
+ </tbody>
394
+ </table>
395
+ </div>
334
396
  </div>
335
397
  </template>
336
398
 
@@ -456,6 +518,17 @@ export default {
456
518
  margin: 30px 0px 0px;
457
519
  height: 40px;
458
520
  }
521
+ .icon-keyboard {
522
+ font-size: 2rem;
523
+ }
524
+ .shortcuts {
525
+ padding-bottom: 10px;
526
+ }
527
+ .monospace {
528
+ font-family: monospace;
529
+ background-color: rgba(0, 0, 0, 0.2);
530
+ padding: 1px;
531
+ }
459
532
  </style>
460
533
 
461
534
  <style>
@@ -212,6 +212,7 @@ export default Vue.extend({
212
212
  :currentFrame="currentFrame"
213
213
  :layers="imageMetadata.channels"
214
214
  :layerMap="imageMetadata.channelmap"
215
+ :active="currentModeId === 2"
215
216
  :class="currentModeId === 2 ? '' : 'invisible'"
216
217
  @updateStyle="(style) => updateStyle(2, style)"
217
218
  />
@@ -222,6 +223,7 @@ export default Vue.extend({
222
223
  :currentFrame="currentFrame"
223
224
  :layers="imageMetadata.bands"
224
225
  :layerMap="undefined"
226
+ :active="currentModeId === 3"
225
227
  :class="currentModeId === 3 ? '' : 'invisible'"
226
228
  @updateStyle="(style) => updateStyle(3, style)"
227
229
  />
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: girder-large-image
3
- Version: 1.23.1.dev44
3
+ Version: 1.23.2.dev6
4
4
  Summary: A Girder plugin to work with large, multiresolution images.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -1,10 +1,10 @@
1
1
  girder>=3.1.18
2
2
  girder-jobs>=3.0.3
3
- large_image>=1.23.1.dev44
3
+ large_image>=1.23.2.dev6
4
4
 
5
5
  [:python_version < "3.8"]
6
6
  importlib-metadata<5
7
7
 
8
8
  [tasks]
9
- large-image-tasks[girder]>=1.23.1.dev44
9
+ large-image-tasks[girder]>=1.23.2.dev6
10
10
  girder-worker[girder]>=0.6.0