histomicsui 1.4.2.dev30__py2.py3-none-any.whl → 1.4.2.dev32__py2.py3-none-any.whl

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.
@@ -11,6 +11,201 @@ import View from '@girder/core/views/View';
11
11
  import MetadataWidget from '../panels/MetadataWidget';
12
12
  import '../stylesheets/dialogs/saveAnnotation.styl';
13
13
  import saveAnnotation from '../templates/dialogs/saveAnnotation.pug';
14
+ import { elementAreaAndEdgeLength } from '../views/utils';
15
+
16
+ /**
17
+ * Collect styleable properties from user parameters in elements.
18
+ *
19
+ * @param {object} styleableFuncs An object with distinct keys for functions.
20
+ * Modified.
21
+ * @param {array} elements A list of elements which might contain metadata
22
+ * properties in the user key.
23
+ * @param {array} [root] A list of keys within objects in an element.
24
+ */
25
+ function collectStyleableProps(styleableFuncs, elements, root) {
26
+ const maxCategories = 20;
27
+
28
+ let children = {};
29
+ root = root || [];
30
+ let key = 'user';
31
+ for (let j = 0; j < root.length; j += 1) {
32
+ key += '.' + root[j];
33
+ }
34
+ for (let i = 0; i < elements.length; i += 1) {
35
+ let proplist = elements[i].user;
36
+ for (let j = 0; j < root.length; j += 1) {
37
+ if (proplist) {
38
+ proplist = proplist[root[j]];
39
+ }
40
+ }
41
+ if (proplist !== undefined && proplist !== null) {
42
+ if (proplist.substring || (proplist.toFixed && _.isFinite(proplist))) {
43
+ if (styleableFuncs[key] === undefined) {
44
+ styleableFuncs[key] = {
45
+ root: root,
46
+ key: key,
47
+ name: root.map((k) => k.replace('_', ' ')).join(' - '),
48
+ categoric: !proplist.toFixed
49
+ };
50
+ styleableFuncs[key].values = [proplist];
51
+ if (!styleableFuncs[key].categoric) {
52
+ styleableFuncs[key].min = styleableFuncs[key].max = +proplist;
53
+ }
54
+ } else {
55
+ if (styleableFuncs[key].values.length <= maxCategories) {
56
+ if (styleableFuncs[key].values.indexOf(proplist) < 0) {
57
+ if (styleableFuncs[key].values.length >= maxCategories) {
58
+ styleableFuncs[key].manyValues = true;
59
+ } else {
60
+ styleableFuncs[key].values.push(proplist);
61
+ }
62
+ }
63
+ }
64
+ if (!styleableFuncs[key].categoric) {
65
+ const val = +proplist;
66
+ if (val < styleableFuncs[key].min) {
67
+ styleableFuncs[key].min = val;
68
+ }
69
+ if (val > styleableFuncs[key].max) {
70
+ styleableFuncs[key].max = val;
71
+ }
72
+ }
73
+ }
74
+ } else {
75
+ Object.keys(proplist).forEach((subkey) => {
76
+ children[subkey] = true;
77
+ });
78
+ }
79
+ }
80
+ }
81
+ Object.keys(children).forEach((subkey) => {
82
+ let subroot = root.slice();
83
+ subroot.push(subkey);
84
+ collectStyleableProps(styleableFuncs, elements, subroot);
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Calculate the min/max values for calculated properties.
90
+ *
91
+ * @param {object} styleableFuncs An object with distinct keys for functions.
92
+ * Modified.
93
+ * @param {array} elements A list of elements which might contain metadata
94
+ * properties in the user key.
95
+ */
96
+ function rangeStyleableProps(styleableFuncs, elements) {
97
+ let needsArea = true;
98
+ Object.entries(styleableFuncs).forEach(([key, func]) => {
99
+ if (['perimeter', 'area', 'length'].indexOf(key) >= 0) {
100
+ needsArea = true;
101
+ return;
102
+ }
103
+ if (!func.calc) {
104
+ return;
105
+ }
106
+ for (let i = 0; i < elements.length; i += 1) {
107
+ let d = elements[i];
108
+ if (d[key] !== undefined) {
109
+ if (func.min === undefined) {
110
+ func.min = func.max = d[key];
111
+ }
112
+ if (d[key] < func.min) {
113
+ func.min = d[key];
114
+ }
115
+ if (d[key] > func.max) {
116
+ func.max = d[key];
117
+ }
118
+ }
119
+ }
120
+ });
121
+ if (needsArea) {
122
+ for (let i = 0; i < elements.length; i += 1) {
123
+ let element = elements[i];
124
+ const { area, edge } = elementAreaAndEdgeLength({el: element});
125
+ if (styleableFuncs.area && area) {
126
+ if (styleableFuncs.area.min === undefined) {
127
+ styleableFuncs.area.min = styleableFuncs.area.max = area;
128
+ styleableFuncs.area.values = new Array(elements.length);
129
+ }
130
+ styleableFuncs.area.values[i] = area;
131
+ if (area < styleableFuncs.area.min) {
132
+ styleableFuncs.area.min = area;
133
+ }
134
+ if (area > styleableFuncs.area.max) {
135
+ styleableFuncs.area.max = area;
136
+ }
137
+ }
138
+ if (styleableFuncs.length && edge) {
139
+ if (styleableFuncs.length.min === undefined) {
140
+ styleableFuncs.length.min = styleableFuncs.length.max = edge;
141
+ styleableFuncs.length.values = new Array(elements.length);
142
+ }
143
+ styleableFuncs.length.values[i] = edge;
144
+ if (edge < styleableFuncs.length.min) {
145
+ styleableFuncs.length.min = edge;
146
+ }
147
+ if (edge > styleableFuncs.length.max) {
148
+ styleableFuncs.length.max = edge;
149
+ }
150
+ }
151
+ if (styleableFuncs.perimeter && edge) {
152
+ if (styleableFuncs.perimeter.min === undefined) {
153
+ styleableFuncs.perimeter.min = styleableFuncs.perimeter.max = edge;
154
+ styleableFuncs.perimeter.values = new Array(elements.perimeter);
155
+ }
156
+ styleableFuncs.perimeter.values[i] = edge;
157
+ if (edge < styleableFuncs.perimeter.min) {
158
+ styleableFuncs.perimeter.min = edge;
159
+ }
160
+ if (edge > styleableFuncs.perimeter.max) {
161
+ styleableFuncs.perimeter.max = edge;
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Given an element and a color function, compute the color needed.
170
+ *
171
+ * @param {elementModel} element The element for which to compute a color
172
+ * @param {number} idx The index in the element collection
173
+ * @param {object} colorParam A functioon record with prepared min, max,
174
+ * range, minColor, and maxColor values.
175
+ * @param {object} funcInfo Information about the function. If calc is true,
176
+ * values is an array of precomputed values. Otherwise, root is an
177
+ * attribute path in the element user object.
178
+ * @returns {string} A color string.
179
+ */
180
+ function colorFromFunc(element, idx, colorParam, funcInfo) {
181
+ const geo = window.geo;
182
+ let val;
183
+ if (funcInfo.calc) {
184
+ val = funcInfo.values[idx];
185
+ } else {
186
+ val = element.get('user');
187
+ for (let i = 0; i < funcInfo.root.length; i += 1) {
188
+ val = (val || {})[funcInfo.root[i]];
189
+ }
190
+ }
191
+ if (!_.isFinite(val)) {
192
+ return 'rgba(0,0,0,0)';
193
+ }
194
+ val = Math.max(Math.min((val - colorParam.min) / colorParam.range, 1), 0);
195
+ if (colorParam.minColor.a === undefined) {
196
+ colorParam.minColor.a = 1;
197
+ }
198
+ if (colorParam.maxColor.a === undefined) {
199
+ colorParam.maxColor.a = 1;
200
+ }
201
+ let clr = {
202
+ r: val * (colorParam.maxColor.r - colorParam.minColor.r) + colorParam.minColor.r,
203
+ g: val * (colorParam.maxColor.g - colorParam.minColor.g) + colorParam.minColor.g,
204
+ b: val * (colorParam.maxColor.b - colorParam.minColor.b) + colorParam.minColor.b,
205
+ a: val * (colorParam.maxColor.a - colorParam.minColor.a) + colorParam.minColor.a
206
+ };
207
+ return geo.util.convertColorToRGBA(clr);
208
+ }
14
209
 
15
210
  /**
16
211
  * Create a modal dialog with fields to edit the properties of
@@ -20,6 +215,19 @@ var SaveAnnotation = View.extend({
20
215
  events: {
21
216
  'click .h-access': 'access',
22
217
  'click .h-cancel': 'cancel',
218
+
219
+ 'input #h-annotation-fill-color': () => $('.h-functional-value #h-annotation-fill-color-fixed').prop('checked', true),
220
+ 'changeColor #h-annotation-colorpicker-fill-color': () => $('.h-functional-value #h-annotation-fill-color-fixed').prop('checked', true),
221
+ 'change #h-annotation-fill-color-func-list': 'changeFillColorFunc',
222
+ 'input #h-annotation-fill-color-min-val': () => $('.h-functional-value #h-annotation-fill-color-min-setval').prop('checked', true),
223
+ 'input #h-annotation-fill-color-max-val': () => $('.h-functional-value #h-annotation-fill-color-max-setval').prop('checked', true),
224
+
225
+ 'input #h-annotation-line-color': () => $('.h-functional-value #h-annotation-line-color-fixed').prop('checked', true),
226
+ 'changeColor #h-annotation-colorpicker-line-color': () => $('.h-functional-value #h-annotation-line-color-fixed').prop('checked', true),
227
+ 'change #h-annotation-line-color-func-list': 'changeLineColorFunc',
228
+ 'input #h-annotation-line-color-min-val': () => $('.h-functional-value #h-annotation-line-color-min-setval').prop('checked', true),
229
+ 'input #h-annotation-line-color-max-val': () => $('.h-functional-value #h-annotation-line-color-max-setval').prop('checked', true),
230
+
23
231
  'submit form': 'save'
24
232
  },
25
233
 
@@ -30,18 +238,38 @@ var SaveAnnotation = View.extend({
30
238
  let elementTypes = [];
31
239
  if (this.annotation.get('annotation').elements) {
32
240
  elementTypes = this.annotation.get('annotation').elements
33
- .map((element) => element.type)
241
+ .map((element) => element.type === 'polyline' ? (element.closed ? 'polygon' : 'line') : element.type)
34
242
  .filter((type, index, types) => types.indexOf(type) === index);
35
243
  }
36
244
  // should be updated when additional shape elements are supported
37
- const styleEditableElementTypes = ['point', 'polyline', 'rectangle', 'arrow', 'circle', 'ellipse'];
38
- const annotationHasEditableElements = _.filter(elementTypes, (type) => styleEditableElementTypes.includes(type)).length > 0;
245
+ const elementTypeProps = {
246
+ point: [],
247
+ polygon: ['perimeter', 'area'],
248
+ line: ['length'],
249
+ rectangle: ['perimeter', 'area', 'width', 'height', 'rotation'],
250
+ arrow: ['length'],
251
+ circle: ['perimeter', 'area', 'radius'],
252
+ ellipse: ['perimeter', 'area', 'width', 'height', 'rotation']
253
+ };
254
+ const annotationHasEditableElements = _.filter(elementTypes, (type) => elementTypeProps[type] !== undefined).length > 0;
39
255
  const showStyleEditor = this.annotation.get('annotation').elements && !this.annotation._pageElements && annotationHasEditableElements;
40
256
 
41
257
  const defaultStyles = {};
42
258
 
259
+ const styleableFuncs = {};
43
260
  if (showStyleEditor) {
261
+ let scale;
262
+ if (this.options.viewer && this.options.viewer._scale) {
263
+ scale = this.options.viewer._scale.scale;
264
+ }
265
+ elementTypes.forEach((type) => {
266
+ (elementTypeProps[type] || []).forEach((key) => {
267
+ styleableFuncs[key] = {calc: true, key: key, scale: scale, name: key};
268
+ });
269
+ });
44
270
  const elements = this.annotation.get('annotation').elements;
271
+ rangeStyleableProps(styleableFuncs, elements);
272
+ collectStyleableProps(styleableFuncs, elements.filter((d) => d.user));
45
273
  const firstElement = elements[0];
46
274
  if (elements.every((d) => d.lineWidth === firstElement.lineWidth)) {
47
275
  defaultStyles.lineWidth = firstElement.lineWidth;
@@ -53,6 +281,17 @@ var SaveAnnotation = View.extend({
53
281
  defaultStyles.fillColor = firstElement.fillColor;
54
282
  }
55
283
  }
284
+ this._showStyleEditor = showStyleEditor;
285
+ this._styleableFuncs = styleableFuncs;
286
+
287
+ let _styleFuncs;
288
+ if (this.annotation.attributes.annotation.attributes) {
289
+ _styleFuncs = this.annotation.attributes.annotation.attributes._styleFuncs;
290
+ }
291
+ if (!_styleFuncs || !_styleFuncs.lineColor || !_styleFuncs.fillColor || !_styleFuncs.lineWidth) {
292
+ _styleFuncs = {lineColor: {}, lineWidth: {}, fillColor: {}};
293
+ }
294
+ this.annotation._styleFuncs = _styleFuncs;
56
295
 
57
296
  this.$el.html(
58
297
  saveAnnotation({
@@ -63,6 +302,8 @@ var SaveAnnotation = View.extend({
63
302
  formatDate: formatDate,
64
303
  DATE_SECOND: DATE_SECOND,
65
304
  showStyleEditor,
305
+ styleableFuncs,
306
+ styleFuncs: this.annotation._styleFuncs,
66
307
  defaultStyles
67
308
  })
68
309
  ).girderModal(this);
@@ -71,6 +312,7 @@ var SaveAnnotation = View.extend({
71
312
  if (this.annotation.id) {
72
313
  if (!this.annotation.meta) {
73
314
  this.annotation._meta = Object.assign({}, (this.annotation.get('annotation') || {}).attributes || {});
315
+ delete this.annotation._meta._styleFuncs;
74
316
  }
75
317
  // copy the metadata to a place that is expected for the widget
76
318
  if (!this.metadataWidget) {
@@ -89,6 +331,7 @@ var SaveAnnotation = View.extend({
89
331
  }
90
332
 
91
333
  this.$el.find('.modal-dialog').addClass('hui-save-annotation-dialog');
334
+ this._updateFuncValues();
92
335
  return this;
93
336
  },
94
337
 
@@ -110,11 +353,71 @@ var SaveAnnotation = View.extend({
110
353
  cancel(evt) {
111
354
  if (this.annotation) {
112
355
  delete this.annotation._meta;
356
+ delete this.annotation._styleFuncs;
113
357
  }
114
358
  evt.preventDefault();
115
359
  this.$el.modal('hide');
116
360
  },
117
361
 
362
+ changeFillColorFunc() {
363
+ $('.h-functional-value #h-annotation-fill-color-func').prop('checked', true);
364
+ this._updateFuncValues();
365
+ },
366
+
367
+ changeLineColorFunc() {
368
+ $('.h-functional-value #h-annotation-line-color-func').prop('checked', true);
369
+ this._updateFuncValues();
370
+ },
371
+
372
+ _updateFuncValues() {
373
+ var names = ['fill-color', 'line-color'];
374
+ names.forEach((name) => {
375
+ let curfunc = this.$el.find('#h-annotation-' + name + '-func-list').val();
376
+ let mintext = '';
377
+ let maxtext = '';
378
+ if (this._styleableFuncs[curfunc]) {
379
+ if (!this._styleableFuncs[curfunc].categoric) {
380
+ mintext = 'Minimum value: ' + this._styleableFuncs[curfunc].min;
381
+ maxtext = 'Maximum value: ' + this._styleableFuncs[curfunc].max;
382
+ }
383
+ }
384
+ this.$el.find('#h-annotation-' + name + '-min-auto').parent().attr('title', mintext);
385
+ this.$el.find('#h-annotation-' + name + '-min-setval').parent().attr('title', mintext);
386
+ this.$el.find('#h-annotation-' + name + '-max-auto').parent().attr('title', maxtext);
387
+ this.$el.find('#h-annotation-' + name + '-max-setval').parent().attr('title', maxtext);
388
+ });
389
+ },
390
+
391
+ _getFunctionalProps(name, key, valueParam, setValue, color) {
392
+ var geo = window.geo;
393
+
394
+ let valueFunc = this.annotation._styleFuncs[key];
395
+ valueFunc.useFunc = this.$('#h-annotation-' + name + '-func').prop('checked');
396
+ valueFunc.key = this.$('#h-annotation-' + name + '-func-list').val();
397
+ valueFunc.minColor = tinycolor(this.$('#h-annotation-' + name + '-min').val()).toRgbString();
398
+ valueFunc.minSet = this.$('#h-annotation-' + name + '-min-setval').prop('checked');
399
+ valueFunc.minValue = parseFloat(this.$('#h-annotation-' + name + '-min-val').val());
400
+ valueFunc.minValue = _.isFinite(valueFunc.minValue) ? valueFunc.minValue : undefined;
401
+ valueFunc.maxColor = tinycolor(this.$('#h-annotation-' + name + '-max').val()).toRgbString();
402
+ valueFunc.maxSet = this.$('#h-annotation-' + name + '-max-setval').prop('checked');
403
+ valueFunc.maxValue = parseFloat(this.$('#h-annotation-' + name + '-max-val').val());
404
+ valueFunc.maxValue = _.isFinite(valueFunc.maxValue) ? valueFunc.maxValue : undefined;
405
+ if (valueFunc.useFunc) {
406
+ setValue = 'func';
407
+ }
408
+ valueParam.key = valueFunc.key;
409
+ if (this._styleableFuncs[valueFunc.key]) {
410
+ valueParam.min = valueFunc.minSet && _.isFinite(valueFunc.minValue) ? valueFunc.minValue : this._styleableFuncs[valueFunc.key].min;
411
+ valueParam.max = valueFunc.maxSet && _.isFinite(valueFunc.maxValue) ? valueFunc.maxValue : this._styleableFuncs[valueFunc.key].max;
412
+ valueParam.range = (valueParam.max - valueParam.min) || 1;
413
+ valueParam.minColor = geo.util.convertColor(valueFunc.minColor);
414
+ valueParam.maxColor = geo.util.convertColor(valueFunc.maxColor);
415
+ } else if (setValue === 'func') {
416
+ setValue = false;
417
+ }
418
+ return setValue;
419
+ },
420
+
118
421
  /**
119
422
  * Respond to form submission. Triggers a `g:save` event on the
120
423
  * AnnotationModel.
@@ -129,10 +432,10 @@ var SaveAnnotation = View.extend({
129
432
  validation += 'Please enter a name. ';
130
433
  }
131
434
 
132
- const setFillColor = !!this.$('#h-annotation-fill-color').val();
133
- const fillColor = tinycolor(this.$('#h-annotation-fill-color').val()).toRgbString();
134
- const setLineColor = !!this.$('#h-annotation-line-color').val();
135
- const lineColor = tinycolor(this.$('#h-annotation-line-color').val()).toRgbString();
435
+ let setFillColor = !!this.$('#h-annotation-fill-color').val();
436
+ let fillColor = tinycolor(this.$('#h-annotation-fill-color').val()).toRgbString();
437
+ let setLineColor = !!this.$('#h-annotation-line-color').val();
438
+ let lineColor = tinycolor(this.$('#h-annotation-line-color').val()).toRgbString();
136
439
  const setLineWidth = !!this.$('#h-annotation-line-width').val();
137
440
  const lineWidth = parseFloat(this.$('#h-annotation-line-width').val());
138
441
 
@@ -141,6 +444,14 @@ var SaveAnnotation = View.extend({
141
444
  this.$('#h-annotation-line-width').parent().addClass('has-error');
142
445
  }
143
446
 
447
+ let fillColorParam = {};
448
+ let lineColorParam = {};
449
+ if (this._showStyleEditor && Object.keys(this._styleableFuncs || {}).length) {
450
+ // get functional values
451
+ setFillColor = this._getFunctionalProps('fill-color', 'fillColor', fillColorParam, fillColor, setFillColor, true);
452
+ setLineColor = this._getFunctionalProps('line-color', 'lineColor', lineColorParam, lineColor, setLineColor, true);
453
+ }
454
+
144
455
  if (validation) {
145
456
  this.$('.g-validation-failed-message').text(validation.trim())
146
457
  .removeClass('hidden');
@@ -148,13 +459,18 @@ var SaveAnnotation = View.extend({
148
459
  }
149
460
 
150
461
  // all valid
151
-
152
462
  if (setFillColor || setLineColor || setLineWidth) {
153
- this.annotation.elements().each((element) => { /* eslint-disable backbone/no-silent */
463
+ this.annotation.elements().each((element, idx) => { /* eslint-disable backbone/no-silent */
154
464
  if (setFillColor) {
465
+ if (setFillColor === 'func') {
466
+ fillColor = colorFromFunc(element, idx, fillColorParam, this._styleableFuncs[fillColorParam.key]);
467
+ }
155
468
  element.set('fillColor', fillColor, {silent: true});
156
469
  }
157
470
  if (setLineColor) {
471
+ if (setLineColor === 'func') {
472
+ lineColor = colorFromFunc(element, idx, lineColorParam, this._styleableFuncs[lineColorParam.key]);
473
+ }
158
474
  element.set('lineColor', lineColor, {silent: true});
159
475
  }
160
476
  if (setLineWidth) {
@@ -163,15 +479,18 @@ var SaveAnnotation = View.extend({
163
479
  });
164
480
  const annotationData = _.extend({}, this.annotation.get('annotation'));
165
481
  annotationData.elements = this.annotation.elements().toJSON();
166
- this.annotation.set('annotation', annotationData);
482
+ this.annotation.set('annotation', annotationData, {silent: true});
167
483
  }
168
484
 
169
485
  _.extend(this.annotation.get('annotation'), {
170
486
  name: this.$('#h-annotation-name').val(),
171
487
  description: this.$('#h-annotation-description').val()
172
488
  });
173
- this.annotation.attributes.annotation.attributes = this.annotation._meta;
489
+ this.annotation.attributes.annotation.attributes = Object.assign({}, this.annotation._meta);
490
+ this.annotation.attributes.annotation.attributes._styleFuncs = this.annotation._styleFuncs;
174
491
  delete this.annotation._meta;
492
+ delete this.annotation._styleFuncs;
493
+ this.annotation.trigger('change:annotation', this.annotation, {});
175
494
  this.trigger('g:submit');
176
495
  this.$el.modal('hide');
177
496
  },
@@ -199,14 +199,12 @@ var AnnotationSelector = Panel.extend({
199
199
  const id = $(evt.currentTarget).parents('.h-annotation').data('id');
200
200
  const model = this.collection.get(id);
201
201
  this.listenToOnce(
202
- showSaveAnnotationDialog(model, {title: 'Edit annotation'}),
202
+ showSaveAnnotationDialog(model, {title: 'Edit annotation', viewer: this.viewer}),
203
203
  'g:submit',
204
204
  () => {
205
- model.save().done(() => {
206
- if (model.get('displayed')) {
207
- this.trigger('h:redraw', model);
208
- }
209
- });
205
+ if (model.get('displayed')) {
206
+ this.trigger('h:redraw', model);
207
+ }
210
208
  }
211
209
  );
212
210
  },
@@ -973,7 +973,6 @@ var DrawWidget = Panel.extend({
973
973
  },
974
974
 
975
975
  _styleGroupEditor() {
976
- console.log(this);
977
976
  var dlg = editStyleGroups(this._style, this._groups, this.parentView._defaultGroup);
978
977
  dlg.$el.on('hidden.bs.modal', () => {
979
978
  this.render();
@@ -23,3 +23,11 @@
23
23
  .modal-dialog.hui-save-annotation-dialog
24
24
  width 70%
25
25
  max-width 900px
26
+ label.unstyled
27
+ margin-bottom unset
28
+ font-weight normal
29
+ margin-left 4px
30
+ .h-functional-value
31
+ input[type="number"]
32
+ width 100px
33
+ margin-left 5px
@@ -1,3 +1,62 @@
1
+ mixin functional(name, key, title, color)
2
+ .form-group.h-functional-value
3
+ label(for='h-annotation-' + name) #{title}
4
+ - console.log(styleableFuncs);
5
+ - let anyFuncs = !!Object.keys(styleableFuncs || {}).length;
6
+ - console.log(anyFuncs);
7
+ if !anyFuncs
8
+ .input-group.h-colorpicker(id="h-annotation-colorpicker-" + name)
9
+ input.input-sm.form-control(id="h-annotation-" + name, type='text', value=defaultStyles[key])
10
+ span.input-group-addon
11
+ i
12
+ else
13
+ .row
14
+ .col-sm-2
15
+ input(id="h-annotation-" + name + "-fixed", type="radio", name=name + "-set", checked=styleFuncs[key].useFunc ? undefined : 'checked')
16
+ label.unstyled(for='h-annotation-' + name + '-fixed') Constant
17
+ .col-sm-10
18
+ .input-group.h-colorpicker(id="h-annotation-colorpicker-" + name)
19
+ input.input-sm.form-control(id="h-annotation-" + name, type='text', value=defaultStyles[key])
20
+ span.input-group-addon
21
+ i
22
+ .row
23
+ .col-sm-2
24
+ input(id="h-annotation-" + name + "-func", type="radio", name=name + "-set", checked=styleFuncs[key].useFunc ? 'checked' : undefined)
25
+ label.unstyled(for='h-annotation-' + name + '-func') From
26
+ .col-sm-10
27
+ select.format-control.input-sm(id="h-annotation-" + name + "-func-list")
28
+ each sfunc in styleableFuncs
29
+ if !sfunc.categoric
30
+ option(value=sfunc.key, selected=styleFuncs[key].key === sfunc.key) #{sfunc.name}
31
+ .row
32
+ .col-sm-2
33
+ .col-sm-3
34
+ | minimum
35
+ .input-group.h-colorpicker
36
+ input.input-sm.form-control(id="h-annotation-" + name + "-min", type='text', value=styleFuncs[key].minColor || defaultStyles[key])
37
+ span.input-group-addon
38
+ i
39
+ .col-sm-2
40
+ div
41
+ input(id="h-annotation-" + name + "-min-auto", type="radio", name=name + "-min-set", checked=styleFuncs[key].minSet ? undefined : 'checked')
42
+ label.unstyled(for='h-annotation-' + name + '-min-auto') auto
43
+ div
44
+ input(id="h-annotation-" + name + "-min-setval", type="radio", name=name + "-min-set", checked=styleFuncs[key].minSet ? 'checked' : undefined)
45
+ input(id="h-annotation-" + name + "-min-val", type="number", step="any", value=styleFuncs[key].minValue)
46
+ .col-sm-3
47
+ | maximum
48
+ .input-group.h-colorpicker
49
+ input.input-sm.form-control(id="h-annotation-" + name + "-max", type='text', value=styleFuncs[key].maxColor || defaultStyles[key])
50
+ span.input-group-addon
51
+ i
52
+ .col-sm-2
53
+ div
54
+ input(id="h-annotation-" + name + "-max-auto", type="radio", name=name + "-max-set", checked=styleFuncs[key].maxSet ? undefined : 'checked')
55
+ label.unstyled(for='h-annotation-' + name + '-max-auto') auto
56
+ div
57
+ input(id="h-annotation-" + name + "-max-setval", type="radio", name=name + "-max-set", checked=styleFuncs[key].maxSet ? 'checked' : undefined)
58
+ input(id="h-annotation-" + name + "-max-val", type="number", step="any", value=styleFuncs[key].maxValue)
59
+
1
60
  - var timestamp = moment().format('YYYY-MM-DD HH:mm')
2
61
  - var defaultName = 'Annotation '+ timestamp
3
62
  .modal-dialog(role='document')
@@ -15,7 +74,7 @@
15
74
  .form-group
16
75
  label(for='h-annotation-description') Description
17
76
  textarea#h-annotation-description.form-control.input-sm(
18
- rows='6', placeholder='Enter an optional description')
77
+ rows='4', placeholder='Enter an optional description')
19
78
  | #{annotation.description}
20
79
  if model && model.id
21
80
  .g-item-created.hui-info-list-entry
@@ -34,25 +93,13 @@
34
93
  .hui-annotation-metadata.hui-annotation-metadata-dialog
35
94
  if showStyleEditor
36
95
  hr
37
- h4 Reset the style for all point, line, and polygon elements in this annotation
96
+ h4 Set the style for all point, line, and polygon elements in this annotation
38
97
  .form-group
39
98
  label(for='h-annotation-line-width') Line Width
40
99
  input#h-annotation-line-width.input-sm.form-control(
41
100
  type='number', min=0, step=0.1, value=defaultStyles.lineWidth)
42
- .form-group
43
- label(for='h-annotation-line-color') Line color
44
- .input-group.h-colorpicker
45
- input#h-annotation-line-color.input-sm.form-control(
46
- type='text', value=defaultStyles.lineColor)
47
- span.input-group-addon
48
- i
49
- .form-group
50
- label(for='h-annotation-fill-color') Fill color
51
- .input-group.h-colorpicker
52
- input#h-annotation-fill-color.input-sm.form-control(
53
- type='text', value=defaultStyles.fillColor)
54
- span.input-group-addon
55
- i
101
+ +functional('line-color', 'lineColor', 'Line color', true)
102
+ +functional('fill-color', 'fillColor', 'Fill color', true)
56
103
  .g-validation-failed-message.hidden
57
104
  .modal-footer
58
105
  if hasAdmin
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: histomicsui
3
- Version: 1.4.2.dev30
3
+ Version: 1.4.2.dev32
4
4
  Summary: Organize, visualize, and analyze histology images.
5
5
  Home-page: https://github.com/DigitalSlideArchive/histomicsui
6
6
  Author: Kitware, Inc.
@@ -34,11 +34,11 @@ histomicsui/web_client/dialogs/index.js,sha256=PzVsFClPf29-a5w2FiPGUCFBnAmNRBu_P
34
34
  histomicsui/web_client/dialogs/metadataPlot.js,sha256=TpMjA1vGfH-qOAoPbLlUlejZDZ0nLRQVvjliHaDJp3Q,1151
35
35
  histomicsui/web_client/dialogs/openAnnotatedImage.js,sha256=E4Vm8KUX6gkXQpzTmFeYY8iPQw88R5EVnDMeuJUQhC8,4938
36
36
  histomicsui/web_client/dialogs/openImage.js,sha256=hY_jn9P_70hBBKF4V-FwXuxjRMqDXmHYf-59XZDn2Vg,2596
37
- histomicsui/web_client/dialogs/saveAnnotation.js,sha256=GwNFDRzPX2yGnfb7HvU93F95Q847MH-Qh280DEJrotg,7825
37
+ histomicsui/web_client/dialogs/saveAnnotation.js,sha256=dQwZXXkKH8k4YwYEQk31dE-pwIbuEfSeHuDch-wIkfo,22761
38
38
  histomicsui/web_client/models/StyleModel.js,sha256=g7BbrR9T7eIEdfmCOeHy3F9u70lPBvlgJszV-P6Qk4g,221
39
39
  histomicsui/web_client/models/index.js,sha256=5dtuUll1D1u1bKFh1bzsNeNsiRPEqDCb-aLN_GeFaTU,67
40
- histomicsui/web_client/panels/AnnotationSelector.js,sha256=c6pvKxUUSFLRfqTWSNoi55t8Xg0v5b6Iht3pXmDRZsQ,22381
41
- histomicsui/web_client/panels/DrawWidget.js,sha256=EgSsEazVMpJgCchn5LACpZFLdYmA29kZ8y0i-qJhNCQ,43115
40
+ histomicsui/web_client/panels/AnnotationSelector.js,sha256=6ouJSV4lABWHuOADlqBqBr5xQN8gbggs5MOj6dmaAKo,22328
41
+ histomicsui/web_client/panels/DrawWidget.js,sha256=D3GRqR6npBc8HVKDkfz-MZHQBLe0R1_705Gzis1fwCg,43088
42
42
  histomicsui/web_client/panels/MetadataPlot.js,sha256=DJqjIeKe3SPhfoHWeWyIDBB4iVu-JIUACpdytZYTAaI,14099
43
43
  histomicsui/web_client/panels/MetadataWidget.js,sha256=9xLUb0B1ytD-8kFBlSrWvL5bCp58mEeH3Em47Hstmjg,22113
44
44
  histomicsui/web_client/panels/OverviewWidget.js,sha256=BB1d-CmfDOu4i40QBN3IB6KDAe3ZBKgLU081ldmNgPs,8027
@@ -51,7 +51,7 @@ histomicsui/web_client/stylesheets/body/frontPage.styl,sha256=j1SwYQyqMkzWxTomLV
51
51
  histomicsui/web_client/stylesheets/body/image.styl,sha256=6oodPCcLKiE6e2jmBLuRl6tOeVEqCj_KG2EAN7PDXLg,1018
52
52
  histomicsui/web_client/stylesheets/dialogs/editStyleGroups.styl,sha256=wmlQdm3UyPb-bI7WI_0PJFOn9Tpctk4PB16UjkU1gNQ,191
53
53
  histomicsui/web_client/stylesheets/dialogs/openAnnotatedImage.styl,sha256=C04OiJAVJlx8PVxRcfYD65QTtKPHFC8u1iI612EXYVk,238
54
- histomicsui/web_client/stylesheets/dialogs/saveAnnotation.styl,sha256=aGi9nrBHRMhgtcBTivtUyb3WEYqUkeQr2KoAEs5Vv9M,614
54
+ histomicsui/web_client/stylesheets/dialogs/saveAnnotation.styl,sha256=WqALpP2VdA19a1_T5IfIkTCgSEvZMh_aGTXtYLZ3uus,769
55
55
  histomicsui/web_client/stylesheets/layout/header.styl,sha256=9rDj4R-MyFYI0BNEcn3BS5qDHWMZa1DtVxnPWes5uA8,976
56
56
  histomicsui/web_client/stylesheets/layout/headerAnalyses.styl,sha256=X3N2MnjPjoUTLybAA1PfjBOUakhRlTuKB3X8w1ae6N8,53
57
57
  histomicsui/web_client/stylesheets/layout/headerImage.styl,sha256=t5drLC5uiPyRHWPQzac8cV-QjI7yqowT5kY4xN994_M,150
@@ -77,7 +77,7 @@ histomicsui/web_client/templates/dialogs/editStyleGroups.pug,sha256=3cTwOH0_wBUV
77
77
  histomicsui/web_client/templates/dialogs/metadataPlot.pug,sha256=SmJ5aX5wuOR7OVws-rxl9RK-0PPOEUcJ8-I8pSmzPx8,1541
78
78
  histomicsui/web_client/templates/dialogs/openAnnotatedImage.pug,sha256=yxE6lc9lMu_XvhvGE-iIAO2TgzJJQYFiASRwSyF9mHc,838
79
79
  histomicsui/web_client/templates/dialogs/openImage.pug,sha256=EG077EI4Iavr5RPhgSCvif0yy2XUVX_VKNxzZ0cRbV4,353
80
- histomicsui/web_client/templates/dialogs/saveAnnotation.pug,sha256=SCe5K7CSRBwJ_x3_hv607jZbYahyhzZCq2qCrIclVIU,2759
80
+ histomicsui/web_client/templates/dialogs/saveAnnotation.pug,sha256=vGaSvQZY2OZSEDo6OwPmx3__-DAR2qRjNsqlNtJ51aA,5456
81
81
  histomicsui/web_client/templates/layout/header.pug,sha256=ZP2TW4cmoDUdnE4QbKgYTy_NjrD3Jf3WLpif5MMWxrA,925
82
82
  histomicsui/web_client/templates/layout/headerAnalyses.pug,sha256=-L60RJqU3_IVKvlxHgautxum122DLAAvR_wUXThx6BY,865
83
83
  histomicsui/web_client/templates/layout/headerImage.pug,sha256=YJXVbOoU05OF5YPYBmnbpri4NRrIAukTIoQO2O44dPk,1467
@@ -144,10 +144,10 @@ tests/web_client_specs/metadataPlotSpec.js,sha256=RPskJXJmKMR1sUseNDPMn1vEdq31qW
144
144
  tests/web_client_specs/overviewPanelSpec.js,sha256=-gz7fKgADN_jhZpiSFrsRZ-xHyi2v0OC3oz-5sv201U,6175
145
145
  tests/web_client_specs/panelLayoutSpec.js,sha256=C2PHkOHkENp3k2DXndxsiVeo0dALyQ1ygmUQUuP0Xu0,2917
146
146
  tests/web_client_specs/pixelmapCategorySpec.js,sha256=HSKhStf5UVef3j5HrEIxhdNqg6xc_QdvgE59VV3GUxc,13890
147
- histomicsui-1.4.2.dev30.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
148
- histomicsui-1.4.2.dev30.dist-info/METADATA,sha256=TuvdVxXWBc5s_RQ21w399sfz8XvZ8IECl3tf0mIBOi0,7267
149
- histomicsui-1.4.2.dev30.dist-info/NOTICE,sha256=Fb_KGPk6UyEsqbF5nJj2J_ux2IaIqze5ljBGfTE_auE,585
150
- histomicsui-1.4.2.dev30.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
151
- histomicsui-1.4.2.dev30.dist-info/entry_points.txt,sha256=SZB5fiWiKFOr_SsVOi94gDeNlJkMDI22AFcdKqoDVfs,55
152
- histomicsui-1.4.2.dev30.dist-info/top_level.txt,sha256=X2MiOqcwTp_HroIOfkJ78GumCBLy5RxeiWkYKTdQaHc,18
153
- histomicsui-1.4.2.dev30.dist-info/RECORD,,
147
+ histomicsui-1.4.2.dev32.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
148
+ histomicsui-1.4.2.dev32.dist-info/METADATA,sha256=jbpwCOs2VpKMU50jTtBZ0AlWGDT9yu-YCsmBWlqKOWw,7267
149
+ histomicsui-1.4.2.dev32.dist-info/NOTICE,sha256=Fb_KGPk6UyEsqbF5nJj2J_ux2IaIqze5ljBGfTE_auE,585
150
+ histomicsui-1.4.2.dev32.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
151
+ histomicsui-1.4.2.dev32.dist-info/entry_points.txt,sha256=SZB5fiWiKFOr_SsVOi94gDeNlJkMDI22AFcdKqoDVfs,55
152
+ histomicsui-1.4.2.dev32.dist-info/top_level.txt,sha256=X2MiOqcwTp_HroIOfkJ78GumCBLy5RxeiWkYKTdQaHc,18
153
+ histomicsui-1.4.2.dev32.dist-info/RECORD,,