UNPKG

smoosic

Version:

<sub>[Github site](https://github.com/Smoosic/smoosic) | [source documentation](https://smoosic.github.io/Smoosic/release/docs/modules.html) | [change notes](https://aarondavidnewman.github.io/Smoosic/changes.html) | [application](https://smoosic.github.i

306 lines (290 loc) 10.1 kB
// [Smoosic](https://github.com/AaronDavidNewman/Smoosic) // Copyright (c) Aaron David Newman 2021. import { SuiLyricSession, SuiChordSession } from '../../../render/sui/textEdit'; import { SuiInlineText } from '../../../render/sui/textRender'; import { KeyEvent } from '../../../smo/data/common'; import { buildDom } from '../../../common/htmlHelpers'; import { SuiScoreViewOperations } from '../../../render/sui/scoreViewOperations'; import { SmoSelection, SmoSelector } from '../../../smo/xform/selections'; import { BrowserEventSource } from '../../eventSource'; import { SuiComponentBase, SuiDialogNotifier } from './baseComponent'; import { SmoLyric } from '../../../smo/data/noteModifiers'; declare var $: any; /** * @category SuiDialog */ export interface SuiNoteTextParams { id: string, classes: string, label: string, smoName: string, control: string, verse?: number } /** * Base class for text editor components that navigate to * different notes. * This has the text editing dialog components for notes, such as lyrics. * Unlike components that are * actual dialog controls, these actually run a text editing session of some kind. * * The heirarchy of text editing objects goes: * dialog -> component -> session -> editor * * ### editor * handles low-level events and renders the preview using one * of the text layout objects. * * ### session * creates and destroys editors, e.g. for lyrics that have a Different * editor instance for each note. * * ### component * is defined in the dialog, and creates/destroys the session based on input from * the dialog * * ### dialog * manages the coponent session, as well as other components of the text like font etc. * @category SuiDialog * */ export abstract class SuiNoteTextComponent extends SuiComponentBase { view: SuiScoreViewOperations; selection: SmoSelection; selector: SmoSelector; eventSource: BrowserEventSource; session: SuiLyricSession | null = null; value: SmoLyric | null = null; started: boolean = false; staticText: Record<string, string>; constructor(dialog: SuiDialogNotifier, parameter: SuiNoteTextParams) { super(dialog, parameter); this.view = this.dialog.getView(); this.eventSource = this.dialog.getEventSource(); this.selection = this.view.tracker.selections[0]; this.selector = JSON.parse(JSON.stringify(this.selection.selector)); this.staticText = this.dialog.getStaticText(); } abstract startEditSession(): void; abstract endSession(): void; mouseMove(ev: any) { if (this.session && this.session.isRunning) { this.session.handleMouseEvent(ev); } } show() {} hide() {} mouseClick(ev: any) { if (this.session && this.session.isRunning) { this.session.handleMouseEvent(ev); } } _getInputElement() { var pid = this.parameterId; return $(this.dialog.dgDom.element).find('#' + pid).find('button'); } get running() { return this.session && this.session.isRunning; } async evKey(evdata: KeyEvent): Promise<boolean> { if (this.session) { return await this.session.evKey(evdata); } return false; } setDialogLyric() { if (this.session && this.session.lyric) { (this.dialog as any).setLyric(this.selector, this.session.lyric); } } async moveSelectionRight() { if (this.session) { await this.session.advanceSelection(false); this.setDialogLyric(); } } async moveSelectionLeft() { if (this.session) { this.session.advanceSelection(true); this.setDialogLyric(); } } async removeText() { if (this.session) { await this.session.removeLyric(); } } async _bind() { $(this._getInputElement()).off('click').on('click', async () => { if (this.session && this.session.isRunning) { this.endSession(); } else { this.startEditSession(); } }); $('#' + this.parameterId + '-left').off('click').on('click', async () => { await this.moveSelectionLeft(); }); $('#' + this.parameterId + '-right').off('click').on('click', async () => { await this.moveSelectionRight(); }); $('#' + this.parameterId + '-remove').off('click').on('click', async () => { await this.removeText(); }); } getValue() { return this.value; } } /** * manage a lyric session that moves from note to note and adds lyrics. * @category SuiDialog **/ export class SuiLyricComponent extends SuiNoteTextComponent { altLabel: string; verse: number; constructor(dialog: SuiDialogNotifier, parameter: SuiNoteTextParams) { super(dialog, parameter); this.altLabel = this.staticText.doneEditing; this.started = false; this.verse = parameter.verse ?? 0; } get html() { var b = buildDom; var id = this.parameterId; var r = b('div').classes(this.makeClasses('cbLyricEdit smoControl')).attr('id', this.parameterId).attr('data-param', this.smoName) .append(b('div').classes('toggleEdit') .append(b('button').classes('toggleTextEdit') .attr('id', id + '-toggleInput').append( b('span').classes('icon icon-pencil'))).append( b('label').attr('for', id + '-toggleInput').text(this.label))) .append(b('div').classes('show-when-editing') .append(b('span') .append( b('button').attr('id', id + '-left').classes('icon-arrow-left buttonComponent'))) .append(b('span') .append( b('button').attr('id', id + '-right').classes('icon-arrow-right buttonComponent'))) .append(b('span') .append( b('button').attr('id', id + '-remove').classes('icon-cross buttonComponent'))) ); return r; } async endSession() { this.started = false; console.log('ending text session'); $(this._getInputElement()).find('label').text(this.label); const button = document.getElementById(this.parameterId); $(button).find('span.icon').removeClass('icon-checkmark').addClass('icon-pencil'); if (this.session) { this.session.stopSession(); } $('body').removeClass('text-edit'); } startEditSession() { $(this._getInputElement()).find('label').text(this.altLabel); console.log('starting text session'); if (this.started) { return; } // this.textElement=$(this.dialog.layout.svg).find('.'+modifier.attrs.id)[0]; this.session = new SuiLyricSession({ renderer: this.view.renderer, selector: this.selector, scroller: this.view.tracker.scroller, verse: this.verse, score: this.view.score, view: this.view } ); this.started = true; $('body').addClass('text-edit'); const button = document.getElementById(this.parameterId); $(button).find('span.icon').removeClass('icon-pencil').addClass('icon-checkmark'); this.session.startSession(); this.setDialogLyric(); } bind() { this._bind(); } } /** * manage a chord editing session that moves from note to note and adds chord symbols. * @category SuiDialog */ export class SuiChordComponent extends SuiNoteTextComponent { altLabel: string; verse: number; constructor(dialog: SuiDialogNotifier, parameter: SuiNoteTextParams) { super(dialog, parameter); this.session = null; this.dialog = dialog; this.selection = this.view.tracker.selections[0]; this.selector = JSON.parse(JSON.stringify(this.selection.selector)); this.altLabel = this.staticText.doneEditing; this.verse = 0; } get html() { const b = buildDom; const id = this.parameterId; const r = b('div').classes(this.makeClasses('cbChordEdit smoControl')).attr('id', this.parameterId).attr('data-param', this.smoName) .append(b('div').classes('toggleEdit') .append(b('button').classes('toggleTextEdit') .attr('id', id + '-toggleInput').append( b('span').classes('icon icon-pencil'))).append( b('label').attr('for', id + '-toggleInput').text(this.label))) .append(b('div').classes('show-when-editing') .append(b('span') .append( b('button').attr('id', id + '-left').classes('icon-arrow-left buttonComponent'))) .append(b('span') .append( b('button').attr('id', id + '-right').classes('icon-arrow-right buttonComponent'))) .append(b('span') .append( b('button').attr('id', id + '-remove').classes('icon-cross buttonComponent'))) ); return r; } endSession() { $(this._getInputElement()).find('label').text(this.label); const button = document.getElementById(this.parameterId); $(button).find('span.icon').removeClass('icon-checkmark').addClass('icon-pencil'); if (this.session) { this.session.stopSession(); } $('body').removeClass('text-edit'); } startEditSession() { $(this._getInputElement()).find('label').text(this.altLabel); // this.textElement=$(this.dialog.layout.svg).find('.'+modifier.attrs.id)[0]; this.session = new SuiChordSession({ renderer: this.view.renderer, selector: this.selector, scroller: this.view.tracker.scroller, verse: 0, view: this.view, score: this.view.score } ); $('body').addClass('text-edit'); const button = document.getElementById(this.parameterId); $(button).find('span.icon').removeClass('icon-pencil').addClass('icon-checkmark'); this.session.startSession(); this.setDialogLyric(); } bind() { this._bind(); } setTextType(type: string | number) { if (this.session) { this.session.textType = parseInt(type.toString(), 10); } } getTextType() { if (this.session) { return this.session.textType; } return SuiInlineText.textTypes.normal; } }