Skip to content

Commit

Permalink
fix bug with lyric, dynamics, add duration dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronDavidNewman committed Sep 26, 2024
1 parent d4036ab commit b6e37fb
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 32 deletions.
6 changes: 4 additions & 2 deletions src/application/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ import { SuiLoadMxmlDialog, SuiLoadFileDialog,
SuiSaveMidiDialog, SuiSaveVexDialog } from '../ui/dialogs/fileDialogs';
// Dialog components

import { SuiTextInputComponent, SuiTextInputComposite } from '../ui/dialogs/components/textInput';
import { SuiTextInputComponent, SuiTextInputComposite, SuiReadOnlyTextComponent } from '../ui/dialogs/components/textInput';
import { SuiDropdownComponent, SuiDropdownComposite } from '../ui/dialogs/components/dropdown';
import { SuiButtonComposite, SuiButtonComponent } from '../ui/dialogs/components/button';
import { SuiButtonArrayComponent, SuiButtonArrayMSComponent } from '../ui/dialogs/components/buttonArray';
Expand Down Expand Up @@ -171,6 +171,7 @@ import { SmoToVex } from '../render/vex/toVex';
import { buildDom, addFileLink, InputTrapper, draggable, closeDialogPromise, getDomContainer, createTopDomContainer } from '../common/htmlHelpers';

