mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
feat(core): flexibility using multiple RootLayouts (#10684)
This commit is contained in:

committed by
GitHub

parent
79a0306f32
commit
4b87a35e51
2
packages/core/ui/layouts/index.d.ts
vendored
2
packages/core/ui/layouts/index.d.ts
vendored
@ -2,7 +2,7 @@ export { AbsoluteLayout } from './absolute-layout';
|
|||||||
export { DockLayout } from './dock-layout';
|
export { DockLayout } from './dock-layout';
|
||||||
export { FlexboxLayout } from './flexbox-layout';
|
export { FlexboxLayout } from './flexbox-layout';
|
||||||
export { GridLayout, GridUnitType, ItemSpec } from './grid-layout';
|
export { GridLayout, GridUnitType, ItemSpec } from './grid-layout';
|
||||||
export { RootLayout, getRootLayout, RootLayoutOptions, ShadeCoverOptions } from './root-layout';
|
export { RootLayout, getRootLayout, getRootLayoutById, RootLayoutOptions, ShadeCoverOptions } from './root-layout';
|
||||||
export { StackLayout } from './stack-layout';
|
export { StackLayout } from './stack-layout';
|
||||||
export { WrapLayout } from './wrap-layout';
|
export { WrapLayout } from './wrap-layout';
|
||||||
export { LayoutBase } from './layout-base';
|
export { LayoutBase } from './layout-base';
|
||||||
|
@ -2,7 +2,7 @@ export { AbsoluteLayout } from './absolute-layout';
|
|||||||
export { DockLayout } from './dock-layout';
|
export { DockLayout } from './dock-layout';
|
||||||
export { FlexboxLayout } from './flexbox-layout';
|
export { FlexboxLayout } from './flexbox-layout';
|
||||||
export { GridLayout, GridUnitType, ItemSpec } from './grid-layout';
|
export { GridLayout, GridUnitType, ItemSpec } from './grid-layout';
|
||||||
export { RootLayout, getRootLayout } from './root-layout';
|
export { RootLayout, getRootLayout, getRootLayoutById } from './root-layout';
|
||||||
export type { RootLayoutOptions, ShadeCoverOptions } from './root-layout';
|
export type { RootLayoutOptions, ShadeCoverOptions } from './root-layout';
|
||||||
export { StackLayout } from './stack-layout';
|
export { StackLayout } from './stack-layout';
|
||||||
export { WrapLayout } from './wrap-layout';
|
export { WrapLayout } from './wrap-layout';
|
||||||
|
@ -8,10 +8,6 @@ import { LinearGradient } from '../../styling/linear-gradient';
|
|||||||
export * from './root-layout-common';
|
export * from './root-layout-common';
|
||||||
|
|
||||||
export class RootLayout extends RootLayoutBase {
|
export class RootLayout extends RootLayoutBase {
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
insertChild(view: View, atIndex: number): void {
|
insertChild(view: View, atIndex: number): void {
|
||||||
super.insertChild(view, atIndex);
|
super.insertChild(view, atIndex);
|
||||||
if (!view.hasGestureObservers()) {
|
if (!view.hasGestureObservers()) {
|
||||||
|
@ -16,6 +16,7 @@ export class RootLayout extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getRootLayout(): RootLayout;
|
export function getRootLayout(): RootLayout;
|
||||||
|
export function getRootLayoutById(id: string): RootLayout;
|
||||||
|
|
||||||
export interface RootLayoutOptions {
|
export interface RootLayoutOptions {
|
||||||
shadeCover?: ShadeCoverOptions;
|
shadeCover?: ShadeCoverOptions;
|
||||||
|
@ -8,16 +8,19 @@ import { parseLinearGradient } from '../../../css/parser';
|
|||||||
export * from './root-layout-common';
|
export * from './root-layout-common';
|
||||||
|
|
||||||
export class RootLayout extends RootLayoutBase {
|
export class RootLayout extends RootLayoutBase {
|
||||||
|
nativeViewProtected: UIView;
|
||||||
|
|
||||||
// perf optimization: only create and insert gradients if settings change
|
// perf optimization: only create and insert gradients if settings change
|
||||||
private _currentGradient: string;
|
private _currentGradient: string;
|
||||||
private _gradientLayer: CAGradientLayer;
|
private _gradientLayer: CAGradientLayer;
|
||||||
|
|
||||||
constructor() {
|
public disposeNativeView(): void {
|
||||||
super();
|
super.disposeNativeView();
|
||||||
|
this._cleanupPlatformShadeCover();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _bringToFront(view: View) {
|
protected _bringToFront(view: View) {
|
||||||
(<UIView>this.nativeViewProtected).bringSubviewToFront(view.nativeViewProtected);
|
this.nativeViewProtected.bringSubviewToFront(view.nativeViewProtected);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _initShadeCover(view: View, shadeOptions: ShadeCoverOptions): void {
|
protected _initShadeCover(view: View, shadeOptions: ShadeCoverOptions): void {
|
||||||
@ -46,7 +49,11 @@ export class RootLayout extends RootLayoutBase {
|
|||||||
iosViewUtils.drawGradient(view.nativeViewProtected, this._gradientLayer, LinearGradient.parse(parsedGradient.value));
|
iosViewUtils.drawGradient(view.nativeViewProtected, this._gradientLayer, LinearGradient.parse(parsedGradient.value));
|
||||||
view.nativeViewProtected.layer.insertSublayerAtIndex(this._gradientLayer, 0);
|
view.nativeViewProtected.layer.insertSublayerAtIndex(this._gradientLayer, 0);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Dispose gradient if new color is null or a plain color
|
||||||
|
this._cleanupPlatformShadeCover();
|
||||||
}
|
}
|
||||||
|
|
||||||
UIView.animateWithDurationAnimationsCompletion(
|
UIView.animateWithDurationAnimationsCompletion(
|
||||||
duration,
|
duration,
|
||||||
() => {
|
() => {
|
||||||
@ -66,7 +73,7 @@ export class RootLayout extends RootLayoutBase {
|
|||||||
},
|
},
|
||||||
(completed: boolean) => {
|
(completed: boolean) => {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -87,7 +94,7 @@ export class RootLayout extends RootLayoutBase {
|
|||||||
},
|
},
|
||||||
(completed: boolean) => {
|
(completed: boolean) => {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -95,6 +102,7 @@ export class RootLayout extends RootLayoutBase {
|
|||||||
|
|
||||||
protected _cleanupPlatformShadeCover(): void {
|
protected _cleanupPlatformShadeCover(): void {
|
||||||
this._currentGradient = null;
|
this._currentGradient = null;
|
||||||
|
|
||||||
if (this._gradientLayer != null) {
|
if (this._gradientLayer != null) {
|
||||||
this._gradientLayer.removeFromSuperlayer();
|
this._gradientLayer.removeFromSuperlayer();
|
||||||
this._gradientLayer = null;
|
this._gradientLayer = null;
|
||||||
|
@ -6,30 +6,29 @@ import { RootLayout, RootLayoutOptions, ShadeCoverOptions, TransitionAnimation }
|
|||||||
import { Animation } from '../../animation';
|
import { Animation } from '../../animation';
|
||||||
import { AnimationDefinition } from '../../animation';
|
import { AnimationDefinition } from '../../animation';
|
||||||
import { isNumber } from '../../../utils/types';
|
import { isNumber } from '../../../utils/types';
|
||||||
|
import { _findRootLayoutById, _pushIntoRootLayoutStack, _removeFromRootLayoutStack, _geRootLayoutFromStack } from './root-layout-stack';
|
||||||
|
|
||||||
@CSSType('RootLayout')
|
@CSSType('RootLayout')
|
||||||
export class RootLayoutBase extends GridLayout {
|
export class RootLayoutBase extends GridLayout {
|
||||||
private shadeCover: View;
|
private _shadeCover: View;
|
||||||
private staticChildCount: number;
|
private _popupViews: { view: View; options: RootLayoutOptions }[] = [];
|
||||||
private popupViews: { view: View; options: RootLayoutOptions }[] = [];
|
|
||||||
|
|
||||||
constructor() {
|
public initNativeView(): void {
|
||||||
super();
|
super.initNativeView();
|
||||||
global.rootLayout = this;
|
|
||||||
|
_pushIntoRootLayoutStack(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onLoaded() {
|
public disposeNativeView(): void {
|
||||||
// get actual content count of rootLayout (elements between the <RootLayout> tags in the template).
|
super.disposeNativeView();
|
||||||
// All popups will be inserted dynamically at a higher index
|
|
||||||
this.staticChildCount = this.getChildrenCount();
|
|
||||||
|
|
||||||
super.onLoaded();
|
_removeFromRootLayoutStack(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public _onLivesync(context?: ModuleContext): boolean {
|
public _onLivesync(context?: ModuleContext): boolean {
|
||||||
let handled = false;
|
let handled = false;
|
||||||
|
|
||||||
if (this.popupViews.length > 0) {
|
if (this._popupViews.length > 0) {
|
||||||
this.closeAll();
|
this.closeAll();
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
@ -55,29 +54,32 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.hasChild(view)) {
|
if (this.hasChild(view)) {
|
||||||
return reject(new Error(`${view} has already been added`));
|
return reject(new Error(`View ${view} has already been added to the root layout`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const toOpen = [];
|
const toOpen = [];
|
||||||
const enterAnimationDefinition = options.animation ? options.animation.enterFrom : null;
|
const enterAnimationDefinition = options.animation ? options.animation.enterFrom : null;
|
||||||
|
|
||||||
// keep track of the views locally to be able to use their options later
|
// Keep track of the views locally to be able to use their options later
|
||||||
this.popupViews.push({ view: view, options: options });
|
this._popupViews.push({ view: view, options: options });
|
||||||
|
|
||||||
|
// Always begin with view invisible when adding dynamically
|
||||||
|
view.opacity = 0;
|
||||||
|
// Add view to view tree before adding shade cover
|
||||||
|
// Before being added to view tree, shade cover calculates the index to be inserted based on existing popup views
|
||||||
|
this.insertChild(view, this.getChildrenCount());
|
||||||
|
|
||||||
if (options.shadeCover) {
|
if (options.shadeCover) {
|
||||||
// perf optimization note: we only need 1 layer of shade cover
|
// perf optimization note: we only need 1 layer of shade cover
|
||||||
// we just update properties if needed by additional overlaid views
|
// we just update properties if needed by additional overlaid views
|
||||||
if (this.shadeCover) {
|
if (this._shadeCover) {
|
||||||
// overwrite current shadeCover options if topmost popupview has additional shadeCover configurations
|
// overwrite current shadeCover options if topmost popupview has additional shadeCover configurations
|
||||||
toOpen.push(this.updateShadeCover(this.shadeCover, options.shadeCover));
|
toOpen.push(this.updateShadeCover(this._shadeCover, options.shadeCover));
|
||||||
} else {
|
} else {
|
||||||
toOpen.push(this.openShadeCover(options.shadeCover));
|
toOpen.push(this.openShadeCover(options.shadeCover));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view.opacity = 0; // always begin with view invisible when adding dynamically
|
|
||||||
this.insertChild(view, this.getChildrenCount() + 1);
|
|
||||||
|
|
||||||
toOpen.push(
|
toOpen.push(
|
||||||
new Promise<void>((res, rej) => {
|
new Promise<void>((res, rej) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -125,12 +127,12 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.hasChild(view)) {
|
if (!this.hasChild(view)) {
|
||||||
return reject(new Error(`Unable to close popup. ${view} not found`));
|
return reject(new Error(`Unable to close popup. View ${view} not found`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const toClose = [];
|
const toClose = [];
|
||||||
const popupIndex = this.getPopupIndex(view);
|
const popupIndex = this.getPopupIndex(view);
|
||||||
const poppedView = this.popupViews[popupIndex];
|
const poppedView = this._popupViews[popupIndex];
|
||||||
const cleanupAndFinish = () => {
|
const cleanupAndFinish = () => {
|
||||||
view.notify({ eventName: 'closed', object: view });
|
view.notify({ eventName: 'closed', object: view });
|
||||||
this.removeChild(view);
|
this.removeChild(view);
|
||||||
@ -141,7 +143,7 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
|
|
||||||
// Remove view from tracked popupviews
|
// Remove view from tracked popupviews
|
||||||
if (popupIndex > -1) {
|
if (popupIndex > -1) {
|
||||||
this.popupViews.splice(popupIndex, 1);
|
this._popupViews.splice(popupIndex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
toClose.push(
|
toClose.push(
|
||||||
@ -158,13 +160,13 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.shadeCover) {
|
if (this._shadeCover) {
|
||||||
// Update shade cover with the topmost popupView options (if not specifically told to ignore)
|
// Update shade cover with the topmost popupView options (if not specifically told to ignore)
|
||||||
if (this.popupViews.length) {
|
if (this._popupViews.length) {
|
||||||
if (!poppedView?.options?.shadeCover?.ignoreShadeRestore) {
|
if (!poppedView?.options?.shadeCover?.ignoreShadeRestore) {
|
||||||
const shadeCoverOptions = this.popupViews[this.popupViews.length - 1].options?.shadeCover;
|
const shadeCoverOptions = this._popupViews[this._popupViews.length - 1].options?.shadeCover;
|
||||||
if (shadeCoverOptions) {
|
if (shadeCoverOptions) {
|
||||||
toClose.push(this.updateShadeCover(this.shadeCover, shadeCoverOptions));
|
toClose.push(this.updateShadeCover(this._shadeCover, shadeCoverOptions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -186,7 +188,7 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
|
|
||||||
closeAll(): Promise<void[]> {
|
closeAll(): Promise<void[]> {
|
||||||
const toClose = [];
|
const toClose = [];
|
||||||
const views = this.popupViews.map((popupView) => popupView.view);
|
const views = this._popupViews.map((popupView) => popupView.view);
|
||||||
|
|
||||||
// Close all views at the same time and wait for all of them
|
// Close all views at the same time and wait for all of them
|
||||||
for (const view of views) {
|
for (const view of views) {
|
||||||
@ -196,12 +198,25 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getShadeCover(): View {
|
getShadeCover(): View {
|
||||||
return this.shadeCover;
|
return this._shadeCover;
|
||||||
}
|
}
|
||||||
|
|
||||||
openShadeCover(options: ShadeCoverOptions = {}): Promise<void> {
|
openShadeCover(options: ShadeCoverOptions = {}): Promise<void> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
if (this.shadeCover) {
|
const childrenCount = this.getChildrenCount();
|
||||||
|
|
||||||
|
let indexToAdd: number;
|
||||||
|
|
||||||
|
if (this._popupViews.length) {
|
||||||
|
const { view } = this._popupViews[0];
|
||||||
|
const index = this.getChildIndex(view);
|
||||||
|
|
||||||
|
indexToAdd = index > -1 ? index : childrenCount;
|
||||||
|
} else {
|
||||||
|
indexToAdd = childrenCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._shadeCover) {
|
||||||
if (Trace.isEnabled()) {
|
if (Trace.isEnabled()) {
|
||||||
Trace.write(`RootLayout shadeCover already open.`, Trace.categories.Layout, Trace.messageType.warn);
|
Trace.write(`RootLayout shadeCover already open.`, Trace.categories.Layout, Trace.messageType.warn);
|
||||||
}
|
}
|
||||||
@ -216,9 +231,9 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.shadeCover = shadeCover;
|
this._shadeCover = shadeCover;
|
||||||
// Insert shade cover at index right above the first layout
|
// Insert shade cover at index right below the first popup view
|
||||||
this.insertChild(this.shadeCover, this.staticChildCount + 1);
|
this.insertChild(this._shadeCover, indexToAdd);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -226,15 +241,15 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
closeShadeCover(shadeCoverOptions: ShadeCoverOptions = {}): Promise<void> {
|
closeShadeCover(shadeCoverOptions: ShadeCoverOptions = {}): Promise<void> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// if shade cover is displayed and the last popup is closed, also close the shade cover
|
// if shade cover is displayed and the last popup is closed, also close the shade cover
|
||||||
if (this.shadeCover) {
|
if (this._shadeCover) {
|
||||||
return this._closeShadeCover(this.shadeCover, shadeCoverOptions).then(() => {
|
return this._closeShadeCover(this._shadeCover, shadeCoverOptions).then(() => {
|
||||||
if (this.shadeCover) {
|
if (this._shadeCover) {
|
||||||
this.shadeCover.off('loaded');
|
this._shadeCover.off('loaded');
|
||||||
if (this.shadeCover.parent) {
|
if (this._shadeCover.parent) {
|
||||||
this.removeChild(this.shadeCover);
|
this.removeChild(this._shadeCover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.shadeCover = null;
|
this._shadeCover = null;
|
||||||
// cleanup any platform specific details related to shade cover
|
// cleanup any platform specific details related to shade cover
|
||||||
this._cleanupPlatformShadeCover();
|
this._cleanupPlatformShadeCover();
|
||||||
resolve();
|
resolve();
|
||||||
@ -245,10 +260,16 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
topmost(): View {
|
topmost(): View {
|
||||||
return this.popupViews.length ? this.popupViews[this.popupViews.length - 1].view : null;
|
return this._popupViews.length ? this._popupViews[this._popupViews.length - 1].view : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bring any view instance open on the rootlayout to front of all the children visually
|
/**
|
||||||
|
* This method causes the requested view to overlap its siblings by bring it to front.
|
||||||
|
*
|
||||||
|
* @param view
|
||||||
|
* @param animated
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
bringToFront(view: View, animated: boolean = false): Promise<void> {
|
bringToFront(view: View, animated: boolean = false): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!(view instanceof View)) {
|
if (!(view instanceof View)) {
|
||||||
@ -256,19 +277,23 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.hasChild(view)) {
|
if (!this.hasChild(view)) {
|
||||||
return reject(new Error(`${view} not found or already at topmost`));
|
return reject(new Error(`View ${view} is not a child of the root layout`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const popupIndex = this.getPopupIndex(view);
|
const popupIndex = this.getPopupIndex(view);
|
||||||
// popupview should be present and not already the topmost view
|
|
||||||
if (popupIndex < 0 || popupIndex == this.popupViews.length - 1) {
|
if (popupIndex < 0) {
|
||||||
return reject(new Error(`${view} not found or already at topmost`));
|
return reject(new Error(`View ${view} is not a child of the root layout`));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (popupIndex == this._popupViews.length - 1) {
|
||||||
|
return reject(new Error(`View ${view} is already the topmost view in the rootlayout`));
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep the popupViews array in sync with the stacking of the views
|
// keep the popupViews array in sync with the stacking of the views
|
||||||
const currentView = this.popupViews[popupIndex];
|
const currentView = this._popupViews[popupIndex];
|
||||||
this.popupViews.splice(popupIndex, 1);
|
this._popupViews.splice(popupIndex, 1);
|
||||||
this.popupViews.push(currentView);
|
this._popupViews.push(currentView);
|
||||||
|
|
||||||
const exitAnimation = this.getViewExitState(view);
|
const exitAnimation = this.getViewExitState(view);
|
||||||
if (animated && exitAnimation) {
|
if (animated && exitAnimation) {
|
||||||
@ -302,14 +327,14 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
// update shadeCover to reflect topmost's shadeCover options
|
// update shadeCover to reflect topmost's shadeCover options
|
||||||
const shadeCoverOptions = currentView?.options?.shadeCover;
|
const shadeCoverOptions = currentView?.options?.shadeCover;
|
||||||
if (shadeCoverOptions) {
|
if (shadeCoverOptions) {
|
||||||
this.updateShadeCover(this.shadeCover, shadeCoverOptions);
|
this.updateShadeCover(this._shadeCover, shadeCoverOptions);
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPopupIndex(view: View): number {
|
private getPopupIndex(view: View): number {
|
||||||
return this.popupViews.findIndex((popupView) => popupView.view === view);
|
return this._popupViews.findIndex((popupView) => popupView.view === view);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getViewInitialState(view: View): TransitionAnimation {
|
private getViewInitialState(view: View): TransitionAnimation {
|
||||||
@ -317,7 +342,7 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
if (popupIndex === -1) {
|
if (popupIndex === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const initialState = this.popupViews[popupIndex]?.options?.animation?.enterFrom;
|
const initialState = this._popupViews[popupIndex]?.options?.animation?.enterFrom;
|
||||||
if (!initialState) {
|
if (!initialState) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -329,7 +354,7 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
if (popupIndex === -1) {
|
if (popupIndex === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const exitAnimation = this.popupViews[popupIndex]?.options?.animation?.exitTo;
|
const exitAnimation = this._popupViews[popupIndex]?.options?.animation?.exitTo;
|
||||||
if (!exitAnimation) {
|
if (!exitAnimation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -428,7 +453,11 @@ export class RootLayoutBase extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getRootLayout(): RootLayout {
|
export function getRootLayout(): RootLayout {
|
||||||
return <RootLayout>global.rootLayout;
|
return _geRootLayoutFromStack(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRootLayoutById(id: string): RootLayout {
|
||||||
|
return _findRootLayoutById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultTransitionAnimation: TransitionAnimation = {
|
export const defaultTransitionAnimation: TransitionAnimation = {
|
||||||
|
25
packages/core/ui/layouts/root-layout/root-layout-stack.ts
Normal file
25
packages/core/ui/layouts/root-layout/root-layout-stack.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { RootLayoutBase } from './root-layout-common';
|
||||||
|
|
||||||
|
const rootLayoutStack: RootLayoutBase[] = [];
|
||||||
|
|
||||||
|
export function _findRootLayoutById(id: string): RootLayoutBase {
|
||||||
|
return rootLayoutStack.find((rootLayout) => rootLayout.id && rootLayout.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _pushIntoRootLayoutStack(rootLayout: RootLayoutBase): void {
|
||||||
|
if (!rootLayoutStack.includes(rootLayout)) {
|
||||||
|
rootLayoutStack.push(rootLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _removeFromRootLayoutStack(rootLayout: RootLayoutBase): void {
|
||||||
|
const index = rootLayoutStack.indexOf(rootLayout);
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
rootLayoutStack.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _geRootLayoutFromStack(index: number): RootLayoutBase {
|
||||||
|
return rootLayoutStack.length > index ? rootLayoutStack[index] : null;
|
||||||
|
}
|
Reference in New Issue
Block a user