');
this.codeMirror = CodeMirror($container[0], {
value: await this.note.getContent(),
mode: this.note.mime,
theme: 'default',
lineNumbers: true
});
return $container;
}
}
```
## Widget Composition
### Container Widgets
```typescript
// Flexible container layouts
class FlexContainer extends BasicWidget {
constructor(private direction: 'row' | 'column') {
super();
}
doRender() {
this.$widget = $('
')
.css('display', 'flex')
.css('flex-direction', this.direction);
for (const child of this.children) {
this.$widget.append(child.render());
}
return this.$widget;
}
}
// Tab container
class TabContainer extends BasicWidget {
private tabs: Array<{title: string, widget: BasicWidget}> = [];
addTab(title: string, widget: BasicWidget) {
this.tabs.push({title, widget});
this.child(widget);
return this;
}
doRender() {
// Render tab headers and content panels
}
}
```
### Composite Widgets
```typescript
class NoteEditorWidget extends NoteContextAwareWidget {
private typeWidget: TypeWidget;
private titleWidget: NoteTitleWidget;
private toolbarWidget: NoteToolbarWidget;
constructor() {
super();
this.child(
this.toolbarWidget = new NoteToolbarWidget(),
this.titleWidget = new NoteTitleWidget(),
// Type widget added dynamically
);
}
async refreshWithNote(note: FNote) {
// Remove old type widget
if (this.typeWidget) {
this.typeWidget.remove();
}
// Add appropriate type widget
const WidgetClass = typeWidgetService.getWidgetClass(note.type);
this.typeWidget = new WidgetClass();
this.child(this.typeWidget);
await this.typeWidget.refresh();
}
}
```
## Widget Communication
### Event System
```typescript
// Publishing events
class PublisherWidget extends BasicWidget {
async handleClick() {
// Local event
this.trigger('itemSelected', { itemId: '123' });
// Global event
appContext.triggerEvent('noteChanged', { noteId: this.noteId });
}
}
// Subscribing to events
class SubscriberWidget extends BasicWidget {
constructor() {
super();
// Local event subscription
this.on('itemSelected', (event) => {
console.log('Item selected:', event.itemId);
});
// Global event subscription
appContext.addEventListener('noteChanged', (event) => {
this.handleNoteChange(event.noteId);
});
}
}
```
### Command System
```typescript
// Registering commands
class CommandWidget extends BasicWidget {
constructor() {
super();
this.bindCommand('saveNote', () => this.saveNote());
this.bindCommand('deleteNote', () => this.deleteNote());
}
getCommands() {
return [
{
command: 'myWidget:doAction',
handler: () => this.doAction(),
hotkey: 'ctrl+shift+a'
}
];
}
}
```
## Custom Widget Development
### Creating Custom Widgets
```typescript
// 1. Define widget class
class TaskListWidget extends NoteContextAwareWidget {
doRender() {
this.$widget = $('