lexgui 0.6.12 → 0.7.1
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/README.md +14 -9
- package/build/{components → extensions}/audio.js +11 -11
- package/build/{components → extensions}/codeeditor.js +95 -63
- package/build/{components → extensions}/docmaker.js +10 -3
- package/build/{components → extensions}/imui.js +19 -12
- package/build/{components → extensions}/nodegraph.js +1 -1
- package/build/{components → extensions}/timeline.js +23 -23
- package/build/{components → extensions}/videoeditor.js +1 -1
- package/build/lexgui-docs.css +9 -9
- package/build/lexgui.css +500 -226
- package/build/lexgui.js +1562 -772
- package/build/lexgui.min.css +8 -2
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +1563 -773
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +81 -21
- package/demo.js +45 -31
- package/examples/{all_widgets.html → all-components.html} +22 -4
- package/examples/{area_tabs.html → area-tabs.html} +3 -3
- package/examples/{asset_view.html → asset-view.html} +3 -3
- package/examples/{code_editor.html → code-editor.html} +4 -4
- package/examples/dialogs.html +3 -3
- package/examples/editor.html +27 -18
- package/examples/{immediate_ui.html → immediate-ui.html} +3 -3
- package/examples/index.html +8 -8
- package/examples/{node_graph.html → node-graph.html} +3 -3
- package/examples/previews/all-components.png +0 -0
- package/examples/previews/area-tabs.png +0 -0
- package/examples/previews/asset-view.png +0 -0
- package/examples/previews/code-editor.png +0 -0
- package/examples/previews/dialogs.png +0 -0
- package/examples/previews/editor.png +0 -0
- package/examples/previews/node-graph.png +0 -0
- package/examples/previews/side-bar.png +0 -0
- package/examples/previews/timeline.png +0 -0
- package/examples/{side_bar.html → side-bar.html} +3 -3
- package/examples/timeline.html +4 -4
- package/examples/{video_editor.html → video-editor.html} +3 -3
- package/examples/{video_editor2.html → video-editor2.html} +3 -3
- package/package.json +2 -2
- package/examples/previews/all_widgets.png +0 -0
- package/examples/previews/area_tabs.png +0 -0
- package/examples/previews/asset_view.png +0 -0
- package/examples/previews/code_editor.png +0 -0
- package/examples/previews/node_graph.png +0 -0
- package/examples/previews/side_bar.png +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+

|
|
2
|
+

