import NoteContextAwareWidget from "../note_context_aware_widget.js"; import keyboardActionsService from "../../services/keyboard_actions.js"; import attributeService from "../../services/attributes.js"; const TPL = `
`; export default class RibbonContainer extends NoteContextAwareWidget { constructor() { super(); this.contentSized(); this.ribbonWidgets = []; this.buttonWidgets = []; } ribbon(widget) { super.child(widget); this.ribbonWidgets.push(widget); return this; } button(widget) { super.child(widget); this.buttonWidgets.push(widget); return this; } doRender() { this.$widget = $(TPL); this.$tabContainer = this.$widget.find('.ribbon-tab-container'); this.$buttonContainer = this.$widget.find('.ribbon-button-container'); this.$bodyContainer = this.$widget.find('.ribbon-body-container'); for (const ribbonWidget of this.ribbonWidgets) { this.$bodyContainer.append( $('
') .attr('data-ribbon-component-id', ribbonWidget.componentId) .append(ribbonWidget.render()) ); } for (const buttonWidget of this.buttonWidgets) { this.$buttonContainer.append(buttonWidget.render()); } this.$tabContainer.on('click', '.ribbon-tab-title', e => { const $ribbonTitle = $(e.target).closest('.ribbon-tab-title'); this.toggleRibbonTab($ribbonTitle); }); } toggleRibbonTab($ribbonTitle, refreshActiveTab = true) { const activate = !$ribbonTitle.hasClass("active"); this.$tabContainer.find('.ribbon-tab-title').removeClass("active"); this.$bodyContainer.find('.ribbon-body').removeClass("active"); if (activate) { const ribbonComponendId = $ribbonTitle.attr('data-ribbon-component-id'); const wasAlreadyActive = this.lastActiveComponentId === ribbonComponendId; this.lastActiveComponentId = ribbonComponendId; this.$tabContainer.find(`.ribbon-tab-title[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active"); this.$bodyContainer.find(`.ribbon-body[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active"); const activeChild = this.getActiveRibbonWidget(); if (activeChild && (refreshActiveTab || !wasAlreadyActive)) { activeChild.handleEvent('noteSwitched', {noteContext: this.noteContext, notePath: this.notePath}); } } else { this.lastActiveComponentId = null; } } async refreshWithNote(note, noExplicitActivation = false) { this.lastNoteType = note.type; let $ribbonTabToActivate, $lastActiveRibbon; this.$tabContainer.empty(); for (const ribbonWidget of this.ribbonWidgets) { const ret = ribbonWidget.getTitle(note); if (!ret.show) { continue; } const $ribbonTitle = $('
') .attr('data-ribbon-component-id', ribbonWidget.componentId) .attr('data-ribbon-component-name', ribbonWidget.name) .append($('') .addClass(ret.icon) .attr("data-title", ret.title) .attr('data-toggle-command', ribbonWidget.toggleCommand)) .append(" ") .append($('').text(ret.title)); this.$tabContainer.append($ribbonTitle); this.$tabContainer.append('
'); if (ret.activate && !this.lastActiveComponentId && !$ribbonTabToActivate && !noExplicitActivation) { $ribbonTabToActivate = $ribbonTitle; } if (this.lastActiveComponentId === ribbonWidget.componentId) { $lastActiveRibbon = $ribbonTitle; } } keyboardActionsService.getActions().then(actions => { this.$tabContainer.find('.ribbon-tab-title-icon').tooltip({ title: function() { const toggleCommandName = $(this).attr("data-toggle-command"); const action = actions.find(act => act.actionName === toggleCommandName); const title = $(this).attr("data-title"); if (action && action.effectiveShortcuts.length > 0) { return `${title} (${action.effectiveShortcuts.join(", ")})`; } else { return title; } } }); }); if (!$ribbonTabToActivate) { $ribbonTabToActivate = $lastActiveRibbon; } if ($ribbonTabToActivate) { this.toggleRibbonTab($ribbonTabToActivate, false); } else { this.$bodyContainer.find('.ribbon-body').removeClass("active"); } } isRibbonTabActive(name) { const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`); return $ribbonComponent.hasClass("active"); } ensureOwnedAttributesAreOpen(ntxId) { if (this.isNoteContext(ntxId) && !this.isRibbonTabActive('ownedAttributes')) { this.toggleRibbonTabWithName('ownedAttributes', ntxId); } } addNewLabelEvent({ntxId}) { this.ensureOwnedAttributesAreOpen(ntxId); } addNewRelationEvent({ntxId}) { this.ensureOwnedAttributesAreOpen(ntxId); } toggleRibbonTabWithName(name, ntxId) { if (!this.isNoteContext(ntxId)) { return false; } const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`); if ($ribbonComponent) { this.toggleRibbonTab($ribbonComponent); } } handleEvent(name, data) { const PREFIX = "toggleRibbonTab"; if (name.startsWith(PREFIX)) { let componentName = name.substr(PREFIX.length); componentName = componentName[0].toLowerCase() + componentName.substr(1); this.toggleRibbonTabWithName(componentName, data.ntxId); } else { return super.handleEvent(name, data); } } async handleEventInChildren(name, data) { if (['activeContextChanged', 'setNoteContext'].includes(name)) { // won't trigger .refresh(); await super.handleEventInChildren('setNoteContext', data); } else if (this.isEnabled() || name === 'initialRenderComplete') { const activeRibbonWidget = this.getActiveRibbonWidget(); // forward events only to active ribbon tab, inactive ones don't need to be updated if (activeRibbonWidget) { await activeRibbonWidget.handleEvent(name, data); } for (const buttonWidget of this.buttonWidgets) { await buttonWidget.handleEvent(name, data); } } } entitiesReloadedEvent({loadResults}) { if (loadResults.isNoteReloaded(this.noteId) && this.lastNoteType !== this.note.type) { // note type influences the list of available ribbon tabs the most // check for type is so that we don't update on each title rename this.lastNoteType = this.note.type; this.refresh(); } else if (loadResults.getAttributes(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) { this.refreshWithNote(this.note, true); } } getActiveRibbonWidget() { return this.ribbonWidgets.find(ch => ch.componentId === this.lastActiveComponentId) } }