lexgui 0.5.6 → 0.5.8

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.
@@ -17,7 +17,7 @@ class TimeBar {
17
17
 
18
18
  static BACKGROUND_COLOR = LX.getThemeColor("global-branch-darker");
19
19
  static COLOR = LX.getThemeColor("global-button-color");
20
- static ACTIVE_COLOR = LX.getThemeColor("global-selected-light");
20
+ static ACTIVE_COLOR = "#668ee4";
21
21
 
22
22
  constructor( area, type, options = {} ) {
23
23
 
@@ -30,60 +30,66 @@ class TimeBar {
30
30
  area.attach( this.canvas );
31
31
 
32
32
  this.ctx = this.canvas.getContext("2d");
33
-
34
- const barHeight = options.barHeight ?? 5;
33
+
35
34
  this.markerWidth = options.markerWidth ?? 8;
36
- this.offset = options.offset || 4;
35
+ this.markerHeight = options.markerHeight ?? (this.canvas.height * 0.5);
36
+ this.offset = options.offset || (this.markerWidth*0.5 + 8);
37
37
 
38
- this.width = this.canvas.width - this.offset * 2;
39
- this.height = barHeight;
38
+ // dimensions of line (not canvas)
39
+ this.lineWidth = this.canvas.width - this.offset * 2;
40
+ this.lineHeight = options.barHeight ?? 5;
40
41
 
41
- this.position = new LX.vec2( this.offset, this.canvas.height * 0.5 - this.height * 0.5);
42
+ this.position = new LX.vec2( this.offset, this.canvas.height * 0.5 - this.lineHeight * 0.5);
42
43
  this.startX = this.position.x;
43
- this.endX = this.width;
44
+ this.endX = this.position.x + this.lineWidth;
44
45
  this.currentX = this.startX;
45
46
 
46
- const y = this.offset * 2;
47
- const w = this.markerWidth;
48
- const h = this.canvas.height - y * 2;
49
- this.trimRec = [this.startX, y, w, h];
47
+ this._draw();
50
48
 
51
- this.lastPosition = new LX.vec2( 0, 0 );
49
+ this.updateTheme();
50
+ LX.addSignal( "@on_new_color_scheme", (el, value) => {
51
+ // Retrieve again the color using LX.getThemeColor, which checks the applied theme
52
+ this.updateTheme();
53
+ } )
54
+ }
52
55
 
53
- this._draw();
56
+ updateTheme(){
57
+ TimeBar.BACKGROUND_COLOR = LX.getThemeColor("global-color-secondary");
58
+ TimeBar.COLOR = LX.getThemeColor("global-color-quaternary");
59
+ TimeBar.ACTIVE_COLOR = "#668ee4";
54
60
  }
55
61
 
56
62
  _draw() {
57
63
  const ctx = this.ctx;
58
-
64
+
59
65
  ctx.save();
60
66
  ctx.fillStyle = TimeBar.BACKGROUND_COLOR;
61
67
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
62
68
  ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
63
69
 
64
- // // Draw background timeline
70
+ // Draw background timeline
65
71
  ctx.fillStyle = TimeBar.COLOR;
66
- ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
72
+ ctx.fillRect(this.position.x, this.position.y, this.lineWidth, this.lineHeight);
67
73
 
68
74
  // Draw background trimed timeline
69
75
  ctx.fillStyle = TimeBar.ACTIVE_COLOR;
70
- ctx.fillRect(this.startX, this.position.y, this.endX - this.offset - this.startX, this.height);
76
+ ctx.fillRect(this.startX, this.position.y, this.endX - this.startX, this.lineHeight);
71
77
 
72
78
  ctx.restore();
73
79
 
74
80
  // Min-Max time markers
75
- this._addTrim('start', this.startX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9'});
76
- this._addTrim('end', this.endX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9'});
77
- this._addMarker('current', this.currentX, { color: '#e5e5e5', fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9', width: this.markerWidth });
81
+ this._drawTrimMarker('start', this.startX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9'});
82
+ this._drawTrimMarker('end', this.endX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9'});
83
+ this._drawTimeMarker('current', this.currentX, { color: '#e5e5e5', fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9', width: this.markerWidth });
78
84
  }
79
85
 
80
- _addTrim(name, x, options) {
86
+ _drawTrimMarker(name, x, options) {
81
87
 
82
88
  options = options || {};
83
89
 
84
- const y = this.trimRec[1];
85
- const w = this.trimRec[2];
86
- const h = this.trimRec[3];
90
+ const w = this.markerWidth;
91
+ const h = this.markerHeight;
92
+ const y = this.canvas.height * 0.5 - h * 0.5;
87
93
 
88
94
  const ctx = this.ctx;
89
95
  if(this.hovering == name) {
@@ -109,7 +115,7 @@ class TimeBar {
109
115
 
110
116
  }
111
117
 
112
- _addMarker(name, x, options) {
118
+ _drawTimeMarker(name, x, options) {
113
119
 
114
120
  options = options || {};
115
121
 
@@ -150,6 +156,15 @@ class TimeBar {
150
156
  ctx.shadowBlur = 0;
151
157
  }
152
158
 
159
+ update (x) {
160
+ this.currentX = Math.min(Math.max(this.startX, x), this.endX);
161
+ this._draw();
162
+
163
+ if(this.onDraw) {
164
+ this.onDraw();
165
+ }
166
+ }
167
+
153
168
  onMouseDown (e) {
154
169
 
155
170
  e.preventDefault();
@@ -166,19 +181,19 @@ class TimeBar {
166
181
  // Check if some marker is clicked
167
182
  const threshold = this.markerWidth;
168
183
 
169
- if(Math.abs(this.startX - x) < threshold && this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1] ) {
184
+ // grab trim markers only from the bottom
185
+ if(Math.abs(this.startX - x) < threshold && this.position.y < y) {
170
186
  this.dragging = 'start';
171
187
  canvas.style.cursor = "grabbing";
172
188
  }
173
- else if(Math.abs(this.endX - x) < threshold && this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1] ) {
189
+ else if(Math.abs(this.endX - x) < threshold && this.position.y < y) {
174
190
  this.dragging = 'end';
175
191
  canvas.style.cursor = "grabbing";
176
192
  }
177
- else if(Math.abs(this.currentX - x) < threshold) {
193
+ else {
178
194
  this.dragging = 'current';
179
195
  canvas.style.cursor = "grabbing";
180
- }
181
- else {
196
+
182
197
  if(x < this.startX) {
183
198
  this.currentX = this.startX;
184
199
  }
@@ -188,18 +203,13 @@ class TimeBar {
188
203
  else {
189
204
  this.currentX = x;
190
205
  }
191
- }
192
206
 
193
- this._draw();
194
- }
207
+ if(this.onChangeCurrent) {
208
+ this.onChangeCurrent(this.currentX);
209
+ }
210
+ }
195
211
 
196
- update (x) {
197
- this.currentX = Math.min(Math.max(this.startX, x), this.endX);
198
212
  this._draw();
199
-
200
- if(this.onDraw) {
201
- this.onDraw();
202
- }
203
213
  }
204
214
 
205
215
  onMouseUp (e) {
@@ -214,100 +224,49 @@ class TimeBar {
214
224
 
215
225
  const canvas = this.canvas;
216
226
  canvas.style.cursor = "default";
217
-
218
- // Process mouse
219
- const x = e.target == this.canvas ? e.offsetX : e.offsetX - this.canvas.offsetLeft ;
220
- const y = e.target == this.canvas ? e.offsetY : e.offsetY - this.canvas.offsetTop ;
221
- const threshold = 5;
222
-
223
- if(this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1]) {
224
- if(x < this.startX) {
225
- this.currentX = this.startX;
226
- }
227
- else if(x > this.endX) {
228
- this.currentX = this.endX;
229
- }
230
- else {
231
- this.currentX = x;
232
- }
233
- if(this.onChangeCurrent) {
234
- this.onChangeCurrent(this.currentX);
235
- }
236
- }
237
227
  }
238
228
 
239
229
  onMouseMove (e) {
230
+ if(!this.canvas) {
231
+ return;
232
+ }
240
233
 
241
234
  e.preventDefault();
235
+ const canvas = this.canvas;
242
236
 
243
237
  // Process mouse
244
- const x = e.target == this.canvas ? e.offsetX : e.offsetX - this.canvas.offsetLeft ;
245
- const y = e.target == this.canvas ? e.offsetY : e.offsetY - this.canvas.offsetTop ;
246
- const threshold = 5;
238
+ const x = e.target == canvas ? e.offsetX : e.clientX - canvas.offsetLeft;
239
+ const y = e.target == canvas ? e.offsetY : e.clientY - canvas.offsetTop;
247
240
 
248
241
  if(this.dragging) {
249
242
  switch(this.dragging) {
250
243
  case 'start':
251
- if(x < this.position.x) {
252
- this.currentX = this.startX = this.position.x;
253
- }
254
- else if(x > this.endX) {
255
- this.currentX = this.startX = this.endX;
256
- }
257
- else {
258
- this.currentX = this.startX = x;
259
- }
260
-
261
- if(this.onChangeStart) {
262
- this.onChangeStart(this.startX);
263
- }
264
- if(this.onChangeCurrent) {
265
- this.onChangeCurrent(this.currentX);
266
- }
244
+ this.startX = Math.max(this.position.x, Math.min(this.endX, x));
245
+ this.currentX = this.startX;
246
+ if(this.onChangeStart) {
247
+ this.onChangeStart(this.startX);
248
+ }
267
249
  break;
268
250
  case 'end':
269
- if(x > this.width || x <= 0) {
270
- this.currentX = this.endX = this.width;
271
- }
272
- else if(x < this.startX) {
273
- this.currentX = this.endX = this.startX;
274
- }
275
- else {
276
- this.currentX = this.endX = x;
277
- }
278
-
279
- if(this.onChangeEnd) {
280
- this.onChangeEnd(this.endX);
281
- }
282
- if(this.onChangeCurrent) {
283
- this.onChangeCurrent(this.currentX);
284
- }
285
- break;
286
- case 'current':
287
-
288
- if(x < this.startX) {
289
- this.currentX = this.startX;
290
- }
291
- else if(x > this.endX) {
292
- this.currentX = this.endX;
293
- }
294
- else {
295
- this.currentX = x;
296
- }
297
- if(this.onChangeCurrent) {
298
- this.onChangeCurrent(this.currentX);
251
+ this.endX = Math.max(this.startX, Math.min(this.position.x + this.lineWidth, x));
252
+ this.currentX = this.endX;
253
+ if(this.onChangeEnd) {
254
+ this.onChangeEnd(this.endX);
299
255
  }
300
256
  break;
257
+ default:
258
+ this.currentX = Math.max(this.startX, Math.min(this.endX, x));
259
+ break;
260
+ }
261
+
262
+ if(this.onChangeCurrent) {
263
+ this.onChangeCurrent(this.currentX);
301
264
  }
302
265
  }
303
266
  else {
304
- if(!this.canvas) {
305
- return;
306
- }
307
-
308
- const canvas = this.canvas;
267
+ const threshold = this.markerWidth * 0.5;
309
268
 
310
- if(Math.abs(this.startX - x) < threshold && this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1] ) {
269
+ if(Math.abs(this.startX - x) < threshold ) {
311
270
  this.hovering = 'start';
312
271
  canvas.style.cursor = "grab";
313
272
  }
@@ -331,14 +290,16 @@ class TimeBar {
331
290
  this.canvas.width = size[0];
332
291
  this.canvas.height = size[1];
333
292
 
334
- const startRatio = this.startX / this.width;
335
- const currentRatio = this.currentX / this.width;
336
- const endRatio = this.endX / this.width;
337
- this.width = this.canvas.width - this.offset * 2;
338
-
339
- this.startX = Math.max(this.width * startRatio, this.offset);
340
- this.currentX = Math.min(Math.max(this.width * currentRatio, this.offset), this.width);
341
- this.endX = Math.min(this.width * endRatio, this.width);
293
+ let newWidth = size[0] - this.offset * 2;
294
+ newWidth = newWidth < 0.00001 ? 0.00001 : newWidth; // actual with of the line = canvas.width - offsetleft - offsetRight
295
+ const startRatio = (this.startX - this.offset) / this.lineWidth;
296
+ const currentRatio = (this.currentX - this.offset) / this.lineWidth;
297
+ const endRatio = (this.endX - this.offset) / this.lineWidth;
298
+
299
+ this.lineWidth = newWidth;
300
+ this.startX = Math.min( Math.max(newWidth * startRatio, 0), newWidth ) + this.offset;
301
+ this.currentX = Math.min(Math.max(newWidth * currentRatio, 0), newWidth) + this.offset;
302
+ this.endX = Math.min( Math.max(newWidth * endRatio, 0 ), newWidth) + this.offset;
342
303
 
343
304
  this._draw();
344
305
  }
@@ -420,24 +381,16 @@ class VideoEditor {
420
381
  this.controlsPanelLeft.refresh = () => {
421
382
  this.controlsPanelLeft.clear();
422
383
  this.controlsPanelLeft.sameLine();
423
- this.controlsPanelLeft.addButton('', '<i class="fa-solid ' + (this.playing ? 'fa-pause' : 'fa-play') + '"></>', (v) => {
384
+ this.controlsPanelLeft.addButton('', "", (v) => {
424
385
  this.playing = !this.playing;
425
386
  if(this.playing) {
426
-
427
387
  this.video.play();
428
- // if(!this.requestId) {
429
- // this.requestId = requestAnimationFrame(this._update.bind(this))
430
- // }
431
388
  }
432
389
  else {
433
- // if(this.requestId) {
434
- // cancelAnimationFrame(this.requestId);
435
- // this.requestId = null;
436
- // }
437
390
  this.video.pause();
438
391
  }
439
392
  this.controlsPanelLeft.refresh();
440
- }, { width: '40px'});
393
+ }, { width: '40px', icon: "fa-solid " + (this.playing ? 'fa-pause' : 'fa-play') });
441
394
 
442
395
  this.controlsPanelLeft.addLabel(this.startTimeString, {width: 50});
443
396
  this.controlsPanelLeft.endLine();
@@ -534,7 +487,6 @@ class VideoEditor {
534
487
  }
535
488
 
536
489
  if(this.isDragging) {
537
-
538
490
  this.dragCropArea(event);
539
491
  }
540
492
  });
@@ -615,24 +567,21 @@ class VideoEditor {
615
567
  y = rectVideo.top;
616
568
  }
617
569
 
618
- if( y + this.cropArea.clientHeight > rectVideo.height ) {
619
- y = rectVideo.height - this.cropArea.clientHeight;
570
+ if( y + this.cropArea.clientHeight > rectVideo.bottom ) {
571
+ y = rectVideo.bottom - this.cropArea.clientHeight;
620
572
  }
621
573
 
622
- this.cropArea.style.left = x + "px";
623
- this.cropArea.style.top = y + "px";
574
+ const parentRect = this.cropArea.parentElement.getBoundingClientRect();
624
575
 
625
- const videoEndX = rectVideo.left + rectVideo.width;
626
- const cropEndX = x + this.cropArea.clientWidth;
627
- const videoEndY = rectVideo.height;
628
- const cropEndY = y + this.cropArea.clientHeight;
576
+ this.cropArea.style.left = x - parentRect.left + "px";
577
+ this.cropArea.style.top = y - parentRect.top + "px";
629
578
 
630
579
  const nodes = this.cropArea.parentElement.childNodes;
631
580
 
632
581
  for( let i = 0; i < nodes.length; i++ ) {
633
582
  if( nodes[i] != this.cropArea ) {
634
583
  const rectEl = nodes[i].getBoundingClientRect();
635
- nodes[i].style.webkitMask = `linear-gradient(#000 0 0) ${x - rectEl.left}px ${y }px / ${this.cropArea.clientWidth}px ${this.cropArea.clientHeight}px, linear-gradient(rgba(0, 0, 0, 0.3) 0 0)`;
584
+ nodes[i].style.webkitMask = `linear-gradient(#000 0 0) ${x - rectEl.left}px ${y - rectEl.top}px / ${this.cropArea.clientWidth}px ${this.cropArea.clientHeight}px, linear-gradient(rgba(0, 0, 0, 0.3) 0 0)`;
636
585
  nodes[i].style.webkitMaskRepeat = 'no-repeat';
637
586
  }
638
587
  }
@@ -645,7 +594,7 @@ class VideoEditor {
645
594
  }
646
595
 
647
596
  this.timebar.startX = this.timebar.position.x;
648
- this.timebar.endX = this.timebar.width;
597
+ this.timebar.endX = this.timebar.position.x + this.timebar.lineWidth;
649
598
 
650
599
  this.video.currentTime = 0.01; // BUG: some videos will not play unless this line is present
651
600
  this.endTime = this.video.duration;
@@ -665,9 +614,9 @@ class VideoEditor {
665
614
  this.hideControls();
666
615
  }
667
616
 
668
- const ratio = this.video.clientHeight / this.video.videoHeight;
669
617
  this.cropArea.style.height = this.video.clientHeight + "px";
670
- this.cropArea.style.width = this.video.videoWidth * ratio + "px";
618
+ this.cropArea.style.width = this.video.clientWidth + "px";
619
+ this.dragCropArea( { clientX: -1, clientY: -1 } );
671
620
 
672
621
  if( this.crop ) {
673
622
  this.showCropArea();
@@ -698,11 +647,11 @@ class VideoEditor {
698
647
  }
699
648
 
700
649
  _xToTime (x) {
701
- return ((x - this.timebar.offset) / (this.timebar.width - this.timebar.offset)) * this.video.duration;
650
+ return ((x - this.timebar.offset) / (this.timebar.lineWidth)) * this.video.duration;
702
651
  }
703
652
 
704
653
  _timeToX (time) {
705
- return (time / this.video.duration) * (this.timebar.width - this.timebar.offset ) + this.timebar.offset;
654
+ return (time / this.video.duration) * (this.timebar.lineWidth) + this.timebar.offset;
706
655
  }
707
656
 
708
657
  _setCurrentValue ( x, updateTime = true ) {
package/build/lexgui.css CHANGED
@@ -656,6 +656,13 @@ a svg, svg path {
656
656
  color: var(--global-text-secondary);
657
657
  }
658
658
 
659
+ .lexfooter ul li a {
660
+ display: flex;
661
+ gap: 0.4rem;
662
+ align-items: center;
663
+ place-content: center;
664
+ }
665
+
659
666
  .lexfooter a {
660
667
  text-decoration: none;
661
668
  color: var(--global-text-secondary);
@@ -1727,6 +1734,7 @@ a svg, svg path {
1727
1734
 
1728
1735
  .lexbutton.left span {
1729
1736
  place-content: start;
1737
+ margin-left: 0.5rem;
1730
1738
  }
1731
1739
 
1732
1740
  .lexbutton.array a {
@@ -3165,7 +3173,7 @@ meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
3165
3173
  }
3166
3174
 
3167
3175
  .lexmenubar .lexbutton {
3168
- padding-inline: 0.15rem;
3176
+ padding-inline: 0.1rem;
3169
3177
  }
3170
3178
 
3171
3179
  .lexmenubar .lexbutton:hover, :root[data-theme="light"] .lexmenubar .lexbutton:hover {
@@ -3188,6 +3196,10 @@ meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
3188
3196
  user-select: none;
3189
3197
  }
3190
3198
 
3199
+ .lexmenubar .lexmenubutton.main:first-child {
3200
+ margin-left: 8px;
3201
+ }
3202
+
3191
3203
  .lexmenubar .lexmenubutton.main:last-child {
3192
3204
  margin-right: 8px;
3193
3205
  }
@@ -3421,6 +3433,14 @@ meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
3421
3433
  background-color: var(--global-color-accent);
3422
3434
  }
3423
3435
 
3436
+ .lexsidebar .lexsidebarentry.selected .lexsidebarentrycontent > a {
3437
+ color: #f4f4f4;
3438
+ }
3439
+
3440
+ .lexsidebar .lexsidebarentry.selected svg path {
3441
+ --color: #f4f4f4;
3442
+ }
3443
+
3424
3444
  .lexsidebar .lexsidebarentry:active {
3425
3445
  transform: scale(0.99);
3426
3446
  }
@@ -3545,6 +3565,10 @@ meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
3545
3565
  background-color: var(--global-color-accent);
3546
3566
  }
3547
3567
 
3568
+ .lexsidebar.collapsing .lexsidebarheader svg path {
3569
+ --color: #f4f4f4;
3570
+ }
3571
+
3548
3572
  .lexsidebar .lexsidebarfooter:active, .lexsidebar .lexsidebarheader:active {
3549
3573
  transform: scale(0.99);
3550
3574
  }