import { renderVexTests } from './generateVexTests';
import { SuiDurationAdapter, SuiDurationButtonComponent, SuiDurationDialog } from '../ui/dialogs/durations';
const getClass = (jsonString: string) => {
return eval('Smo.' + jsonString);
};
Expand All @@ -193,6 +194,7 @@ export const Smo = {
SuiPartSelectionMenu, SuiTextMenu, SuiVoiceMenu, SuiBeamMenu,
// Dialogs
SuiGraceNoteAdapter, SuiGraceNoteDialog, SuiGraceNoteButtonsComponent,
SuiDurationAdapter, SuiDurationDialog, SuiDurationButtonComponent,
SuiTempoDialog, SuiInstrumentDialog, SuiModifierDialogFactory, SuiLibraryDialog,
SuiTextBracketDialog, SuiKeySignatureDialog, SuiKeySignatureAdapter,
SuiScoreViewDialog, SuiGlobalLayoutDialog, SuiScoreIdentificationDialog, SuiTransposeScoreAdapter,
Expand All @@ -218,7 +220,7 @@ export const Smo = {
SuiToggleComponent, SuiButtonComponent, SuiDropdownComposite,
SuiToggleComposite, SuiButtonComposite, SuiRockerComposite, SuiTextInputComposite,
SuiFontComponent, SuiTextInPlace, SuiLyricComponent, SuiChordComponent, SuiDragText,
SuiNoteTextComponent, SuiTextBlockComponent, SuiTextInputComponent,
SuiNoteTextComponent, SuiTextBlockComponent, SuiTextInputComponent, SuiReadOnlyTextComponent,
SuiDynamicModifierDialog, CheckboxDropdownComponent, TieMappingComponent, StaffAddRemoveComponent,
StaffCheckComponent, TextCheckComponent, SuiArpeggioDialog, SuiClefChangeDialog,
SuiPitchArrayComponent, SuiPitchArrayComponentTab, SuiPitchComponent,
Expand Down
4 changes: 3 additions & 1 deletion src/common/serializationHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,9 @@ export class smoSerialize {
"th": "tabStaves",
"uh": "noteId",
"vh": "tupletId",
"wh": "metadata" }`;
"wh": "metadata",
"xh": "tupletTrees",
"yh": "displayString" }`;
return JSON.parse(_tm);
}

Expand Down
6 changes: 4 additions & 2 deletions src/ui/dialogs/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ export class SuiDialogAdapterBase<T extends SuiComponentAdapter> extends SuiDial
bindComponents() {
this.components.forEach((component) => {
// do some runtime validation of the adapter
if (typeof((this.adapter as any)[component.smoName]) === 'undefined') {
throw ('Dialog ' + this.label + ' has component ' + component.smoName + ' but no setter in the adapter ');
if (!component.noProperty) {
if (typeof((this.adapter as any)[component.smoName]) === 'undefined') {
throw ('Dialog ' + this.label + ' has component ' + component.smoName + ' but no setter in the adapter ');
}
}
component.bind();
});
Expand Down
3 changes: 3 additions & 0 deletions src/ui/dialogs/components/baseComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface SuiBaseComponentParams {
label: string,
smoName: string,
control: string,
noProperty?: boolean,
parentComponent?: SuiComponentParent
}
/**
Expand Down Expand Up @@ -109,6 +110,7 @@ export abstract class SuiComponentBase {
css: string;
dialog: SuiDialogNotifier;
id: string;
noProperty: boolean;
label: string;
control: string;
smoName: string;
Expand All @@ -120,6 +122,7 @@ export abstract class SuiComponentBase {
this.label = parameters.label;
this.control = parameters.control;
this.smoName = parameters.smoName;
this.noProperty = parameters.noProperty ?? false;
}
/**
* Called by the dialog after rendering, so the derived class can
Expand Down
6 changes: 6 additions & 0 deletions src/ui/dialogs/components/textInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,9 @@ export class SuiTextInputComposite extends SuiTextInputComponent {
this.changeFlag = false;
}
}
export class SuiReadOnlyTextComponent extends SuiTextInputComponent {
constructor(dialog: SuiDialogNotifier, parameter: SuiTextInputComponentParams) {
super(dialog, parameter);
this.noProperty = true;
}
}
173 changes: 173 additions & 0 deletions src/ui/dialogs/durations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { SuiScoreViewOperations } from '../../render/sui/scoreViewOperations';
import { buildDom } from '../../common/htmlHelpers';
import { SuiButtonComposite } from './components/button';
import { SuiComponentParent } from './components/baseComponent';
import { DialogDefinition, SuiDialogParams } from './dialog';
import { SuiComponentAdapter, SuiDialogAdapterBase } from './adapter';
import { getButtonsFcn, SuiButtonArrayComponent, SuiButtonArrayParameters } from './components/buttonArray';
import { SuiDialogNotifier, SuiBaseComponentParams } from './components/baseComponent';

export class SuiDurationButtonComponent extends SuiComponentParent {
growDurationComponent: SuiButtonComposite;
lessDurationComponent: SuiButtonComposite;
growDotComponent: SuiButtonComposite;
lessDotComponent: SuiButtonComposite;
constructor(dialog: SuiDialogNotifier, params: SuiBaseComponentParams) {
super(dialog, params);
this.growDurationComponent = new SuiButtonComposite(this.dialog,
{
id: this.id + 'addGraceNote',
smoName: 'growDuration',
parentControl: this,
icon: 'icon-smo ribbon-button-text icon-duration_grow',
classes: 'icon collapseParent button-hotkey',
control: 'SuiButtonComponent',
label: 'Increase Duration',
text: '.'
});
this.lessDurationComponent = new SuiButtonComposite(this.dialog,
{
id: this.id + 'addGraceNote',
smoName: 'lessDuration',
parentControl: this,
icon: 'icon-smo ribbon-button-text icon-duration_less',
classes: 'icon collapseParent button-hotkey',
control: 'SuiButtonComponent',
label: 'Decrease Duration',
text: ','
});
this.growDotComponent = new SuiButtonComposite(this.dialog,
{
id: this.id + 'addGraceNote',
smoName: 'growDot',
parentControl: this,
icon: 'icon-smo ribbon-button-text icon-duration_grow_dot',
classes: 'icon collapseParent button-hotkey',
control: 'SuiButtonComponent',
label: 'Add Dot',
text: '>'
});
this.lessDotComponent = new SuiButtonComposite(this.dialog,
{
id: this.id + 'addGraceNote',
smoName: 'lessDot',
parentControl: this,
icon: 'icon-smo ribbon-button-text icon-duration_less_dot',
classes: 'icon collapseParent button-hotkey',
control: 'SuiButtonComponent',
label: 'Remove Dot',
text: '<'
});
}
getValue(): string {
if (this.growDurationComponent.changeFlag) {
return this.growDurationComponent.smoName;
}
if (this.lessDurationComponent.changeFlag) {
return this.lessDurationComponent.smoName;
}
if (this.growDotComponent.changeFlag) {
return this.growDotComponent.smoName;
}
if (this.lessDotComponent.changeFlag) {
return this.lessDotComponent.smoName;
}
return '';
}
setValue(value: string) {
// ignore
}
async changed() {
this.handleChanged();
}
get html() {
const b = buildDom;
const q = b('div').classes(this.makeClasses('multiControl smoControl buttonArray'))
.attr('id', this.parameterId);
q.append(this.growDurationComponent.html);
q.append(this.lessDurationComponent.html);
q.append(this.growDotComponent.html);
q.append(this.lessDotComponent.html);
return q;
}
bind() {
this.growDurationComponent.bind();
this.lessDurationComponent.bind();
this.lessDotComponent.bind();
this.growDotComponent.bind();
}
}

export class SuiDurationAdapter extends SuiComponentAdapter {
constructor(view: SuiScoreViewOperations) {
super(view);
this.view.groupUndo(true);
}
get durationButtons() {
return '';
}
set durationButtons(value: string) {
if (value === 'growDuration') {
this.view.batchDurationOperation('doubleDuration');
}
if (value === 'lessDuration') {
this.view.batchDurationOperation('halveDuration');
}
if (value === 'growDot') {
this.view.batchDurationOperation('dotDuration');
}
if (value === 'lessDot') {
this.view.batchDurationOperation('undotDuration');
}
}
async cancel() {
await this.view.undo();
}
async commit() {
}
}
export class SuiDurationDialog extends SuiDialogAdapterBase<SuiDurationAdapter> {
static get applyTo() {
return {
score: 0, selected: 1, remaining: 3
};
}
// export type Clef = 'treble' | 'bass' | 'tenor' | 'alto' | 'soprano' | 'percussion'
//| 'mezzo-soprano' | 'baritone-c' | 'baritone-f' | 'subbass' | 'french';
static dialogElements: DialogDefinition =
{
label: 'Duration',
elements:
[{
smoName: 'durationButtons',
control: 'SuiDurationButtonComponent',
label: 'Note Head'
}, {
smoName: 'textMessage',
control: 'SuiReadOnlyTextComponent',
label: 'Use , . to decrease/increase note length.',
classes: 'hide-input'
}, {
smoName: 'textMessage2',
control: 'SuiReadOnlyTextComponent',
label: 'Use <> to add/remove dots.',
classes: 'hide-input'
}, {
smoName: 'textMessage3',
control: 'SuiReadOnlyTextComponent',
label: 'Use shift+arrow navigation keys to select notes',
classes: 'hide-input'
}, {
smoName: 'textMessage4',
control: 'SuiReadOnlyTextComponent',
label: `Learn the keyboard shortcuts, they're much faster!`,
classes: 'hide-input'
}],
staticText: []
};
constructor(parameters: SuiDialogParams) {
const adapter = new SuiDurationAdapter(parameters.view);
super(SuiDurationDialog.dialogElements, { adapter, ...parameters });
this.displayOptions = ['BINDCOMPONENTS', 'DRAGGABLE', 'KEYBOARD_CAPTURE', 'MODIFIERPOS', 'HIDEREMOVE'];
}
}
6 changes: 5 additions & 1 deletion src/ui/dialogs/dynamics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export class SuiDynamicDialogAdapter extends SuiComponentAdapter {
super(view);
this.modifier = modifier;
this.backup = new SmoDynamicText(this.modifier);
this.selection = this.view.tracker.modifierSelections[0].selection!;
if (this.view.tracker.modifierSelections.length) {
this.selection = this.view.tracker.modifierSelections[0].selection!;
} else {
this.selection = this.view.tracker.selections[0];
}
}
async cancel() {
await this.view.addDynamic(this.selection, this.backup);
Expand Down
16 changes: 2 additions & 14 deletions src/ui/dialogs/gracenote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,6 @@ export class SuiGraceNoteAdapter extends SuiComponentAdapter {
this.view.slashGraceNotes();
}
}
set textLabel(value: string) {
// ignore
}
get textLabel() {
return '';
}
set textLabelSelect(value: string) {
// ignore
}
get textLabelSelect() {
return '';
}
async commit() {
await this.view.renderPromise();
}
Expand All @@ -128,12 +116,12 @@ export class SuiGraceNoteDialog extends SuiDialogAdapterBase<SuiGraceNoteAdapter
label: 'Add/Remove Grace notes'
}, {
smoName: 'textLabel',
control: 'SuiTextInputComponent',
control: 'SuiReadOnlyTextComponent',
label: 'Use hot keys shift-G to add grace notes, alt-g to remove.',
classes: 'hide-input'
}, {
smoName: 'textLabelSelect',
control: 'SuiTextInputComponent',
control: 'SuiReadOnlyTextComponent',
label: 'Use hot key alt-l to select grace notes for pitches, durations',
classes: 'hide-input'
}],
Expand Down
8 changes: 1 addition & 7 deletions src/ui/dialogs/noteHead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,6 @@ export class SuiNoteHeadAdapter extends SuiComponentAdapter {
this.code = keys[0];
}
}
get textMessage() {
return '';
}
set textMessage(value: string) {
// ignore
}
get stemComponent() {
return this.stemCode;
}
Expand Down Expand Up @@ -288,7 +282,7 @@ export class SuiNoteHeadDialog extends SuiDialogAdapterBase<SuiNoteHeadAdapter>
label: 'Rest'
}, {
smoName: 'textMessage',
control: 'SuiTextInputComponent',
control: 'SuiReadOnlyTextComponent',
label: 'Use r to toggle note to rest. Use delete to toggle visibility.',
classes: 'hide-input'
}],
Expand Down
23 changes: 22 additions & 1 deletion src/ui/menus/note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {SuiArpeggioDialog } from '../dialogs/arpeggio';
import { SuiClefChangeDialog } from '../dialogs/clefChange';
import { SuiNoteHeadDialog } from '../dialogs/noteHead';
import { SuiOrnamentDialog } from '../dialogs/ornament';
import { SuiDurationDialog } from '../dialogs/durations';
import { SuiArticulationDialog } from '../dialogs/articulation';
import { SuiGraceNoteDialog } from '../dialogs/gracenote';
import { SuiMicrotoneDialog } from '../dialogs/microtones';
Expand Down Expand Up @@ -164,6 +165,25 @@ const ornamentNoteDialogMenuOption: SuiConfiguredMenuOption = {
value: 'ornamentDialog'
}
}
const durationDialogMenuOption: SuiConfiguredMenuOption = {
handler: async (menu: SuiMenuBase) => {
createAndDisplayDialog(SuiDurationDialog, {
view: menu.view,
completeNotifier: menu.completeNotifier,
startPromise: menu.closePromise,
eventSource: menu.eventSource,
tracker: menu.tracker,
ctor: 'SuiDurationDialog',
id: 'duration-dialog',
modifier: null
});
}, display: (menu: SuiMenuBase) => true,
menuChoice: {
icon: '',
text: 'Durations',
value: 'durationDialog'
}
}
const articulationNoteDialogMenuOption: SuiConfiguredMenuOption = {
handler: async (menu: SuiMenuBase) => {
createAndDisplayDialog(SuiArticulationDialog, {
Expand Down Expand Up @@ -206,5 +226,6 @@ const SuiNoteMenuOptions: SuiConfiguredMenuOption[] = [
toggleCueMenuOption, arpeggioMenuOption, clefNoteDialogMenuOption,
graceNotesMenuOption,
noteHeadMenuOption, ornamentNoteDialogMenuOption,
articulationNoteDialogMenuOption, microtoneNoteDialogMenuOption, togglePedalRelease
articulationNoteDialogMenuOption,
microtoneNoteDialogMenuOption, togglePedalRelease, durationDialogMenuOption
];
5 changes: 1 addition & 4 deletions src/ui/menus/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ const chordChangeDialogMenuOption: SuiConfiguredMenuOption = {
}
const lyricsDialogMenuOption: SuiConfiguredMenuOption = {
handler: async (menu: SuiMenuBase) => {
if (menu.closePromise) {
await menu.closePromise;
}
const sel = menu.view.tracker.selections[0];
const note = sel.note;
if (!note) {
Expand All @@ -99,7 +96,7 @@ const lyricsDialogMenuOption: SuiConfiguredMenuOption = {
menuChoice: {
icon: '',
text: 'Lyrics',
value: 'lyricDialog'
value: 'lyricMenu'
}
}
const dynamicsDialogMenuOption: SuiConfiguredMenuOption = {
Expand Down

0 comments on commit b6e37fb

Please sign in to comment.