@usman404/crowjs 1.0.3 → 1.1.0
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/Core/Component.js +207 -1
- package/Core/GUIEvent/KeyboardEvent.js +2 -1
- package/Core/Root.js +40 -30
- package/Frames/DummyFrame.js +14 -12
- package/Frames/Frame.js +117 -57
- package/Frames/FrameComponent.js +9 -2
- package/Frames/GridFrame.js +131 -27
- package/Frames/ScrollFrame.js +154 -40
- package/README.md +8 -8
- package/UIComponents/Button.js +281 -0
- package/UIComponents/Icon.js +374 -0
- package/UIComponents/Input.js +15 -8
- package/UIComponents/Label.js +102 -158
- package/UIComponents/TextComponent.js +838 -0
- package/UIComponents/TextField.js +170 -39
- package/UIComponents/UIComponent.js +68 -35
- package/index.js +45 -0
- package/package.json +10 -3
- package/problems.txt +1 -0
package/Frames/Frame.js
CHANGED
|
@@ -22,6 +22,8 @@ export class Frame extends FrameComponent{
|
|
|
22
22
|
* @param {number} pady - Vertical padding
|
|
23
23
|
* @param {boolean} alwaysShowBanner - Whether to always show the banner
|
|
24
24
|
* @param {number} bannerHeight - Height of the top banner
|
|
25
|
+
* @param {p5.Color|string} bannerColor - Banner background color
|
|
26
|
+
* @param {p5.Color|string} bannerDotColor - Banner dot indicator color
|
|
25
27
|
* @param {number} nearestBorderThreshold - Distance threshold for border detection
|
|
26
28
|
* @param {Component|null} parent - Parent component
|
|
27
29
|
* @param {string} type - Component type
|
|
@@ -30,15 +32,24 @@ export class Frame extends FrameComponent{
|
|
|
30
32
|
* @param {boolean} enableResizing - Allow resizing
|
|
31
33
|
* @param {boolean} enableOptimisedResizing - Use optimized resizing
|
|
32
34
|
* @param {boolean} enableShadow - Enable shadow rendering
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
* @param {string} shadowColor - Shadow color (CSS color string)
|
|
36
|
+
* @param {number} shadowBlur - Shadow blur radius
|
|
37
|
+
* @param {number} shadowOffsetX - Shadow offset on X axis
|
|
38
|
+
* @param {number} shadowOffsetY - Shadow offset on Y axis
|
|
39
|
+
* @param {Object} marginOptions - Margin options
|
|
40
|
+
* @param {number} marginOptions.margin - General margin for all sides
|
|
41
|
+
* @param {number} marginOptions.marginx - Horizontal margin (left and right)
|
|
42
|
+
* @param {number} marginOptions.marginy - Vertical margin (top and bottom)
|
|
43
|
+
* @param {number} marginOptions.marginl - Left margin
|
|
44
|
+
* @param {number} marginOptions.marginr - Right margin
|
|
45
|
+
* @param {number} marginOptions.margint - Top margin
|
|
46
|
+
* @param {number} marginOptions.marginb - Bottom margin
|
|
37
47
|
*/
|
|
38
48
|
constructor(x, y, width, height, id, backgroundColor, borderColor, highlightedBorderColor, borderWidth,
|
|
39
|
-
cornerRadius, padx, pady, alwaysShowBanner, bannerHeight, nearestBorderThreshold, parent, type,
|
|
40
|
-
enableReposition, enableOptimisedReposition, enableResizing, enableOptimisedResizing, enableShadow, shadowColor,
|
|
41
|
-
|
|
49
|
+
cornerRadius, padx, pady, alwaysShowBanner, bannerHeight, bannerColor, bannerDotColor, nearestBorderThreshold, parent, type,
|
|
50
|
+
enableReposition, enableOptimisedReposition, enableResizing, enableOptimisedResizing, enableShadow, shadowColor, shadowBlur, shadowOffsetX, shadowOffsetY,
|
|
51
|
+
{margin=0, marginx=null, marginy=null, marginl=null, marginr=null, margint=null, marginb=null, minWidth=0, minHeight=0, showDebugOverlay=false} = {}){
|
|
52
|
+
super(x, y, width, height, {parent: parent, type: type, id: id, margin: margin, marginx: marginx, marginy: marginy, marginl: marginl, marginr: marginr, margint: margint, marginb: marginb, minWidth: minWidth, minHeight: minHeight, showDebugOverlay: showDebugOverlay});
|
|
42
53
|
|
|
43
54
|
this.backgroundColor = backgroundColor;
|
|
44
55
|
this.borderColor = borderColor;
|
|
@@ -47,6 +58,7 @@ export class Frame extends FrameComponent{
|
|
|
47
58
|
this.cornerRadius = cornerRadius;
|
|
48
59
|
this.padx = padx;
|
|
49
60
|
this.pady = pady;
|
|
61
|
+
this.pad = (this.padx === this.pady) ? this.padx : null;
|
|
50
62
|
|
|
51
63
|
this.enableShadow = enableShadow;
|
|
52
64
|
this.enableReposition = enableReposition;
|
|
@@ -57,6 +69,8 @@ export class Frame extends FrameComponent{
|
|
|
57
69
|
|
|
58
70
|
if(this.enableReposition || this.alwaysShowBanner){
|
|
59
71
|
this.bannerHeight = bannerHeight;
|
|
72
|
+
this.bannerColor = bannerColor;
|
|
73
|
+
this.bannerDotColor = bannerDotColor;
|
|
60
74
|
|
|
61
75
|
if(this.enableReposition){
|
|
62
76
|
this.isBannerShown = false;
|
|
@@ -74,13 +88,14 @@ export class Frame extends FrameComponent{
|
|
|
74
88
|
if(this.enableResizing){
|
|
75
89
|
this.nearestBorder = null;
|
|
76
90
|
this.nearestBorderThreshold = nearestBorderThreshold;
|
|
91
|
+
this._isResizing = false;
|
|
77
92
|
}
|
|
78
93
|
|
|
79
94
|
if(this.enableShadow){
|
|
80
|
-
this.shadowColor = shadowColor
|
|
81
|
-
this.
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
95
|
+
this.shadowColor = shadowColor;
|
|
96
|
+
this.shadowBlur = shadowBlur;
|
|
97
|
+
this.shadowOffsetX = shadowOffsetX;
|
|
98
|
+
this.shadowOffsetY = shadowOffsetY;
|
|
84
99
|
}
|
|
85
100
|
|
|
86
101
|
this.addEventListener("hover", (event) => this.onMouseHover(event));
|
|
@@ -92,12 +107,21 @@ export class Frame extends FrameComponent{
|
|
|
92
107
|
this.addEventListener("reposition", (event) => this.onRepos(event));
|
|
93
108
|
}
|
|
94
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Sets a unified padding value for both axes
|
|
112
|
+
* @param {number} pad - Padding value to apply to both axes
|
|
113
|
+
*/
|
|
114
|
+
setPad(pad){
|
|
115
|
+
this.pad = pad;
|
|
116
|
+
this.padx = pad;
|
|
117
|
+
this.pady = pad;
|
|
118
|
+
}
|
|
119
|
+
|
|
95
120
|
/**
|
|
96
121
|
* Handles frame resize events
|
|
97
122
|
* @param {GUIEvent} event - The resize event
|
|
98
123
|
*/
|
|
99
124
|
onResize(event){
|
|
100
|
-
console.log("resizing...");
|
|
101
125
|
event.stopPropagation();
|
|
102
126
|
}
|
|
103
127
|
|
|
@@ -106,7 +130,6 @@ export class Frame extends FrameComponent{
|
|
|
106
130
|
* @param {GUIEvent} event - The reposition event
|
|
107
131
|
*/
|
|
108
132
|
onRepos(event){
|
|
109
|
-
console.log("repositioning...");
|
|
110
133
|
}
|
|
111
134
|
|
|
112
135
|
/**
|
|
@@ -114,6 +137,10 @@ export class Frame extends FrameComponent{
|
|
|
114
137
|
* @param {GUIEvent} event - The release event
|
|
115
138
|
*/
|
|
116
139
|
onMouseRelease(event){
|
|
140
|
+
if(this.enableResizing){
|
|
141
|
+
this._isResizing = false;
|
|
142
|
+
}
|
|
143
|
+
|
|
117
144
|
if(!this.isOverBannerArea()){
|
|
118
145
|
cursor("");
|
|
119
146
|
}
|
|
@@ -144,7 +171,9 @@ export class Frame extends FrameComponent{
|
|
|
144
171
|
onMouseHover(event){
|
|
145
172
|
// console.log("mouse hovering...");
|
|
146
173
|
if(this.enableResizing) {
|
|
147
|
-
this.
|
|
174
|
+
if(!this._isResizing){
|
|
175
|
+
this.checkAndFindNearestBorder();
|
|
176
|
+
}
|
|
148
177
|
if(this.isNearBorder()){
|
|
149
178
|
if(this.isBannerShown){
|
|
150
179
|
this.clearHoverCache({clearResizingCache:false});
|
|
@@ -182,6 +211,8 @@ export class Frame extends FrameComponent{
|
|
|
182
211
|
*/
|
|
183
212
|
onMouseBtnPress(event) {
|
|
184
213
|
if(this.enableResizing && this.isNearBorder()){
|
|
214
|
+
this._isResizing = true;
|
|
215
|
+
|
|
185
216
|
//dummy resize frame
|
|
186
217
|
if(this.enableOptimisedResizing){
|
|
187
218
|
this.createDummyFrame(DummyFrame.RESIZE_DF);
|
|
@@ -218,16 +249,14 @@ export class Frame extends FrameComponent{
|
|
|
218
249
|
*/
|
|
219
250
|
onMouseDrag(event){
|
|
220
251
|
if(this.enableResizing){
|
|
221
|
-
if(this.isNearBorder() && !this.isRepositioning()){
|
|
252
|
+
if((this.isNearBorder() || this._isResizing) && !this.isRepositioning()){
|
|
222
253
|
this.updateDimensions();
|
|
223
|
-
this.dispatchTrickleDownEvent(new GUIEvent(event.x, event.y, "resize", this));
|
|
224
254
|
return;
|
|
225
255
|
}
|
|
226
256
|
}
|
|
227
257
|
|
|
228
258
|
if(this.enableReposition && this.isRepositioning()){
|
|
229
259
|
this.updatePosition();
|
|
230
|
-
this.dispatchTrickleDownEvent(new GUIEvent(event.x, event.y, "reposition", this));
|
|
231
260
|
}
|
|
232
261
|
}
|
|
233
262
|
|
|
@@ -358,14 +387,17 @@ export class Frame extends FrameComponent{
|
|
|
358
387
|
* Updates frame dimensions during resizing
|
|
359
388
|
*/
|
|
360
389
|
updateDimensions(){
|
|
390
|
+
const effMinW = this.getEffectiveMinWidth();
|
|
391
|
+
const effMinH = this.getEffectiveMinHeight();
|
|
392
|
+
|
|
361
393
|
if(this.nearestBorder=="left" || this.nearestBorder=="right"){
|
|
362
394
|
if( this.nearestBorder=="left"){
|
|
363
|
-
if(this.x+this.width-mouseX>=
|
|
395
|
+
if(this.x+this.width-mouseX>=effMinW){
|
|
364
396
|
this.width = this.x + this.width - mouseX;
|
|
365
397
|
this.x = mouseX;
|
|
366
398
|
}
|
|
367
399
|
} else {
|
|
368
|
-
if(mouseX-this.x>=
|
|
400
|
+
if(mouseX-this.x>=effMinW){
|
|
369
401
|
this.width = mouseX - this.x;
|
|
370
402
|
}
|
|
371
403
|
}
|
|
@@ -378,12 +410,12 @@ export class Frame extends FrameComponent{
|
|
|
378
410
|
|
|
379
411
|
} else if(this.nearestBorder=="top"||this.nearestBorder=="bottom"){
|
|
380
412
|
if(this.nearestBorder=="top"){
|
|
381
|
-
if(this.y+this.height-mouseY>=
|
|
413
|
+
if(this.y+this.height-mouseY>=effMinH){
|
|
382
414
|
this.height =this.y + this.height - mouseY;
|
|
383
415
|
this.y = mouseY;
|
|
384
416
|
}
|
|
385
417
|
} else {
|
|
386
|
-
if(mouseY-this.y>=
|
|
418
|
+
if(mouseY-this.y>=effMinH){
|
|
387
419
|
this.height = mouseY - this.y;
|
|
388
420
|
}
|
|
389
421
|
}
|
|
@@ -400,39 +432,39 @@ export class Frame extends FrameComponent{
|
|
|
400
432
|
|
|
401
433
|
} else {
|
|
402
434
|
if(this.nearestBorder=="top-left"){
|
|
403
|
-
if(this.x+this.width-mouseX>=
|
|
435
|
+
if(this.x+this.width-mouseX>=effMinW){
|
|
404
436
|
this.width = this.x + this.width - mouseX;
|
|
405
437
|
this.x = mouseX;
|
|
406
438
|
}
|
|
407
439
|
|
|
408
|
-
if(this.y+this.height-mouseY>=
|
|
440
|
+
if(this.y+this.height-mouseY>=effMinH){
|
|
409
441
|
this.height =this.y + this.height - mouseY;
|
|
410
442
|
this.y = mouseY;
|
|
411
443
|
}
|
|
412
444
|
} else if(this.nearestBorder=="top-right"){
|
|
413
|
-
if(mouseX-this.x>=
|
|
445
|
+
if(mouseX-this.x>=effMinW){
|
|
414
446
|
this.width = mouseX - this.x;
|
|
415
447
|
}
|
|
416
448
|
|
|
417
|
-
if(this.y+this.height-mouseY>=
|
|
449
|
+
if(this.y+this.height-mouseY>=effMinH){
|
|
418
450
|
this.height =this.y + this.height - mouseY;
|
|
419
451
|
this.y = mouseY;
|
|
420
452
|
}
|
|
421
453
|
} else if(this.nearestBorder=="bottom-left"){
|
|
422
|
-
if(this.x+this.width-mouseX>=
|
|
454
|
+
if(this.x+this.width-mouseX>=effMinW){
|
|
423
455
|
this.width = this.x + this.width - mouseX;
|
|
424
456
|
this.x = mouseX;
|
|
425
457
|
}
|
|
426
458
|
|
|
427
|
-
if(mouseY-this.y>=
|
|
459
|
+
if(mouseY-this.y>=effMinH){
|
|
428
460
|
this.height = mouseY - this.y;
|
|
429
461
|
}
|
|
430
462
|
} else if(this.nearestBorder=="bottom-right"){
|
|
431
|
-
if(mouseX-this.x>=
|
|
463
|
+
if(mouseX-this.x>=effMinW){
|
|
432
464
|
this.width = mouseX - this.x;
|
|
433
465
|
}
|
|
434
466
|
|
|
435
|
-
if(mouseY-this.y>=
|
|
467
|
+
if(mouseY-this.y>=effMinH){
|
|
436
468
|
this.height = mouseY - this.y;
|
|
437
469
|
}
|
|
438
470
|
}
|
|
@@ -455,13 +487,14 @@ export class Frame extends FrameComponent{
|
|
|
455
487
|
this.x = mouseX - abs(this.xDist);
|
|
456
488
|
this.y = mouseY - abs(this.yDist);
|
|
457
489
|
|
|
458
|
-
|
|
490
|
+
let xDiff = this.prevX - this.x;
|
|
491
|
+
let yDiff = this.prevY - this.y;
|
|
492
|
+
|
|
493
|
+
if(xDiff === 0 && yDiff === 0){
|
|
459
494
|
return;
|
|
460
495
|
}
|
|
461
496
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
this.updatePosUtil(this.prevX-this.x, this.prevY-this.y);
|
|
497
|
+
this.updatePosUtil(xDiff, yDiff);
|
|
465
498
|
}
|
|
466
499
|
/**
|
|
467
500
|
* Clears hover and interaction cache
|
|
@@ -485,47 +518,74 @@ export class Frame extends FrameComponent{
|
|
|
485
518
|
|
|
486
519
|
if(clearResizingCache && this.enableResizing){
|
|
487
520
|
this.nearestBorder=null;
|
|
521
|
+
this._isResizing = false;
|
|
488
522
|
// console.log("resizing cache removed...");
|
|
489
523
|
}
|
|
490
524
|
|
|
491
525
|
// console.log("");
|
|
492
526
|
}
|
|
493
527
|
/**
|
|
494
|
-
*
|
|
495
|
-
* @param {string} shadowColor -
|
|
496
|
-
* @returns {number[]|null} Array of RGB values or null
|
|
528
|
+
* Updates shadow color
|
|
529
|
+
* @param {string} shadowColor - Shadow color (CSS color string)
|
|
497
530
|
*/
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
531
|
+
setShadowColor(shadowColor){
|
|
532
|
+
this.shadowColor = shadowColor;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Updates shadow blur radius
|
|
537
|
+
* @param {number} shadowBlur - Shadow blur
|
|
538
|
+
*/
|
|
539
|
+
setShadowBlur(shadowBlur){
|
|
540
|
+
this.shadowBlur = shadowBlur;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Updates shadow X offset
|
|
545
|
+
* @param {number} shadowOffsetX - Shadow offset on X axis
|
|
546
|
+
*/
|
|
547
|
+
setShadowOffsetX(shadowOffsetX){
|
|
548
|
+
this.shadowOffsetX = shadowOffsetX;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Updates shadow Y offset
|
|
553
|
+
* @param {number} shadowOffsetY - Shadow offset on Y axis
|
|
554
|
+
*/
|
|
555
|
+
setShadowOffsetY(shadowOffsetY){
|
|
556
|
+
this.shadowOffsetY = shadowOffsetY;
|
|
501
557
|
}
|
|
502
558
|
/**
|
|
503
559
|
* Renders shadow effect around the frame
|
|
504
560
|
* @param {Object} options - Shadow options
|
|
505
561
|
*/
|
|
506
562
|
drawShadow({}={}){
|
|
507
|
-
|
|
508
|
-
if(color==null){
|
|
509
|
-
console.log("shadow color value is not in the correct format: rgb(0,0,0)");
|
|
563
|
+
if(this.width<=0 || this.height<=0){
|
|
510
564
|
return;
|
|
511
565
|
}
|
|
512
566
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
this.
|
|
519
|
-
}
|
|
567
|
+
let blur = Math.max(0, this.shadowBlur ?? 0);
|
|
568
|
+
let offsetX = this.shadowOffsetX ?? 0;
|
|
569
|
+
let offsetY = this.shadowOffsetY ?? 0;
|
|
570
|
+
let resolvedShadowColor = (typeof this.shadowColor === "string")
|
|
571
|
+
? this.shadowColor
|
|
572
|
+
: (this.shadowColor && this.shadowColor.toString ? this.shadowColor.toString() : "rgba(0,0,0,0.35)");
|
|
520
573
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
noFill();
|
|
524
|
-
let alpha = this.shadowIntensity * pow(1 - i / this.shadowDetail, 2);
|
|
525
|
-
stroke(`rgba(${color[0]}, ${color[1]}, ${color[2]}, ${alpha})`);
|
|
526
|
-
strokeWeight(this.shadowSpread);
|
|
527
|
-
rect(this.x-((i*this.shadowSpread)/2), this.y-((i*this.shadowSpread)/2), this.width+(i*this.shadowSpread), this.height+(i*this.shadowSpread), this.cornerRadius);
|
|
528
|
-
pop();
|
|
574
|
+
if(blur===0 && offsetX===0 && offsetY===0){
|
|
575
|
+
return;
|
|
529
576
|
}
|
|
577
|
+
|
|
578
|
+
let baseFill = this.backgroundColor ?? color(0, 0, 0, 0);
|
|
579
|
+
|
|
580
|
+
push();
|
|
581
|
+
let ctx = drawingContext;
|
|
582
|
+
ctx.shadowColor = resolvedShadowColor;
|
|
583
|
+
ctx.shadowBlur = blur;
|
|
584
|
+
ctx.shadowOffsetX = offsetX;
|
|
585
|
+
ctx.shadowOffsetY = offsetY;
|
|
586
|
+
noStroke();
|
|
587
|
+
fill(baseFill);
|
|
588
|
+
rect(this.x, this.y, this.width, this.height, this.cornerRadius);
|
|
589
|
+
pop();
|
|
530
590
|
}
|
|
531
591
|
}
|
package/Frames/FrameComponent.js
CHANGED
|
@@ -11,9 +11,16 @@ export class FrameComponent extends Component{
|
|
|
11
11
|
* @param {Component|null} options.parent - Parent component
|
|
12
12
|
* @param {string} options.type - Component type
|
|
13
13
|
* @param {string|null} options.id - Component ID
|
|
14
|
+
* @param {number} options.margin - General margin for all sides
|
|
15
|
+
* @param {number} options.marginx - Horizontal margin (left and right)
|
|
16
|
+
* @param {number} options.marginy - Vertical margin (top and bottom)
|
|
17
|
+
* @param {number} options.marginl - Left margin
|
|
18
|
+
* @param {number} options.marginr - Right margin
|
|
19
|
+
* @param {number} options.margint - Top margin
|
|
20
|
+
* @param {number} options.marginb - Bottom margin
|
|
14
21
|
*/
|
|
15
|
-
constructor(x, y, width, height, {parent=null, type="", id=null} = {}){
|
|
16
|
-
super(x, y, width, height, {parent: parent, type: type, id: id,});
|
|
22
|
+
constructor(x, y, width, height, {parent=null, type="", id=null, margin=0, marginx=null, marginy=null, marginl=null, marginr=null, margint=null, marginb=null, minWidth=0, minHeight=0, showDebugOverlay=false} = {}){
|
|
23
|
+
super(x, y, width, height, {parent: parent, type: type, id: id, margin: margin, marginx: marginx, marginy: marginy, marginl: marginl, marginr: marginr, margint: margint, marginb: marginb, minWidth: minWidth, minHeight: minHeight, showDebugOverlay: showDebugOverlay});
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
/**
|
package/Frames/GridFrame.js
CHANGED
|
@@ -14,6 +14,7 @@ export class GridFrame extends Frame{
|
|
|
14
14
|
* @param {p5.Color} options.highlightedBorderColor - Highlighted border color
|
|
15
15
|
* @param {number} options.borderWidth - Border width
|
|
16
16
|
* @param {number} options.cornerRadius - Corner radius
|
|
17
|
+
* @param {number} options.pad - Unified padding for both axes
|
|
17
18
|
* @param {number} options.padx - Horizontal padding
|
|
18
19
|
* @param {number} options.pady - Vertical padding
|
|
19
20
|
* @param {boolean} options.alwaysShowBanner - Always show banner
|
|
@@ -21,47 +22,83 @@ export class GridFrame extends Frame{
|
|
|
21
22
|
* @param {number} options.cols - Number of columns in grid
|
|
22
23
|
* @param {number} options.nearestBorderThreshold - Border detection threshold
|
|
23
24
|
* @param {number} options.bannerHeight - Banner height
|
|
25
|
+
* @param {p5.Color|string} options.bannerColor - Banner background color
|
|
26
|
+
* @param {p5.Color|string} options.bannerDotColor - Banner dot indicator color
|
|
24
27
|
* @param {Component|null} options.parent - Parent component
|
|
25
28
|
* @param {boolean} options.enableReposition - Allow dragging
|
|
26
29
|
* @param {boolean} options.enableOptimisedReposition - Optimized repositioning
|
|
27
30
|
* @param {boolean} options.enableResizing - Allow resizing
|
|
28
31
|
* @param {boolean} options.enableOptimisedResizing - Optimized resizing
|
|
29
32
|
* @param {boolean} options.enableShadow - Enable shadow
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
* @param {string} options.shadowColor - Shadow color (CSS color string)
|
|
34
|
+
* @param {number} options.shadowBlur - Shadow blur radius
|
|
35
|
+
* @param {number} options.shadowOffsetX - Shadow offset on X axis
|
|
36
|
+
* @param {number} options.shadowOffsetY - Shadow offset on Y axis
|
|
37
|
+
* @param {number} options.margin - General margin for all sides
|
|
38
|
+
* @param {number} options.marginx - Horizontal margin (left and right)
|
|
39
|
+
* @param {number} options.marginy - Vertical margin (top and bottom)
|
|
40
|
+
* @param {number} options.marginl - Left margin
|
|
41
|
+
* @param {number} options.marginr - Right margin
|
|
42
|
+
* @param {number} options.margint - Top margin
|
|
43
|
+
* @param {number} options.marginb - Bottom margin
|
|
34
44
|
*/
|
|
35
45
|
constructor(x, y, width, height, {
|
|
36
46
|
id=null,
|
|
37
|
-
backgroundColor = color(
|
|
38
|
-
borderColor = color(
|
|
39
|
-
highlightedBorderColor = color(
|
|
47
|
+
backgroundColor = color('#1e1e2e'),
|
|
48
|
+
borderColor = color('#3a3a4d'),
|
|
49
|
+
highlightedBorderColor = color('#5a5a7a'),
|
|
40
50
|
borderWidth = 1,
|
|
41
|
-
cornerRadius =
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
cornerRadius = 8,
|
|
52
|
+
pad=null,
|
|
53
|
+
padx=null,
|
|
54
|
+
pady=null,
|
|
44
55
|
alwaysShowBanner = false,
|
|
45
56
|
rows=1,
|
|
46
57
|
cols=1,
|
|
47
58
|
nearestBorderThreshold=8,
|
|
48
59
|
bannerHeight=35,
|
|
60
|
+
bannerColor='#2a2a3d',
|
|
61
|
+
bannerDotColor='#6a6a8a',
|
|
49
62
|
parent=null,
|
|
50
63
|
enableReposition=false,
|
|
51
64
|
enableOptimisedReposition=false,
|
|
52
65
|
enableResizing=false,
|
|
53
66
|
enableOptimisedResizing=false,
|
|
54
67
|
enableShadow=false,
|
|
55
|
-
shadowColor= '
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
shadowColor= 'rgba(0,0,0,0.5)',
|
|
69
|
+
shadowBlur = 12,
|
|
70
|
+
shadowOffsetX = 0,
|
|
71
|
+
shadowOffsetY = 4,
|
|
72
|
+
margin = 0,
|
|
73
|
+
marginx = null,
|
|
74
|
+
marginy = null,
|
|
75
|
+
marginl = null,
|
|
76
|
+
marginr = null,
|
|
77
|
+
margint = null,
|
|
78
|
+
marginb = null,
|
|
79
|
+
minWidth = 0,
|
|
80
|
+
minHeight = 0,
|
|
81
|
+
showDebugOverlay = false,
|
|
59
82
|
}
|
|
60
83
|
){
|
|
84
|
+
if (pad !== null && pad !== undefined) {
|
|
85
|
+
padx = pad;
|
|
86
|
+
pady = pad;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (padx === null || padx === undefined) {
|
|
90
|
+
padx = 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (pady === null || pady === undefined) {
|
|
94
|
+
pady = 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
61
97
|
bannerHeight = bannerHeight%height;
|
|
62
98
|
super(x, y, width, height, id, backgroundColor, borderColor, highlightedBorderColor, borderWidth,
|
|
63
|
-
cornerRadius, padx, pady, alwaysShowBanner, bannerHeight, nearestBorderThreshold, parent, "Frame",
|
|
64
|
-
enableReposition, enableOptimisedReposition, enableResizing, enableOptimisedResizing, enableShadow, shadowColor,
|
|
99
|
+
cornerRadius, padx, pady, alwaysShowBanner, bannerHeight, bannerColor, bannerDotColor, nearestBorderThreshold, parent, "Frame",
|
|
100
|
+
enableReposition, enableOptimisedReposition, enableResizing, enableOptimisedResizing, enableShadow, shadowColor, shadowBlur, shadowOffsetX, shadowOffsetY,
|
|
101
|
+
{margin, marginx, marginy, marginl, marginr, margint, marginb, minWidth, minHeight, showDebugOverlay});
|
|
65
102
|
|
|
66
103
|
//for storing child elements
|
|
67
104
|
this.rows=rows;
|
|
@@ -224,6 +261,62 @@ export class GridFrame extends Frame{
|
|
|
224
261
|
this.colWeights[colNum] = weight;
|
|
225
262
|
this.totalColWeight+=weight;
|
|
226
263
|
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Computes the effective minimum width from children's constraints.
|
|
267
|
+
* @returns {number}
|
|
268
|
+
*/
|
|
269
|
+
getEffectiveMinWidth() {
|
|
270
|
+
let minW = this.minWidth;
|
|
271
|
+
if (!this.grid) return minW;
|
|
272
|
+
|
|
273
|
+
let maxNeeded = 0;
|
|
274
|
+
for (let i = 0; i < this.cols; i++) {
|
|
275
|
+
for (let j = 0; j < this.rows; j++) {
|
|
276
|
+
if (this.grid[j][i] != null && this.grid[j][i] != "taken") {
|
|
277
|
+
let curr = this.grid[j][i];
|
|
278
|
+
let childMin = curr[0].getEffectiveMinWidth();
|
|
279
|
+
if (childMin <= 0) continue;
|
|
280
|
+
let childNeeded = childMin + curr[3] + curr[4] + curr[0].marginl + curr[0].marginr;
|
|
281
|
+
let spanWeight = 0;
|
|
282
|
+
for (let k = 0; k < curr[2]; k++) spanWeight += this.colWeights[i + k];
|
|
283
|
+
let needed = childNeeded * this.totalColWeight / spanWeight + 2 * this.padx;
|
|
284
|
+
maxNeeded = Math.max(maxNeeded, needed);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return Math.max(minW, maxNeeded);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Computes the effective minimum height from children's constraints.
|
|
294
|
+
* @returns {number}
|
|
295
|
+
*/
|
|
296
|
+
getEffectiveMinHeight() {
|
|
297
|
+
let minH = this.minHeight;
|
|
298
|
+
if (!this.grid) return minH;
|
|
299
|
+
|
|
300
|
+
let bannerH = (this.alwaysShowBanner || this.enableReposition) ? (this.bannerHeight || 0) : 0;
|
|
301
|
+
|
|
302
|
+
let maxNeeded = 0;
|
|
303
|
+
for (let i = 0; i < this.rows; i++) {
|
|
304
|
+
for (let j = 0; j < this.cols; j++) {
|
|
305
|
+
if (this.grid[i][j] != null && this.grid[i][j] != "taken") {
|
|
306
|
+
let curr = this.grid[i][j];
|
|
307
|
+
let childMin = curr[0].getEffectiveMinHeight();
|
|
308
|
+
if (childMin <= 0) continue;
|
|
309
|
+
let childNeeded = childMin + curr[5] + curr[6] + curr[0].margint + curr[0].marginb;
|
|
310
|
+
let spanWeight = 0;
|
|
311
|
+
for (let k = 0; k < curr[1]; k++) spanWeight += this.rowWeights[i + k];
|
|
312
|
+
let needed = childNeeded * this.totalRowWeight / spanWeight + 2 * this.pady + bannerH;
|
|
313
|
+
maxNeeded = Math.max(maxNeeded, needed);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return Math.max(minH, maxNeeded);
|
|
319
|
+
}
|
|
227
320
|
|
|
228
321
|
/**
|
|
229
322
|
* Initializes the grid structure with specified rows and columns
|
|
@@ -266,14 +359,17 @@ export class GridFrame extends Frame{
|
|
|
266
359
|
if(this.grid && this.grid[j][i]!=null && this.grid[j][i]!="taken"){
|
|
267
360
|
let curr = this.grid[j][i];
|
|
268
361
|
|
|
269
|
-
curr[0].x = x + curr[3];
|
|
362
|
+
curr[0].x = x + curr[3] + curr[0].marginl;
|
|
270
363
|
curr[0].width = 0;
|
|
271
364
|
|
|
272
365
|
for(let k=0; k<curr[2]; k++){
|
|
273
366
|
curr[0].width += (this.colWeights[i+k]/this.totalColWeight) * w;
|
|
274
367
|
}
|
|
275
368
|
|
|
276
|
-
curr[0].width -= curr[3] + curr[4];
|
|
369
|
+
curr[0].width -= curr[3] + curr[4] + curr[0].marginl + curr[0].marginr;
|
|
370
|
+
|
|
371
|
+
// Clamp to child's effective minimum width
|
|
372
|
+
curr[0].width = Math.max(curr[0].width, curr[0].getEffectiveMinWidth());
|
|
277
373
|
|
|
278
374
|
if(curr[0].type=="Frame"){
|
|
279
375
|
curr[0].adjustWidth(curr[0].x + curr[0].padx, curr[0].width - 2*curr[0].padx);
|
|
@@ -300,15 +396,18 @@ export class GridFrame extends Frame{
|
|
|
300
396
|
if(this.grid && this.grid[i][j]!=null && this.grid[i][j]!="taken"){
|
|
301
397
|
let curr = this.grid[i][j];
|
|
302
398
|
|
|
303
|
-
curr[0].y = y + curr[5];
|
|
399
|
+
curr[0].y = y + curr[5] + curr[0].margint;
|
|
304
400
|
curr[0].height = 0;
|
|
305
401
|
|
|
306
402
|
for(let k=0; k<curr[1]; k++){
|
|
307
403
|
curr[0].height += (this.rowWeights[i+k]/this.totalRowWeight) * h;
|
|
308
404
|
}
|
|
309
405
|
|
|
310
|
-
curr[0].height -= curr[5] + curr[6];
|
|
406
|
+
curr[0].height -= curr[5] + curr[6] + curr[0].margint + curr[0].marginb;
|
|
311
407
|
|
|
408
|
+
// Clamp to child's effective minimum height
|
|
409
|
+
curr[0].height = Math.max(curr[0].height, curr[0].getEffectiveMinHeight());
|
|
410
|
+
|
|
312
411
|
//console.log("curr[0].type:"+curr[0].type);
|
|
313
412
|
|
|
314
413
|
if(curr[0].type=="Frame"){
|
|
@@ -353,8 +452,8 @@ export class GridFrame extends Frame{
|
|
|
353
452
|
y += (this.rowWeights[i]/this.totalRowWeight) * h;
|
|
354
453
|
}
|
|
355
454
|
|
|
356
|
-
this.grid[row][col][0].x = x + this.grid[row][col][3];
|
|
357
|
-
this.grid[row][col][0].y = y + this.grid[row][col][5];
|
|
455
|
+
this.grid[row][col][0].x = x + this.grid[row][col][3] + this.grid[row][col][0].marginl;
|
|
456
|
+
this.grid[row][col][0].y = y + this.grid[row][col][5] + this.grid[row][col][0].margint;
|
|
358
457
|
|
|
359
458
|
this.expandElement(row, col, rowSpan, colSpan);
|
|
360
459
|
|
|
@@ -445,8 +544,13 @@ export class GridFrame extends Frame{
|
|
|
445
544
|
}
|
|
446
545
|
}
|
|
447
546
|
|
|
448
|
-
this.grid[row][col][0].width = w - this.grid[row][col][3] - this.grid[row][col][4];
|
|
449
|
-
this.grid[row][col][0].height = h - this.grid[row][col][5] - this.grid[row][col][6];
|
|
547
|
+
this.grid[row][col][0].width = w - this.grid[row][col][3] - this.grid[row][col][4] - this.grid[row][col][0].marginl - this.grid[row][col][0].marginr;
|
|
548
|
+
this.grid[row][col][0].height = h - this.grid[row][col][5] - this.grid[row][col][6] - this.grid[row][col][0].margint - this.grid[row][col][0].marginb;
|
|
549
|
+
|
|
550
|
+
// Clamp to child's effective min dimensions
|
|
551
|
+
this.grid[row][col][0].width = Math.max(this.grid[row][col][0].width, this.grid[row][col][0].getEffectiveMinWidth());
|
|
552
|
+
this.grid[row][col][0].height = Math.max(this.grid[row][col][0].height, this.grid[row][col][0].getEffectiveMinHeight());
|
|
553
|
+
|
|
450
554
|
this.grid[row][col][1] = yLimit+1;
|
|
451
555
|
this.grid[row][col][2] = xLimit+1;
|
|
452
556
|
}
|
|
@@ -523,10 +627,10 @@ export class GridFrame extends Frame{
|
|
|
523
627
|
//showing the top banner
|
|
524
628
|
if(this.alwaysShowBanner || (this.enableReposition && this.isBannerShown==true)){
|
|
525
629
|
noStroke();
|
|
526
|
-
fill(
|
|
527
|
-
rect(this.x, this.y, this.width, this.bannerHeight);
|
|
630
|
+
fill(this.bannerColor);
|
|
631
|
+
rect(this.x, this.y, this.width, this.bannerHeight, this.cornerRadius, this.cornerRadius, 0, 0);
|
|
528
632
|
|
|
529
|
-
fill(
|
|
633
|
+
fill(this.bannerDotColor);
|
|
530
634
|
ellipse(this.x+this.width/2,
|
|
531
635
|
this.y+(this.bannerHeight)/2,
|
|
532
636
|
(this.bannerHeight)/4,
|