|
|
3
|
+
|
|
1
4
|
# lexgui.js
|
|
2
5
|
|
|
3
|
-
**lexgui.js** is a lightweight JavaScript library for building web interfaces. No bloated frameworks, no unnecessary complexity, just pure HTML, CSS, and JavaScript magic. It gives you an easy API for crafting dynamic, interactive editor interfaces without the headache of big libraries.
|
|
6
|
+
**lexgui.js** is a lightweight JavaScript library for building web user interfaces. No bloated frameworks, no unnecessary complexity, just pure HTML, CSS, and JavaScript magic. It gives you an easy API for crafting dynamic, interactive editor interfaces without the headache of big libraries.
|
|
4
7
|
|
|
5
8
|
NPM Package: [npmjs.com/package/lexgui](https://www.npmjs.com/package/lexgui)
|
|
6
9
|
|
|
@@ -18,12 +21,14 @@ NPM Package: [npmjs.com/package/lexgui](https://www.npmjs.com/package/lexgui)
|
|
|
18
21
|
</tr>
|
|
19
22
|
</table>
|
|
20
23
|
|
|
21
|
-
##
|
|
24
|
+
## Extension Features
|
|
22
25
|
|
|
23
|
-
- [x] Asset Browser
|
|
24
26
|
- [x] Timeline
|
|
25
27
|
- [x] Code Editor
|
|
26
|
-
- [
|
|
28
|
+
- [x] Docs Maker
|
|
29
|
+
- [ ] Node Graph Editor (WIP)
|
|
30
|
+
- [ ] Video Editor (WIP)
|
|
31
|
+
- [ ] Immediate UI (WIP)
|
|
27
32
|
|
|
28
33
|
## Quick start
|
|
29
34
|
|
|
@@ -40,7 +45,7 @@ NPM Package: [npmjs.com/package/lexgui](https://www.npmjs.com/package/lexgui)
|
|
|
40
45
|
{
|
|
41
46
|
"imports": {
|
|
42
47
|
"lexgui": "https://cdn.skypack.dev/lexgui@^<version>/build/lexgui.module.js",
|
|
43
|
-
"lexgui/
|
|
48
|
+
"lexgui/extensions/": "https://cdn.skypack.dev/lexgui@^<version>/build/extensions/"
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
</script>
|
|
@@ -56,8 +61,8 @@ NPM Package: [npmjs.com/package/lexgui](https://www.npmjs.com/package/lexgui)
|
|
|
56
61
|
```js
|
|
57
62
|
import { LX } from 'lexgui';
|
|
58
63
|
|
|
59
|
-
// Using
|
|
60
|
-
import { CodeEditor } from 'lexgui/
|
|
64
|
+
// Using extensions
|
|
65
|
+
import { CodeEditor } from 'lexgui/extensions/codeeditor.js';
|
|
61
66
|
|
|
62
67
|
// Create main area
|
|
63
68
|
let area = await LX.init();
|
|
@@ -68,7 +73,7 @@ let panel = area.addPanel();
|
|
|
68
73
|
// Start branch/section
|
|
69
74
|
panel.branch("Section Title");
|
|
70
75
|
|
|
71
|
-
// Add some
|
|
76
|
+
// Add some components
|
|
72
77
|
panel.addButton(null, "Click me, Im Full Width...");
|
|
73
78
|
panel.addText("Text", "Warning text", null, { warning: true });
|
|
74
79
|
|
|
@@ -82,7 +87,7 @@ The library documentation is available at [lexgui.js/docs/](https://jxarco.githu
|
|
|
82
87
|
|
|
83
88
|
## Examples
|
|
84
89
|
|
|
85
|
-
Look at this [examples](https://jxarco.github.io/lexgui.js/examples/) to see how to create the different
|
|
90
|
+
Look at this [examples](https://jxarco.github.io/lexgui.js/examples/) to see how to create the different components and integrate the extensions!
|
|
86
91
|
|
|
87
92
|
## Projects using lexgui.js
|
|
88
93
|
|
|
@@ -5,14 +5,14 @@ if( !LX )
|
|
|
5
5
|
throw("lexgui.js missing!");
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
LX.
|
|
8
|
+
LX.extensions.push( 'Audio' );
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @class Knob
|
|
12
|
-
* @description Knob
|
|
12
|
+
* @description Knob Component
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
class Knob extends LX.
|
|
15
|
+
class Knob extends LX.BaseComponent {
|
|
16
16
|
|
|
17
17
|
constructor( name, value, min, max, callback, options = {} ) {
|
|
18
18
|
|
|
@@ -22,7 +22,7 @@ class Knob extends LX.Widget {
|
|
|
22
22
|
value = options.precision ? LX.round( value, options.precision ) : value;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
super( LX.
|
|
25
|
+
super( LX.BaseComponent.KNOB, name, value, options );
|
|
26
26
|
|
|
27
27
|
this.onGetValue = () => {
|
|
28
28
|
return innerKnobCircle.value;
|
|
@@ -30,7 +30,7 @@ class Knob extends LX.Widget {
|
|
|
30
30
|
|
|
31
31
|
this.onSetValue = ( newValue, skipCallback ) => {
|
|
32
32
|
innerSetValue( newValue );
|
|
33
|
-
LX.
|
|
33
|
+
LX.BaseComponent._dispatchEvent( innerKnobCircle, "change", skipCallback );
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
this.onResize = ( rect ) => {
|
|
@@ -107,7 +107,7 @@ class Knob extends LX.Widget {
|
|
|
107
107
|
// Reset button (default value)
|
|
108
108
|
if( !skipCallback )
|
|
109
109
|
{
|
|
110
|
-
let btn = this.root.querySelector( ".
|
|
110
|
+
let btn = this.root.querySelector( ".lexcomponentname .lexicon" );
|
|
111
111
|
if( btn ) btn.style.display = val != innerKnobCircle.iValue ? "block": "none";
|
|
112
112
|
|
|
113
113
|
if( !( snapEnabled && !mustSnap ) )
|
|
@@ -157,7 +157,7 @@ class Knob extends LX.Widget {
|
|
|
157
157
|
else if(e.altKey) mult *= 0.1;
|
|
158
158
|
let new_value = (innerKnobCircle.value - mult * dt);
|
|
159
159
|
innerKnobCircle.value = new_value;
|
|
160
|
-
LX.
|
|
160
|
+
LX.BaseComponent._dispatchEvent( innerKnobCircle, 'change' );
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
e.stopPropagation();
|
|
@@ -175,7 +175,7 @@ class Knob extends LX.Widget {
|
|
|
175
175
|
if( snapEnabled )
|
|
176
176
|
{
|
|
177
177
|
mustSnap = true;
|
|
178
|
-
LX.
|
|
178
|
+
LX.BaseComponent._dispatchEvent( innerKnobCircle, 'change' );
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
if( document.pointerLockElement )
|
|
@@ -196,7 +196,7 @@ LX.Knob = Knob;
|
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
198
|
* @method addKnob
|
|
199
|
-
* @param {String} name
|
|
199
|
+
* @param {String} name Component name
|
|
200
200
|
* @param {Number} value Knob value
|
|
201
201
|
* @param {Number} min Min Knob value
|
|
202
202
|
* @param {Number} max Max Knob value
|
|
@@ -207,6 +207,6 @@ LX.Knob = Knob;
|
|
|
207
207
|
*/
|
|
208
208
|
|
|
209
209
|
LX.Panel.prototype.addKnob = function( name, value, min, max, callback, options = {} ) {
|
|
210
|
-
const
|
|
211
|
-
return this.
|
|
210
|
+
const component = new Knob( name, value, min, max, callback, options );
|
|
211
|
+
return this._attachComponent( component );
|
|
212
212
|
}
|
|
@@ -4,7 +4,7 @@ if(!LX) {
|
|
|
4
4
|
throw("lexgui.js missing!");
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
LX.
|
|
7
|
+
LX.extensions.push( 'CodeEditor' );
|
|
8
8
|
|
|
9
9
|
function swapElements( obj, a, b ) {
|
|
10
10
|
[obj[a], obj[b]] = [obj[b], obj[a]];
|
|
@@ -458,7 +458,7 @@ class CodeEditor {
|
|
|
458
458
|
const dX = ( e.deltaY > 0.0 ? 10.0 : -10.0 ) * ( e.shiftKey ? 1.0 : 0.0 );
|
|
459
459
|
if( dX != 0.0 ) this.setScrollBarValue( 'horizontal', dX );
|
|
460
460
|
}
|
|
461
|
-
});
|
|
461
|
+
}, { passive: true });
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
|
|
@@ -822,8 +822,9 @@ class CodeEditor {
|
|
|
822
822
|
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
823
823
|
this.cursorToString( cursor, this.code.lines[ ln ] );
|
|
824
824
|
|
|
825
|
-
|
|
826
|
-
|
|
825
|
+
var viewportSizeX = ( this.codeScroller.clientWidth + this.getScrollLeft() ) - CodeEditor.LINE_GUTTER_WIDTH; // Gutter offset
|
|
826
|
+
if( ( cursor.position * this.charWidth ) >= viewportSizeX )
|
|
827
|
+
this.setScrollLeft( this.code.lines[ ln ].length * this.charWidth );
|
|
827
828
|
|
|
828
829
|
// Merge cursors
|
|
829
830
|
this.mergeCursors( ln );
|
|
@@ -1097,39 +1098,50 @@ class CodeEditor {
|
|
|
1097
1098
|
this.loadedTabs = { };
|
|
1098
1099
|
this.openedTabs = { };
|
|
1099
1100
|
|
|
1101
|
+
const onLoadAll = () => {
|
|
1102
|
+
// Create inspector panel when the initial state is complete
|
|
1103
|
+
// and we have at least 1 tab opened
|
|
1104
|
+
this.infoPanel = this._createInfoPanel();
|
|
1105
|
+
if( this.infoPanel )
|
|
1106
|
+
{
|
|
1107
|
+
area.attach( this.infoPanel );
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// Wait until the fonts are all loaded
|
|
1111
|
+
document.fonts.ready.then(() => {
|
|
1112
|
+
this.charWidth = this._measureChar( "a", true );
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
window.editor = this;
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1100
1118
|
if( options.allowAddScripts ?? true )
|
|
1101
1119
|
{
|
|
1102
1120
|
this.addTab("+", false, "New File");
|
|
1103
1121
|
}
|
|
1104
1122
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1123
|
+
if( options.files )
|
|
1124
|
+
{
|
|
1125
|
+
console.assert( options.files.constructor === Array, "_files_ must be an Array!" );
|
|
1126
|
+
const numFiles = options.files.length;
|
|
1127
|
+
let filesLoaded = 0;
|
|
1110
1128
|
|
|
1111
|
-
|
|
1112
|
-
const commitMono = new FontFace(
|
|
1113
|
-
"CommitMono",
|
|
1114
|
-
`url(${ fontUrl })`,
|
|
1129
|
+
for( let url of options.files )
|
|
1115
1130
|
{
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1131
|
+
this.loadFile( url, { callback: () => {
|
|
1132
|
+
filesLoaded++;
|
|
1133
|
+
if( filesLoaded == numFiles )
|
|
1134
|
+
{
|
|
1135
|
+
onLoadAll();
|
|
1136
|
+
}
|
|
1137
|
+
}});
|
|
1119
1138
|
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
commitMono.load();
|
|
1127
|
-
|
|
1128
|
-
// Wait until the fonts are all loaded
|
|
1129
|
-
document.fonts.ready.then(() => {
|
|
1130
|
-
// console.log("commitMono loaded")
|
|
1131
|
-
this.charWidth = this._measureChar( "a", true );
|
|
1132
|
-
});
|
|
1139
|
+
}
|
|
1140
|
+
else
|
|
1141
|
+
{
|
|
1142
|
+
this.addTab( options.name || "untitled", true, options.title, { language: options.highlight ?? "Plain Text" } );
|
|
1143
|
+
onLoadAll();
|
|
1144
|
+
}
|
|
1133
1145
|
}
|
|
1134
1146
|
|
|
1135
1147
|
static getInstances()
|
|
@@ -1287,6 +1299,11 @@ class CodeEditor {
|
|
|
1287
1299
|
this._changeLanguageFromExtension( LX.getExtension( name ) );
|
|
1288
1300
|
}
|
|
1289
1301
|
}
|
|
1302
|
+
|
|
1303
|
+
if( options.callback )
|
|
1304
|
+
{
|
|
1305
|
+
options.callback( text );
|
|
1306
|
+
}
|
|
1290
1307
|
};
|
|
1291
1308
|
|
|
1292
1309
|
if( file.constructor == String )
|
|
@@ -1560,7 +1577,7 @@ class CodeEditor {
|
|
|
1560
1577
|
this._changeLanguage( 'Plain Text' );
|
|
1561
1578
|
}
|
|
1562
1579
|
|
|
1563
|
-
|
|
1580
|
+
_createInfoPanel() {
|
|
1564
1581
|
|
|
1565
1582
|
if( !this.skipInfo )
|
|
1566
1583
|
{
|
|
@@ -3567,12 +3584,12 @@ class CodeEditor {
|
|
|
3567
3584
|
this.restartBlink();
|
|
3568
3585
|
|
|
3569
3586
|
// Add horizontal scroll
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
}
|
|
3587
|
+
const currentScrollLeft = this.getScrollLeft();
|
|
3588
|
+
var viewportSizeX = ( this.codeScroller.clientWidth + currentScrollLeft ) - CodeEditor.LINE_GUTTER_WIDTH; // Gutter offset
|
|
3589
|
+
if( (cursor.position * this.charWidth) >= viewportSizeX )
|
|
3590
|
+
{
|
|
3591
|
+
this.setScrollLeft( currentScrollLeft + this.charWidth );
|
|
3592
|
+
}
|
|
3576
3593
|
}
|
|
3577
3594
|
|
|
3578
3595
|
cursorToLeft( key, cursor ) {
|
|
@@ -3588,11 +3605,12 @@ class CodeEditor {
|
|
|
3588
3605
|
|
|
3589
3606
|
// Add horizontal scroll
|
|
3590
3607
|
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3608
|
+
const currentScrollLeft = this.getScrollLeft();
|
|
3609
|
+
var viewportSizeX = currentScrollLeft; // Gutter offset
|
|
3610
|
+
if( ( ( cursor.position - 1 ) * this.charWidth ) < viewportSizeX )
|
|
3611
|
+
{
|
|
3612
|
+
this.setScrollLeft( currentScrollLeft - this.charWidth );
|
|
3613
|
+
}
|
|
3596
3614
|
}
|
|
3597
3615
|
|
|
3598
3616
|
cursorToTop( cursor, resetLeft = false ) {
|
|
@@ -3603,30 +3621,40 @@ class CodeEditor {
|
|
|
3603
3621
|
this.restartBlink();
|
|
3604
3622
|
|
|
3605
3623
|
if( resetLeft )
|
|
3624
|
+
{
|
|
3606
3625
|
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
3626
|
+
}
|
|
3607
3627
|
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3628
|
+
const currentScrollTop = this.getScrollTop();
|
|
3629
|
+
var firstLine = ( currentScrollTop / this.lineHeight )|0;
|
|
3630
|
+
if( (cursor.line - 1) < firstLine )
|
|
3631
|
+
{
|
|
3632
|
+
this.setScrollTop( currentScrollTop - this.lineHeight );
|
|
3633
|
+
}
|
|
3613
3634
|
}
|
|
3614
3635
|
|
|
3615
3636
|
cursorToBottom( cursor, resetLeft = false ) {
|
|
3616
3637
|
|
|
3617
3638
|
cursor._top += this.lineHeight;
|
|
3618
|
-
cursor.style.top =
|
|
3639
|
+
cursor.style.top = `calc(${ cursor._top }px)`;
|
|
3619
3640
|
|
|
3620
3641
|
this.restartBlink();
|
|
3621
3642
|
|
|
3622
3643
|
if( resetLeft )
|
|
3644
|
+
{
|
|
3623
3645
|
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
3646
|
+
}
|
|
3624
3647
|
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3648
|
+
const currentScrollTop = this.getScrollTop();
|
|
3649
|
+
const tabsHeight = this.tabs.root.getBoundingClientRect().height;
|
|
3650
|
+
const infoPanelHeight = this.skipInfo ? 0 : this.infoPanel.root.getBoundingClientRect().height;
|
|
3651
|
+
const scrollerHeight = this.codeScroller.offsetHeight;
|
|
3652
|
+
|
|
3653
|
+
var lastLine = ( ( scrollerHeight - tabsHeight - infoPanelHeight + currentScrollTop ) / this.lineHeight )|0;
|
|
3654
|
+
if( cursor.line >= lastLine )
|
|
3655
|
+
{
|
|
3656
|
+
this.setScrollTop( currentScrollTop + this.lineHeight );
|
|
3657
|
+
}
|
|
3630
3658
|
}
|
|
3631
3659
|
|
|
3632
3660
|
cursorToString( cursor, text, reverse ) {
|
|
@@ -3635,7 +3663,9 @@ class CodeEditor {
|
|
|
3635
3663
|
return;
|
|
3636
3664
|
|
|
3637
3665
|
for( let char of text )
|
|
3666
|
+
{
|
|
3638
3667
|
reverse ? this.cursorToLeft( char, cursor ) : this.cursorToRight( char, cursor );
|
|
3668
|
+
}
|
|
3639
3669
|
}
|
|
3640
3670
|
|
|
3641
3671
|
cursorToPosition( cursor, position ) {
|
|
@@ -3759,9 +3789,8 @@ class CodeEditor {
|
|
|
3759
3789
|
}
|
|
3760
3790
|
|
|
3761
3791
|
_removeSpaces( cursor ) {
|
|
3762
|
-
|
|
3763
|
-
// Remove indentation
|
|
3764
3792
|
const lidx = cursor.line;
|
|
3793
|
+
// Remove indentation
|
|
3765
3794
|
let lineStart = firstNonspaceIndex( this.code.lines[ lidx ] );
|
|
3766
3795
|
|
|
3767
3796
|
// Nothing to remove... we are at the start of the line
|
|
@@ -3795,29 +3824,29 @@ class CodeEditor {
|
|
|
3795
3824
|
}
|
|
3796
3825
|
|
|
3797
3826
|
getScrollLeft() {
|
|
3798
|
-
|
|
3799
3827
|
if( !this.codeScroller ) return 0;
|
|
3800
3828
|
return this.codeScroller.scrollLeft;
|
|
3801
3829
|
}
|
|
3802
3830
|
|
|
3803
3831
|
getScrollTop() {
|
|
3804
|
-
|
|
3805
3832
|
if( !this.codeScroller ) return 0;
|
|
3806
3833
|
return this.codeScroller.scrollTop;
|
|
3807
3834
|
}
|
|
3808
3835
|
|
|
3809
3836
|
setScrollLeft( value ) {
|
|
3810
|
-
|
|
3811
3837
|
if( !this.codeScroller ) return;
|
|
3812
|
-
|
|
3813
|
-
|
|
3838
|
+
doAsync( () => {
|
|
3839
|
+
this.codeScroller.scrollLeft = value;
|
|
3840
|
+
this.setScrollBarValue( 'horizontal', 0 );
|
|
3841
|
+
}, 20 );
|
|
3814
3842
|
}
|
|
3815
3843
|
|
|
3816
3844
|
setScrollTop( value ) {
|
|
3817
|
-
|
|
3818
3845
|
if( !this.codeScroller ) return;
|
|
3819
|
-
|
|
3820
|
-
|
|
3846
|
+
doAsync( () => {
|
|
3847
|
+
this.codeScroller.scrollTop = value;
|
|
3848
|
+
this.setScrollBarValue( 'vertical' );
|
|
3849
|
+
}, 20 );
|
|
3821
3850
|
}
|
|
3822
3851
|
|
|
3823
3852
|
resize( pMaxLength, onResize ) {
|
|
@@ -3827,12 +3856,15 @@ class CodeEditor {
|
|
|
3827
3856
|
// Update max viewport
|
|
3828
3857
|
const maxLineLength = pMaxLength ?? this.getMaxLineLength();
|
|
3829
3858
|
const scrollWidth = maxLineLength * this.charWidth + CodeEditor.LINE_GUTTER_WIDTH;
|
|
3859
|
+
|
|
3860
|
+
const tabsHeight = this.tabs.root.getBoundingClientRect().height;
|
|
3861
|
+
const infoPanelHeight = this.skipInfo ? 0 : this.infoPanel.root.getBoundingClientRect().height;
|
|
3830
3862
|
const scrollHeight = this.code.lines.length * this.lineHeight;
|
|
3831
3863
|
|
|
3832
3864
|
this._lastMaxLineLength = maxLineLength;
|
|
3833
3865
|
|
|
3834
3866
|
this.codeSizer.style.minWidth = scrollWidth + "px";
|
|
3835
|
-
this.codeSizer.style.minHeight = scrollHeight + "px";
|
|
3867
|
+
this.codeSizer.style.minHeight = ( scrollHeight + tabsHeight + infoPanelHeight ) + "px";
|
|
3836
3868
|
|
|
3837
3869
|
this.resizeScrollBars();
|
|
3838
3870
|
|
|
@@ -190,19 +190,24 @@ function MAKE_CODE( text, language = "js" )
|
|
|
190
190
|
|
|
191
191
|
window.MAKE_CODE = MAKE_CODE;
|
|
192
192
|
|
|
193
|
-
function MAKE_LIST( list, type )
|
|
193
|
+
function MAKE_LIST( list, type, target )
|
|
194
194
|
{
|
|
195
195
|
const validTypes = [ 'bullet', 'numbered' ];
|
|
196
196
|
console.assert( list && list.length > 0 && validTypes.includes(type), "Invalid list type or empty list" + type );
|
|
197
197
|
const typeString = type == 'bullet' ? 'ul' : 'ol';
|
|
198
198
|
let ul = document.createElement( typeString );
|
|
199
|
+
target = target ?? mainContainer;
|
|
200
|
+
target.appendChild( ul );
|
|
199
201
|
for( var el of list ) {
|
|
202
|
+
if( el.constructor === Array ) {
|
|
203
|
+
MAKE_LIST( el, type, ul );
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
200
206
|
let li = document.createElement( 'li' );
|
|
201
207
|
li.className = "leading-loose";
|
|
202
208
|
li.innerHTML = el;
|
|
203
209
|
ul.appendChild( li );
|
|
204
210
|
}
|
|
205
|
-
mainContainer.appendChild( ul );
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
function MAKE_BULLET_LIST( list )
|
|
@@ -316,7 +321,9 @@ window.INLINE_LINK = INLINE_LINK;
|
|
|
316
321
|
function INLINE_PAGE( string, page )
|
|
317
322
|
{
|
|
318
323
|
console.assert(string && page);
|
|
319
|
-
|
|
324
|
+
const startPage = page.replace(".html", "");
|
|
325
|
+
const tabName = window.setPath( startPage );
|
|
326
|
+
return `<a onclick="loadPage('${ page }', true, '${ tabName }')">${ string }</a>`;
|
|
320
327
|
}
|
|
321
328
|
|
|
322
329
|
window.INLINE_PAGE = INLINE_PAGE;
|
|
@@ -4,7 +4,7 @@ if(!LX) {
|
|
|
4
4
|
throw("lexgui.js missing!");
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
LX.
|
|
7
|
+
LX.extensions.push( 'ImUI' );
|
|
8
8
|
|
|
9
9
|
function swapElements (obj, a, b) {
|
|
10
10
|
[obj[a], obj[b]] = [obj[b], obj[a]];
|
|
@@ -49,9 +49,9 @@ class ImUI {
|
|
|
49
49
|
// },
|
|
50
50
|
// );
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// Components
|
|
53
53
|
|
|
54
|
-
this.
|
|
54
|
+
this.components = { };
|
|
55
55
|
|
|
56
56
|
// Mouse state
|
|
57
57
|
|
|
@@ -157,10 +157,10 @@ class ImUI {
|
|
|
157
157
|
|
|
158
158
|
// Store slider value
|
|
159
159
|
|
|
160
|
-
if(!this.
|
|
161
|
-
this.
|
|
160
|
+
if(!this.components[ text ])
|
|
161
|
+
this.components[ text ] = { value: value };
|
|
162
162
|
else
|
|
163
|
-
value = this.
|
|
163
|
+
value = this.components[ text ].value;
|
|
164
164
|
|
|
165
165
|
// Element properties
|
|
166
166
|
|
|
@@ -196,7 +196,7 @@ class ImUI {
|
|
|
196
196
|
if(active)
|
|
197
197
|
{
|
|
198
198
|
value = LX.clamp((this.mousePosition.x - min) / (max - min), 0.0, 1.0);
|
|
199
|
-
this.
|
|
199
|
+
this.components[ text ].value = value;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
let valueSize = new LX.vec2( fullSize.x * value, size.y );
|
|
@@ -240,10 +240,14 @@ class ImUI {
|
|
|
240
240
|
|
|
241
241
|
// Store slider value
|
|
242
242
|
|
|
243
|
-
if(!this.
|
|
244
|
-
|
|
243
|
+
if( !this.components[ text ] )
|
|
244
|
+
{
|
|
245
|
+
this.components[ text ] = { value: value };
|
|
246
|
+
}
|
|
245
247
|
else
|
|
246
|
-
|
|
248
|
+
{
|
|
249
|
+
value = this.components[ text ].value;
|
|
250
|
+
}
|
|
247
251
|
|
|
248
252
|
// Element properties
|
|
249
253
|
|
|
@@ -280,8 +284,11 @@ class ImUI {
|
|
|
280
284
|
if( pressed )
|
|
281
285
|
{
|
|
282
286
|
value = !value;
|
|
283
|
-
this.
|
|
284
|
-
if(
|
|
287
|
+
this.components[ text ].value = value;
|
|
288
|
+
if( callback )
|
|
289
|
+
{
|
|
290
|
+
callback( value );
|
|
291
|
+
}
|
|
285
292
|
}
|
|
286
293
|
|
|
287
294
|
ctx.fillStyle = value ? (active ? "#ddd" : (hovered ? "#6074e7" : "#3e57e4")) :
|