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.
- histomicsui/web_client/dialogs/saveAnnotation.js +330 -11
- histomicsui/web_client/panels/AnnotationSelector.js +4 -6
- histomicsui/web_client/panels/DrawWidget.js +0 -1
- histomicsui/web_client/stylesheets/dialogs/saveAnnotation.styl +8 -0
- histomicsui/web_client/templates/dialogs/saveAnnotation.pug +63 -16
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/METADATA +1 -1
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/RECORD +12 -12
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/LICENSE +0 -0
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/NOTICE +0 -0
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/WHEEL +0 -0
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/entry_points.txt +0 -0
- {histomicsui-1.4.2.dev30.dist-info → histomicsui-1.4.2.dev32.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
38
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
});
|
|
205
|
+
if (model.get('displayed')) {
|
|
206
|
+
this.trigger('h:redraw', model);
|
|
207
|
+
}
|
|
210
208
|
}
|
|
211
209
|
);
|
|
212
210
|
},
|
|
@@ -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='
|
|
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
|
|
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
|
-
|
|
43
|
-
|
|
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
|
|
@@ -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=
|
|
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=
|
|
41
|
-
histomicsui/web_client/panels/DrawWidget.js,sha256=
|
|
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=
|
|
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=
|
|
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.
|
|
148
|
-
histomicsui-1.4.2.
|
|
149
|
-
histomicsui-1.4.2.
|
|
150
|
-
histomicsui-1.4.2.
|
|
151
|
-
histomicsui-1.4.2.
|
|
152
|
-
histomicsui-1.4.2.
|
|
153
|
-
histomicsui-1.4.2.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|