UNPKG

@eclipse-scout/core

Version:
271 lines (235 loc) 9.61 kB
/* * Copyright (c) 2010, 2025 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import { App, Desktop, DesktopCancelFormsEvent, DesktopFormActivateEvent, DesktopHistoryState, DesktopNotification, DisplayParent, Event, FileChooser, FileChooserAdapter, Form, FormAdapter, MessageBox, MessageBoxAdapter, ModelAdapter, objects, Outline, RemoteEvent, Widget } from '../index'; import $ from 'jquery'; export class DesktopAdapter extends ModelAdapter { declare widget: Desktop; constructor() { super(); this._addRemoteProperties(['benchVisible', 'navigationVisible', 'navigationHandleVisible', 'headerVisible', 'geolocationServiceAvailable', 'inBackground', 'focusedElement']); } protected override _goOffline() { this.widget.goOffline(); } protected override _goOnline() { this.widget.goOnline(); } protected _onWidgetHistoryEntryActivate(event: Event & DesktopHistoryState) { this._send('historyEntryActivate', { deepLinkPath: event.deepLinkPath }); } protected _onWidgetRender(event: Event<Desktop>) { this._send('desktopReady'); } protected _onWidgetFormActivate(event: DesktopFormActivateEvent) { if (event.form && !ModelAdapter.getModelAdapterForWidget(event.form, true)) { return; // Ignore ScoutJS forms } this._sendFormActivate(event.form); } protected _sendFormActivate(form: Form) { let eventData = { formId: ModelAdapter.getModelAdapterForWidget(form, true)?.id }; this._send('formActivate', eventData, { coalesce: function(previous) { // Do not coalesce if formId was set to null by the previous event, // this is the only way the server knows that the desktop was brought to front return this.target === previous.target && this.type === previous.type && !(!previous.formId && this.formId); } }); } protected override _prepareRemoteProperty(propertyName: string, value: any): any { if (propertyName === 'focusedElement') { return value; } return super._prepareRemoteProperty(propertyName, value); } protected _sendFocusedElement(focusedElement: Widget) { // Find the nearest widget with a model adapter while (focusedElement && !focusedElement.modelAdapter) { focusedElement = focusedElement.parent; } this._sendProperty('focusedElement', focusedElement ? focusedElement.id : null); } protected _logoAction(event: Event) { this._send('logoAction'); } protected override _onWidgetEvent(event: Event<Desktop>) { if (event.type === 'formActivate') { this._onWidgetFormActivate(event as DesktopFormActivateEvent); } else if (event.type === 'historyEntryActivate') { this._onWidgetHistoryEntryActivate(event as Event<Desktop> & DesktopHistoryState); } else if (event.type === 'logoAction') { this._logoAction(event); } else if (event.type === 'cancelForms') { this._onWidgetCancelAllForms(event as DesktopCancelFormsEvent); } else if (event.type === 'render') { this._onWidgetRender(event); } else { super._onWidgetEvent(event); } } protected _onFormShow(event: RemoteEvent) { let displayParent = this.session.getModelAdapter(event.displayParent); if (displayParent) { let form = this.session.getOrCreateWidget(event.form, displayParent.widget) as Form; form.setDisplayParent(displayParent.widget as DisplayParent); let hasPendingFormActivateEvent = this.session.asyncEvents.some(event => event.type === 'formActivate' && event.target === this.id); if (!hasPendingFormActivateEvent) { this.addFilterForWidgetEvent(widgetEvent => widgetEvent.type === 'formActivate' && (widgetEvent as DesktopFormActivateEvent).form === form); } this.widget.showForm(form, event.position); } } protected _onFormHide(event: RemoteEvent) { let displayParent = this.session.getModelAdapter(event.displayParent); if (displayParent) { let form = this.session.getModelAdapter(event.form) as FormAdapter; this.widget.hideForm(form.widget); } } protected _onFormActivate(event: RemoteEvent) { let form = this.session.getWidget(event.form) as Form; this.widget.activateForm(form); } protected _onWidgetCancelAllForms(event: DesktopCancelFormsEvent) { const formIds: string[] = []; const jsForms: Form[] = []; for (const form of event.forms || []) { if (form.modelAdapter) { formIds.push(form.modelAdapter.id); } else { jsForms.push(form); } } if (!formIds.length) { // no remote forms, return without preventDefault // this will cancel the js forms implicitly return; } event.preventDefault(); // cancel all js forms first let cancelJsForms: JQuery.Promise<void> = $.resolvedPromise(); if (jsForms.length) { cancelJsForms = this.widget.cancelViews(jsForms); } // cancel remote forms after js forms are canceled (i.e. the promise was resolved) or the js-form-cancellation was cancelled (i.e. the promise was rejected) if (formIds.length) { cancelJsForms.always(() => this._send('cancelForms', {formIds})); } } protected _onMessageBoxShow(event: RemoteEvent) { let displayParent = this.session.getModelAdapter(event.displayParent); if (displayParent) { let messageBox = this.session.getOrCreateWidget(event.messageBox, displayParent.widget) as MessageBox; let parent = displayParent.widget as DisplayParent; messageBox.setDisplayParent(parent); parent.messageBoxController.registerAndRender(messageBox); } } protected _onMessageBoxHide(event: RemoteEvent) { let displayParent = this.session.getModelAdapter(event.displayParent); if (displayParent) { let messageBox = this.session.getModelAdapter(event.messageBox) as MessageBoxAdapter; let parent = displayParent.widget as DisplayParent; parent.messageBoxController.unregisterAndRemove(messageBox.widget); } } protected _onFileChooserShow(event: RemoteEvent) { let displayParent = this.session.getModelAdapter(event.displayParent); if (displayParent) { let parent = displayParent.widget as DisplayParent; let fileChooser = this.session.getOrCreateWidget(event.fileChooser, parent) as FileChooser; fileChooser.setDisplayParent(parent); parent.fileChooserController.registerAndRender(fileChooser); } } protected _onFileChooserHide(event: RemoteEvent) { let displayParent = this.session.getModelAdapter(event.displayParent); if (displayParent) { let fileChooser = this.session.getModelAdapter(event.fileChooser) as FileChooserAdapter; let parent = displayParent.widget as DisplayParent; parent.fileChooserController.unregisterAndRemove(fileChooser.widget); } } protected _onOpenUri(event: RemoteEvent) { this.widget.openUri(event.uri, event.action); } protected _onOutlineChanged(event: RemoteEvent) { let outline = this.session.getOrCreateWidget(event.outline, this.widget) as Outline; this.widget.setOutline(outline); } protected _onAddNotification(event: RemoteEvent) { let notification = this.session.getOrCreateWidget(event.notification, this.widget) as DesktopNotification; this.widget.addNotification(notification); } protected _onRemoveNotification(event: RemoteEvent) { this.widget.removeNotification(event.notification); } protected _onOutlineContentActivate(event: RemoteEvent) { this.widget.bringOutlineToFront(); } override onModelAction(event: RemoteEvent) { if (event.type === 'formShow') { this._onFormShow(event); } else if (event.type === 'formHide') { this._onFormHide(event); } else if (event.type === 'formActivate') { this._onFormActivate(event); } else if (event.type === 'messageBoxShow') { this._onMessageBoxShow(event); } else if (event.type === 'messageBoxHide') { this._onMessageBoxHide(event); } else if (event.type === 'fileChooserShow') { this._onFileChooserShow(event); } else if (event.type === 'fileChooserHide') { this._onFileChooserHide(event); } else if (event.type === 'openUri') { this._onOpenUri(event); } else if (event.type === 'outlineChanged') { this._onOutlineChanged(event); } else if (event.type === 'outlineContentActivate') { this._onOutlineContentActivate(event); } else if (event.type === 'addNotification') { this._onAddNotification(event); } else if (event.type === 'removeNotification') { this._onRemoveNotification(event); } else { super.onModelAction(event); } } /** * Static method to modify the prototype of Desktop. */ static modifyDesktopPrototype() { if (!App.get().remote) { return; } objects.replacePrototypeFunction(Desktop, '_initTheme', DesktopAdapter._initTheme, true); } static _initTheme(this: Desktop & { _initThemeOrig; _activeTheme }) { if (this.modelAdapter) { // Write the active theme (defined by the UI server) to the desktop widget this.setTheme(this._activeTheme()); } else { this._initThemeOrig(); } } } export interface FormWithModelAdapterId extends Form { __modelAdapterId?: string; } App.addListener('bootstrap', DesktopAdapter.modifyDesktopPrototype);