UNPKG

@eclipse-scout/core

Version:
118 lines (100 loc) 4.54 kB
/* * Copyright (c) 2010, 2023 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 {Dimension, graphics, HtmlComponent, HtmlCompPrefSizeOptions, HtmlEnvironment, PopupLayout, SmartFieldPopup} from '../../../index'; /** * The popup layout is different from other layouts, since it can determine its own size * when the autoSize flag is set to true. Otherwise it uses the given size, like a regular * layout. The autoSize feature is used, when a child of the SmartFieldPopupLayout invalidates the * tree up to the popup. Since the popup is a validate root it must re-layout itself. * However: the size of the popup depends on the field it belongs to. * * The proposal-chooser DIV is not always present. */ export class SmartFieldPopupLayout extends PopupLayout { declare popup: SmartFieldPopup<any>; animating: boolean; constructor(popup: SmartFieldPopup<any>) { super(popup); this.animating = false; this.doubleCalcPrefSize = false; } override layout($container: JQuery) { let size, popupSize, htmlProposalChooser = this._htmlProposalChooser(); // skip layout while CSS animation is running (prefSize would not work while animation is running) if (this.animating) { this.popup.htmlComp.$comp.oneAnimationEnd(() => { this.popup.revalidateLayout(); }); return; } super.layout($container); popupSize = this.popup.htmlComp.size(); size = popupSize.subtract(this.popup.htmlComp.insets()); htmlProposalChooser.setSize(size); if (this.popup.htmlComp.layouted) { // Reposition because opening direction may have to be switched if popup gets bigger // Don't do it the first time (will be done by popup.open), only if the popup is already // open and gets layouted again this.popup.position(); } else if (SmartFieldPopup.hasPopupAnimation()) { // This code here is a bit complicated because: // 1. we must position the scrollTo position before we start the animation // because it looks ugly, when we jump to the scroll position after the // animation has ended // 2. we must first layout the popup with the table/tree correctly because // revealSelection doesn't work when popup has not the right size or is // not visible. That's why we must set the visibility to hidden. // 3. we wait for the layout validator until the popup layout is validated // which means the scroll position is set correctly. Then we make the // popup visible again and start the animation (which shrinks the popup // to 1px height initially. this.animating = true; this.popup.htmlComp.$comp.css('visibility', 'hidden'); this.popup.session.layoutValidator.schedulePostValidateFunction(() => { this.popup.htmlComp.$comp.css('visibility', ''); this.popup.htmlComp.$comp.addClassForAnimation('animate-open'); this.popup.htmlComp.$comp.oneAnimationEnd(() => { this.animating = false; this.popup._onAnimationEnd(); }); }); } } override preferredLayoutSize($container: JQuery, options?: HtmlCompPrefSizeOptions): Dimension { let prefSize, htmlProposalChooser = this._htmlProposalChooser(), fieldBounds = graphics.offsetBounds(this.popup.smartField.$field); if (htmlProposalChooser) { prefSize = htmlProposalChooser.prefSize(options); prefSize = prefSize.add(this.popup.htmlComp.insets()); } else { prefSize = new Dimension( HtmlEnvironment.get().formColumnWidth, HtmlEnvironment.get().formRowHeight * 2); } prefSize.width = Math.max(fieldBounds.width, prefSize.width); prefSize.height = Math.max(15, Math.min(350, prefSize.height)); // at least some pixels height in case there is no data, no status, no active filter if (prefSize.width > this._maxWindowSize()) { prefSize.width = this._maxWindowSize(); } return prefSize; } protected _htmlProposalChooser(): HtmlComponent { let proposalChooser = this.popup.proposalChooser; if (!proposalChooser) { return null; } return proposalChooser.htmlComp; } protected _maxWindowSize(): number { return this.popup.$container.window().width() - (2 * this.popup.windowPaddingX); } }