0
# Widget Foundation
1
2
The foundation of the Lumino Widgets system, providing the core base classes that all UI components are built upon. This includes the fundamental `Widget` class, the `Title` system for widget metadata, and the abstract `Layout` base class for managing widget arrangements.
3
4
## Capabilities
5
6
### Widget Class
7
8
The base class for all widgets in the Lumino system, providing lifecycle management, DOM integration, and event handling.
9
10
```typescript { .api }
11
/**
12
* The base class of the lumino widget hierarchy.
13
* Provides lifecycle management, DOM integration, and event handling.
14
*/
15
class Widget {
16
/**
17
* Construct a new widget.
18
* @param options - The options for initializing the widget
19
*/
20
constructor(options?: Widget.IOptions);
21
22
/** The widget's DOM node (read-only) */
23
readonly node: HTMLElement;
24
25
/** Whether the widget has been disposed (read-only) */
26
readonly isDisposed: boolean;
27
28
/** Whether the widget is attached to the DOM (read-only) */
29
readonly isAttached: boolean;
30
31
/** Whether the widget is explicitly hidden (read-only) */
32
readonly isHidden: boolean;
33
34
/** Whether the widget is visible (read-only) */
35
readonly isVisible: boolean;
36
37
/** The title object for the widget (read-only) */
38
readonly title: Title<Widget>;
39
40
/** The ID of the widget's DOM node */
41
id: string;
42
43
/** The dataset for the widget's DOM node (read-only) */
44
readonly dataset: DOMStringMap;
45
46
/** The method for hiding the widget */
47
hiddenMode: Widget.HiddenMode;
48
49
/** The parent widget, or null if no parent */
50
parent: Widget | null;
51
52
/** The layout for the widget, or null if no layout */
53
layout: Layout | null;
54
55
/** Dispose of the widget and its resources */
56
dispose(): void;
57
58
/** Get an iterator over the widget's children */
59
children(): IterableIterator<Widget>;
60
61
/** Test whether the widget contains another widget */
62
contains(widget: Widget): boolean;
63
64
/** Test whether the widget has a CSS class */
65
hasClass(name: string): boolean;
66
67
/** Add a CSS class to the widget */
68
addClass(name: string): void;
69
70
/** Remove a CSS class from the widget */
71
removeClass(name: string): void;
72
73
/** Toggle a CSS class on the widget */
74
toggleClass(name: string, force?: boolean): boolean;
75
76
/** Post an update request message to the widget */
77
update(): void;
78
79
/** Post a fit request message to the widget */
80
fit(): void;
81
82
/** Post an activate request message to the widget */
83
activate(): void;
84
85
/** Send a close request message to the widget */
86
close(): void;
87
88
/** Show the widget */
89
show(): void;
90
91
/** Hide the widget */
92
hide(): void;
93
94
/** Set the hidden state of the widget */
95
setHidden(hidden: boolean): void;
96
97
/** Test whether a widget flag is set */
98
testFlag(flag: Widget.Flag): boolean;
99
100
/** Set a widget flag */
101
setFlag(flag: Widget.Flag): void;
102
103
/** Clear a widget flag */
104
clearFlag(flag: Widget.Flag): void;
105
106
/** Process a message sent to the widget */
107
processMessage(msg: Message): void;
108
109
/** A signal emitted when the widget is disposed */
110
readonly disposed: ISignal<this, void>;
111
}
112
113
namespace Widget {
114
/**
115
* Options for initializing a widget.
116
*/
117
interface IOptions {
118
/** The DOM node to use for the widget (optional, creates div if not provided) */
119
node?: HTMLElement;
120
121
/** The HTML tag name for creating the widget's DOM node (if node not provided) */
122
tag?: keyof HTMLElementTagNameMap;
123
}
124
125
/**
126
* An enum of widget hidden modes.
127
*/
128
enum HiddenMode {
129
/** Hide using CSS display: none */
130
Display = 0,
131
132
/** Hide using CSS transform: scale(0) */
133
Scale = 1,
134
135
/** Hide using CSS content-visibility: hidden */
136
ContentVisibility = 2
137
}
138
139
/**
140
* An enum of widget state flags.
141
*/
142
enum Flag {
143
/** The widget has been disposed */
144
IsDisposed = 0x1,
145
146
/** The widget is attached to the DOM */
147
IsAttached = 0x2,
148
149
/** The widget is explicitly hidden */
150
IsHidden = 0x4,
151
152
/** The widget is visible (deprecated) */
153
IsVisible = 0x8,
154
155
/** The widget disallows layout changes */
156
DisallowLayout = 0x10
157
}
158
159
/**
160
* A message class for resize messages.
161
*/
162
class ResizeMessage {
163
constructor(width: number, height: number);
164
readonly width: number;
165
readonly height: number;
166
}
167
168
/**
169
* A message class for child widget messages.
170
*/
171
class ChildMessage {
172
constructor(type: string, child: Widget);
173
readonly child: Widget;
174
}
175
176
/**
177
* Predefined widget messages.
178
*/
179
namespace Msg {
180
const BeforeShow: Message;
181
const AfterShow: Message;
182
const BeforeHide: Message;
183
const AfterHide: Message;
184
const BeforeAttach: Message;
185
const AfterAttach: Message;
186
const BeforeDetach: Message;
187
const AfterDetach: Message;
188
const ParentChanged: Message;
189
const UpdateRequest: Message;
190
const FitRequest: Message;
191
const ActivateRequest: Message;
192
const CloseRequest: Message;
193
}
194
}
195
196
/**
197
* Static methods for widget management.
198
*/
199
namespace Widget {
200
/**
201
* Attach a widget to a host DOM element.
202
* @param widget - The widget to attach
203
* @param host - The host DOM element
204
* @param ref - Optional reference element for insertion point
205
*/
206
function attach(widget: Widget, host: HTMLElement, ref?: HTMLElement | null): void;
207
208
/**
209
* Detach a widget from its host DOM element.
210
* @param widget - The widget to detach
211
*/
212
function detach(widget: Widget): void;
213
}
214
```
215
216
**Usage Examples:**
217
218
```typescript
219
import { Widget } from "@lumino/widgets";
220
221
// Create a simple widget
222
const widget = new Widget();
223
widget.addClass('my-widget');
224
widget.node.textContent = 'Hello, World!';
225
226
// Create with custom DOM node
227
const customNode = document.createElement('section');
228
const customWidget = new Widget({ node: customNode });
229
230
// Widget lifecycle
231
Widget.attach(widget, document.body);
232
widget.show();
233
widget.update();
234
widget.fit();
235
236
// Handle disposal
237
widget.disposed.connect(() => {
238
console.log('Widget disposed');
239
});
240
widget.dispose();
241
```
242
243
### Title Class
244
245
Manages metadata associated with widgets, including labels, icons, and other display properties.
246
247
```typescript { .api }
248
/**
249
* An object which holds data related to an object's title.
250
* Provides metadata for widgets displayed in containers like tabs and menus.
251
*/
252
class Title<T> {
253
/**
254
* Construct a new title.
255
* @param options - The options for initializing the title
256
*/
257
constructor(options: Title.IOptions<T>);
258
259
/** The object that owns the title (read-only) */
260
readonly owner: T;
261
262
/** The label text for the title */
263
label: string;
264
265
/** The mnemonic index for the label */
266
mnemonic: number;
267
268
/** The icon renderer for the title */
269
icon: VirtualElement.IRenderer | undefined;
270
271
/** The icon class name for the title */
272
iconClass: string;
273
274
/** The icon label for the title */
275
iconLabel: string;
276
277
/** The caption for the title */
278
caption: string;
279
280
/** The extra class name for the title */
281
className: string;
282
283
/** Whether the title is closable */
284
closable: boolean;
285
286
/** The dataset for the title */
287
dataset: Title.Dataset;
288
289
/** Whether the title has been disposed (read-only) */
290
readonly isDisposed: boolean;
291
292
/** Dispose of the title */
293
dispose(): void;
294
295
/** A signal emitted when the title state changes */
296
readonly changed: ISignal<this, void>;
297
}
298
299
namespace Title {
300
/**
301
* Options for initializing a title.
302
*/
303
interface IOptions<T> {
304
/** The object that owns the title */
305
owner: T;
306
307
/** The label for the title (default: empty string) */
308
label?: string;
309
310
/** The mnemonic index for the label (default: -1) */
311
mnemonic?: number;
312
313
/** The icon renderer for the title */
314
icon?: VirtualElement.IRenderer;
315
316
/** The icon class name for the title (default: empty string) */
317
iconClass?: string;
318
319
/** The icon label for the title (default: empty string) */
320
iconLabel?: string;
321
322
/** The caption for the title (default: empty string) */
323
caption?: string;
324
325
/** The extra class name for the title (default: empty string) */
326
className?: string;
327
328
/** Whether the title is closable (default: false) */
329
closable?: boolean;
330
331
/** The dataset for the title */
332
dataset?: Dataset;
333
}
334
335
/**
336
* A type alias for a data attribute dataset.
337
*/
338
type Dataset = { readonly [key: string]: string };
339
}
340
```
341
342
**Usage Examples:**
343
344
```typescript
345
import { Widget, Title } from "@lumino/widgets";
346
347
// Create widget with custom title
348
const widget = new Widget();
349
widget.title.label = 'My Document';
350
widget.title.caption = 'Important document';
351
widget.title.closable = true;
352
widget.title.iconClass = 'fa fa-file';
353
354
// Listen for title changes
355
widget.title.changed.connect(() => {
356
console.log('Title changed:', widget.title.label);
357
});
358
359
// Custom title with dataset
360
widget.title.dataset = {
361
'document-id': '12345',
362
'document-type': 'text'
363
};
364
```
365
366
### Layout Class
367
368
Abstract base class for all widget layout managers, defining the interface for arranging child widgets.
369
370
```typescript { .api }
371
/**
372
* Abstract base class for widget layouts.
373
* Manages the arrangement and sizing of child widgets within a container.
374
*/
375
abstract class Layout implements Iterable<Widget>, IDisposable {
376
/**
377
* Construct a new layout.
378
* @param options - The options for initializing the layout
379
*/
380
constructor(options?: Layout.IOptions);
381
382
/** The parent widget of the layout, or null */
383
parent: Widget | null;
384
385
/** The fit policy for the layout */
386
fitPolicy: Layout.FitPolicy;
387
388
/** Whether the layout has been disposed (read-only) */
389
readonly isDisposed: boolean;
390
391
/** Dispose of the layout and its resources */
392
abstract dispose(): void;
393
394
/** Get an iterator over the widgets in the layout */
395
abstract [Symbol.iterator](): IterableIterator<Widget>;
396
397
/** Remove a widget from the layout */
398
abstract removeWidget(widget: Widget): void;
399
400
/** Process a message sent to the parent widget */
401
processParentMessage(msg: Message): void;
402
403
/** Initialize the layout (called when attached to parent) */
404
protected init(): void;
405
406
/** Attach a widget to the layout at the specified index */
407
protected abstract attachWidget(index: number, widget: Widget): void;
408
409
/** Move a widget from one index to another in the layout */
410
protected abstract moveWidget(fromIndex: number, toIndex: number, widget: Widget): void;
411
412
/** Detach a widget from the layout at the specified index */
413
protected abstract detachWidget(index: number, widget: Widget): void;
414
415
/** Handle before-show messages */
416
protected onBeforeShow(msg: Message): void;
417
418
/** Handle before-attach messages */
419
protected onBeforeAttach(msg: Message): void;
420
421
/** Handle after-attach messages */
422
protected onAfterAttach(msg: Message): void;
423
424
/** Handle before-detach messages */
425
protected onBeforeDetach(msg: Message): void;
426
427
/** Handle after-detach messages */
428
protected onAfterDetach(msg: Message): void;
429
430
/** Handle resize messages */
431
protected onResize(msg: Widget.ResizeMessage): void;
432
433
/** Handle update-request messages */
434
protected onUpdateRequest(msg: Message): void;
435
436
/** Handle fit-request messages */
437
protected onFitRequest(msg: Message): void;
438
439
/** Handle child-shown messages */
440
protected onChildShown(msg: Widget.ChildMessage): void;
441
442
/** Handle child-hidden messages */
443
protected onChildHidden(msg: Widget.ChildMessage): void;
444
}
445
446
namespace Layout {
447
/**
448
* Options for initializing a layout.
449
*/
450
interface IOptions {
451
/** The fit policy for the layout (default: 'set-no-constraint') */
452
fitPolicy?: FitPolicy;
453
}
454
455
/**
456
* The available fit policies for a layout.
457
*/
458
type FitPolicy = 'set-no-constraint' | 'set-min-size';
459
460
/**
461
* The available horizontal alignments for a widget.
462
*/
463
type HorizontalAlignment = 'left' | 'center' | 'right';
464
465
/**
466
* The available vertical alignments for a widget.
467
*/
468
type VerticalAlignment = 'top' | 'center' | 'bottom';
469
470
/**
471
* Get the horizontal alignment for a widget.
472
* @param widget - The widget of interest
473
* @returns The horizontal alignment for the widget
474
*/
475
function getHorizontalAlignment(widget: Widget): HorizontalAlignment;
476
477
/**
478
* Set the horizontal alignment for a widget.
479
* @param widget - The widget of interest
480
* @param value - The desired horizontal alignment
481
*/
482
function setHorizontalAlignment(widget: Widget, value: HorizontalAlignment): void;
483
484
/**
485
* Get the vertical alignment for a widget.
486
* @param widget - The widget of interest
487
* @returns The vertical alignment for the widget
488
*/
489
function getVerticalAlignment(widget: Widget): VerticalAlignment;
490
491
/**
492
* Set the vertical alignment for a widget.
493
* @param widget - The widget of interest
494
* @param value - The desired vertical alignment
495
*/
496
function setVerticalAlignment(widget: Widget, value: VerticalAlignment): void;
497
}
498
```
499
500
### LayoutItem Class
501
502
A utility class that manages individual widgets within layouts, handling sizing and positioning.
503
504
```typescript { .api }
505
/**
506
* A layout item that manages a widget in a layout.
507
* Handles sizing constraints and positioning for widgets.
508
*/
509
class LayoutItem {
510
/**
511
* Construct a new layout item.
512
* @param widget - The widget to manage
513
*/
514
constructor(widget: Widget);
515
516
/** The widget managed by this layout item (read-only) */
517
readonly widget: Widget;
518
519
/** The computed minimum width for the widget (read-only) */
520
readonly minWidth: number;
521
522
/** The computed minimum height for the widget (read-only) */
523
readonly minHeight: number;
524
525
/** The computed maximum width for the widget (read-only) */
526
readonly maxWidth: number;
527
528
/** The computed maximum height for the widget (read-only) */
529
readonly maxHeight: number;
530
531
/** Whether the layout item has been disposed (read-only) */
532
readonly isDisposed: boolean;
533
534
/** Whether the managed widget is hidden (read-only) */
535
readonly isHidden: boolean;
536
537
/** Whether the managed widget is visible (read-only) */
538
readonly isVisible: boolean;
539
540
/** Whether the managed widget is attached (read-only) */
541
readonly isAttached: boolean;
542
543
/** Dispose of the layout item */
544
dispose(): void;
545
546
/** Fit the managed widget to its content */
547
fit(): void;
548
549
/**
550
* Update the position and size of the managed widget.
551
* @param left - The left position in pixels
552
* @param top - The top position in pixels
553
* @param width - The width in pixels
554
* @param height - The height in pixels
555
*/
556
update(left: number, top: number, width: number, height: number): void;
557
}
558
```
559
560
**Usage Examples:**
561
562
```typescript
563
import { Widget, Layout, LayoutItem } from "@lumino/widgets";
564
565
// Custom layout implementation
566
class CustomLayout extends Layout {
567
private _items: LayoutItem[] = [];
568
569
dispose(): void {
570
// Dispose all layout items
571
this._items.forEach(item => item.dispose());
572
this._items.length = 0;
573
super.dispose();
574
}
575
576
*widgets(): IterableIterator<Widget> {
577
for (const item of this._items) {
578
yield item.widget;
579
}
580
}
581
582
protected attachWidget(index: number, widget: Widget): void {
583
const item = new LayoutItem(widget);
584
this._items.splice(index, 0, item);
585
}
586
587
protected moveWidget(fromIndex: number, toIndex: number, widget: Widget): void {
588
const item = this._items.splice(fromIndex, 1)[0];
589
this._items.splice(toIndex, 0, item);
590
}
591
592
protected detachWidget(index: number, widget: Widget): void {
593
const item = this._items.splice(index, 1)[0];
594
item.dispose();
595
}
596
597
protected onUpdateRequest(msg: Message): void {
598
// Position widgets using layout items
599
this._items.forEach((item, index) => {
600
const x = index * 100;
601
const y = 0;
602
item.update(x, y, 100, 100);
603
});
604
}
605
}
606
```