@checksub_team/peaks_timeline 1.4.17
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.
- package/CHANGELOG.md +530 -0
- package/COPYING +165 -0
- package/README.md +1184 -0
- package/package.json +88 -0
- package/peaks.js +20174 -0
- package/peaks.js.d.ts +332 -0
- package/src/data-retriever.js +90 -0
- package/src/data.js +56 -0
- package/src/default-segment-marker.js +132 -0
- package/src/keyboard-handler.js +112 -0
- package/src/line-indicator.js +312 -0
- package/src/line.js +629 -0
- package/src/lines.js +356 -0
- package/src/main.js +663 -0
- package/src/marker-factories.js +91 -0
- package/src/mode-layer.js +361 -0
- package/src/mouse-drag-handler.js +207 -0
- package/src/player.js +178 -0
- package/src/playhead-layer.js +413 -0
- package/src/segment-marker.js +155 -0
- package/src/segment-shape.js +345 -0
- package/src/segment.js +229 -0
- package/src/segments-group.js +697 -0
- package/src/source-group.js +975 -0
- package/src/source.js +688 -0
- package/src/sources-layer.js +509 -0
- package/src/timeline-axis.js +238 -0
- package/src/timeline-segments.js +389 -0
- package/src/timeline-sources.js +431 -0
- package/src/timeline-zoomview.js +866 -0
- package/src/utils.js +339 -0
- package/src/waveform-builder.js +458 -0
- package/src/waveform-shape.js +223 -0
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* Defines the {@link SegmentsGroup} class.
|
|
5
|
+
*
|
|
6
|
+
* @module segments-group
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
define([
|
|
10
|
+
'./segment-shape',
|
|
11
|
+
'./utils',
|
|
12
|
+
'konva'
|
|
13
|
+
], function(
|
|
14
|
+
SegmentShape,
|
|
15
|
+
Utils,
|
|
16
|
+
Konva) {
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates a Konva.Group that displays segment markers against the audio
|
|
21
|
+
* waveform.
|
|
22
|
+
*
|
|
23
|
+
* @class
|
|
24
|
+
* @alias SegmentsGroup
|
|
25
|
+
*
|
|
26
|
+
* @param {Peaks} peaks
|
|
27
|
+
* @param {WaveformOverview|WaveformZoomView} view
|
|
28
|
+
* @param {Boolean} allowEditing
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
function SegmentsGroup(peaks, view, allowEditing) {
|
|
32
|
+
this._peaks = peaks;
|
|
33
|
+
this._view = view;
|
|
34
|
+
this._allowEditing = allowEditing;
|
|
35
|
+
|
|
36
|
+
this._firstSegmentId = null;
|
|
37
|
+
this._segments = {};
|
|
38
|
+
this._lastSegmentId = null;
|
|
39
|
+
|
|
40
|
+
this._segmentShapes = {};
|
|
41
|
+
this._group = new Konva.Group();
|
|
42
|
+
|
|
43
|
+
this._updatedSegments = [];
|
|
44
|
+
|
|
45
|
+
this._isMagnetized = false;
|
|
46
|
+
|
|
47
|
+
this._peaks.on('segment.updated', this._onSegmentsUpdate.bind(this));
|
|
48
|
+
this._peaks.on('segments.add', this._onSegmentsAdd.bind(this));
|
|
49
|
+
this._peaks.on('segments.remove', this._onSegmentsRemove.bind(this));
|
|
50
|
+
this._peaks.on('segments.remove_all', this._onSegmentsRemoveAll.bind(this));
|
|
51
|
+
this._peaks.on('segments.dragend', this._onSegmentUpdated.bind(this));
|
|
52
|
+
this._peaks.on('segments.setMagnetizing', this.setMagnetizing.bind(this));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Adds the group to the given {Konva.Group}.
|
|
57
|
+
*
|
|
58
|
+
* @param {Konva.Group} group
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
SegmentsGroup.prototype.addToGroup = function(group) {
|
|
62
|
+
group.add(this._group);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
SegmentsGroup.prototype.moveToTop = function() {
|
|
66
|
+
this._group.moveToTop();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
SegmentsGroup.prototype.enableEditing = function(enable) {
|
|
70
|
+
this._allowEditing = enable;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
SegmentsGroup.prototype.isEditingEnabled = function() {
|
|
74
|
+
return this._allowEditing;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
SegmentsGroup.prototype.y = function(value) {
|
|
78
|
+
return this._group.y(value);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
SegmentsGroup.prototype.getActiveSegment = function(time) {
|
|
82
|
+
var activeSegment = null;
|
|
83
|
+
var currentSegment = null;
|
|
84
|
+
var nextSegmentId = null;
|
|
85
|
+
|
|
86
|
+
do {
|
|
87
|
+
if (!currentSegment) {
|
|
88
|
+
currentSegment = this._segments[this._firstSegmentId];
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
currentSegment = this._segments[currentSegment.nextSegmentId];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (currentSegment) {
|
|
95
|
+
if (currentSegment.segment.startTime > time) {
|
|
96
|
+
// We didn't find an active segment and will not in the remainings segments
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (currentSegment.segment.startTime <= time && currentSegment.segment.endTime > time) {
|
|
101
|
+
activeSegment = currentSegment.segment;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
nextSegmentId = currentSegment.nextSegmentId;
|
|
110
|
+
} while (nextSegmentId);
|
|
111
|
+
|
|
112
|
+
return activeSegment;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
SegmentsGroup.prototype._onSegmentsUpdate = function(segment) {
|
|
116
|
+
if (this._segments[segment.id]) {
|
|
117
|
+
var redraw = false;
|
|
118
|
+
var segmentShape = this._segmentShapes[segment.id];
|
|
119
|
+
var frameOffset = this._view.getFrameOffset();
|
|
120
|
+
var width = this._view.getWidth();
|
|
121
|
+
var frameStartTime = this._view.pixelsToTime(frameOffset);
|
|
122
|
+
var frameEndTime = this._view.pixelsToTime(frameOffset + width);
|
|
123
|
+
|
|
124
|
+
this._deleteSegment(segment);
|
|
125
|
+
this._addSegment(segment);
|
|
126
|
+
|
|
127
|
+
if (segmentShape) {
|
|
128
|
+
this._removeSegment(segment);
|
|
129
|
+
redraw = true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (segment.isVisible(frameStartTime, frameEndTime)) {
|
|
133
|
+
this._addSegmentShape(segment);
|
|
134
|
+
redraw = true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (redraw) {
|
|
138
|
+
this.updateSegments(frameStartTime, frameEndTime);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
SegmentsGroup.prototype._onSegmentUpdated = function() {
|
|
144
|
+
this._peaks.emit('segments.updated', this._updatedSegments);
|
|
145
|
+
this._updatedSegments = [];
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
SegmentsGroup.prototype._onSegmentsAdd = function(segments) {
|
|
149
|
+
var self = this;
|
|
150
|
+
|
|
151
|
+
var frameOffset = self._view.getFrameOffset();
|
|
152
|
+
var width = self._view.getWidth();
|
|
153
|
+
|
|
154
|
+
var frameStartTime = self._view.pixelsToTime(frameOffset);
|
|
155
|
+
var frameEndTime = self._view.pixelsToTime(frameOffset + width);
|
|
156
|
+
|
|
157
|
+
segments.forEach(function(segment) {
|
|
158
|
+
self._addSegment(segment);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
self.updateSegments(frameStartTime, frameEndTime);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
SegmentsGroup.prototype._onSegmentsRemove = function(segments) {
|
|
165
|
+
var self = this;
|
|
166
|
+
|
|
167
|
+
segments.forEach(function(segment) {
|
|
168
|
+
var index = self._updatedSegments.indexOf(segment);
|
|
169
|
+
|
|
170
|
+
if (index > -1) {
|
|
171
|
+
self._updatedSegments.splice(index, 1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
self._removeSegment(segment);
|
|
175
|
+
self._deleteSegment(segment);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
this._draw();
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
SegmentsGroup.prototype._onSegmentsRemoveAll = function() {
|
|
182
|
+
this._group.removeChildren();
|
|
183
|
+
this._firstSegmentId = null;
|
|
184
|
+
this._segments = {};
|
|
185
|
+
this._lastSegmentId = null;
|
|
186
|
+
|
|
187
|
+
this._segmentShapes = {};
|
|
188
|
+
|
|
189
|
+
this._draw();
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
SegmentsGroup.prototype._addSegment = function(segment) {
|
|
193
|
+
var newSegment = {
|
|
194
|
+
segment: segment,
|
|
195
|
+
prevSegmentId: null,
|
|
196
|
+
nextSegmentId: null
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
if (this._firstSegmentId) {
|
|
200
|
+
var currentSegment = null;
|
|
201
|
+
|
|
202
|
+
do {
|
|
203
|
+
if (!currentSegment) {
|
|
204
|
+
currentSegment = this._segments[this._firstSegmentId];
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
currentSegment = this._segments[currentSegment.nextSegmentId];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (segment.startTime <= currentSegment.segment.startTime) {
|
|
211
|
+
if (currentSegment.prevSegmentId) {
|
|
212
|
+
this._segments[currentSegment.prevSegmentId].nextSegmentId = segment.id;
|
|
213
|
+
newSegment.prevSegmentId = currentSegment.prevSegmentId;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
this._firstSegmentId = segment.id;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
currentSegment.prevSegmentId = segment.id;
|
|
220
|
+
newSegment.nextSegmentId = currentSegment.segment.id;
|
|
221
|
+
|
|
222
|
+
this._segments[segment.id] = newSegment;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
} while (currentSegment.nextSegmentId);
|
|
226
|
+
|
|
227
|
+
if (!newSegment.prevSegmentId && !newSegment.nextSegmentId) {
|
|
228
|
+
currentSegment.nextSegmentId = segment.id;
|
|
229
|
+
newSegment.prevSegmentId = currentSegment.segment.id;
|
|
230
|
+
this._segments[segment.id] = newSegment;
|
|
231
|
+
this._lastSegmentId = segment.id;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
this._firstSegmentId = segment.id;
|
|
236
|
+
this._segments[segment.id] = newSegment;
|
|
237
|
+
this._lastSegmentId = segment.id;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
SegmentsGroup.prototype._deleteSegment = function(segment) {
|
|
242
|
+
if (this._segments[segment.id].prevSegmentId) {
|
|
243
|
+
this._segments[this._segments[segment.id].prevSegmentId].nextSegmentId
|
|
244
|
+
= this._segments[segment.id].nextSegmentId;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (this._segments[segment.id].nextSegmentId) {
|
|
248
|
+
this._segments[this._segments[segment.id].nextSegmentId].prevSegmentId
|
|
249
|
+
= this._segments[segment.id].prevSegmentId;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (this._firstSegmentId === segment.id) {
|
|
253
|
+
this._firstSegmentId = this._segments[segment.id].nextSegmentId;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (this._lastSegmentId === segment.id) {
|
|
257
|
+
this._lastSegmentId = this._segments[segment.id].prevSegmentId;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
delete this._segments[segment.id];
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
SegmentsGroup.prototype.getSegmentsGroupLength = function() {
|
|
264
|
+
if (this._segments[this._lastSegmentId]) {
|
|
265
|
+
return this._view.timeToPixels(this._segments[this._lastSegmentId].segment.endTime);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return 0;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Creates the Konva UI objects for a given segment.
|
|
273
|
+
*
|
|
274
|
+
* @private
|
|
275
|
+
* @param {Segment} segment
|
|
276
|
+
* @returns {SegmentShape}
|
|
277
|
+
*/
|
|
278
|
+
|
|
279
|
+
SegmentsGroup.prototype._createSegmentShape = function(segment) {
|
|
280
|
+
return new SegmentShape(segment, this._peaks, this, this._view);
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Adds a Konva UI object to the group for a given segment.
|
|
285
|
+
*
|
|
286
|
+
* @private
|
|
287
|
+
* @param {Segment} segment
|
|
288
|
+
* @returns {SegmentShape}
|
|
289
|
+
*/
|
|
290
|
+
|
|
291
|
+
SegmentsGroup.prototype._addSegmentShape = function(segment) {
|
|
292
|
+
var segmentShape = this._createSegmentShape(segment);
|
|
293
|
+
|
|
294
|
+
segmentShape.addToGroup(this._group, this);
|
|
295
|
+
|
|
296
|
+
this._segmentShapes[segment.id] = segmentShape;
|
|
297
|
+
|
|
298
|
+
return segmentShape;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
SegmentsGroup.prototype.updateSegmentsOnMove = function(segment, marker) {
|
|
302
|
+
this._updateSegments(segment, marker);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Updates the positions of all displayed segments in the view.
|
|
307
|
+
*
|
|
308
|
+
* @param {Number} startTime The start of the visible range in the view,
|
|
309
|
+
* in seconds.
|
|
310
|
+
* @param {Number} endTime The end of the visible range in the view,
|
|
311
|
+
* in seconds.
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
SegmentsGroup.prototype.updateSegments = function(startTime, endTime) {
|
|
315
|
+
// Update segments in visible time range.
|
|
316
|
+
var segments = this._peaks.segments.find(startTime, endTime);
|
|
317
|
+
|
|
318
|
+
var count = segments.length;
|
|
319
|
+
|
|
320
|
+
segments.forEach(this._updateSegment.bind(this));
|
|
321
|
+
|
|
322
|
+
// TODO: in the overview all segments are visible, so no need to check
|
|
323
|
+
count += this._removeInvisibleSegments(startTime, endTime);
|
|
324
|
+
|
|
325
|
+
if (count > 0) {
|
|
326
|
+
this._draw();
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
SegmentsGroup.prototype._draw = function() {
|
|
331
|
+
this._view.drawSourcesLayer();
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @private
|
|
336
|
+
* @param {Segment} segment
|
|
337
|
+
*/
|
|
338
|
+
|
|
339
|
+
SegmentsGroup.prototype._updateSegment = function(segment) {
|
|
340
|
+
var segmentShape = this._findOrAddSegmentShape(segment);
|
|
341
|
+
|
|
342
|
+
segmentShape.update();
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
SegmentsGroup.prototype.getCurrentHeight = function() {
|
|
346
|
+
var currentHeight = 0;
|
|
347
|
+
|
|
348
|
+
for (var id in this._segmentShapes) {
|
|
349
|
+
if (Utils.objectHasProperty(this._segmentShapes, id)) {
|
|
350
|
+
currentHeight = this._segmentShapes[id].getSegmentHeight();
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (!currentHeight && this._segments) {
|
|
356
|
+
currentHeight = this._peaks.options.segmentHeight;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return currentHeight;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* @private
|
|
364
|
+
* @param {Segment} segment
|
|
365
|
+
*/
|
|
366
|
+
|
|
367
|
+
SegmentsGroup.prototype._findOrAddSegmentShape = function(segment) {
|
|
368
|
+
var segmentShape = this._segmentShapes[segment.id];
|
|
369
|
+
|
|
370
|
+
if (!segmentShape) {
|
|
371
|
+
segmentShape = this._addSegmentShape(segment);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return segmentShape;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Removes any segments that are not visible, i.e., are not within and do not
|
|
379
|
+
* overlap the given time range.
|
|
380
|
+
*
|
|
381
|
+
* @private
|
|
382
|
+
* @param {Number} startTime The start of the visible time range, in seconds.
|
|
383
|
+
* @param {Number} endTime The end of the visible time range, in seconds.
|
|
384
|
+
* @returns {Number} The number of segments removed.
|
|
385
|
+
*/
|
|
386
|
+
|
|
387
|
+
SegmentsGroup.prototype._removeInvisibleSegments = function(startTime, endTime) {
|
|
388
|
+
var count = 0;
|
|
389
|
+
|
|
390
|
+
for (var segmentId in this._segmentShapes) {
|
|
391
|
+
if (Utils.objectHasProperty(this._segmentShapes, segmentId)) {
|
|
392
|
+
var segment = this._segmentShapes[segmentId].getSegment();
|
|
393
|
+
|
|
394
|
+
if (!segment.isVisible(startTime, endTime)) {
|
|
395
|
+
this._removeSegment(segment);
|
|
396
|
+
count++;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return count;
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
SegmentsGroup.prototype.getVisibleSegments = function() {
|
|
405
|
+
return this._getVisibleSegments();
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
SegmentsGroup.prototype._getVisibleSegments = function() {
|
|
409
|
+
var frameOffset = this._view.getFrameOffset();
|
|
410
|
+
var width = this._view.getWidth();
|
|
411
|
+
var frameStartTime = this._view.pixelsToTime(frameOffset);
|
|
412
|
+
var frameEndTime = this._view.pixelsToTime(frameOffset + width);
|
|
413
|
+
|
|
414
|
+
var visibleSegments = [];
|
|
415
|
+
|
|
416
|
+
for (var segmentId in this._segmentShapes) {
|
|
417
|
+
if (Utils.objectHasProperty(this._segmentShapes, segmentId)) {
|
|
418
|
+
var segment = this._segmentShapes[segmentId]._segment;
|
|
419
|
+
|
|
420
|
+
if (segment.isVisible(frameStartTime, frameEndTime)) {
|
|
421
|
+
visibleSegments.push(segment);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return visibleSegments;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
SegmentsGroup.prototype.setMagnetizing = function(bool) {
|
|
430
|
+
this._isMagnetized = bool;
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
SegmentsGroup.prototype.isMagnetized = function() {
|
|
434
|
+
return this._isMagnetized;
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
SegmentsGroup.prototype.addToUpdatedSegments = function(segment) {
|
|
438
|
+
if (this._updatedSegments.indexOf(segment) === -1) {
|
|
439
|
+
this._updatedSegments.push(segment);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
SegmentsGroup.prototype.updateSegment = function(segment, newStartX, newEndX) {
|
|
444
|
+
var newXs = this.manageCollision(segment, newStartX, newEndX);
|
|
445
|
+
|
|
446
|
+
if (newXs.startX !== null) {
|
|
447
|
+
segment.startTime = this._view.pixelsToTime(newXs.startX);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (newXs.endX !== null) {
|
|
451
|
+
segment.endTime = this._view.pixelsToTime(newXs.endX);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (newXs) {
|
|
455
|
+
this._updateSegment(segment);
|
|
456
|
+
|
|
457
|
+
this.addToUpdatedSegments(segment);
|
|
458
|
+
|
|
459
|
+
this._draw();
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
SegmentsGroup.prototype.manageCollision = function(segment, newStartX, newEndX) {
|
|
464
|
+
var newStartTime = null;
|
|
465
|
+
var newEndTime = null;
|
|
466
|
+
var startLimited = false;
|
|
467
|
+
var endLimited = false;
|
|
468
|
+
var segmentMagnetThreshold, width;
|
|
469
|
+
|
|
470
|
+
if (this._isMagnetized) {
|
|
471
|
+
segmentMagnetThreshold = this._view.pixelsToTime(
|
|
472
|
+
this._peaks.options.segmentMagnetThreshold
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
if (newStartX !== null && newEndX !== null) {
|
|
476
|
+
width = newEndX - newStartX;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (newStartX !== null) {
|
|
481
|
+
// startMarker changed
|
|
482
|
+
newStartTime = this._view.pixelsToTime(newStartX);
|
|
483
|
+
|
|
484
|
+
if (this._segments[segment.id].prevSegmentId) {
|
|
485
|
+
// there is another segment to the left
|
|
486
|
+
var previousSegment = this._segments[this._segments[segment.id].prevSegmentId].segment;
|
|
487
|
+
|
|
488
|
+
if (this._isMagnetized) {
|
|
489
|
+
if (newStartTime < previousSegment.endTime + segmentMagnetThreshold) {
|
|
490
|
+
newStartX = this._view.timeToPixels(previousSegment.endTime);
|
|
491
|
+
if (width) {
|
|
492
|
+
newEndX = newStartX + width;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return {
|
|
496
|
+
startX: newStartX,
|
|
497
|
+
endX: newEndX
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
else if (segment.startTime > newStartTime) {
|
|
502
|
+
// startMarker moved to the left
|
|
503
|
+
if (newStartTime < previousSegment.endTime) {
|
|
504
|
+
// there is collision
|
|
505
|
+
if (previousSegment.startTime + previousSegment.minSize > newStartTime) {
|
|
506
|
+
newStartTime = previousSegment.startTime + previousSegment.minSize;
|
|
507
|
+
startLimited = true;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (previousSegment.endTime !== newStartTime) {
|
|
511
|
+
previousSegment.endTime = newStartTime;
|
|
512
|
+
this._updateSegment(previousSegment);
|
|
513
|
+
this.addToUpdatedSegments(previousSegment);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
if (newStartTime < 0) {
|
|
520
|
+
newStartTime = 0;
|
|
521
|
+
startLimited = true;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (newEndX !== null) {
|
|
527
|
+
// endMarker changed
|
|
528
|
+
newEndTime = this._view.pixelsToTime(newEndX);
|
|
529
|
+
|
|
530
|
+
if (this._segments[segment.id].nextSegmentId) {
|
|
531
|
+
// there is another segment to the right
|
|
532
|
+
var nextSegment = this._segments[this._segments[segment.id].nextSegmentId].segment;
|
|
533
|
+
|
|
534
|
+
if (this._isMagnetized) {
|
|
535
|
+
if (newEndTime > nextSegment.startTime - segmentMagnetThreshold) {
|
|
536
|
+
newEndX = this._view.timeToPixels(nextSegment.startTime);
|
|
537
|
+
if (width) {
|
|
538
|
+
newStartX = newEndX - width;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return {
|
|
542
|
+
startX: newStartX,
|
|
543
|
+
endX: newEndX
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
else if (segment.endTime < newEndTime) {
|
|
548
|
+
// endMarker moved to the right
|
|
549
|
+
if (newEndTime > nextSegment.startTime) {
|
|
550
|
+
// there is collision
|
|
551
|
+
if (nextSegment.endTime - nextSegment.minSize < newEndTime) {
|
|
552
|
+
newEndTime = nextSegment.endTime - nextSegment.minSize;
|
|
553
|
+
endLimited = true;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (nextSegment.startTime !== newEndTime) {
|
|
557
|
+
nextSegment.startTime = newEndTime;
|
|
558
|
+
this._updateSegment(nextSegment);
|
|
559
|
+
this.addToUpdatedSegments(nextSegment);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
// No limits on the right
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Check for minimal size of segment
|
|
570
|
+
if (newStartTime !== null && newEndTime !== null) {
|
|
571
|
+
if (newEndTime - newStartTime < segment.minSize) {
|
|
572
|
+
if (startLimited) {
|
|
573
|
+
newEndTime = newStartTime + segment.minSize;
|
|
574
|
+
}
|
|
575
|
+
else if (endLimited) {
|
|
576
|
+
newStartTime = newEndTime - segment.minSize;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else if (newStartTime !== null) {
|
|
581
|
+
if (segment.endTime - newStartTime < segment.minSize) {
|
|
582
|
+
newStartTime = segment.endTime - segment.minSize;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
else if (newEndTime !== null) {
|
|
586
|
+
if (newEndTime - segment.startTime < segment.minSize) {
|
|
587
|
+
newEndTime = segment.startTime + segment.minSize;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
var output = {
|
|
592
|
+
startX: null,
|
|
593
|
+
endX: null
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
if (newStartTime !== null) {
|
|
597
|
+
output.startX = this._view.timeToPixels(newStartTime);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (newEndTime !== null) {
|
|
601
|
+
output.endX = this._view.timeToPixels(newEndTime);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return output;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
SegmentsGroup.prototype._getOverlappedSegments = function() {
|
|
608
|
+
var self = this;
|
|
609
|
+
var segments = this._getVisibleSegments();
|
|
610
|
+
|
|
611
|
+
return segments.reduce(function(result, segment) {
|
|
612
|
+
segments.forEach(function(segment2) {
|
|
613
|
+
if (self._segmentsOverlapped(segment, segment2)) {
|
|
614
|
+
if (!result.includes(segment2.id)) {
|
|
615
|
+
result.push(segment2);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
return result;
|
|
621
|
+
}, []);
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Removes the given segment from the view.
|
|
626
|
+
*
|
|
627
|
+
* @param {Segment} segment
|
|
628
|
+
*/
|
|
629
|
+
|
|
630
|
+
SegmentsGroup.prototype._removeSegment = function(segment) {
|
|
631
|
+
var segmentShape = this._segmentShapes[segment.id];
|
|
632
|
+
|
|
633
|
+
if (segmentShape) {
|
|
634
|
+
delete this._segmentShapes[segment.id];
|
|
635
|
+
segmentShape.destroy();
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Toggles visibility of the segments layer.
|
|
641
|
+
*
|
|
642
|
+
* @param {Boolean} visible
|
|
643
|
+
*/
|
|
644
|
+
|
|
645
|
+
SegmentsGroup.prototype.setVisible = function(visible) {
|
|
646
|
+
this._group.setVisible(visible);
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
SegmentsGroup.prototype.draw = function() {
|
|
650
|
+
this._draw();
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
SegmentsGroup.prototype._segmentsOverlapped = function(segment1, segment2) {
|
|
654
|
+
var endsLater = (segment1.startTime < segment2.startTime)
|
|
655
|
+
&& (segment1.endTime > segment2.startTime);
|
|
656
|
+
var startsEarlier = (segment1.startTime > segment2.startTime)
|
|
657
|
+
&& (segment1.startTime < segment2.endTime);
|
|
658
|
+
|
|
659
|
+
return endsLater || startsEarlier;
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
SegmentsGroup.prototype.destroy = function() {
|
|
663
|
+
this._peaks.off('segment.updated', this._onSegmentsUpdate);
|
|
664
|
+
this._peaks.off('segments.add', this._onSegmentsAdd);
|
|
665
|
+
this._peaks.off('segments.remove', this._onSegmentsRemove);
|
|
666
|
+
this._peaks.off('segments.remove_all', this._onSegmentsRemoveAll);
|
|
667
|
+
this._peaks.off('segments.dragged', this._onSegmentsDragged);
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
SegmentsGroup.prototype.fitToView = function() {
|
|
671
|
+
for (var segmentId in this._segmentShapes) {
|
|
672
|
+
if (Utils.objectHasProperty(this._segmentShapes, segmentId)) {
|
|
673
|
+
var segmentShape = this._segmentShapes[segmentId];
|
|
674
|
+
|
|
675
|
+
segmentShape.fitToView();
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
SegmentsGroup.prototype.contains = function(segment) {
|
|
681
|
+
for (var id in this._segments) {
|
|
682
|
+
if (Utils.objectHasProperty(this._segments, id)) {
|
|
683
|
+
if (id === segment.id) {
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
return false;
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
SegmentsGroup.prototype.getHeight = function() {
|
|
693
|
+
return this._group.getHeight();
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
return SegmentsGroup;
|
|
697
|
+
});
|