lexgui 0.1.37 → 0.1.39

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/build/lexgui.js CHANGED
@@ -12,7 +12,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
12
12
  */
13
13
 
14
14
  var LX = global.LX = {
15
- version: "0.1.37",
15
+ version: "0.1.39",
16
16
  ready: false,
17
17
  components: [], // specific pre-build components
18
18
  signals: {} // events and triggers
@@ -30,6 +30,11 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
30
30
 
31
31
  function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
32
32
  function round( number, precision ) { return +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
33
+ function remapRange( oldValue, oldMin, oldMax, newMin, newMax ) { return ((( oldValue - oldMin ) * ( newMax - newMin )) / ( oldMax - oldMin )) + newMin; }
34
+
35
+ LX.clamp = clamp;
36
+ LX.round = round;
37
+ LX.remapRange = remapRange;
33
38
 
34
39
  function getSupportedDOMName( string )
35
40
  {
@@ -106,6 +111,18 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
106
111
 
107
112
  LX.rgbToHex = rgbToHex;
108
113
 
114
+ function measureRealWidth( value, paddingPlusMargin = 8 ) {
115
+ var i = document.createElement( "span" );
116
+ i.className = "lexinputmeasure";
117
+ i.innerHTML = value;
118
+ document.body.appendChild( i );
119
+ var rect = i.getBoundingClientRect();
120
+ LX.UTILS.deleteElement( i );
121
+ return rect.width + paddingPlusMargin;
122
+ }
123
+
124
+ LX.measureRealWidth = measureRealWidth;
125
+
109
126
  function simple_guidGenerator() {
110
127
  var S4 = function() {
111
128
  return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
@@ -167,46 +184,79 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
167
184
  len () { return Math.sqrt( this.len2() ); }
168
185
  nrm ( v0 = new vec2() ) { v0.set( this.x, this.y ); return v0.mul( 1.0 / this.len(), v0 ); }
169
186
  dst ( v ) { return v.sub( this ).len(); }
187
+ clp ( min, max, v0 = new vec2() ) { v0.set( clamp( this.x, min, max ), clamp( this.y, min, max ) ); return v0; }
170
188
  };
171
189
 
172
190
  LX.vec2 = vec2;
173
191
 
174
192
  // Other utils
175
193
 
194
+ /**
195
+ * @method makeDraggable
196
+ * @param {Element} domEl
197
+ * @param {Object} options
198
+ * autoAdjust (Bool): Sets in a correct position at the beggining
199
+ * dragMargin (Number): Margin of drag container
200
+ * onMove (Function): Called each move event
201
+ * onDragStart (Function): Called when drag event starts
202
+ */
176
203
  function makeDraggable( domEl, options = { } ) {
177
204
 
178
- let offsetX;
179
- let offsetY;
205
+ let offsetX = 0;
206
+ let offsetY = 0;
180
207
  let currentTarget = null;
181
208
  let targetClass = options.targetClass;
182
-
209
+ let dragMargin = options.dragMargin ?? 3;
210
+
211
+ let _computePosition = ( e, top, left ) => {
212
+ const nullRect = { x: 0, y: 0, width: 0, height: 0 };
213
+ const parentRect = domEl.parentElement ? domEl.parentElement.getBoundingClientRect() : nullRect;
214
+ const isFixed = ( domEl.style.position == "fixed" );
215
+ const fixedOffset = isFixed ? new LX.vec2( parentRect.x, parentRect.y ) : new LX.vec2();
216
+ left = left ?? e.clientX - offsetX - parentRect.x;
217
+ top = top ?? e.clientY - offsetY - parentRect.y;
218
+ domEl.style.left = clamp( left, dragMargin + fixedOffset.x, fixedOffset.x + parentRect.width - domEl.offsetWidth - dragMargin ) + 'px';
219
+ domEl.style.top = clamp( top, dragMargin + fixedOffset.y, fixedOffset.y + parentRect.height - domEl.offsetHeight - dragMargin ) + 'px';
220
+ };
221
+
222
+ // Initial adjustment
223
+ if( options.autoAdjust )
224
+ {
225
+ _computePosition( null, parseInt( domEl.style.left ), parseInt( domEl.style.top ) )
226
+ }
227
+
183
228
  let id = LX.UTILS.uidGenerator();
184
229
  domEl[ 'draggable-id' ] = id;
185
-
230
+
186
231
  const defaultMoveFunc = e => {
187
- if( !currentTarget ) return;
188
- let left = e.clientX - offsetX;
189
- let top = e.clientY - offsetY;
190
- if( left > 3 && ( left + domEl.offsetWidth + 6 ) <= window.innerWidth )
191
- domEl.style.left = left + 'px';
192
- if( top > 3 && ( top + domEl.offsetHeight + 6 ) <= window.innerHeight )
193
- domEl.style.top = top + 'px';
232
+ if( !currentTarget )
233
+ {
234
+ return;
235
+ }
236
+
237
+ _computePosition( e );
194
238
  };
195
-
239
+
196
240
  const customMoveFunc = e => {
197
- if( !currentTarget ) return;
241
+ if( !currentTarget )
242
+ {
243
+ return;
244
+ }
245
+
198
246
  if( options.onMove )
247
+ {
199
248
  options.onMove( currentTarget );
249
+ }
200
250
  };
201
-
251
+
202
252
  let onMove = options.onMove ? customMoveFunc : defaultMoveFunc;
203
253
  let onDragStart = options.onDragStart;
204
-
254
+
205
255
  domEl.setAttribute( 'draggable', true );
206
256
  domEl.addEventListener( "mousedown", function( e ) {
207
- currentTarget = (e.target.classList.contains(targetClass) || !targetClass) ? e.target : null;
257
+ currentTarget = ( e.target.classList.contains( targetClass ) || !targetClass ) ? e.target : null;
208
258
  } );
209
-
259
+
210
260
  domEl.addEventListener( "dragstart", function( e ) {
211
261
  e.preventDefault();
212
262
  e.stopPropagation();
@@ -218,15 +268,21 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
218
268
  e.dataTransfer.setDragImage( img, 0, 0 );
219
269
  e.dataTransfer.effectAllowed = "move";
220
270
  const rect = e.target.getBoundingClientRect();
221
- offsetX = e.clientX - rect.x;
222
- offsetY = e.clientY - rect.y;
271
+ const parentRect = currentTarget.parentElement.getBoundingClientRect();
272
+ const isFixed = ( currentTarget.style.position == "fixed" );
273
+ const fixedOffset = isFixed ? new LX.vec2( parentRect.x, parentRect.y ) : new LX.vec2();
274
+ offsetX = e.clientX - rect.x - fixedOffset.x;
275
+ offsetY = e.clientY - rect.y - fixedOffset.y;
223
276
  document.addEventListener( "mousemove", onMove );
224
277
  if( onDragStart )
278
+ {
225
279
  onDragStart( currentTarget, e );
280
+ }
226
281
  }, false );
227
282
 
228
283
  document.addEventListener( 'mouseup', () => {
229
- if( currentTarget ) {
284
+ if( currentTarget )
285
+ {
230
286
  currentTarget = null;
231
287
  document.removeEventListener( "mousemove", onMove );
232
288
  }
@@ -665,7 +721,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
665
721
  }
666
722
 
667
723
  string() {
668
- switch(this.type) {
724
+ switch( this.type )
725
+ {
669
726
  case TreeEvent.NONE: return "tree_event_none";
670
727
  case TreeEvent.NODE_SELECTED: return "tree_event_selected";
671
728
  case TreeEvent.NODE_DELETED: return "tree_event_deleted";
@@ -819,7 +876,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
819
876
 
820
877
  const draggable = options.draggable ?? true;
821
878
  if( draggable )
822
- makeDraggable( root );
879
+ {
880
+ makeDraggable( root, options );
881
+ }
823
882
 
824
883
  if( options.resizeable ) {
825
884
  root.classList.add("resizeable");
@@ -1181,23 +1240,33 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
1181
1240
  * @method resize
1182
1241
  * Resize element
1183
1242
  */
1184
- setSize(size) {
1243
+ setSize( size ) {
1185
1244
 
1186
- let [width, height] = size;
1187
-
1188
- if(width != undefined && width.constructor == Number)
1245
+ let [ width, height ] = size;
1246
+
1247
+ if( width != undefined && width.constructor == Number )
1248
+ {
1189
1249
  width += "px";
1190
- if(height != undefined && height.constructor == Number)
1250
+ }
1251
+
1252
+ if( height != undefined && height.constructor == Number )
1253
+ {
1191
1254
  height += "px";
1192
-
1193
- if(width)
1255
+ }
1256
+
1257
+ if( width )
1258
+ {
1194
1259
  this.root.style.width = width;
1195
- if(height)
1260
+ }
1261
+
1262
+ if( height )
1263
+ {
1196
1264
  this.root.style.height = height;
1265
+ }
1197
1266
 
1198
- this.size = [this.root.clientWidth, this.root.clientHeight];
1267
+ this.size = [ this.root.clientWidth, this.root.clientHeight ];
1199
1268
 
1200
- this.propagateEvent("onresize");
1269
+ this.propagateEvent( "onresize" );
1201
1270
  }
1202
1271
 
1203
1272
  /**
@@ -1207,7 +1276,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
1207
1276
  extend() {
1208
1277
 
1209
1278
  if( this.split_extended )
1210
- return;
1279
+ {
1280
+ return;
1281
+ }
1211
1282
 
1212
1283
  let [area1, area2] = this.sections;
1213
1284
  this.split_extended = true;
@@ -1877,11 +1948,15 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
1877
1948
 
1878
1949
  const tabEl = this.tabDOMs[ name ];
1879
1950
 
1880
- if(!tabEl || tabEl.fixed)
1881
- return;
1951
+ if( !tabEl || tabEl.fixed )
1952
+ {
1953
+ return;
1954
+ }
1882
1955
 
1883
1956
  if( this.onclose )
1957
+ {
1884
1958
  this.onclose( name );
1959
+ }
1885
1960
 
1886
1961
  // Delete tab element
1887
1962
  this.tabDOMs[ name ].remove();
@@ -1892,11 +1967,12 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
1892
1967
  delete this.tabs[ name ];
1893
1968
 
1894
1969
  // Select last tab
1895
- const last_tab = this.root.lastChild;
1896
- if(last_tab && !last_tab.fixed)
1970
+ const lastTab = this.root.lastChild;
1971
+ if( lastTab && !lastTab.fixed )
1972
+ {
1897
1973
  this.root.lastChild.click();
1974
+ }
1898
1975
  }
1899
-
1900
1976
  }
1901
1977
 
1902
1978
  LX.Tabs = Tabs;
@@ -2463,6 +2539,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2463
2539
  static CUSTOM = 21;
2464
2540
  static SEPARATOR = 22;
2465
2541
  static KNOB = 23;
2542
+ static SIZE = 24;
2543
+ static PAD = 25;
2466
2544
 
2467
2545
  static NO_CONTEXT_TYPES = [
2468
2546
  Widget.BUTTON,
@@ -2520,14 +2598,16 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2520
2598
 
2521
2599
  paste() {
2522
2600
  if( !this._can_paste() )
2523
- return;
2601
+ {
2602
+ return;
2603
+ }
2524
2604
 
2525
2605
  this.set(navigator.clipboard.data);
2526
2606
  }
2527
2607
 
2528
2608
  typeName() {
2529
2609
 
2530
- switch(this.type) {
2610
+ switch( this.type ) {
2531
2611
  case Widget.TEXT: return "Text";
2532
2612
  case Widget.TEXTAREA: return "TextArea";
2533
2613
  case Widget.BUTTON: return "Button";
@@ -2545,6 +2625,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2545
2625
  case Widget.TAGS: return "Tags";
2546
2626
  case Widget.CURVE: return "Curve";
2547
2627
  case Widget.KNOB: return "Knob";
2628
+ case Widget.SIZE: return "Size";
2629
+ case Widget.PAD: return "Pad";
2548
2630
  case Widget.CUSTOM: return this.customName;
2549
2631
  }
2550
2632
  }
@@ -2639,40 +2721,50 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2639
2721
  custom_widgets.className = "lexcustomitems";
2640
2722
  custom_widgets.toggleAttribute('hidden', true);
2641
2723
 
2642
- element.appendChild(container);
2643
- element.appendChild(custom_widgets);
2644
-
2645
- if( instance ) {
2646
-
2724
+ element.appendChild( container );
2725
+ element.appendChild( custom_widgets );
2726
+
2727
+ if( instance )
2728
+ {
2729
+
2647
2730
  this.queue( custom_widgets );
2648
2731
 
2649
- const on_instance_changed = (key, value, event) => {
2650
- instance[key] = value;
2651
- this._trigger( new IEvent(name, instance, event), callback );
2732
+ const on_instance_changed = ( key, value, event ) => {
2733
+ instance[ key ] = value;
2734
+ this._trigger( new IEvent( name, instance, event ), callback );
2652
2735
  };
2653
2736
 
2654
2737
  for( let key in default_instance )
2655
2738
  {
2656
- const value = instance[key] ?? default_instance[key];
2739
+ const value = instance[ key ] ?? default_instance[ key ];
2657
2740
 
2658
- switch(value.constructor) {
2741
+ switch( value.constructor )
2742
+ {
2659
2743
  case String:
2660
- if(value[0] === '#')
2661
- this.addColor(key, value, on_instance_changed.bind(this, key));
2744
+ if( value[ 0 ] === '#' )
2745
+ {
2746
+ this.addColor( key, value, on_instance_changed.bind( this, key ) );
2747
+ }
2662
2748
  else
2663
- this.addText(key, value, on_instance_changed.bind(this, key));
2749
+ {
2750
+ this.addText( key, value, on_instance_changed.bind( this, key ) );
2751
+ }
2664
2752
  break;
2665
2753
  case Number:
2666
- this.addNumber(key, value, on_instance_changed.bind(this, key));
2754
+ this.addNumber( key, value, on_instance_changed.bind( this, key ) );
2667
2755
  break;
2668
2756
  case Boolean:
2669
- this.addCheckbox(key, value, on_instance_changed.bind(this, key));
2757
+ this.addCheckbox( key, value, on_instance_changed.bind( this, key ) );
2670
2758
  break;
2671
2759
  case Array:
2672
2760
  if( value.length > 4 )
2673
- this.addArray(key, value, on_instance_changed.bind(this, key));
2761
+ {
2762
+ this.addArray( key, value, on_instance_changed.bind( this, key ) );
2763
+ }
2674
2764
  else
2675
- this._add_vector(value.length, key, value, on_instance_changed.bind(this, key));
2765
+ {
2766
+ this._add_vector( value.length, key, value, on_instance_changed.bind( this, key ) );
2767
+ }
2676
2768
  break;
2677
2769
  }
2678
2770
  }
@@ -2710,37 +2802,40 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2710
2802
  _create_item( parent, node, level = 0, selectedId ) {
2711
2803
 
2712
2804
  const that = this;
2713
- const node_filter_input = this.domEl.querySelector("#lexnodetree_filter");
2805
+ const node_filter_input = this.domEl.querySelector( "#lexnodetree_filter" );
2714
2806
 
2715
2807
  node.children = node.children ?? [];
2716
- if(node_filter_input && !node.id.includes(node_filter_input.value) || (selectedId != undefined) && selectedId != node.id)
2808
+ if( node_filter_input && !node.id.includes( node_filter_input.value ) || (selectedId != undefined) && selectedId != node.id )
2717
2809
  {
2718
2810
  for( var i = 0; i < node.children.length; ++i )
2719
- this._create_item( node, node.children[i], level + 1, selectedId );
2811
+ {
2812
+ this._create_item( node, node.children[ i ], level + 1, selectedId );
2813
+ }
2720
2814
  return;
2721
2815
  }
2722
2816
 
2723
- const list = this.domEl.querySelector("ul");
2817
+ const list = this.domEl.querySelector( 'ul' );
2724
2818
 
2725
2819
  node.visible = node.visible ?? true;
2726
2820
  node.parent = parent;
2727
- let is_parent = node.children.length > 0;
2728
- let is_selected = this.selected.indexOf( node ) > -1;
2821
+ let isParent = node.children.length > 0;
2822
+ let isSelected = this.selected.indexOf( node ) > -1;
2729
2823
 
2730
- if( this.options.only_folders ) {
2824
+ if( this.options.only_folders )
2825
+ {
2731
2826
  let has_folders = false;
2732
2827
  node.children.forEach( c => has_folders |= (c.type == 'folder') );
2733
- is_parent = !!has_folders;
2828
+ isParent = !!has_folders;
2734
2829
  }
2735
2830
 
2736
2831
  let item = document.createElement('li');
2737
- item.className = "lextreeitem " + "datalevel" + level + (is_parent ? " parent" : "") + (is_selected ? " selected" : "");
2832
+ item.className = "lextreeitem " + "datalevel" + level + (isParent ? " parent" : "") + (isSelected ? " selected" : "");
2738
2833
  item.id = LX.getSupportedDOMName( node.id );
2739
2834
  item.tabIndex = "0";
2740
2835
 
2741
2836
  // Select hierarchy icon
2742
2837
  let icon = (this.options.skip_default_icon ?? true) ? "" : "fa-solid fa-square"; // Default: no childs
2743
- if( is_parent ) icon = node.closed ? "fa-solid fa-caret-right" : "fa-solid fa-caret-down";
2838
+ if( isParent ) icon = node.closed ? "fa-solid fa-caret-right" : "fa-solid fa-caret-down";
2744
2839
  item.innerHTML = "<a class='" + icon + " hierarchy'></a>";
2745
2840
 
2746
2841
  // Add display icon
@@ -2760,18 +2855,20 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2760
2855
 
2761
2856
  item.innerHTML += (node.rename ? "" : node.id);
2762
2857
 
2763
- item.setAttribute('draggable', true);
2764
- item.style.paddingLeft = ((is_parent ? 0 : 3 ) + (3 + (level+1) * 15)) + "px";
2765
- list.appendChild(item);
2858
+ item.setAttribute( 'draggable', true );
2859
+ item.style.paddingLeft = ((isParent ? 0 : 3 ) + (3 + (level+1) * 15)) + "px";
2860
+ list.appendChild( item );
2766
2861
 
2767
2862
  // Callbacks
2768
2863
  item.addEventListener("click", e => {
2769
- if( handled ) {
2864
+ if( handled )
2865
+ {
2770
2866
  handled = false;
2771
2867
  return;
2772
2868
  }
2773
2869
 
2774
- if(!e.shiftKey) {
2870
+ if( !e.shiftKey )
2871
+ {
2775
2872
  list.querySelectorAll("li").forEach( e => { e.classList.remove('selected'); } );
2776
2873
  this.selected.length = 0;
2777
2874
  }
@@ -2787,16 +2884,18 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2787
2884
  }
2788
2885
 
2789
2886
  // Only Show children...
2790
- if(is_parent && node.id.length > 1 /* Strange case... */) {
2887
+ if(isParent && node.id.length > 1 /* Strange case... */) {
2791
2888
  node.closed = false;
2792
- if(that.onevent) {
2793
- const event = new TreeEvent(TreeEvent.NODE_CARETCHANGED, node, node.closed);
2889
+ if( that.onevent )
2890
+ {
2891
+ const event = new TreeEvent( TreeEvent.NODE_CARETCHANGED, node, node.closed );
2794
2892
  that.onevent( event );
2795
2893
  }
2796
2894
  that.frefresh( node.id );
2797
2895
  }
2798
2896
 
2799
- if(that.onevent) {
2897
+ if( that.onevent )
2898
+ {
2800
2899
  const event = new TreeEvent(TreeEvent.NODE_SELECTED, e.shiftKey ? this.selected : node );
2801
2900
  event.multiple = e.shiftKey;
2802
2901
  that.onevent( event );
@@ -2804,37 +2903,110 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2804
2903
  });
2805
2904
 
2806
2905
  item.addEventListener("dblclick", function() {
2906
+
2807
2907
  if( that.options.rename ?? true )
2808
2908
  {
2809
2909
  // Trigger rename
2810
2910
  node.rename = true;
2811
2911
  that.refresh();
2812
2912
  }
2913
+
2813
2914
  if( that.onevent )
2814
2915
  {
2815
- const event = new TreeEvent(TreeEvent.NODE_DBLCLICKED, node);
2916
+ const event = new TreeEvent( TreeEvent.NODE_DBLCLICKED, node );
2816
2917
  that.onevent( event );
2817
2918
  }
2818
2919
  });
2819
2920
 
2820
- item.addEventListener("contextmenu", e => {
2921
+ item.addEventListener( "contextmenu", e => {
2922
+
2821
2923
  e.preventDefault();
2822
- if(that.onevent) {
2823
- const event = new TreeEvent(TreeEvent.NODE_CONTEXTMENU, this.selected.length > 1 ? this.selected : node, e);
2824
- event.multiple = this.selected.length > 1;
2825
- that.onevent( event );
2924
+
2925
+ if( !that.onevent )
2926
+ {
2927
+ return;
2928
+ }
2929
+
2930
+ const event = new TreeEvent(TreeEvent.NODE_CONTEXTMENU, this.selected.length > 1 ? this.selected : node, e);
2931
+ event.multiple = this.selected.length > 1;
2932
+
2933
+ LX.addContextMenu( event.multiple ? "Selected Nodes" : event.node.id, event.value, m => {
2934
+ event.panel = m;
2935
+ });
2936
+
2937
+ that.onevent( event );
2938
+
2939
+ if( ( this.options.addDefault ?? false ) == true )
2940
+ {
2941
+ if( event.panel.items )
2942
+ {
2943
+ event.panel.add( "" );
2944
+ }
2945
+
2946
+ event.panel.add( "Select Children", () => {
2947
+
2948
+ const selectChildren = ( n ) => {
2949
+
2950
+ if( n.closed )
2951
+ {
2952
+ return;
2953
+ }
2954
+
2955
+ for( let child of n.children ?? [] )
2956
+ {
2957
+ if( !child )
2958
+ {
2959
+ continue;
2960
+ }
2961
+
2962
+ let nodeItem = this.domEl.querySelector( '#' + child.id );
2963
+ nodeItem.classList.add('selected');
2964
+ this.selected.push( child );
2965
+ selectChildren( child );
2966
+ }
2967
+ };
2968
+
2969
+ // Add childs of the clicked node
2970
+ selectChildren( node );
2971
+ } );
2972
+
2973
+ event.panel.add( "Delete", { callback: () => {
2974
+
2975
+ // It's the root node
2976
+ if( !node.parent )
2977
+ {
2978
+ return;
2979
+ }
2980
+
2981
+ if( that.onevent ) {
2982
+ const event = new TreeEvent( TreeEvent.NODE_DELETED, node, e );
2983
+ that.onevent( event );
2984
+ }
2985
+
2986
+ // Delete nodes now
2987
+ let childs = node.parent.children;
2988
+ const index = childs.indexOf( node );
2989
+ childs.splice( index, 1 );
2990
+
2991
+ this.refresh();
2992
+ } } );
2826
2993
  }
2827
2994
  });
2828
2995
 
2829
2996
  item.addEventListener("keydown", e => {
2830
- if(node.rename)
2831
- return;
2997
+
2998
+ if( node.rename )
2999
+ {
3000
+ return;
3001
+ }
3002
+
2832
3003
  e.preventDefault();
3004
+
2833
3005
  if( e.key == "Delete" )
2834
3006
  {
2835
3007
  // Send event now so we have the info in selected array..
2836
- if(that.onevent) {
2837
- const event = new TreeEvent(TreeEvent.NODE_DELETED, this.selected.length > 1 ? this.selected : node, e);
3008
+ if( that.onevent ) {
3009
+ const event = new TreeEvent( TreeEvent.NODE_DELETED, this.selected.length > 1 ? this.selected : node, e );
2838
3010
  event.multiple = this.selected.length > 1;
2839
3011
  that.onevent( event );
2840
3012
  }
@@ -2852,10 +3024,13 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2852
3024
  }
2853
3025
  else if( e.key == "ArrowUp" || e.key == "ArrowDown" ) // Unique or zero selected
2854
3026
  {
2855
- var selected = this.selected.length > 1 ? (e.key == "ArrowUp" ? this.selected.shift() : this.selected.pop()) : this.selected[0];
2856
- var el = this.domEl.querySelector("#" + LX.getSupportedDOMName( selected.id ) );
3027
+ var selected = this.selected.length > 1 ? ( e.key == "ArrowUp" ? this.selected.shift() : this.selected.pop() ) : this.selected[ 0 ];
3028
+ var el = this.domEl.querySelector( "#" + LX.getSupportedDOMName( selected.id ) );
2857
3029
  var sibling = e.key == "ArrowUp" ? el.previousSibling : el.nextSibling;
2858
- if( sibling ) sibling.click();
3030
+ if( sibling )
3031
+ {
3032
+ sibling.click();
3033
+ }
2859
3034
  }
2860
3035
  });
2861
3036
 
@@ -2961,7 +3136,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2961
3136
  let handled = false;
2962
3137
 
2963
3138
  // Show/hide children
2964
- if(is_parent) {
3139
+ if(isParent) {
2965
3140
  item.querySelector('a.hierarchy').addEventListener("click", function(e) {
2966
3141
 
2967
3142
  handled = true;
@@ -3099,19 +3274,25 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
3099
3274
  getValue( name ) {
3100
3275
 
3101
3276
  let widget = this.widgets[ name ];
3102
- if(!widget)
3103
- throw("No widget called " + name);
3277
+
3278
+ if( !widget )
3279
+ {
3280
+ throw( "No widget called " + name );
3281
+ }
3104
3282
 
3105
3283
  return widget.value();
3106
3284
  }
3107
3285
 
3108
- setValue( name, value ) {
3286
+ setValue( name, value, skipCallback ) {
3109
3287
 
3110
3288
  let widget = this.widgets[ name ];
3111
- if(!widget)
3112
- throw("No widget called " + name);
3113
3289
 
3114
- return widget.set(value);
3290
+ if( !widget )
3291
+ {
3292
+ throw( "No widget called " + name );
3293
+ }
3294
+
3295
+ return widget.set( value, skipCallback );
3115
3296
  }
3116
3297
 
3117
3298
  /**
@@ -3290,9 +3471,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
3290
3471
  return (typeof arg == 'undefined' ? def : arg);
3291
3472
  }
3292
3473
 
3293
- static _dispatch_event( element, type, bubbles, cancelable ) {
3294
- let event = new Event(type, { 'bubbles': bubbles, 'cancelable': cancelable });
3295
- element.dispatchEvent(event);
3474
+ static _dispatch_event( element, type, data, bubbles, cancelable ) {
3475
+ let event = new CustomEvent( type, { 'detail': data, 'bubbles': bubbles, 'cancelable': cancelable } );
3476
+ element.dispatchEvent( event );
3296
3477
  }
3297
3478
 
3298
3479
  static _add_reset_property( container, callback ) {
@@ -3300,8 +3481,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
3300
3481
  domEl.style.display = "none";
3301
3482
  domEl.style.marginRight = "6px";
3302
3483
  domEl.className = "lexicon fa fa-rotate-left";
3303
- domEl.addEventListener("click", callback);
3304
- container.appendChild(domEl);
3484
+ domEl.addEventListener( "click", callback );
3485
+ container.appendChild( domEl );
3305
3486
  return domEl;
3306
3487
  }
3307
3488
 
@@ -3311,39 +3492,45 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
3311
3492
 
3312
3493
  create_widget( name, type, options = {} ) {
3313
3494
 
3314
- let widget = new Widget(name, type, options);
3495
+ let widget = new Widget( name, type, options );
3315
3496
 
3316
- let element = document.createElement('div');
3497
+ let element = document.createElement( 'div' );
3317
3498
  element.className = "lexwidget";
3318
- if(options.id)
3319
- element.id = options.id;
3320
- if(options.className)
3499
+ element.id = options.id ?? "";
3500
+ element.title = options.title ?? "";
3501
+
3502
+ if( options.className )
3503
+ {
3321
3504
  element.className += " " + options.className;
3322
- if(options.title)
3323
- element.title = options.title;
3505
+ }
3324
3506
 
3325
3507
  if( type != Widget.TITLE )
3326
3508
  {
3327
3509
  element.style.width = "calc(100% - " + (this.current_branch || type == Widget.FILE ? 10 : 20) + "px)";
3328
- if( options.width ) {
3510
+
3511
+ if( options.width )
3512
+ {
3329
3513
  element.style.width = element.style.minWidth = options.width;
3330
3514
  }
3331
- if( options.maxWidth ) {
3515
+ if( options.maxWidth )
3516
+ {
3332
3517
  element.style.maxWidth = options.maxWidth;
3333
3518
  }
3334
- if( options.minWidth ) {
3519
+ if( options.minWidth )
3520
+ {
3335
3521
  element.style.minWidth = options.minWidth;
3336
3522
  }
3337
- if( options.height ) {
3523
+ if( options.height )
3524
+ {
3338
3525
  element.style.height = element.style.minHeight = options.height;
3339
3526
  }
3340
3527
  }
3341
3528
 
3342
- if(name != undefined) {
3343
-
3344
- if(!(options.no_name ?? false) )
3529
+ if( name != undefined )
3530
+ {
3531
+ if( !(options.no_name ?? false) )
3345
3532
  {
3346
- let domName = document.createElement('div');
3533
+ let domName = document.createElement( 'div' );
3347
3534
  domName.className = "lexwidgetname";
3348
3535
  if( options.justifyName )
3349
3536
  {
@@ -3356,22 +3543,27 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
3356
3543
  element.domName = domName;
3357
3544
 
3358
3545
  // Copy-paste info
3359
- domName.addEventListener('contextmenu', function(e) {
3546
+ domName.addEventListener('contextmenu', function( e ) {
3360
3547
  e.preventDefault();
3361
- widget.oncontextmenu(e);
3548
+ widget.oncontextmenu( e );
3362
3549
  });
3363
3550
  }
3364
3551
 
3365
3552
  this.widgets[ name ] = widget;
3366
3553
  }
3367
3554
 
3368
- if(options.signal)
3555
+ if( options.signal )
3369
3556
  {
3370
- if(!name) {
3371
- if(!this.signals)
3557
+ if( !name )
3558
+ {
3559
+ if( !this.signals )
3560
+ {
3372
3561
  this.signals = [];
3373
- this.signals.push({[options.signal]: widget})
3562
+ }
3563
+
3564
+ this.signals.push( { [ options.signal ]: widget } )
3374
3565
  }
3566
+
3375
3567
  LX.addSignal( options.signal, widget );
3376
3568
  }
3377
3569
 
@@ -5027,6 +5219,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5027
5219
  * min, max: Min and Max values for the input
5028
5220
  * skipSlider: If there are min and max values, skip the slider
5029
5221
  * units: Unit as string added to the end of the value
5222
+ * onPress: Callback function on mouse down
5223
+ * onRelease: Callback function on mouse is released
5030
5224
  */
5031
5225
 
5032
5226
  addNumber( name, value, callback, options = {} ) {
@@ -5036,6 +5230,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5036
5230
  widget.onGetValue = () => {
5037
5231
  return +vecinput.value;
5038
5232
  };
5233
+
5039
5234
  widget.onSetValue = ( newValue, skipCallback ) => {
5040
5235
  vecinput.value = round( newValue, options.precision );
5041
5236
  Panel._dispatch_event( vecinput, "change", skipCallback );
@@ -5078,16 +5273,6 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5078
5273
  vecinput.value = vecinput.iValue = value;
5079
5274
  box.appendChild( vecinput );
5080
5275
 
5081
- let measureRealWidth = function( value, paddingPlusMargin = 8 ) {
5082
- var i = document.createElement( "span" );
5083
- i.className = "lexinputmeasure";
5084
- i.innerHTML = value;
5085
- document.body.appendChild( i );
5086
- var rect = i.getBoundingClientRect();
5087
- LX.UTILS.deleteElement( i );
5088
- return rect.width + paddingPlusMargin;
5089
- }
5090
-
5091
5276
  if( options.units )
5092
5277
  {
5093
5278
  let unitSpan = document.createElement( 'span' );
@@ -5107,21 +5292,47 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5107
5292
  vecinput.disabled = true;
5108
5293
  }
5109
5294
 
5110
- // add slider below
5111
- if( !options.skipSlider && options.min !== undefined && options.max !== undefined ) {
5295
+ // Add slider below
5296
+ if( !options.skipSlider && options.min !== undefined && options.max !== undefined )
5297
+ {
5112
5298
  let slider = document.createElement( 'input' );
5113
5299
  slider.className = "lexinputslider";
5114
- slider.step = options.step ?? 1;
5115
5300
  slider.min = options.min;
5116
5301
  slider.max = options.max;
5302
+ slider.step = options.step ?? 1;
5117
5303
  slider.type = "range";
5118
5304
  slider.value = value;
5305
+
5119
5306
  slider.addEventListener( "input", function( e ) {
5120
5307
  let new_value = +this.valueAsNumber;
5121
5308
  vecinput.value = round( new_value, options.precision );
5122
5309
  Panel._dispatch_event( vecinput, "change" );
5123
5310
  }, false );
5311
+
5312
+ slider.addEventListener( "mousedown", function( e ) {
5313
+ if( options.onPress )
5314
+ {
5315
+ options.onPress.bind( slider )( e, slider );
5316
+ }
5317
+ }, false );
5318
+
5319
+ slider.addEventListener( "mouseup", function( e ) {
5320
+ if( options.onRelease )
5321
+ {
5322
+ options.onRelease.bind( slider )( e, slider );
5323
+ }
5324
+ }, false );
5325
+
5124
5326
  box.appendChild( slider );
5327
+
5328
+ // Method to change min, max, step parameters
5329
+ widget.setLimits = ( newMin, newMax, newStep ) => {
5330
+ vecinput.min = slider.min = newMin ?? vecinput.min;
5331
+ vecinput.max = slider.max = newMax ?? vecinput.max;
5332
+ vecinput.step = newStep ?? vecinput.step;
5333
+ slider.step = newStep ?? slider.step;
5334
+ Panel._dispatch_event( vecinput, "change", true );
5335
+ };
5125
5336
  }
5126
5337
 
5127
5338
  // Add wheel input
@@ -5129,7 +5340,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5129
5340
  vecinput.addEventListener( "wheel", function( e ) {
5130
5341
  e.preventDefault();
5131
5342
  if( this !== document.activeElement )
5343
+ {
5132
5344
  return;
5345
+ }
5133
5346
  let mult = options.step ?? 1;
5134
5347
  if( e.shiftKey ) mult *= 10;
5135
5348
  else if( e.altKey ) mult *= 0.1;
@@ -5141,7 +5354,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5141
5354
  vecinput.addEventListener( "change", e => {
5142
5355
 
5143
5356
  if( isNaN( e.target.valueAsNumber ) )
5357
+ {
5144
5358
  return;
5359
+ }
5145
5360
 
5146
5361
  const skipCallback = e.detail;
5147
5362
 
@@ -5177,27 +5392,39 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5177
5392
 
5178
5393
  var that = this;
5179
5394
  var lastY = 0;
5180
- function inner_mousedown(e) {
5181
- if(document.activeElement == vecinput) return;
5395
+
5396
+ function inner_mousedown( e )
5397
+ {
5398
+ if( document.activeElement == vecinput )
5399
+ {
5400
+ return;
5401
+ }
5402
+
5182
5403
  var doc = that.root.ownerDocument;
5183
- doc.addEventListener("mousemove",inner_mousemove);
5184
- doc.addEventListener("mouseup",inner_mouseup);
5404
+ doc.addEventListener( 'mousemove', inner_mousemove );
5405
+ doc.addEventListener( 'mouseup', inner_mouseup );
5185
5406
  lastY = e.pageY;
5186
- document.body.classList.add('nocursor');
5187
- document.body.classList.add('noevents');
5188
- dragIcon.classList.remove('hidden');
5407
+ document.body.classList.add( 'nocursor' );
5408
+ document.body.classList.add( 'noevents' );
5409
+ dragIcon.classList.remove( 'hidden' );
5189
5410
  e.stopImmediatePropagation();
5190
5411
  e.stopPropagation();
5412
+
5413
+ if( options.onPress )
5414
+ {
5415
+ options.onPress.bind( vecinput )( e, vecinput );
5416
+ }
5191
5417
  }
5192
5418
 
5193
- function inner_mousemove(e) {
5194
- if (lastY != e.pageY) {
5419
+ function inner_mousemove( e )
5420
+ {
5421
+ if ( lastY != e.pageY ) {
5195
5422
  let dt = lastY - e.pageY;
5196
5423
  let mult = options.step ?? 1;
5197
- if(e.shiftKey) mult *= 10;
5198
- else if(e.altKey) mult *= 0.1;
5199
- let new_value = (+vecinput.valueAsNumber + mult * dt);
5200
- vecinput.value = (+new_value).toFixed( 4 ).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1');
5424
+ if( e.shiftKey ) mult *= 10;
5425
+ else if( e.altKey ) mult *= 0.1;
5426
+ let new_value = ( +vecinput.valueAsNumber + mult * dt );
5427
+ vecinput.value = ( +new_value ).toFixed( 4 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' );
5201
5428
  Panel._dispatch_event( vecinput, "change" );
5202
5429
  }
5203
5430
 
@@ -5206,20 +5433,27 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5206
5433
  e.preventDefault();
5207
5434
  }
5208
5435
 
5209
- function inner_mouseup(e) {
5436
+ function inner_mouseup( e )
5437
+ {
5210
5438
  var doc = that.root.ownerDocument;
5211
- doc.removeEventListener("mousemove",inner_mousemove);
5212
- doc.removeEventListener("mouseup",inner_mouseup);
5213
- document.body.classList.remove('nocursor');
5214
- document.body.classList.remove('noevents');
5215
- dragIcon.classList.add('hidden');
5439
+ doc.removeEventListener( 'mousemove', inner_mousemove );
5440
+ doc.removeEventListener( 'mouseup', inner_mouseup );
5441
+ document.body.classList.remove( 'nocursor' );
5442
+ document.body.classList.remove( 'noevents' );
5443
+ dragIcon.classList.add( 'hidden' );
5444
+
5445
+ if( options.onRelease )
5446
+ {
5447
+ options.onRelease.bind( vecinput )( e, vecinput );
5448
+ }
5216
5449
  }
5217
5450
 
5218
- container.appendChild(box);
5219
- element.appendChild(container);
5451
+ container.appendChild( box );
5452
+ element.appendChild( container );
5220
5453
 
5221
5454
  // Remove branch padding and margins
5222
- if(!widget.name) {
5455
+ if( !widget.name )
5456
+ {
5223
5457
  element.className += " noname";
5224
5458
  container.style.width = "100%";
5225
5459
  }
@@ -5227,14 +5461,15 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5227
5461
  return widget;
5228
5462
  }
5229
5463
 
5230
- static VECTOR_COMPONENTS = {0: 'x', 1: 'y', 2: 'z', 3: 'w'};
5464
+ static VECTOR_COMPONENTS = { 0: 'x', 1: 'y', 2: 'z', 3: 'w' };
5231
5465
 
5232
5466
  _add_vector( num_components, name, value, callback, options = {} ) {
5233
5467
 
5234
5468
  num_components = clamp( num_components, 2, 4 );
5235
5469
  value = value ?? new Array( num_components ).fill( 0 );
5236
5470
 
5237
- if( !name ) {
5471
+ if( !name )
5472
+ {
5238
5473
  throw( "Set Widget Name!" );
5239
5474
  }
5240
5475
 
@@ -5244,9 +5479,12 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5244
5479
  let inputs = element.querySelectorAll( "input" );
5245
5480
  let value = [];
5246
5481
  for( var v of inputs )
5482
+ {
5247
5483
  value.push( +v.value );
5484
+ }
5248
5485
  return value;
5249
5486
  };
5487
+
5250
5488
  widget.onSetValue = ( newValue, skipCallback ) => {
5251
5489
  const inputs = element.querySelectorAll( ".vecinput" );
5252
5490
  if( inputs.length == newValue.length )
@@ -5255,7 +5493,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5255
5493
  return;
5256
5494
  }
5257
5495
 
5258
- for( var i = 0; i < inputs.length; ++i ) {
5496
+ for( let i = 0; i < inputs.length; ++i ) {
5259
5497
  let value = newValue[ i ];
5260
5498
  inputs[ i ].value = round( value, options.precision ) ?? 0;
5261
5499
  Panel._dispatch_event( inputs[ i ], "change", skipCallback );
@@ -5275,7 +5513,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5275
5513
 
5276
5514
  // Add widget value
5277
5515
 
5278
- var container = document.createElement('div');
5516
+ var container = document.createElement( 'div' );
5279
5517
  container.className = "lexvector";
5280
5518
  container.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
5281
5519
 
@@ -5306,12 +5544,12 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5306
5544
  dragIcon.className = "fa-solid fa-arrows-up-down drag-icon hidden";
5307
5545
  box.appendChild( dragIcon );
5308
5546
 
5309
- if( options.disabled ) {
5547
+ if( options.disabled )
5548
+ {
5310
5549
  vecinput.disabled = true;
5311
5550
  }
5312
5551
 
5313
5552
  // Add wheel input
5314
-
5315
5553
  vecinput.addEventListener( "wheel", function( e ) {
5316
5554
  e.preventDefault();
5317
5555
  if( this !== document.activeElement )
@@ -5325,7 +5563,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5325
5563
  for( let v of element.querySelectorAll(".vecinput") )
5326
5564
  {
5327
5565
  v.value = round( +v.valueAsNumber - mult * ( e.deltaY > 0 ? 1 : -1 ), options.precision );
5328
- Panel._dispatch_event(v, "change");
5566
+ Panel._dispatch_event( v, "change" );
5329
5567
  }
5330
5568
  }
5331
5569
  else
@@ -5358,7 +5596,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5358
5596
  v.value = val;
5359
5597
  value[ v.idx ] = val;
5360
5598
  }
5361
- } else {
5599
+ } else
5600
+ {
5362
5601
  vecinput.value = val;
5363
5602
  value[ e.target.idx ] = val;
5364
5603
  }
@@ -5372,35 +5611,48 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5372
5611
 
5373
5612
  var that = this;
5374
5613
  var lastY = 0;
5375
- function inner_mousedown(e) {
5376
- if(document.activeElement == vecinput) return;
5614
+ function inner_mousedown( e )
5615
+ {
5616
+ if( document.activeElement == vecinput )
5617
+ {
5618
+ return;
5619
+ }
5620
+
5377
5621
  var doc = that.root.ownerDocument;
5378
- doc.addEventListener("mousemove",inner_mousemove);
5379
- doc.addEventListener("mouseup",inner_mouseup);
5622
+ doc.addEventListener( 'mousemove', inner_mousemove );
5623
+ doc.addEventListener( 'mouseup', inner_mouseup );
5380
5624
  lastY = e.pageY;
5381
- document.body.classList.add('nocursor');
5382
- document.body.classList.add('noevents');
5383
- dragIcon.classList.remove('hidden');
5625
+ document.body.classList.add( 'nocursor' );
5626
+ document.body.classList.add( 'noevents' );
5627
+ dragIcon.classList.remove( 'hidden' );
5384
5628
  e.stopImmediatePropagation();
5385
5629
  e.stopPropagation();
5630
+
5631
+ if( options.onPress )
5632
+ {
5633
+ options.onPress.bind( vecinput )( e, vecinput );
5634
+ }
5386
5635
  }
5387
5636
 
5388
- function inner_mousemove(e) {
5389
- if (lastY != e.pageY) {
5637
+ function inner_mousemove( e )
5638
+ {
5639
+ if ( lastY != e.pageY ) {
5390
5640
  let dt = lastY - e.pageY;
5391
5641
  let mult = options.step ?? 1;
5392
- if(e.shiftKey) mult = 10;
5393
- else if(e.altKey) mult = 0.1;
5642
+ if( e.shiftKey ) mult = 10;
5643
+ else if( e.altKey ) mult = 0.1;
5394
5644
 
5395
5645
  if( locker.locked )
5396
5646
  {
5397
- for( let v of element.querySelectorAll(".vecinput") ) {
5647
+ for( let v of element.querySelectorAll( ".vecinput" ) ) {
5398
5648
  v.value = round( +v.valueAsNumber + mult * dt, options.precision );
5399
- Panel._dispatch_event(v, "change");
5649
+ Panel._dispatch_event( v, "change" );
5400
5650
  }
5401
- } else {
5651
+ }
5652
+ else
5653
+ {
5402
5654
  vecinput.value = round( +vecinput.valueAsNumber + mult * dt, options.precision );
5403
- Panel._dispatch_event(vecinput, "change");
5655
+ Panel._dispatch_event( vecinput, "change" );
5404
5656
  }
5405
5657
  }
5406
5658
 
@@ -5409,32 +5661,57 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5409
5661
  e.preventDefault();
5410
5662
  }
5411
5663
 
5412
- function inner_mouseup( e ) {
5664
+ function inner_mouseup( e )
5665
+ {
5413
5666
  var doc = that.root.ownerDocument;
5414
- doc.removeEventListener("mousemove",inner_mousemove);
5415
- doc.removeEventListener("mouseup",inner_mouseup);
5416
- document.body.classList.remove('nocursor');
5417
- document.body.classList.remove('noevents');
5667
+ doc.removeEventListener( 'mousemove', inner_mousemove );
5668
+ doc.removeEventListener( 'mouseup', inner_mouseup );
5669
+ document.body.classList.remove( 'nocursor' );
5670
+ document.body.classList.remove( 'noevents' );
5418
5671
  dragIcon.classList.add('hidden');
5672
+
5673
+ if( options.onRelease )
5674
+ {
5675
+ options.onRelease.bind( vecinput )( e, vecinput );
5676
+ }
5419
5677
  }
5420
5678
 
5421
5679
  box.appendChild( vecinput );
5422
5680
  container.appendChild( box );
5423
5681
  }
5424
5682
 
5425
- let locker = document.createElement('a');
5683
+ // Method to change min, max, step parameters
5684
+ if( options.min !== undefined || options.max !== undefined )
5685
+ {
5686
+ widget.setLimits = ( newMin, newMax, newStep ) => {
5687
+ const inputs = element.querySelectorAll(".vecinput");
5688
+ for( let v of inputs )
5689
+ {
5690
+ v.min = newMin ?? v.min;
5691
+ v.max = newMax ?? v.max;
5692
+ v.step = newStep ?? v.step;
5693
+ Panel._dispatch_event( v, "change", true );
5694
+ }
5695
+
5696
+ // To call onChange callback
5697
+ this._trigger( new IEvent( name, value ), callback );
5698
+ };
5699
+ }
5700
+
5701
+ let locker = document.createElement( 'a' );
5426
5702
  locker.className = "fa-solid fa-lock-open lexicon";
5427
- container.appendChild(locker);
5428
- locker.addEventListener("click", function(e) {
5703
+ container.appendChild( locker );
5704
+ locker.addEventListener( "click", function( e ) {
5429
5705
  this.locked = !this.locked;
5430
- if(this.locked){
5431
- this.classList.add("fa-lock");
5432
- this.classList.remove("fa-lock-open");
5706
+ if( this.locked )
5707
+ {
5708
+ this.classList.add( "fa-lock" );
5709
+ this.classList.remove( "fa-lock-open" );
5433
5710
  } else {
5434
- this.classList.add("fa-lock-open");
5435
- this.classList.remove("fa-lock");
5711
+ this.classList.add( "fa-lock-open" );
5712
+ this.classList.remove( "fa-lock" );
5436
5713
  }
5437
- }, false);
5714
+ }, false );
5438
5715
 
5439
5716
  element.appendChild( container );
5440
5717
 
@@ -5450,21 +5727,231 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5450
5727
  * disabled: Make the widget disabled [false]
5451
5728
  * step: Step of the inputs
5452
5729
  * min, max: Min and Max values for the inputs
5730
+ * onPress: Callback function on mouse down
5731
+ * onRelease: Callback function on mouse up
5453
5732
  */
5454
5733
 
5455
5734
  addVector2( name, value, callback, options ) {
5456
5735
 
5457
- return this._add_vector(2, name, value, callback, options);
5736
+ return this._add_vector( 2, name, value, callback, options );
5458
5737
  }
5459
5738
 
5460
5739
  addVector3( name, value, callback, options ) {
5461
5740
 
5462
- return this._add_vector(3, name, value, callback, options);
5741
+ return this._add_vector( 3, name, value, callback, options );
5463
5742
  }
5464
5743
 
5465
5744
  addVector4( name, value, callback, options ) {
5466
5745
 
5467
- return this._add_vector(4, name, value, callback, options);
5746
+ return this._add_vector( 4, name, value, callback, options );
5747
+ }
5748
+
5749
+ /**
5750
+ * @method addSize
5751
+ * @param {String} name Widget name
5752
+ * @param {Number} value Default number value
5753
+ * @param {Function} callback Callback function on change
5754
+ * @param {*} options:
5755
+ * disabled: Make the widget disabled [false]
5756
+ * units: Unit as string added to the end of the value
5757
+ */
5758
+
5759
+ addSize( name, value, callback, options = {} ) {
5760
+
5761
+ let widget = this.create_widget( name, Widget.SIZE, options );
5762
+
5763
+ widget.onGetValue = () => {
5764
+ const value = [];
5765
+ for( let i = 0; i < element.dimensions.length; ++i )
5766
+ {
5767
+ value.push( element.dimensions[ i ].onGetValue() );
5768
+ }
5769
+ return value;
5770
+ };
5771
+
5772
+ widget.onSetValue = ( newValue, skipCallback ) => {
5773
+ for( let i = 0; i < element.dimensions.length; ++i )
5774
+ {
5775
+ element.dimensions[ i ].onSetValue( newValue[ i ], skipCallback );
5776
+ }
5777
+ };
5778
+
5779
+ let element = widget.domEl;
5780
+
5781
+ this.queue( element );
5782
+
5783
+ element.dimensions = [];
5784
+
5785
+ for( let i = 0; i < value.length; ++i )
5786
+ {
5787
+ const size = measureRealWidth( JSON.stringify( value[ i ] ), 24 ) + 'px';
5788
+ element.dimensions[ i ] = this.addNumber( null, value[ i ], ( v ) => {
5789
+
5790
+ const value = [];
5791
+
5792
+ for( let i = 0; i < element.dimensions.length; ++i )
5793
+ {
5794
+ value.push( element.dimensions[ i ].onGetValue() );
5795
+ }
5796
+
5797
+ if( callback )
5798
+ {
5799
+ callback( value );
5800
+ }
5801
+
5802
+ }, { width: size, min: 0, disabled: options.disabled } );
5803
+
5804
+ if( ( i + 1 ) != value.length )
5805
+ {
5806
+ let cross = document.createElement( 'a' );
5807
+ cross.className = "lexsizecross fa-solid fa-xmark";
5808
+ element.appendChild( cross );
5809
+ }
5810
+ }
5811
+
5812
+ this.clearQueue();
5813
+
5814
+ if( options.units )
5815
+ {
5816
+ let unitSpan = document.createElement( 'span' );
5817
+ unitSpan.className = "lexunit";
5818
+ unitSpan.innerText = options.units;
5819
+ element.appendChild( unitSpan );
5820
+ }
5821
+
5822
+ // Remove branch padding and margins
5823
+ if( !widget.name )
5824
+ {
5825
+ element.className += " noname";
5826
+ container.style.width = "100%";
5827
+ }
5828
+
5829
+ return widget;
5830
+ }
5831
+
5832
+ /**
5833
+ * @method addPad
5834
+ * @param {String} name Widget name
5835
+ * @param {Number} value Pad value
5836
+ * @param {Function} callback Callback function on change
5837
+ * @param {*} options:
5838
+ * disabled: Make the widget disabled [false]
5839
+ * min, max: Min and Max values
5840
+ * onPress: Callback function on mouse down
5841
+ * onRelease: Callback function on mouse up
5842
+ */
5843
+
5844
+ addPad( name, value, callback, options = {} ) {
5845
+
5846
+ if( !name )
5847
+ {
5848
+ throw( "Set Widget Name!" );
5849
+ }
5850
+
5851
+ let widget = this.create_widget( name, Widget.PAD, options );
5852
+
5853
+ widget.onGetValue = () => {
5854
+ return thumb.value.xy;
5855
+ };
5856
+
5857
+ widget.onSetValue = ( newValue, skipCallback ) => {
5858
+ thumb.value.set( newValue[ 0 ], newValue[ 1 ] );
5859
+ _updateValue( thumb.value );
5860
+ if( !skipCallback )
5861
+ {
5862
+ this._trigger( new IEvent( name, thumb.value.xy ), callback );
5863
+ }
5864
+ };
5865
+
5866
+ let element = widget.domEl;
5867
+
5868
+ var container = document.createElement( 'div' );
5869
+ container.className = "lexpad";
5870
+ container.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
5871
+
5872
+ let pad = document.createElement('div');
5873
+ pad.id = "lexpad-" + name;
5874
+ pad.className = "lexinnerpad";
5875
+ pad.style.width = options.padSize ?? '96px';
5876
+ pad.style.height = options.padSize ?? '96px';
5877
+
5878
+ let thumb = document.createElement('div');
5879
+ thumb.className = "lexpadthumb";
5880
+ thumb.value = new LX.vec2( value[ 0 ], value[ 1 ] );
5881
+ thumb.min = options.min ?? 0;
5882
+ thumb.max = options.max ?? 1;
5883
+
5884
+ let _updateValue = v => {
5885
+ const [ w, h ] = [ pad.offsetWidth, pad.offsetHeight ];
5886
+ const value0to1 = new LX.vec2( remapRange( v.x, thumb.min, thumb.max, 0.0, 1.0 ), remapRange( v.y, thumb.min, thumb.max, 0.0, 1.0 ) );
5887
+ thumb.style.transform = `translate(calc( ${ w * value0to1.x }px - 50% ), calc( ${ h * value0to1.y }px - 50%)`;
5888
+ }
5889
+
5890
+ doAsync( () => {
5891
+ _updateValue( thumb.value )
5892
+ } );
5893
+
5894
+ pad.appendChild( thumb );
5895
+ container.appendChild( pad );
5896
+ element.appendChild( container );
5897
+
5898
+ pad.addEventListener( "mousedown", innerMouseDown );
5899
+
5900
+ let that = this;
5901
+
5902
+ function innerMouseDown( e )
5903
+ {
5904
+ if( document.activeElement == thumb )
5905
+ {
5906
+ return;
5907
+ }
5908
+
5909
+ var doc = that.root.ownerDocument;
5910
+ doc.addEventListener( 'mousemove', innerMouseMove );
5911
+ doc.addEventListener( 'mouseup', innerMouseUp );
5912
+ document.body.classList.add( 'nocursor' );
5913
+ document.body.classList.add( 'noevents' );
5914
+ e.stopImmediatePropagation();
5915
+ e.stopPropagation();
5916
+
5917
+ if( options.onPress )
5918
+ {
5919
+ options.onPress.bind( thumb )( e, thumb );
5920
+ }
5921
+ }
5922
+
5923
+ function innerMouseMove( e )
5924
+ {
5925
+ const rect = pad.getBoundingClientRect();
5926
+ const relativePosition = new LX.vec2( e.x - rect.x, e.y - rect.y );
5927
+ relativePosition.clp( 0.0, pad.offsetWidth, relativePosition);
5928
+ const [ w, h ] = [ pad.offsetWidth, pad.offsetHeight ];
5929
+ const value0to1 = relativePosition.div( new LX.vec2( pad.offsetWidth, pad.offsetHeight ) );
5930
+
5931
+ thumb.style.transform = `translate(calc( ${ w * value0to1.x }px - 50% ), calc( ${ h * value0to1.y }px - 50%)`;
5932
+ thumb.value = new LX.vec2( remapRange( value0to1.x, 0.0, 1.0, thumb.min, thumb.max ), remapRange( value0to1.y, 0.0, 1.0, thumb.min, thumb.max ) );
5933
+
5934
+ that._trigger( new IEvent( name, thumb.value.xy, e ), callback );
5935
+
5936
+ e.stopPropagation();
5937
+ e.preventDefault();
5938
+ }
5939
+
5940
+ function innerMouseUp( e )
5941
+ {
5942
+ var doc = that.root.ownerDocument;
5943
+ doc.removeEventListener( 'mousemove', innerMouseMove );
5944
+ doc.removeEventListener( 'mouseup', innerMouseUp );
5945
+ document.body.classList.remove( 'nocursor' );
5946
+ document.body.classList.remove( 'noevents' );
5947
+
5948
+ if( options.onRelease )
5949
+ {
5950
+ options.onRelease.bind( thumb )( e, thumb );
5951
+ }
5952
+ }
5953
+
5954
+ return widget;
5468
5955
  }
5469
5956
 
5470
5957
  /**
@@ -5965,8 +6452,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
5965
6452
 
5966
6453
  this.grabber = grabber;
5967
6454
 
5968
- function getBranchHeight(){
5969
-
6455
+ function getBranchHeight() {
5970
6456
  return that.root.offsetHeight - that.root.children[0].offsetHeight;
5971
6457
  }
5972
6458
 
@@ -6020,20 +6506,23 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6020
6506
  var size = this.grabber.style.marginLeft;
6021
6507
 
6022
6508
  // Update sizes of widgets inside
6023
- for(var i = 0; i < this.widgets.length;i++) {
6509
+ for(var i = 0; i < this.widgets.length; i++) {
6024
6510
 
6025
- let widget = this.widgets[i];
6511
+ let widget = this.widgets[ i ];
6026
6512
  let element = widget.domEl;
6027
6513
 
6028
- if(element.children.length < 2)
6514
+ if( element.children.length < 2 )
6515
+ {
6029
6516
  continue;
6517
+ }
6030
6518
 
6031
- var name = element.children[0];
6032
- var value = element.children[1];
6519
+ var name = element.children[ 0 ];
6520
+ var value = element.children[ 1 ];
6033
6521
 
6034
6522
  name.style.width = size;
6035
6523
  let padding = "0px";
6036
- switch(widget.type) {
6524
+ switch( widget.type )
6525
+ {
6037
6526
  case Widget.FILE:
6038
6527
  padding = "10%";
6039
6528
  break;
@@ -6046,7 +6535,10 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6046
6535
  value.style.width = "-webkit-calc( 100% - " + size + " - " + padding + " )";
6047
6536
  value.style.width = "calc( 100% - " + size + " - " + padding + " )";
6048
6537
 
6049
- if(widget.onresize) widget.onresize();
6538
+ if( widget.onresize )
6539
+ {
6540
+ widget.onresize();
6541
+ }
6050
6542
  }
6051
6543
  }
6052
6544
  };
@@ -6063,8 +6555,10 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6063
6555
 
6064
6556
  constructor( title, callback, options = {} ) {
6065
6557
 
6066
- if(!callback)
6067
- console.warn("Content is empty, add some widgets using 'callback' parameter!");
6558
+ if( !callback )
6559
+ {
6560
+ console.warn("Content is empty, add some widgets using 'callback' parameter!");
6561
+ }
6068
6562
 
6069
6563
  this._oncreate = callback;
6070
6564
  this.id = simple_guidGenerator();
@@ -6074,8 +6568,10 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6074
6568
  draggable = options.draggable ?? true,
6075
6569
  modal = options.modal ?? false;
6076
6570
 
6077
- if(modal)
6078
- LX.modal.toggle(false);
6571
+ if( modal )
6572
+ {
6573
+ LX.modal.toggle( false );
6574
+ }
6079
6575
 
6080
6576
  var root = document.createElement('div');
6081
6577
  root.className = "lexdialog " + (options.class ?? "");
@@ -6086,8 +6582,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6086
6582
 
6087
6583
  var titleDiv = document.createElement('div');
6088
6584
 
6089
- if(title) {
6090
-
6585
+ if( title )
6586
+ {
6091
6587
  titleDiv.className = "lexdialogtitle";
6092
6588
  titleDiv.innerHTML = title;
6093
6589
  titleDiv.setAttribute('draggable', false);
@@ -6191,7 +6687,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6191
6687
  this.title = titleDiv;
6192
6688
 
6193
6689
  if( draggable )
6194
- makeDraggable( root, { targetClass: 'lexdialogtitle' } );
6690
+ {
6691
+ makeDraggable( root, Object.assign( { targetClass: 'lexdialogtitle' }, options ) );
6692
+ }
6195
6693
 
6196
6694
  // Process position and size
6197
6695
  if(size.length && typeof(size[0]) != "string")
@@ -6366,28 +6864,42 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
6366
6864
  }
6367
6865
  }
6368
6866
 
6369
- _adjust_position(div, margin, useAbsolute = false) {
6370
-
6867
+ _adjust_position( div, margin, useAbsolute = false ) {
6868
+
6371
6869
  let rect = div.getBoundingClientRect();
6372
6870
 
6373
- if(!useAbsolute)
6871
+ if( !useAbsolute )
6374
6872
  {
6375
6873
  let width = rect.width;
6376
- if(window.innerWidth - rect.right < 0)
6874
+ if( rect.left < 0 )
6875
+ {
6876
+ div.style.left = margin + "px";
6877
+ }
6878
+ else if( window.innerWidth - rect.right < 0 )
6879
+ {
6377
6880
  div.style.left = (window.innerWidth - width - margin) + "px";
6881
+ }
6378
6882
 
6379
- if(rect.top + rect.height > window.innerHeight)
6883
+ if( rect.top < 0 )
6884
+ {
6885
+ div.style.top = margin + "px";
6886
+ }
6887
+ else if( (rect.top + rect.height) > window.innerHeight )
6888
+ {
6380
6889
  div.style.top = (window.innerHeight - rect.height - margin) + "px";
6890
+ }
6381
6891
  }
6382
6892
  else
6383
6893
  {
6384
6894
  let dt = window.innerWidth - rect.right;
6385
- if(dt < 0) {
6895
+ if( dt < 0 )
6896
+ {
6386
6897
  div.style.left = div.offsetLeft + (dt - margin) + "px";
6387
6898
  }
6388
6899
 
6389
6900
  dt = window.innerHeight - (rect.top + rect.height);
6390
- if(dt < 0) {
6901
+ if( dt < 0 )
6902
+ {
6391
6903
  div.style.top = div.offsetTop + (dt - margin + 20 ) + "px";
6392
6904
  }
6393
6905
  }